3.3.6. pci.api.dsops module¶
Introduces higher-order functions and decorators to simplify working with
Dataset
.
New in version 2018.
3.3.6.1. Context managers¶
- class pci.api.dsops.multi_dataset_open(*fargs, **kwargs)¶
Bases:
object
A context manager that can be used to open multiple datasets in one with statement. This context manager accepts filenames or tuples containing a filename and mode (
AccessMode
) via variable length argument.By default the dataset is opened as read-only. This behaviour can be modified by using the keyword argument mode (which accepts
AccessMode
).The datasets are opened by calling the function
default_dataset_open_func()
or the callable object supplied via keyword arguments open_dataset_func. This callable object must accept the argument filename and mode and returnDataset
objectThis example opens ‘ortho2input.pix’ as read-only and ‘ortho2result.pix’ for read/write and transfers a metadata from ‘ortho2input.pix’ to ‘ortho2result.pix’:
from pci.api import dsops from pci.api.datasource import AccessMode with dsops.multi_dataset_open('ortho2input.pix', ('ortho2result.pix', AccessMode.eAM_WRITE)) as datasets: # datasets is a tuple of Dataset objects where # datasets[0] is ortho2input.pix # datasets[1] is ortho2result.pix (and writeable) # transfer a file metadata from ortho2input.pix to ortho2result.pix metadata_val = dsops.get_file_metadata(dataset[0], 'Sensor') dsops.set_file_metadata(dataset[1], 'Sensor', metadata_val)
3.3.6.2. Segments and attributes¶
- class pci.api.dsops.Segments¶
Bases:
object
Specifies the supported segment types to be used with the following functions:
get_segment_ids()
,get_all_segment_ids()
,get_all_segment_id_map()
,get_segment()
,create_segment()
,create_segment()
,delete_segment()
- Bitmap = 'BIT'¶
- Vector = 'VEC'¶
- Text = 'TEX'¶
- Orbital = 'EPH'¶
- LUT = 'LUT'¶
- PCT = 'PCT'¶
- MathModel = 'MTH'¶
- Array = 'ARR'¶
- GCP = 'GCP'¶
- class pci.api.dsops.SegAttr(ids, get, get_md, create, delete)¶
Bases:
tuple
A named tuple to store functions and/or properties to access or modify a dataset (
Dataset
).ids - A list of segment ids
get - Get the segment specified by its segment id.
get_md - Get the segment metadata accessor specified by its segment id.
create - Create a new segment and return the segment id.
delete - Delete the segment specified by id.
- pci.api.dsops.seg_type_to_attr¶
A dictionary that has the segment type
Segments
as the key and the named tupleSegAttr
as the value.The following example demonstrates how to get the create segment function for LUT and Vector segments and use it to create the segment:
from pci.api import datasource as ds from pci.api.datasource import AccessMode from pci.api import dsops with ds.open_dataset('irvine.pix', AccessMode.eAM_WRITE) as dataset: # Get the create function for Vector segment vec_create_func = dsops.seg_type_to_attr[ dsops.Segments.Vector].create(dataset) # Get the create function for LUT segment lut_create_func = dsops.seg_type_to_attr[ dsops.Segments.LUT].create(dataset) # Create a Vector segment vec_seg_id = vec_create_func() # Create a Vector segment lut_seg_id = lut_create_func()
3.3.6.3. Decorators¶
- pci.api.dsops.inject_dataset(*args_to_inject, **inject_kwargs)¶
Returns a decorator to wrap functions that require filenames to be converted to
Dataset
object. Call this function with the argument names or argument indexes of the argument that require this capability. The argument index starts at 0, so first argument is 0, the second is 1 and so on.By default, the files are opened as read-only (
AccessMode.eAM_READ
) and this can modified by setting the keyword argument mode to either (AccessMode.eAM_READ
) or (AccessMode.eAM_WRITE
).The files are opened using the context manager,multi_dataset_open
. The file access mode can be overridden per argument by keyword arguments and these keyword argument names are determined as follows:For arguments with name, the mode keyword argument name is {argument_name}_mode.
For arguments without name (*args of the decorated function), the mode keyword argument name is dataset{argument_index}_mode. Examples:
If the argument name is input_dataset, then mode keyword argument name is input_dataset_mode.
If the argument does not have a name and the index of the argument is 2, then, the mode keyword argument name is dataset2_mode.
If allow_mode_kwarg is True, then the decorated function will gain the ability to change the mode per call and Keyword argument (**kwargs) will be added to the function to be decorated. This uses the same naming convention as above, so for argument name input_dataset, setting input_dataset_mode would override the mode used to open the file. For variable arguments on index 4, setting dataset4_mode would override the mode used to open the file.
The following example shows various way to to inject dataset into argument input_dataset (read-only) and output_dataset (read/write)
from pci.api import dsops from pci.api.datasource import AccessMode # inject_dataset using argument indexes @dsops.inject_dataset(0, 3, output_dataset_mode=AccessMode.eAM_WRITE) def process1(input_dataset, arg1, arg2, output_dataset): pass # inject_dataset using argument index and argument name @dsops.inject_dataset(0, 'output_dataset', output_dataset_mode=AccessMode.eAM_WRITE)) def process2(input_dataset, arg1, arg2, output_dataset): pass # inject_dataset using argument names and allow mode to be passed # as a argument to the decorated function @dsops.inject_dataset('input_dataset', 'output_dataset', allow_mode_kwarg=True) def process3(input_dataset, arg1, arg2, output_dataset): # The decorator will change this functions signature to # process3(input_dataset, arg1, arg2, output_dataset, **_kwargs) pass # Call process3 and set output_dataset to be open for read/write process3('irvine.pix', None, None, 'outputfile.pix', output_dataset_mode=AccessMode.eAM_WRITE)
- pci.api.dsops.inject_dataset_ro(*args_to_inject, **inject_kwargs)¶
Read only version of
inject_dataset()
decorator. Using this decorator is same as doing @inject_dataset(mode=AccessMode.eAM_READ).
- pci.api.dsops.inject_dataset_rw(*args_to_inject, **inject_kwargs)¶
Read/write version of
inject_dataset()
decorator. Using this decorator is same as doing @inject_dataset(mode=AccessMode.eAM_WRITE).
- pci.api.dsops.inject_crs(*args_to_inject, **inject_kwargs)¶
Return a decorator to use with functions that take
CRS
objects as arguments. This decorator can injectCRS
object in place ofDataset
object. Call this function with the argument names or argument indexes of the argument that require this capability. The argument index starts at 0, so first argument is 0, the second is 1 and so on. This decorator can be stacked withinject_dataset()
.By default the
Dataset
object’sCRS
is injected.This decorator adds the ability to specify type and id (
CRS
) of the segment to where to obtain theCRS
object usingget_crs()
. if allow_crs_kwargs is True (default True) then the function to be decorated will gain keyword arguments, i.e **kwargs so that crs type and id can be specified. If the argument name is crs then the decorator will look for type and id in keyword arguments crs_type and crs_id, respectively. For variable arguments on index 4, decorator will look for segment id and type in keyword arguments crs4_id and crs_type.Example:
from pci.api import dsops from pci.api.datasource import AccessMode from pci.api.datasource import open_dataset # inject_crs will only inject dataset crs @dsops.inject_crs(0) def process1(crs, arg1): pass # src_crs, dst_crs will be injected and the caller can specify # which crs @dsops.inject_dataset(2, 'src_crs') @dsops.inject_crs('src_crs', 'dst_crs') def process2(arg0, src_crs, points, dst_crs): # The decorator will change this functions signature to # process2(arg0, src_crs, points, dst_crs, **_kwargs) pass # Inject the 3rd (index 2) argument and keyword argument 'acrs' @dsops.inject_dataset(2, 'acrs', dataset2_mode=AccessMode.eAM_WRITE) @dsops.inject_crs(2, 'acrs') def process3(*args, **kwargs): acrs = kwargs.pop('acrs', None) pass # process1's argument crs will accept CRS object and Dataset Object with open_dataset('irvine.pix') as dataset: process1(dataset, None) process1(dataset.crs) # call process2 with vector CRS process2(5, 'irvine.pix', [(2, 5), (1, 3)], 'ortho2input.pix', src_crs_type=dsops.Segments.Vector, src_crs_id=2, dst_crs_type=Segments.MathModel, dst_crs_id=dsops.last_segment) # Pass the last GCP segment's CRS of 'testfile' as the 3rd argument # Pass the CRS of the Vector segment 25 of 'testfile2.pix' for argument # 'acrs' process3("Test", None, "ortho2input.pix.pix", crs2_type=Segments.MathModel, crs2_id=dsops.first_segment, acrs="california_files.pix", acrs_type=Segments.Vector, acrs_id=25)
- pci.api.dsops.inject_geocoding(*args_to_inject, **inject_kwargs)¶
Return a decorator to use with functions that take
GeocodingInfo
objects as arguments. This decorator can inject theGeocodingInfo
object in place ofDataset
object. Call this function with the argument names or argument indexes of the argument that require this capability. The argument index starts at 0, so first argument is 0, the second is 1 and so on. This decorator can be stacked withinject_dataset()
.from pci.api import dsops from pci.api.datasource import AccessMode from pci.api.datasource import open_dataset @dsops.inject_geocoding(1) def process1(arg0, geocoding, arg2): pass # Inject coding for arguments 'first_geocoding', 'second_geocoding' # and argument at index 3 (first argument in (*args) @dsops.inject_dataset('first_geocoding', 'second_geocoding', 3) @dsops.inject_geocoding('first_geocoding', 'second_geocoding', 3) def process2(arg0, first_geocoding, second_geocoding, *args): pass
- pci.api.dsops.inject_segment(*args_to_inject, **inject_kwargs)¶
Return a decorator to use with functions that take segment objects (e.g:
VectorIO
,EphemerisData
, etc.) as arguments. This decorator can inject any segment object in place ofDataset
object. Call this function with the argument names or argument indexes of the argument that require this capability. The argument index starts at 0, so first argument is 0, the second is 1 and so on. This decorator can be stacked withinject_dataset()
.To set the default segment type and id for all the arguments, set the following keyword arguments, segtype and segid respectively.
This decorator adds the ability to specify type and id of the segment per argument. If the argument name is seg then the decorator will look for type and id in keyword arguments seg_type and seg_id, respectively. For variable arguments on index 4, decorator will look for segment id and type in keyword arguments seg4_id and seg_type. If allow_segment_kwargs is True (default True) then the function to be decorated will gain keyword arguments, i.e. **kwargs so that segment id can be overridden by the caller of the decorated function. The segment type can only be overridden if it is not specified in the decorator.
Example:
from pci.api import dsops # If the argument segment is a filename or Dataset object, then file's # or Dataset's last Vector segment is injected. @dsops.inject_dataset(0) @dsops.inject_segment(0, segtype=dsops.Segments.Vector, segid=dsops.last_segment) def process_vector(segment, arg1): pass # The caller can specify first_seg's and second_seg's segment type and # id. If no segment type is specified then it is assumed to be # MathModel segment. @dsops.inject_dataset(0, 1) @dsops.inject_segment(0, 1, segtype=dsops.Segments.MathModel) def process_segments(first_seg, second_seg): # The decorator will change this functions signature to # process_segments(first_seg, second_seg, **_kwargs) pass # The caller can specify first_seg's and second_seg's segment type and # id. If no segment type is specified then first_segment is MathModel # segment and second_seg is LUT segment. If no segment id specified # then first_seg is the first segment of its type. @dsops.inject_dataset(0, 1) @dsops.inject_segment('first_seg', 'second_seg', first_seg_type=dsops.Segments.MathModel, first_seg_id=dsops.first_segment) def process_segments2(first_seg, second_seg): # The decorator will change this functions signature to # process_segments2(first_seg, second_seg, **_kwargs) pass # The function process_vector will receive the last vector segment # in argument segment. Since the segment type is specified in the # decorator the segment type cannot be overridden in the call. process_vector('california_files.pix', 4) # Call process_segments and pass last MathModel segment for the # argument first_seg and GCP segment 2 for argument second_seg of file # testfile1.pix. Since the segment type of both arguments are specified # in the decorator the segment type cannot be overridden in the call. process_segments('ortho2input.pix', 'ortho2input.pix', first_seg_id=dsops.last_segment, second_seg_id=2) # Call process_segments2 and pass first MathModel segment for the # argument first_seg and last LUT segment for the argument second_seg # of file testfile1.pix. Since the segment type for argument first_seg # is specified in the decorator the segment type for that argument # cannot be overridden in the call. process_segments2('ortho2input.pix', 'irvine.pix', second_seg_id=dsops.last_segment, second_seg_type=dsops.Segments.LUT)
3.3.6.4. Dataset operations¶
- pci.api.dsops.open_dataset_func(mode=pci.api.datasource.AccessMode.eAM_READ, frmt=None)¶
Generate a function that opens a file and presets access mode to mode and format to frmt. If frmt is None then use
open_dataset
, otherwise useopen_dataset_format
.
- pci.api.dsops.default_dataset_open_func(filename, mode=pci.api.datasource.AccessMode.eAM_READ)¶
The default function to use when opening files in
multi_dataset_open
.
- pci.api.dsops.get_mapunits(crs)¶
Get the map units from
CRS
,Dataset
or filename. If crs is not aCRS
instance thenCRS
object is determined using keyword arguments crs_type and crs_id.
- pci.api.dsops.get_crs(dataset, segtype=None, segid=None)¶
Returns the crs of the dataset or specified segment. If segtype is None, then the crs of the dataset is returned, otherwise return the crs of the segment specified by segtype (
Segments
) and segid. Only the following segment types are supported: GCP, Vector and MathModel. The parameter dataset can beDataset
object or filename. The argument segid can be the segment id or function that returns the segment id given the list of all segment ids.
- pci.api.dsops.get_geocoding(dataset)¶
Return the geocoding of the dataset. The dataset is either a filename or
Dataset
object. The parameter dataset can beDataset
object or filename.
- pci.api.dsops.get_raster_resolution(geocoding)¶
Get the resolution from
GeocodingInfo
,Dataset
or filename.
- pci.api.dsops.determine_segid(dataset, segtype, segid)¶
Determine the segment id by evaluating segid. If segid is callable, the result of calling segid is returned, otherwise segid is returned. The callable segid is called with the list of ids for segment type segtype in dataset dataset.
- pci.api.dsops.get_segment_ids(dataset, segtype)¶
Get the list of segment ids for type segtype from dataset. The parameter dataset can be
Dataset
object or filename.
- pci.api.dsops.get_all_segment_ids(dataset, segtypes)¶
Get single sorted list of all the ids for the list of segments specified by segtypes in dataset. The parameter dataset can be
Dataset
object or filename.
- pci.api.dsops.get_all_segment_id_map(dataset, segtypes, include_empty=False)¶
Get a dictionary of segment type (key) and segment ids (value) for the list of segments specified by segtypes in dataset. If include_empty is False, then empty lists are excluded. The parameter dataset can be
Dataset
object or filename.
- pci.api.dsops.get_segment(dataset, segtype, segid)¶
Get the object that is associated with segtype for the segment segid in the dataset. The parameter dataset must be an open
Dataset
object. The argument segid can be the segment id or function that returns the segment id given the list of all segment ids. If segtype == Segments.Bitmap, then segid can also be a list of bitmap segment ids.For example, if segtype == Segments.Vector then an instance of
VectorIO
is returnedThe following example code will get the vector segment 28 in the file irvine.pix:
from pci.api import dsops testfile = 'irvine.pix' with ds.open_dataset(testfile) as dataset: vector = dsops.get_segment(dataset, dsops.Segments.Vector, 28) last_vector = dsops.get_segment(dataset, dsops.Segments.Vector, dsops.last_segment)
- pci.api.dsops.get_segment_md(dataset, segtype, segid)¶
Get the object that is used to access the metadata for the segment segid of type segtype in the dataset. The parameter dataset must be a
Dataset
object. The argument segid can be the segment id or function that returns the segment id given the list of all segment ids.For example, if segtype == Segments.Bitmap then an instance of
MetadataIO
is returnedThe following example code will get the vector metadata I/O object for segment 28 in the file irvine.pix:
from pci.api import dsops with ds.open_dataset('irvine.pix') as dataset: vector = dsops.get_segment_md(dataset, dsops.Segments.Vector, 28) last_vector = dsops.get_segment_md(dataset, dsops.Segments.Vector, dsops.last_segment)
- pci.api.dsops.create_segment(dataset, segtype, *args, **kwargs)¶
Create a segment of type segtype in the dataset by passing the arguments args and kwargs to the create function. The parameter dataset can be
Dataset
object or filename. Returns the ID of the new segment. If creation is not supported for the segment type segtype thenNotImplementedError
is raised.The following example will create an array segment in the file irvine.pix:
from pci.api import dsops testfile = 'irvine.pix' array_seg_id = dsops.create_segment(testfile, dsops.Segments.Array)
- pci.api.dsops.delete_segment(dataset, segtype, segid)¶
Delete the segment specified by segment id segid of segment type segtype in the dataset. The parameter dataset can be
Dataset
object or filename. If deletion is not supported for the segment type segtype thenNotImplementedError
is raised.The following example will delete the LUT segment number 3 in the file irvine.pix:
from pci.api import dsops testfile = 'irvine.pix' array_seg_id = dsops.delete_segment(testfile, dsops.Segments.LUT, 3)
- pci.api.dsops.get_raster_size(dataset)¶
Get the raster size (in pixels) of the dataset as a tuple of (x-size, y-size). The parameter dataset can be
Dataset
object or filename.
- pci.api.dsops.set_file_metadata(dataset, key, value)¶
Associates the specified value with key in the file level metadata in dataset. The parameter dataset can be
Dataset
object or filename.The following example will set the file metadata key=’Filename’ and value=’irvine’ in the file irvine.pix:
from pci.api import dsops testfile = 'irvine.pix' dsops.set_file_metadata(testfile, 'TestName', 'dsops')
- pci.api.dsops.get_file_metadata(dataset, key)¶
Retrieve the file level metadata value for key from the dataset. The parameter dataset can be
Dataset
object or filename.The following example will get the file metadata for key=’Filename’ in the file irvine.pix:
from pci.api import dsops testfile = 'irvine.pix' value = dsops.get_file_metadata(testfile, 'TestName')
- pci.api.dsops.get_all_shape_ids(vector)¶
Get all shape ids from vector (
VectorIO
,Dataset
or filename. If vector is notVectorIO
instance thenVectorIO
is determined using keyword argument vector_id.
- pci.api.dsops.get_channel_data_types(dataset)¶
Get channel info which is a list containing a tuple; channel number and data type [(channel_num, DataType)]. The parameter dataset can be
Dataset
object or filename.Example:
[(1, DT_16U), (2, DT_16U))]
- pci.api.dsops.lssegids(dataset, include_empty=False)¶
List all the segments ids in the dataset as a dictionary where segment type is the key and the list of segments is the value. If include_empty is False, then empty lists are excluded. The parameter dataset can be
Dataset
object or filename.