Introduction

This section outlines the general usage of the Python bindings for a Raster.

All the examples assume the import has been done.

from caris.coverage import *

Opening a Raster for Reading

The following will open a raster for reading.

raster = Raster('source_raster.csar')

One can specify the named parameter.

raster = Raster(filename='source_raster.csar')

One can also supply a URI

raster = Raster(uri='file:///source_raster.csar')

Opening from BDB Server

To open a database surface, a URI must be given formatted as:

bdb://username:password@hostname/database/boid

Note

The database name is case sensitive.

Boids (object IDs for database objects) can be found by via caris.bathy.db.Database.query_objects().

In BASE Editor the boid can be found by selecting a surfac, the boid will be shown in the Selection window. The URI for opened rasters or clouds is shown in the Properties window’s the “Surface Name” field.

raster = caris.coverage.Raster(uri='bdb://dba:sql@example.com/MyDB/02000001')

Listing Bands

The band information is found in the Raster.band_info property. It is simply a dictionary where the key is the band name and the value is an instance of BandInfo. The band information contains properties such as its type, category, minimum, maximum, no-data-value, etc. See BandInfo for more info.

raster = Raster('source_raster.csar')

for band_name in raster.band_info:
    print(str(raster.band_info[band_name]))

Reading from a Raster

Reading is done via the read() method.

The following will read the entire band named Depth. Note that this is not a good idea for large rasters. Reading in smaller blocks would be advisable.

raster = Raster('source_raster.csar')

data = raster.read(band_name = 'Depth', area = ((0,0),raster.dims), level = raster.highest_level)

The level is optional. It defaults to the highest level. This is equvalent code.

raster = Raster('source_raster.csar')

data = raster.read(band_name = 'Depth', area = ((0,0),raster.dims))

The levels will be numerically lower for the coarser levels down to raster.lowest_level inclusive.

Note that in most cases, using named parameters is an optional feature. One may specify the arguments in order without the names.

raster = Raster('source_raster.csar')

data = raster.read('Depth', ((0,0),raster.dims))

Example counting no-data-values

raster = Raster('source_raster.csar')

area = ((0,0), raster.dims)
ndvCount = sum(1 for x in raster2.read('Depth', area) if x == raster2.band_info['Depth'].ndv)
print('no-data-value count: ' + str(ndvCount))

Examples converting between grid and geographic coordinates

Grid coordinates go from (0,0) to Raster.dims. They are in pixels. Suppose you wanted to know what the coordinate (100,100) is in geographic coordinates. Use the convertGridToGeo() method on the Raster’s transform.

raster = Raster('source_raster.csar')

geoPoint = raster.transform.convertGridToGeo((100,100), raster.highest_level)

Converting a grid area is similar.

raster = Raster('source_raster.csar')

gridArea = ((100,100),(200,200))
geoArea = raster.transform.convertGridToGeo(gridArea, raster.highest_level)

To convert in the other direction, use the convertGeoToGrid() method.

raster = Raster('source_raster.csar')

gridPoint = raster.transform.convertGeoToGrid((417760.1, 5579348.0), raster.highest_level)
raster = Raster('source_raster.csar')

geoArea = ((417760.1, 5579348.0),(417770.1, 5579358.0))
gridArea = raster.transform.convertGeoToGrid(geoArea, raster.highest_level)

Examples converting areas to a different level

If you have an area defined at the highest resolution, but you now want to read from a coarser level that represents the same geographic area, you can simply convert your coordinates before reading.

raster = Raster('source_raster.csar')

gridArea = ((100,100),(200,200))
gridArea2 = raster.transform.convertGridBox(raster.highest_level, raster.highest_level - 1, gridArea)
data = raster.read('Depth', gridArea2, raster.highest_level - 1)

Example expanding a geographic area to pixel boundary

Geographic coordinates don’t necessarilly match up to pixel coordinates. It is often desirable to expand the geographic extents to fully encompass all of the underlying pixels. The following example demonstrates how to do such a read.

raster = Raster('source_raster.csar')

geoArea = ((417760.1, 5579348.0),(417770.1, 5579358.0))

# Expand extents before converting to grid coordinates.
geoArea = raster.transform.expandGeo(geoArea, raster.highest_level)

# Now convert to grid space
gridArea = raster.transform.convertGeoToGrid(geoArea, raster.highest_level)

# Finally, read our data
data = raster.read('Depth', gridArea)

Copying a Raster

There are many ways to copy a raster. The simplest is opening a raster and copying all the required info into an Options instance.

raster = Raster('source_raster.csar')
outputFilename = 'dest_raster.csar'

# Setup options
opts = Options();
opts.open_type = OpenType.WRITE
opts.band_info = raster.band_info
opts.dims = raster.dims
opts.wkt_cosys = raster.wkt_cosys
opts.iso19139_xml = raster.iso19139_xml
opts.raster2geo_matrix = raster.transform.matrix
opts.pixel_type = raster.transform.pixel_type
opts.raster_read_callback_func = raster.read

# Create Raster
raster2 = Raster(outputFilename, options = opts)

Converting between BandInfo and a dictionary

A BandInfo class is not a dictionary and is not modifiable. However, one can convert to a dictionary, apply the changes you want and then convert it back. Here is how to convert to a dictionary.

raster = Raster('source_raster.csar')
bi = raster.band_info['Depth']

# Do the conversion
dbi = dict((x, getattr(bi, x)) for x in bi)

Converting back is much easier. Simply pass the dictionary to the BandInfo‘s constructor.

raster = Raster('source_raster.csar')
bi = raster.band_info['Depth']

# Do the conversion
dbi = dict((x, getattr(bi, x)) for x in bi)

# Convert back
bandInfo = BandInfo(dbi)

Example modifying Level Policies

A Level Policy is how to build the other pyramid levels of the raster. Each band can have its own level policy. Here is an example where we copy a Raster with known bands and we modify each band’s level policy.

raster = Raster('source_raster.csar')
outputFilename = 'dest_raster.csar'

# Setup options
opts = Options();
opts.open_type = OpenType.WRITE
opts.band_info = raster.band_info

# Change level policies
bi = opts.band_info['Depth']
dbi = dict((x, getattr(bi, x)) for x in bi)
dbi['level_policy'] = LevelPolicy.BILINEAR_HOLDNODATA
opts.band_info['Depth'] = BandInfo(dbi)

bi = opts.band_info['Density']
dbi = dict((x, getattr(bi, x)) for x in bi)
dbi['level_policy'] = LevelPolicy.FOLLOW
dbi['follow_band_name'] = 'Deep'
opts.band_info['Density'] = BandInfo(dbi)

bi = opts.band_info['Mean']
dbi = dict((x, getattr(bi, x)) for x in bi)
dbi['level_policy'] = LevelPolicy.FOLLOW
dbi['follow_band_name'] = 'Deep'
opts.band_info['Mean'] = BandInfo(dbi)

bi = opts.band_info['Shoal']
dbi = dict((x, getattr(bi, x)) for x in bi)
dbi['level_policy'] = LevelPolicy.MAX
opts.band_info['Shoal'] = BandInfo(dbi)

bi = opts.band_info['Weight']
dbi = dict((x, getattr(bi, x)) for x in bi)
dbi['level_policy'] = LevelPolicy.FOLLOW
dbi['follow_band_name'] = 'Shoal'
opts.band_info['Weight'] = BandInfo(dbi)

# Setup remaining options for copying
opts.dims = raster.dims
opts.wkt_cosys = raster.wkt_cosys
opts.iso19139_xml = raster.iso19139_xml
opts.raster2geo_matrix = raster.transform.matrix
opts.pixel_type = raster.transform.pixel_type
opts.raster_read_callback_func = raster.read

# Create raster
raster2 = Raster(outputFilename, options = opts)

Copying a Raster with Lambda

When creating a Raster, we must always copy from another source. This need not be from a Raster. In this case, we will use a lambda function. It does read from a source raster, but can be redirected to whatever source the user wishes.

def proxy_read_function(raster, offset, *args, **kwargs):
    in_box = args[1]
    level = raster.highest_level
    if (len(args) >= 3):
        level = args[2]
    if ('level' in kwargs):
        level = kwargs['level']

    box = ((in_box[0][0] + offset[0], in_box[0][1] + offset[1]), (in_box[1][0] + offset[0], in_box[1][1] + offset[1]))
    return raster.read(args[0], box, level)

def create_read_function(raster, offset):
    func = lambda args, kwargs, raster=raster, offset=offset: proxy_read_function(raster, offset, args, kwargs)
    return func

def create_copy_with_lambda():
    raster = Raster('source_raster.csar')
    outputFilename = 'dest_raster.csar'

    # Setup options
    opts = Options();
    opts.open_type = OpenType.WRITE
    opts.band_info = raster.band_info

    opts.dims = raster.dims
    opts.wkt_cosys = raster.wkt_cosys
    opts.iso19139_xml = raster.iso19139_xml
    opts.raster2geo_matrix = raster.transform.matrix
    opts.pixel_type = raster.transform.pixel_type

    # Use lambda function for reading from source.
    opts.raster_read_callback_func = create_read_function(raster, (0,0))

    # Create raster
    raster2 = Raster(outputFilename, options = opts)