class TxRcvType(Serializable): """ Parameters that describe the transmitted waveform(s) and receiver configurations used in the collection """ _fields = ('NumTxWFs', 'TxWFParameters', 'NumRcvs', 'RcvParameters') _required = ('TxWFParameters', 'RcvParameters') _collections_tags = { 'TxWFParameters': {'array': False, 'child_tag': 'TxWFParameters'}, 'RcvParameters': {'array': False, 'child_tag': 'RcvParameters'}} # descriptors TxWFParameters = SerializableListDescriptor( 'TxWFParameters', TxWFParametersType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Parameters that describe a Transmit Waveform.') # type: List[TxWFParametersType] RcvParameters = SerializableListDescriptor( 'RcvParameters', RcvParametersType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Parameters that describe a Receive configuration.') # type: List[RcvParametersType] def __init__(self, TxWFParameters=None, RcvParameters=None, **kwargs): """ Parameters ---------- TxWFParameters : List[TxWFParametersType] RcvParameters : List[RcvParametersType] kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.TxWFParameters = TxWFParameters self.RcvParameters = RcvParameters super(TxRcvType, self).__init__(**kwargs) @property def NumTxWFs(self): """ int: The number of transmit waveforms used. """ if self.TxWFParameters is None: return 0 return len(self.TxWFParameters) @property def NumRcvs(self): """ int: The number of receive configurations used. """ if self.RcvParameters is None: return 0 return len(self.RcvParameters)
class ChannelType(Serializable): """ The channel definition. """ _fields = ('RefChId', 'Parameters') _required = _fields _collections_tags = {'Parameters': {'array': False, 'child_tag': 'Parameters'}} # descriptors RefChId = StringDescriptor( 'RefChId', _required, strict=DEFAULT_STRICT, docstring='Channel ID for the Reference Channel in the ' 'product.') # type: str Parameters = SerializableListDescriptor( 'Parameters', ChannelParametersType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Parameter Set that describes a CRSD data ' 'channel.') # type: List[ChannelParametersType] def __init__(self, RefChId=None, Parameters=None, **kwargs): """ Parameters ---------- RefChId : str Parameters : List[ChannelParametersType] kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.RefChId = RefChId self.Parameters = Parameters super(ChannelType, self).__init__(**kwargs)
class AnnotationsType(Serializable): """ The list of annotations. """ _fields = ('Annotations', ) _required = ('Annotations', ) _collections_tags = {'Annotations': {'array': False, 'child_tag': 'Annotation'}} # Descriptor Annotations = SerializableListDescriptor( 'Annotations', AnnotationType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='') # type: List[AnnotationType] def __init__(self, Annotations=None, **kwargs): """ Parameters ---------- Annotations : List[AnnotationType] kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.Annotations = Annotations super(AnnotationsType, self).__init__(**kwargs) def __len__(self): return len(self.Annotations) def __getitem__(self, item): return self.Annotations[item]
class GeographicAndTargetType(Serializable): """ Container specifying the image coverage area in geographic coordinates, as well as optional data about the target of the collection/product. """ _fields = ('GeographicCoverage', 'TargetInformations') _required = ('GeographicCoverage', ) _collections_tags = {'TargetInformations': {'array': False, 'child_tag': 'TargetInformation'}} # Descriptors GeographicCoverage = SerializableDescriptor( 'GeographicCoverage', GeographicCoverageType, _required, strict=DEFAULT_STRICT, docstring='Provides geographic coverage information.') # type: GeographicCoverageType TargetInformations = SerializableListDescriptor( 'TargetInformations', TargetInformationType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Provides target specific geographic ' 'information.') # type: Union[None, List[TargetInformationType]] def __init__(self, GeographicCoverage=None, TargetInformations=None, **kwargs): """ Parameters ---------- GeographicCoverage : GeographicCoverageType TargetInformations : None|List[TargetInformationType] kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.GeographicCoverage = GeographicCoverage self.TargetInformations = TargetInformations super(GeographicAndTargetType, self).__init__(**kwargs)
class AnnotationType(Serializable): """ The annotation type. """ _fields = ('Identifier', 'SpatialReferenceSystem', 'Objects') _required = ('Identifier', 'Objects') _collections_tags = {'Objects': {'array': False, 'child_tag': 'Object'}} # Descriptor Identifier = StringDescriptor('Identifier', _required, strict=DEFAULT_STRICT, docstring='') # type: str SpatialReferenceSystem = SerializableDescriptor( 'SpatialReferenceSystem', ReferenceSystemType, _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, ReferenceSystemType] Objects = SerializableListDescriptor( 'Objects', AnnotationObjectType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='') # type: List[AnnotationObjectType] def __init__(self, Identifier=None, SpatialReferenceSystem=None, Objects=None, **kwargs): """ Parameters ---------- Identifier : str SpatialReferenceSystem : None|ReferenceSystemType Objects : List[AnnotationObjectType] kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.Identifier = Identifier self.SpatialReferenceSystem = SpatialReferenceSystem self.Objects = Objects super(AnnotationType, self).__init__(**kwargs)
class DownstreamReprocessingType(Serializable): """ Further processing after initial image creation. """ _fields = ('GeometricChip', 'ProcessingEvents') _required = () _collections_tags = { 'ProcessingEvents': { 'array': False, 'child_tag': 'ProcessingEvent' } } # Descriptor GeometricChip = SerializableDescriptor( 'GeometricChip', GeometricChipType, _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, GeometricChipType] ProcessingEvents = SerializableListDescriptor( 'ProcessingEvents', ProcessingEventType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, List[ProcessingEventType]] def __init__(self, GeometricChip=None, ProcessingEvents=None, **kwargs): """ Parameters ---------- GeometricChip : None|GeometricChipType ProcessingEvents : None|List[ProcessingEventType] kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.GeometricChip = GeometricChip self.ProcessingEvents = ProcessingEvents super(DownstreamReprocessingType, self).__init__(**kwargs)
class ChannelType(Serializable): """ Channel specific parameters for CPHD. """ _fields = ('Parameters', ) _required = ('Parameters', ) _collections_tags = { 'Parameters': { 'array': False, 'child_tag': 'Parameters' } } # descriptors Parameters = SerializableListDescriptor( 'Parameters', ParametersType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Channel dependent parameter list.' ) # type: List[ParametersType] def __init__(self, Parameters=None, **kwargs): """ Parameters ---------- Parameters : List[ParametersType] kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.Parameters = Parameters super(ChannelType, self).__init__(**kwargs)
class ExploitationFeaturesType(Serializable): """ Computed metadata regarding the collect. """ _fields = ('Collections', 'Products') _required = ('Collections', 'Products') _collections_tags = { 'Collections': { 'array': False, 'child_tag': 'Collection' }, 'Products': { 'array': False, 'child_tag': 'Product' } } # Descriptor Collections = SerializableListDescriptor( 'Collections', CollectionType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='') # type: List[CollectionType] Products = SerializableListDescriptor( 'Products', ExploitationFeaturesProductType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='') # type: List[ExploitationFeaturesProductType] def __init__(self, Collections=None, Products=None, **kwargs): """ Parameters ---------- Collections : List[CollectionType] Products : List[ExploitationFeaturesProductType] kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.Collections = Collections self.Products = Products super(ExploitationFeaturesType, self).__init__(**kwargs) @classmethod def from_sicd(cls, sicd, row_vector, col_vector): """ Construct from a sicd element. Parameters ---------- sicd : SICDType|List[SICDType] row_vector : numpy.ndarray col_vector : numpy.ndarray Returns ------- ExploitationFeaturesType """ if isinstance(sicd, (list, tuple)): collections = [] feats = [] for i, entry in sicd: calculator = ExploitationCalculator.from_sicd( entry, row_vector, col_vector) collections.append( CollectionType.from_calculator(calculator, entry)) feats.append( ExploitationFeaturesProductType.from_calculator( calculator, entry)) return cls(Collections=collections, Products=feats) if not isinstance(sicd, SICDType): raise TypeError(_sicd_type_text.format(type(sicd))) calculator = ExploitationCalculator.from_sicd(sicd, row_vector, col_vector) return cls(Collections=[ CollectionType.from_calculator(calculator, sicd), ], Products=[ ExploitationFeaturesProductType.from_calculator( calculator, sicd) ])
class GeoInfoType(Serializable): """ A geographic feature. """ _fields = ('name', 'Descriptions', 'Point', 'Line', 'Polygon', 'GeoInfo') _required = ('name', ) _set_as_attribute = ('name', ) _collections_tags = { 'Descriptions': { 'array': False, 'child_tag': 'Desc' }, 'Point': { 'array': False, 'child_tag': 'Point' }, 'Line': { 'array': False, 'child_tag': 'Line' }, 'Polygon': { 'array': False, 'child_tag': 'Polygon' }, 'GeoInfo': { 'array': False, 'child_tag': 'GeoInfo' } } # descriptors name = StringDescriptor('name', _required, strict=DEFAULT_STRICT, docstring='The name.') # type: str Descriptions = ParametersDescriptor( 'Descriptions', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Descriptions of the geographic feature.' ) # type: ParametersCollection Point = SerializableListDescriptor( 'Point', LatLonRestrictionType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Geographic points with WGS-84 coordinates.' ) # type: List[LatLonRestrictionType] Line = SerializableListDescriptor( 'Line', LineType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Geographic lines (array) with WGS-84 coordinates.' ) # type: List[LineType] Polygon = SerializableListDescriptor( 'Polygon', PolygonType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Geographic polygons (array) with WGS-84 coordinates.' ) # type: List[PolygonType] def __init__(self, name=None, Descriptions=None, Point=None, Line=None, Polygon=None, GeoInfo=None, **kwargs): """ Parameters ---------- name : str Descriptions : ParametersCollection|dict Point : List[LatLonRestrictionType] Line : List[LineType] Polygon : List[PolygonType] GeoInfo : Dict[GeoInfoTpe] kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.name = name self.Descriptions = Descriptions self.Point = Point self.Line = Line self.Polygon = Polygon self._GeoInfo = [] if GeoInfo is None: pass elif isinstance(GeoInfo, GeoInfoType): self.addGeoInfo(GeoInfo) elif isinstance(GeoInfo, (list, tuple)): for el in GeoInfo: self.addGeoInfo(el) else: raise ValueError('GeoInfo got unexpected type {}'.format( type(GeoInfo))) super(GeoInfoType, self).__init__(**kwargs) @property def GeoInfo(self): """ List[GeoInfoType]: list of GeoInfo objects. """ return self._GeoInfo def getGeoInfo(self, key): """ Get GeoInfo(s) with name attribute == `key`. Parameters ---------- key : str Returns ------- List[GeoInfoType] """ return [entry for entry in self._GeoInfo if entry.name == key] def addGeoInfo(self, value): """ Add the given GeoInfo to the GeoInfo list. Parameters ---------- value : GeoInfoType Returns ------- None """ if isinstance(value, ElementTree.Element): gi_key = self._child_xml_ns_key.get('GeoInfo', self._xml_ns_key) value = GeoInfoType.from_node(value, self._xml_ns, ns_key=gi_key) elif isinstance(value, dict): value = GeoInfoType.from_dict(value) if isinstance(value, GeoInfoType): self._GeoInfo.append(value) else: raise TypeError( 'Trying to set GeoInfo element with unexpected type {}'.format( type(value))) @classmethod def from_node(cls, node, xml_ns, ns_key=None, kwargs=None): if kwargs is None: kwargs = OrderedDict() gi_key = cls._child_xml_ns_key.get('GeoInfo', ns_key) kwargs['GeoInfo'] = find_children(node, 'GeoInfo', xml_ns, gi_key) return super(GeoInfoType, cls).from_node(node, xml_ns, ns_key=ns_key, kwargs=kwargs) def to_node(self, doc, tag, ns_key=None, parent=None, check_validity=False, strict=DEFAULT_STRICT, exclude=()): node = super(GeoInfoType, self).to_node(doc, tag, ns_key=ns_key, parent=parent, check_validity=check_validity, strict=strict, exclude=exclude + ('GeoInfo', )) # slap on the GeoInfo children if self._GeoInfo is not None and len(self._GeoInfo) > 0: for entry in self._GeoInfo: entry.to_node(doc, tag, ns_key=ns_key, parent=node, strict=strict) return node def to_dict(self, check_validity=False, strict=DEFAULT_STRICT, exclude=()): out = super(GeoInfoType, self).to_dict(check_validity=check_validity, strict=strict, exclude=exclude + ('GeoInfo', )) # slap on the GeoInfo children if self.GeoInfo is not None and len(self.GeoInfo) > 0: out['GeoInfo'] = [ entry.to_dict(check_validity=check_validity, strict=strict) for entry in self._GeoInfo ] return out
class PVPType(Serializable): _fields = ('TxTime', 'TxPos', 'TxVel', 'RcvTime', 'RcvPos', 'RcvVel', 'SRPPos', 'AmpSF', 'aFDOP', 'aFRR1', 'aFRR2', 'FX1', 'FX2', 'FXN1', 'FXN2', 'TOA1', 'TOA2', 'TOAE1', 'TOAE2', 'TDTropoSRP', 'TDIonoSRP', 'SC0', 'SCSS', 'SIGNAL', 'AddedPVP') _required = ('TxTime', 'TxPos', 'TxVel', 'RcvTime', 'RcvPos', 'RcvVel', 'SRPPos', 'aFDOP', 'aFRR1', 'aFRR2', 'FX1', 'FX2', 'TOA1', 'TOA2', 'TDTropoSRP', 'SC0', 'SCSS') _collections_tags = {'AddedPVP': {'array': False, 'child_tag': 'AddedPVP'}} # descriptors TxTime = SerializableDescriptor('TxTime', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 TxPos = SerializableDescriptor('TxPos', PerVectorParameterXYZ, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterXYZ TxVel = SerializableDescriptor('TxVel', PerVectorParameterXYZ, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterXYZ RcvTime = SerializableDescriptor( 'RcvTime', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 RcvPos = SerializableDescriptor( 'RcvPos', PerVectorParameterXYZ, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterXYZ RcvVel = SerializableDescriptor( 'RcvVel', PerVectorParameterXYZ, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterXYZ SRPPos = SerializableDescriptor( 'SRPPos', PerVectorParameterXYZ, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterXYZ AmpSF = SerializableDescriptor('AmpSF', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 aFDOP = SerializableDescriptor('aFDOP', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 aFRR1 = SerializableDescriptor('aFRR1', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 aFRR2 = SerializableDescriptor('aFRR2', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 FX1 = SerializableDescriptor('FX1', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 FX2 = SerializableDescriptor('FX2', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 FXN1 = SerializableDescriptor('FXN1', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 FXN2 = SerializableDescriptor('FXN2', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 TOA1 = SerializableDescriptor('TOA1', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 TOA2 = SerializableDescriptor('TOA2', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 TOAE1 = SerializableDescriptor('TOAE1', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 TOAE2 = SerializableDescriptor('TOAE2', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 TDTropoSRP = SerializableDescriptor( 'TDTropoSRP', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 TDIonoSRP = SerializableDescriptor( 'TDIonoSRP', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 SC0 = SerializableDescriptor('SC0', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 SCSS = SerializableDescriptor('SCSS', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 SIGNAL = SerializableDescriptor('SIGNAL', PerVectorParameterI8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterI8 AddedPVP = SerializableListDescriptor( 'AddedPVP', UserDefinedPVPType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, List[UserDefinedPVPType]] def __init__(self, TxTime=None, TxPos=None, TxVel=None, RcvTime=None, RcvPos=None, RcvVel=None, SRPPos=None, AmpSF=None, aFDOP=None, aFRR1=None, aFRR2=None, FX1=None, FX2=None, FXN1=None, FXN2=None, TOA1=None, TOA2=None, TOAE1=None, TOAE2=None, TDTropoSRP=None, TDIonoSRP=None, SC0=None, SCSS=None, SIGNAL=None, AddedPVP=None, **kwargs): """ Parameters ---------- TxTime : PerVectorParameterF8 TxPos : PerVectorParameterXYZ TxVel : PerVectorParameterXYZ RcvTime : PerVectorParameterF8 RcvPos : PerVectorParameterXYZ RcvVel : PerVectorParameterXYZ SRPPos : PerVectorParameterXYZ AmpSF : None|PerVectorParameterF8 aFDOP : PerVectorParameterF8 aFRR1 : PerVectorParameterF8 aFRR2 : PerVectorParameterF8 FX1 : PerVectorParameterF8 FX2 : PerVectorParameterF8 FXN1 : None|PerVectorParameterF8 FXN2 : None|PerVectorParameterF8 TOA1 : PerVectorParameterF8 TOA2 : PerVectorParameterF8 TOAE1 : None|PerVectorParameterF8 TOAE2 : None|PerVectorParameterF8 TDTropoSRP : PerVectorParameterF8 TDIonoSRP : None|PerVectorParameterF8 SC0 : PerVectorParameterF8 SCSS : PerVectorParameterF8 SIGNAL : None|PerVectorParameterI8 AddedPVP : None|List[UserDefinedPVPType] kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.TxTime = TxTime self.TxPos = TxPos self.TxVel = TxVel self.RcvTime = RcvTime self.RcvPos = RcvPos self.RcvVel = RcvVel self.SRPPos = SRPPos self.AmpSF = AmpSF self.aFDOP = aFDOP self.aFRR1 = aFRR1 self.aFRR2 = aFRR2 self.FX1 = FX1 self.FX2 = FX2 self.FXN1 = FXN1 self.FXN2 = FXN2 self.TOA1 = TOA1 self.TOA2 = TOA2 self.TOAE1 = TOAE1 self.TOAE2 = TOAE2 self.TDTropoSRP = TDTropoSRP self.TDIonoSRP = TDIonoSRP self.SC0 = SC0 self.SCSS = SCSS self.SIGNAL = SIGNAL self.AddedPVP = AddedPVP super(PVPType, self).__init__(**kwargs) def get_size(self): """ Gets the size in bytes of each vector. Returns ------- int """ out = 0 for fld in self._fields[:-1]: val = getattr(self, fld) if val is not None: out += val.Size * 8 if self.AddedPVP is not None: for entry in self.AddedPVP: out += entry.Size * 8 return out def get_offset_size_format(self, field): """ Get the Offset (in bytes), Size (in bytes) for the given field, as well as the corresponding struct format string. Parameters ---------- field : str The desired field name. Returns ------- None|(int, int, str) """ if field in self._fields[:-1]: val = getattr(self, field) if val is None: return None return val.Offset * 8, val.Size * 8, homogeneous_dtype( val.Format).char else: if self.AddedPVP is None: return None for val in self.AddedPVP: if field == val.Name: return val.Offset * 8, val.Size * 8, homogeneous_dtype( val.Format).char return None def get_vector_dtype(self): """ Gets the dtype for the corresponding structured array for the full PVP array. Returns ------- numpy.dtype This will be a compound dtype for a structured array. """ bytes_per_word = 8 names = [] formats = [] offsets = [] for fld in self._fields: val = getattr(self, fld) if val is None: continue elif fld == 'AddedPVP': for entry in val: assert isinstance(entry, UserDefinedPVPType) names.append(entry.Name) formats.append(binary_format_string_to_dtype(entry.Format)) offsets.append(entry.Offset * bytes_per_word) else: names.append(fld) formats.append(binary_format_string_to_dtype(val.Format)) offsets.append(val.Offset * bytes_per_word) return numpy.dtype({ 'names': names, 'formats': formats, 'offsets': offsets })
class DataType(Serializable): """ Parameters that describe binary data components contained in the product. """ _fields = ('SampleType', 'NumCPHDChannels', 'NumBytesVBP', 'ArraySize') _required = ('SampleType', 'NumBytesVBP', 'ArraySize') _collections_tags = { 'ArraySize': { 'array': False, 'child_tag': 'ArraySize' } } # descriptors SampleType = StringEnumDescriptor( 'SampleType', ("RE32F_IM32F", "RE16I_IM16I", "RE08I_IM08I"), _required, strict=True, docstring= "Indicates the PHD sample format of the PHD array(s). All arrays " "have the sample type. Real and imaginary components stored in adjacent " "bytes, real component stored first.") # type: str NumBytesVBP = IntegerDescriptor( 'NumBytesVBP', _required, strict=DEFAULT_STRICT, bounds=(1, None), docstring='Number of bytes per set of Vector Based Parameters.' ) # type: int ArraySize = SerializableListDescriptor( 'ArraySize', ArraySizeType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='CPHD array size parameters.') # type: List[ArraySizeType] def __init__(self, SampleType=None, NumBytesVBP=None, ArraySize=None, **kwargs): """ Parameters ---------- SampleType : str NumBytesVBP : int ArraySize : List[ArraySizeType] kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.SampleType = SampleType self.NumBytesVBP = NumBytesVBP self.ArraySize = ArraySize super(DataType, self).__init__(**kwargs) @property def NumCPHDChannels(self): """ int: The number of CPHD channels. """ if self.ArraySize is None: return 0 return len(self.ArraySize)
class DwellType(Serializable): """ Parameters that specify the dwell time supported by the signal arrays contained in the CPHD product. """ _fields = ('NumCODTimes', 'CODTimes', 'NumDwellTimes', 'DwellTimes') _required = ('CODTimes', 'DwellTimes') _collections_tags = { 'CODTimes': { 'array': False, 'child_tag': 'CODTime' }, 'DwellTimes': { 'array': False, 'child_tag': 'DwellTime' } } # descriptors CODTimes = SerializableListDescriptor( 'CODTimes', CODTimeType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='The Center of Dwell (COD) time polynomials.' ) # type: List[CODTimeType] DwellTimes = SerializableListDescriptor( 'DwellTimes', DwellTimeType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='The dwell time polynomials.') # type: List[DwellTimeType] def __init__(self, CODTimes=None, DwellTimes=None, **kwargs): """ Parameters ---------- CODTimes : List[CODTimeType] DwellTimes : List[DwellTimeType] kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.CODTimes = CODTimes self.DwellTimes = DwellTimes super(DwellType, self).__init__(**kwargs) @property def NumCODTimes(self): """ int: The number of cod time polynomial elements. """ if self.CODTimes is None: return 0 else: return len(self.CODTimes) @property def NumDwellTimes(self): """ int: The number of dwell time polynomial elements. """ if self.DwellTimes is None: return 0 else: return len(self.DwellTimes)
class AntennaType(Serializable): """ Parameters that describe the transmit and receive antennas used to collect the signal array(s). """ _fields = ('NumACFs', 'NumAPCs', 'NumAntPats', 'AntCoordFrame', 'AntPhaseCenter', 'AntPattern') _required = ('AntCoordFrame', 'AntPhaseCenter', 'AntPattern') _collections_tags = { 'AntCoordFrame': { 'array': False, 'child_tag': 'AntCoordFrame' }, 'AntPhaseCenter': { 'array': False, 'child_tag': 'AntPhaseCenter' }, 'AntPattern': { 'array': False, 'child_tag': 'AntPattern' } } # descriptors AntCoordFrame = SerializableListDescriptor( 'AntCoordFrame', AntCoordFrameType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring= 'Antenna coordinate frame (ACF) in which one or more phase centers' ' may lie.') # type: List[AntCoordFrameType] AntPhaseCenter = SerializableListDescriptor( 'AntPhaseCenter', AntPhaseCenterType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring= 'Parameters that describe each Antenna Phase Center (APC). Parameter ' 'set repeated for each APC.') # type: List[AntPhaseCenterType] AntPattern = SerializableListDescriptor( 'AntPattern', AntPatternType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Parameter set that defines each one-way Antenna Pattern.' ) # type: List[AntPatternType] def __init__(self, AntCoordFrame=None, AntPhaseCenter=None, AntPattern=None, **kwargs): """ Parameters ---------- AntCoordFrame : List[AntCoordFrameType] AntPhaseCenter : List[AntPhaseCenterType] AntPattern : List[AntPatternType] kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.AntCoordFrame = AntCoordFrame self.AntPhaseCenter = AntPhaseCenter self.AntPattern = AntPattern super(AntennaType, self).__init__(**kwargs) @property def NumACFs(self): """ int: The number of antenna coordinate frame elements. """ if self.AntCoordFrame is None: return 0 return len(self.AntCoordFrame) @property def NumAPCs(self): """ int: The number of antenna phase center elements. """ if self.AntPhaseCenter is None: return 0 return len(self.AntPhaseCenter) @property def NumAntPats(self): """ int: The number of antenna pattern elements. """ if self.AntPattern is None: return 0 return len(self.AntPattern)
class AntennaType(Serializable): """ Antenna parameters that describe antenna orientation, mainlobe steering and gain patterns vs. time. """ _fields = ('NumTxAnt', 'NumRcvAnt', 'NumTWAnt', 'Tx', 'Rcv', 'TwoWay') _required = () _collections_tags = { 'Tx': { 'array': False, 'child_tag': 'Tx' }, 'Rcv': { 'array': False, 'child_tag': 'Rcv' }, 'TwoWay': { 'array': False, 'child_tag': 'TwoWay' } } # descriptors Tx = SerializableListDescriptor( 'Tx', AntParamType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Transmit antenna pattern parameters.' ) # type: Union[None, List[AntParamType]] Rcv = SerializableListDescriptor( 'Rcv', AntParamType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Receive antenna pattern parameters.' ) # type: Union[None, List[AntParamType]] TwoWay = SerializableListDescriptor( 'TwoWay', AntParamType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Two-way antenna pattern parameters.' ) # type: Union[None, List[AntParamType]] def __init__(self, Tx=None, Rcv=None, TwoWay=None, **kwargs): """ Parameters ---------- Tx : None|List[AntParamType] Rcv : None|List[AntParamType] TwoWay : None|List[AntParamType] kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.Tx = Tx self.Rcv = Rcv self.TwoWay = TwoWay super(AntennaType, self).__init__(**kwargs) @property def NumTxAnt(self): """ int: The number of transmit elements. """ if self.Tx is None: return 0 return len(self.Tx) @property def NumRcvAnt(self): """ int: The number of receive elements. """ if self.Rcv is None: return 0 return len(self.Rcv) @property def NumTWAnt(self): """ int: The number of two way elements. """ if self.TwoWay is None: return 0 return len(self.TwoWay)
class ExploitationFeaturesCollectionInformationType(Serializable): """ General collection information. """ _fields = ('SensorName', 'RadarMode', 'CollectionDateTime', 'LocalDateTime', 'CollectionDuration', 'Resolution', 'InputROI', 'Polarizations') _required = ('SensorName', 'RadarMode', 'CollectionDateTime', 'CollectionDuration') _collections_tags = { 'Polarizations': { 'array': False, 'child_tag': 'Polarization' } } _numeric_format = {'CollectionDuration': FLOAT_FORMAT} # Descriptor SensorName = StringDescriptor('SensorName', _required, strict=DEFAULT_STRICT, docstring='The name of the sensor.') # str RadarMode = SerializableDescriptor( 'RadarMode', RadarModeType, _required, strict=DEFAULT_STRICT, docstring='Radar collection mode.') # type: RadarModeType CollectionDateTime = DateTimeDescriptor( 'CollectionDateTime', _required, strict=DEFAULT_STRICT, docstring= 'Collection date and time defined in Coordinated Universal Time (UTC). The seconds ' 'should be followed by a Z to indicate UTC.') # type: numpy.datetime64 CollectionDuration = FloatDescriptor( 'CollectionDuration', _required, strict=DEFAULT_STRICT, docstring='The duration of the collection (units = seconds).' ) # type: float Resolution = SerializableDescriptor( 'Resolution', RangeAzimuthType, _required, strict=DEFAULT_STRICT, docstring= 'Uniformly-weighted resolution (range and azimuth) processed in ' 'the slant plane.') # type: Union[None, RangeAzimuthType] InputROI = SerializableDescriptor( 'InputROI', InputROIType, _required, strict=DEFAULT_STRICT, docstring='ROI representing portion of input data used to make ' 'this product.') # type: Union[None, InputROIType] Polarizations = SerializableListDescriptor( 'Polarizations', TxRcvPolarizationType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Transmit and receive polarization(s).' ) # type: Union[None, List[TxRcvPolarizationType]] def __init__(self, SensorName=None, RadarMode=None, CollectionDateTime=None, LocalDateTime=None, CollectionDuration=None, Resolution=None, Polarizations=None, **kwargs): """ Parameters ---------- SensorName : str RadarMode : RadarModeType CollectionDateTime : numpy.datetime64|datetime.datetime|datetime.date|str LocalDateTime : None|str|datetime.datetime CollectionDuration : float Resolution : None|RangeAzimuthType|numpy.ndarray|list|tuple Polarizations : None|List[TxRcvPolarizationType] kwargs """ self._local_date_time = None if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.SensorName = SensorName self.RadarMode = RadarMode self.CollectionDateTime = CollectionDateTime self.CollectionDuration = CollectionDuration self.LocalDateTime = LocalDateTime self.Resolution = Resolution self.Polarizations = Polarizations super(ExploitationFeaturesCollectionInformationType, self).__init__(**kwargs) @property def LocalDateTime(self): """None|str: The local date/time string of the collection. *Optional.*""" return self._local_date_time @LocalDateTime.setter def LocalDateTime( self, value): # type: (Union[None, str, datetime.datetime]) -> None if value is None: self._local_date_time = None return elif isinstance(value, datetime.datetime): value = value.isoformat('T') if isinstance(value, str): self._local_date_time = value else: logger.error( 'Attribute LocalDateTime of class ExploitationFeaturesCollectionInformationType\n\t' 'requires a datetime.datetime or string. Got unsupported type {}.\n\t' 'Setting value to None.'.format(type(value))) self._local_date_time = None @classmethod def from_sicd(cls, sicd): """ Construct from a sicd element. Parameters ---------- sicd : SICDType Returns ------- ExploitationFeaturesCollectionInformationType """ if not isinstance(sicd, SICDType): raise TypeError(_sicd_type_text.format(type(sicd))) polarizations = [ TxRcvPolarizationType.from_sicd_value(entry.TxRcvPolarization) for entry in sicd.RadarCollection.RcvChannels ] return cls( SensorName=sicd.CollectionInfo.CollectorName, RadarMode=RadarModeType(**sicd.CollectionInfo.RadarMode.to_dict()), CollectionDateTime=sicd.Timeline.CollectStart, CollectionDuration=sicd.Timeline.CollectDuration, Resolution=(sicd.Grid.Row.SS, sicd.Grid.Col.SS), Polarizations=polarizations)
class ProductInfoType(Serializable): """ Parameters that provide general information about the CPHD product and/or the derived products that may be created from it. """ _fields = ('Profile', 'CreationInfos', 'Parameters') _required = () _collections_tags = { 'CreationInfos': { 'array': False, 'child_tag': 'CreationInfo' }, 'Parameters': { 'array': False, 'child_tag': 'Parameter' } } # descriptors Profile = StringDescriptor( 'Profile', _required, strict=DEFAULT_STRICT, docstring='Identifies what profile was used to create this CPHD product.' ) # type: str CreationInfos = SerializableListDescriptor( 'CreationInfos', CreationInfoType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Parameters that provide general information about the CPHD ' 'product generation.') # type: Union[None, List[CreationInfoType]] Parameters = ParametersDescriptor( 'Parameters', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Additional parameters.' ) # type: Union[None, ParametersCollection] def __init__(self, Profile=None, CreationInfos=None, Parameters=None, **kwargs): """ Parameters ---------- Profile : str CreationInfos : None|List[CreationInfoType] Parameters : None|ParametersCollection|dict kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.Profile = Profile self.CreationInfos = CreationInfos self.Parameters = Parameters super(ProductInfoType, self).__init__(**kwargs)
class ChannelType(Serializable): """ The channel definition. """ _fields = ( 'RefChId', 'FXFixedCPHD', 'TOAFixedCPHD', 'SRPFixedCPHD', 'Parameters', 'AddedParameters') _required = ( 'RefChId', 'FXFixedCPHD', 'TOAFixedCPHD', 'SRPFixedCPHD', 'Parameters') _collections_tags = { 'Parameters': {'array': False, 'child_tag': 'Parameters'}, 'AddedParameters': {'array': False, 'child_tag': 'AddedParameters'}} # descriptors RefChId = StringDescriptor( 'RefChId', _required, strict=DEFAULT_STRICT, docstring='Channel ID for the Reference Channel in the ' 'product.') # type: str FXFixedCPHD = BooleanDescriptor( 'FXFixedCPHD', _required, strict=DEFAULT_STRICT, docstring='Flag to indicate when a constant FX band is saved for all ' 'signal vectors of all channels.') # type: bool TOAFixedCPHD = BooleanDescriptor( 'TOAFixedCPHD', _required, strict=DEFAULT_STRICT, docstring='Flag to indicate when a constant TOA swath is saved for all ' 'signal vectors of all channels.') # type: bool SRPFixedCPHD = BooleanDescriptor( 'SRPFixedCPHD', _required, strict=DEFAULT_STRICT, docstring='Flag to indicate when a constant SRP position is used all ' 'signal vectors of all channels.') # type: bool Parameters = SerializableListDescriptor( 'Parameters', ChannelParametersType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Parameter Set that describes a CPHD data ' 'channel.') # type: List[ChannelParametersType] AddedParameters = ParametersDescriptor( 'AddedParameters', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Additional free form parameters.') # type: Union[None, ParametersCollection] def __init__(self, RefChId=None, FXFixedCPHD=None, TOAFixedCPHD=None, SRPFixedCPHD=None, Parameters=None, AddedParameters=None, **kwargs): """ Parameters ---------- RefChId : str FXFixedCPHD : bool TOAFixedCPHD : bool SRPFixedCPHD : bool Parameters : List[ChannelParametersType] AddedParameters kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.RefChId = RefChId self.FXFixedCPHD = FXFixedCPHD self.TOAFixedCPHD = TOAFixedCPHD self.SRPFixedCPHD = SRPFixedCPHD self.Parameters = Parameters self.AddedParameters = AddedParameters super(ChannelType, self).__init__(**kwargs)
class SupportArrayType(Serializable): """ Parameters that describe the binary support array(s) content and grid coordinates. """ _fields = ('IAZArray', 'AntGainPhase', 'AddedSupportArray') _required = () _collections_tags = { 'IAZArray': {'array': False, 'child_tag': 'IAZArray'}, 'AntGainPhase': {'array': False, 'child_tag': 'AntGainPhase'}, 'AddedSupportArray': {'array': False, 'child_tag': 'AddedSupportArray'}} # descriptors IAZArray = SerializableListDescriptor( 'IAZArray', IAZArrayType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Arrays of scene surface heights expressed in image coordinate IAZ ' 'values (meters). Grid coordinates are image area coordinates ' '(IAX, IAY).') # type: Union[None, List[IAZArrayType]] AntGainPhase = SerializableListDescriptor( 'AntGainPhase', AntGainPhaseType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Antenna arrays with values are antenna gain and phase expressed in dB ' 'and cycles. Array coordinates are direction cosines with respect to ' 'the ACF (DCX, DCY).') # type: Union[None, List[AntGainPhaseType]] AddedSupportArray = SerializableListDescriptor( 'AddedSupportArray', AddedSupportArrayType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Additional arrays (two-dimensional), where the content and format and units of each ' 'element are user defined.') # type: Union[None, List[AddedSupportArrayType]] def __init__(self, IAZArray=None, AntGainPhase=None, AddedSupportArray=None, **kwargs): """ Parameters ---------- IAZArray : None|List[IAZArrayType] AntGainPhase : None|List[AntGainPhaseType] AddedSupportArray : None|List[AddedSupportArrayType] kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.IAZArray = IAZArray self.AntGainPhase = AntGainPhase self.AddedSupportArray = AddedSupportArray super(SupportArrayType, self).__init__(**kwargs) def find_support_array(self, identifier): """ Find and return the details for support array associated with the given identifier. Parameters ---------- identifier : str Returns ------- IAZArrayType|AntGainPhaseType|AddedSupportArrayType """ if self.IAZArray is not None: for entry in self.IAZArray: if entry.Identifier == identifier: return entry if self.AntGainPhase is not None: for entry in self.AntGainPhase: if entry.Identifier == identifier: return entry if self.AddedSupportArray is not None: for entry in self.AddedSupportArray: if entry.Identifier == identifier: return entry raise KeyError('Identifier {} not associated with a support array.'.format(identifier))
class ImageFormationType(Serializable): """The image formation process parameters.""" _fields = ('RcvChanProc', 'TxRcvPolarizationProc', 'TStartProc', 'TEndProc', 'TxFrequencyProc', 'SegmentIdentifier', 'ImageFormAlgo', 'STBeamComp', 'ImageBeamComp', 'AzAutofocus', 'RgAutofocus', 'Processings', 'PolarizationCalibration') _required = ('RcvChanProc', 'TxRcvPolarizationProc', 'TStartProc', 'TEndProc', 'TxFrequencyProc', 'ImageFormAlgo', 'STBeamComp', 'ImageBeamComp', 'AzAutofocus', 'RgAutofocus') _collections_tags = { 'Processings': { 'array': False, 'child_tag': 'Processing' } } _numeric_format = {'TStartProc': '0.16G', 'EndProc': '0.16G'} # class variables _IMG_FORM_ALGO_VALUES = ('PFA', 'RMA', 'RGAZCOMP', 'OTHER') _ST_BEAM_COMP_VALUES = ('NO', 'GLOBAL', 'SV') _IMG_BEAM_COMP_VALUES = ('NO', 'SV') _AZ_AUTOFOCUS_VALUES = _ST_BEAM_COMP_VALUES _RG_AUTOFOCUS_VALUES = _ST_BEAM_COMP_VALUES # descriptors RcvChanProc = SerializableDescriptor( 'RcvChanProc', RcvChanProcType, _required, strict=DEFAULT_STRICT, docstring='The received processed channels.') # type: RcvChanProcType TxRcvPolarizationProc = StringEnumDescriptor( 'TxRcvPolarizationProc', DUAL_POLARIZATION_VALUES, _required, strict=DEFAULT_STRICT, docstring= 'The combined transmit/receive polarization processed to form the image.' ) # type: str TStartProc = FloatDescriptor( 'TStartProc', _required, strict=DEFAULT_STRICT, docstring= 'Earliest slow time value for data processed to form the image ' 'from `CollectionStart`.') # type: float TEndProc = FloatDescriptor( 'TEndProc', _required, strict=DEFAULT_STRICT, docstring= 'Latest slow time value for data processed to form the image from `CollectionStart`.' ) # type: float TxFrequencyProc = SerializableDescriptor( 'TxFrequencyProc', TxFrequencyProcType, _required, strict=DEFAULT_STRICT, docstring='The range of transmit frequency processed to form the image.' ) # type: TxFrequencyProcType SegmentIdentifier = StringDescriptor( 'SegmentIdentifier', _required, strict=DEFAULT_STRICT, docstring='Identifier that describes the image that was processed. ' 'Must be included when `SICD.RadarCollection.Area.Plane.SegmentList` is included.' ) # type: str ImageFormAlgo = StringEnumDescriptor('ImageFormAlgo', _IMG_FORM_ALGO_VALUES, _required, strict=DEFAULT_STRICT, docstring=""" The image formation algorithm used: * `PFA` - Polar Format Algorithm * `RMA` - Range Migration (Omega-K, Chirp Scaling, Range-Doppler) * `RGAZCOMP` - Simple range, Doppler compression. """) # type: str STBeamComp = StringEnumDescriptor('STBeamComp', _ST_BEAM_COMP_VALUES, _required, strict=DEFAULT_STRICT, docstring=""" Indicates if slow time beam shape compensation has been applied. * `NO` - No ST beam shape compensation. * `GLOBAL` - Global ST beam shape compensation applied. * `SV` - Spatially variant beam shape compensation applied. """) # type: str ImageBeamComp = StringEnumDescriptor('ImageBeamComp', _IMG_BEAM_COMP_VALUES, _required, strict=DEFAULT_STRICT, docstring=""" Indicates if image domain beam shape compensation has been applied. * `NO` - No image domain beam shape compensation. * `SV` - Spatially variant image domain beam shape compensation applied. """) # type: str AzAutofocus = StringEnumDescriptor( 'AzAutofocus', _AZ_AUTOFOCUS_VALUES, _required, strict=DEFAULT_STRICT, docstring= 'Indicates if azimuth autofocus correction has been applied, with similar ' 'interpretation as `STBeamComp`.') # type: str RgAutofocus = StringEnumDescriptor( 'RgAutofocus', _RG_AUTOFOCUS_VALUES, _required, strict=DEFAULT_STRICT, docstring= 'Indicates if range autofocus correction has been applied, with similar ' 'interpretation as `STBeamComp`.') # type: str Processings = SerializableListDescriptor( 'Processings', ProcessingType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring= 'Parameters to describe types of specific processing that may have been applied ' 'such as additional compensations.' ) # type: Union[None, List[ProcessingType]] PolarizationCalibration = SerializableDescriptor( 'PolarizationCalibration', PolarizationCalibrationType, _required, strict=DEFAULT_STRICT, docstring='The polarization calibration details.' ) # type: PolarizationCalibrationType def __init__(self, RcvChanProc=None, TxRcvPolarizationProc=None, TStartProc=None, TEndProc=None, TxFrequencyProc=None, SegmentIdentifier=None, ImageFormAlgo=None, STBeamComp=None, ImageBeamComp=None, AzAutofocus=None, RgAutofocus=None, Processings=None, PolarizationCalibration=None, **kwargs): """ Parameters ---------- RcvChanProc : RcvChanProcType TxRcvPolarizationProc : str TStartProc : float TEndProc : float TxFrequencyProc : TxFrequencyProcType|numpy.ndarray|list|tuple SegmentIdentifier : str ImageFormAlgo : str STBeamComp : str ImageBeamComp :str AzAutofocus : str RgAutofocus : str Processings : None|List[ProcessingType] PolarizationCalibration : PolarizationCalibrationType kwargs : dict """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.RcvChanProc = RcvChanProc self.TxRcvPolarizationProc = TxRcvPolarizationProc self.TStartProc, self.TEndProc = TStartProc, TEndProc if isinstance( TxFrequencyProc, (numpy.ndarray, list, tuple)) and len(TxFrequencyProc) >= 2: self.TxFrequencyProc = TxFrequencyProcType( MinProc=TxFrequencyProc[0], MaxProc=TxFrequencyProc[1]) else: self.TxFrequencyProc = TxFrequencyProc self.SegmentIdentifier = SegmentIdentifier self.ImageFormAlgo = ImageFormAlgo self.STBeamComp, self.ImageBeamComp = STBeamComp, ImageBeamComp self.AzAutofocus, self.RgAutofocus = AzAutofocus, RgAutofocus self.Processings = Processings self.PolarizationCalibration = PolarizationCalibration super(ImageFormationType, self).__init__(**kwargs) def _basic_validity_check(self): condition = super(ImageFormationType, self)._basic_validity_check() if self.TStartProc is not None and self.TEndProc is not None and self.TEndProc < self.TStartProc: self.log_validity_error( 'Invalid time processing bounds TStartProc ({}) > TEndProc ({})' .format(self.TStartProc, self.TEndProc)) condition = False return condition def _derive_tx_frequency_proc(self, RadarCollection): """ Populate a default for processed frequency values, based on the assumption that the entire transmitted bandwidth was processed. This is expected to be called by SICD parent. Parameters ---------- RadarCollection : sarpy.io.complex.sicd_elements.RadarCollection.RadarCollectionType Returns ------- None """ if RadarCollection is not None and RadarCollection.TxFrequency is not None and \ RadarCollection.TxFrequency.Min is not None and RadarCollection.TxFrequency.Max is not None: # this is based on the assumption that the entire transmitted bandwidth was processed. if self.TxFrequencyProc is not None: self.TxFrequencyProc = TxFrequencyProcType( MinProc=RadarCollection.TxFrequency.Min, MaxProc=RadarCollection.TxFrequency.Max) # how would it make sense to set only one end? elif self.TxFrequencyProc.MinProc is None: self.TxFrequencyProc.MinProc = RadarCollection.TxFrequency.Min elif self.TxFrequencyProc.MaxProc is None: self.TxFrequencyProc.MaxProc = RadarCollection.TxFrequency.Max def _apply_reference_frequency(self, reference_frequency): """ If the reference frequency is used, adjust the necessary fields accordingly. Expected to be called by SICD parent. Parameters ---------- reference_frequency : float The reference frequency. Returns ------- None """ if self.TxFrequencyProc is not None: # noinspection PyProtectedMember self.TxFrequencyProc._apply_reference_frequency( reference_frequency) def get_polarization(self): """ Gets the transmit/receive polarization. Returns ------- str """ return self.TxRcvPolarizationProc if self.TxRcvPolarizationProc is not None else 'UNKNOWN' def get_polarization_abbreviation(self): """ Gets the transmit/receive polarization abbreviation for the suggested name. Returns ------- str """ pol = self.TxRcvPolarizationProc if pol is None or pol in ('OTHER', 'UNKNOWN'): return 'UN' fp, sp = pol.split(':') return fp[0] + sp[0] def get_transmit_band_name(self): """ Gets the transmit band name. Returns ------- str """ if self.TxFrequencyProc is not None: return self.TxFrequencyProc.get_band_name() else: return 'UN' def permits_version_1_1(self): """ Does this value permit storage in SICD version 1.1? Returns ------- bool """ return is_polstring_version1(self.TxRcvPolarizationProc)
class ExploitationFeaturesProductType(Serializable): """ Metadata regarding the product. """ _fields = ('Resolution', 'Ellipticity', 'Polarizations', 'North', 'Extensions') _required = ('Resolution', 'Ellipticity', 'Polarizations') _collections_tags = { 'Polarizations': { 'array': False, 'child_tag': 'Polarization' }, 'Extensions': { 'array': False, 'child_tag': 'Extension' } } _numeric_format = {'Ellipticity': FLOAT_FORMAT, 'North': FLOAT_FORMAT} # Descriptor Resolution = SerializableDescriptor( 'Resolution', RowColDoubleType, _required, strict=DEFAULT_STRICT, docstring= 'Uniformly-weighted resolution projected into the Earth Tangent ' 'Plane (ETP).') # type: RowColDoubleType Ellipticity = FloatDescriptor( 'Ellipticity', _required, strict=DEFAULT_STRICT, docstring= "Ellipticity of the 2D-IPR at the ORP, measured in the *Earth Geodetic " "Tangent Plane (EGTP)*. Ellipticity is the ratio of the IPR ellipse's " "major axis to minor axis.") # type: float Polarizations = SerializableListDescriptor( 'Polarizations', ProcTxRcvPolarizationType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring= 'Describes the processed transmit and receive polarizations for the ' 'product.') # type: List[ProcTxRcvPolarizationType] North = FloatModularDescriptor( 'North', 180.0, _required, strict=DEFAULT_STRICT, docstring= 'Counter-clockwise angle from increasing row direction to north at the center ' 'of the image.') # type: float Extensions = ParametersDescriptor( 'Extensions', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Exploitation feature extension related to geometry for a ' 'single input image.') # type: ParametersCollection def __init__(self, Resolution=None, Ellipticity=None, Polarizations=None, North=None, Extensions=None, **kwargs): """ Parameters ---------- Resolution : RowColDoubleType|numpy.ndarray|list|tuple Ellipticity : float Polarizations : List[ProcTxRcvPolarizationType] North : None|float Extensions : None|ParametersCollection|dict kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.Resolution = Resolution self.Ellipticity = Ellipticity self.Polarizations = Polarizations self.North = North self.Extensions = Extensions super(ExploitationFeaturesProductType, self).__init__(**kwargs) @classmethod def from_calculator(cls, calculator, sicd): """ Construct from a sicd element. Parameters ---------- calculator : ExploitationCalculator sicd : SICDType Returns ------- ExploitationFeaturesProductType """ if not isinstance(sicd, SICDType): raise TypeError(_sicd_type_text.format(type(sicd))) row_ground, col_ground = sicd.get_ground_resolution() ellipticity = row_ground / col_ground if row_ground >= col_ground else col_ground / row_ground return cls(Resolution=(row_ground, col_ground), Ellipticity=ellipticity, Polarizations=[ ProcTxRcvPolarizationType.from_sicd_value( sicd.ImageFormation.TxRcvPolarizationProc), ], North=calculator.North)
class AntPatternType(Serializable): """ Parameter set that defines each Antenna Pattern as function time. """ _fields = ('Identifier', 'FreqZero', 'GainZero', 'EBFreqShift', 'MLFreqDilation', 'GainBSPoly', 'EB', 'Array', 'Element', 'GainPhaseArray') _required = ('Identifier', 'FreqZero', 'EB', 'Array', 'Element') _collections_tags = { 'GainPhaseArray': { 'array': False, 'child_tag': 'GainPhaseArray' } } _numeric_format = {'FreqZero': '0.16G', 'GainZero': '0.16G'} # descriptors Identifier = StringDescriptor( 'Identifier', _required, strict=DEFAULT_STRICT, docstring='String that uniquely identifies this ACF.') # type: str FreqZero = FloatDescriptor( 'FreqZero', _required, strict=DEFAULT_STRICT, docstring= 'The reference frequency value for which the Electrical Boresight ' 'and array pattern polynomials are computed.') # type: float GainZero = FloatDescriptor( 'GainZero', _required, strict=DEFAULT_STRICT, docstring='The reference antenna gain at zero steering angle at the ' 'reference frequency, measured in dB.') # type: float EBFreqShift = BooleanDescriptor( 'EBFreqShift', _required, strict=DEFAULT_STRICT, docstring= "Parameter indicating whether the electronic boresite shifts with " "frequency.") # type: bool MLFreqDilation = BooleanDescriptor( 'MLFreqDilation', _required, strict=DEFAULT_STRICT, docstring="Parameter indicating the mainlobe (ML) width changes with " "frequency.") # type: bool GainBSPoly = SerializableDescriptor( 'GainBSPoly', Poly1DType, _required, strict=DEFAULT_STRICT, docstring= 'Gain polynomial *(in dB)* as a function of frequency for boresight *(BS)* ' 'at :math:`DCX=0, DCY=0`. ' 'Frequency ratio :math:`(f-f0)/f0` is the input variable, and the constant ' 'coefficient is always `0.0`.') # type: Poly1DType EB = SerializableDescriptor( 'EB', EBType, _required, strict=DEFAULT_STRICT, docstring= 'Electrical boresight *(EB)* steering directions for an electronically ' 'steered array.') # type: EBType Array = SerializableDescriptor( 'Array', GainPhasePolyType, _required, strict=DEFAULT_STRICT, docstring='Array pattern polynomials that define the shape of the ' 'main-lobe.') # type: GainPhasePolyType Element = SerializableDescriptor( 'Element', GainPhasePolyType, _required, strict=DEFAULT_STRICT, docstring='Element array pattern polynomials for electronically steered ' 'arrays.') # type: GainPhasePolyType GainPhaseArray = SerializableListDescriptor( 'GainPhaseArray', GainPhaseArrayType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring= 'Array of parameters that identify 2-D sampled Gain and Phase patterns at ' 'single frequency value.' ) # type: Union[None, List[GainPhaseArrayType]] def __init__(self, Identifier=None, FreqZero=None, GainZero=None, EBFreqShift=None, MLFreqDilation=None, GainBSPoly=None, EB=None, Array=None, Element=None, GainPhaseArray=None, **kwargs): """ Parameters ---------- Identifier : str FreqZero : float GainZero : float EBFreqShift : bool MLFreqDilation : bool GainBSPoly : None|Poly1DType EB : EBType Array : GainPhasePolyType Element : GainPhasePolyType GainPhaseArray : None|List[GainPhaseArrayType] kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.Identifier = Identifier self.FreqZero = FreqZero self.GainZero = GainZero self.EBFreqShift = EBFreqShift self.MLFreqDilation = MLFreqDilation self.GainBSPoly = GainBSPoly self.EB = EB self.Array = Array self.Element = Element self.GainPhaseArray = GainPhaseArray super(AntPatternType, self).__init__(**kwargs)
class DataType(Serializable): """ Parameters that describe binary data components contained in the product. """ _fields = ( 'SignalArrayFormat', 'NumBytesPVP', 'NumCRSDChannels', 'Channels', 'NumSupportArrays', 'SupportArrays') _required = ('SignalArrayFormat', 'NumBytesPVP', 'Channels') _collections_tags = { 'Channels': {'array': False, 'child_tag': 'Channel'}, 'SupportArrays': {'array': False, 'child_tag': 'SupportArray'}} # descriptors SignalArrayFormat = StringEnumDescriptor( 'SignalArrayFormat', ('CI2', 'CI4', 'CF8'), _required, strict=DEFAULT_STRICT, docstring="Signal Array sample binary format of the CRSD signal arrays, where" "`CI2` denotes a 1 byte signed integer parameter, 2's complement format, and 2 Bytes Per Sample;" "`CI4` denotes a 2 byte signed integer parameter, 2's complement format, and 4 Bytes Per Sample;" "`CF8` denotes a 4 byte floating point parameter, and 8 Bytes Per Sample.") # type: str NumBytesPVP = IntegerDescriptor( 'NumBytesPVP', _required, strict=DEFAULT_STRICT, bounds=(0, None), docstring='Number of bytes per set of Per Vector Parameters, where there is ' 'one set of PVPs for each CRSD signal vector') # type: int Channels = SerializableListDescriptor( 'Channels', ChannelSizeType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Parameters that define the Channel signal array and PVP array size ' 'and location.') # type: List[ChannelSizeType] SupportArrays = SerializableListDescriptor( 'SupportArrays', SupportArraySizeType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Support Array size parameters. Branch repeated for each binary support array. ' 'Support Array referenced by its unique Support Array ' 'identifier.') # type: List[SupportArraySizeType] def __init__(self, SignalArrayFormat=None, NumBytesPVP=None, Channels=None, SupportArrays=None, **kwargs): """ Parameters ---------- SignalArrayFormat : str NumBytesPVP : int Channels : List[ChannelSizeType] SupportArrays : None|List[SupportArraySizeType] kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.SignalArrayFormat = SignalArrayFormat self.NumBytesPVP = NumBytesPVP self.Channels = Channels self.SupportArrays = SupportArrays super(DataType, self).__init__(**kwargs) @property def NumSupportArrays(self): """ int: The number of support arrays. """ if self.SupportArrays is None: return 0 else: return len(self.SupportArrays) @property def NumCRSDChannels(self): """ int: The number of CRSD channels. """ if self.Channels is None: return 0 else: return len(self.Channels) def calculate_support_block_size(self): """ Calculates the size of the support block in bytes as described by the SupportArray fields. """ return sum([s.calculate_size() for s in self.SupportArrays]) def calculate_pvp_block_size(self): """ Calculates the size of the PVP block in bytes as described by the Data fields. """ return self.NumBytesPVP * sum([c.NumVectors for c in self.Channels]) def calculate_signal_block_size(self): """ Calculates the size of the signal block in bytes as described by the Data fields. """ num_bytes_per_sample = binary_format_string_to_dtype(self.SignalArrayFormat).itemsize return num_bytes_per_sample * sum([c.NumVectors * c.NumSamples for c in self.Channels])
class MatchInfoType(Serializable): """ The match information container. This contains data for multiple collection taskings. """ _fields = ('NumMatchTypes', 'MatchTypes') _required = ('MatchTypes', ) _collections_tags = { 'MatchTypes': { 'array': False, 'child_tag': 'MatchType' } } # descriptors MatchTypes = SerializableListDescriptor( 'MatchTypes', MatchType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='The match types list.') # type: List[MatchType] def __init__(self, MatchTypes=None, **kwargs): """ Parameters ---------- MatchTypes : List[MatchType] kwargs : dict """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.MatchTypes = MatchTypes super(MatchInfoType, self).__init__(**kwargs) @property def NumMatchTypes(self): """int: The number of types of matched collections.""" if self.MatchTypes is None: return 0 else: return len(self.MatchTypes) @classmethod def _from_node_0_5(cls, node, xml_ns, ns_key): """ Helper method, not really for public usage. For XML deserialization from SICD version prior to 1.0. Parameters ---------- node : ElementTree.Element dom element for serialized class instance xml_ns : dict The xml namespace dictionary ns_key : str The namespace key in the dictionary Returns ------- Serializable corresponding class instance """ def get_element(tid, cid, cname, params): return { 'TypeID': tid, 'CurrentIndex': cid, 'MatchCollections': [ { 'CoreName': cname, 'Parameters': params }, ] } # Note that this is NOT converting the MatchType.MatchCollection in spirit. # There isn't enough structure to guarantee that you actually can. This will # always yield MatchType.MatchCollection length 1, because the collection details are stuffed # into the parameters free form, while CurrentIndex is extracted and actually yields the # collection index number (likely larger than 1). This is at least confusing, but more likely # completely misleading. match_types = [] coll_key = cls._child_xml_ns_key.get('Collect', ns_key) cnodes = find_children(node, 'Collect', xml_ns, coll_key) for cnode in cnodes: # assumed non-empty # this describes one series of collects, possibly with more than one MatchType = TypeID # It is not clear how it would be possible to deconflict a repeat of MatchType between # Collect tags, so I will not. core_key = cls._child_xml_ns_key.get('CoreName', ns_key) core_name = get_node_value( find_first_child(cnode, 'CoreName', xml_ns, core_key)) current_index = None parameters = [] pkey = cls._child_xml_ns_key.get('Parameters', ns_key) pnodes = find_children(cnode, 'Parameter', xml_ns, pkey) for pnode in pnodes: name = pnode.attrib['name'] value = get_node_value(pnode) if name == 'CURRENT_INSTANCE': current_index = int( value) # extract the current index (and exclude) else: parameters.append({ 'name': name, 'value': value }) # copy the parameter if current_index is None: continue # I don't know what we would do? mt_key = cls._child_xml_ns_key.get('MatchType', ns_key) mtypes = find_children(cnode, 'MatchType', xml_ns, mt_key) for tnode in mtypes: type_id = get_node_value(tnode) match_types.append( get_element(type_id, current_index, core_name, parameters)) if len(match_types) > 0: # noinspection PyTypeChecker return cls(MatchTypes=match_types) else: return None @classmethod def from_node(cls, node, xml_ns, ns_key=None, kwargs=None): coll_key = cls._child_xml_ns_key.get('Collect', ns_key) coll = find_first_child(node, 'Collect', xml_ns, coll_key) if coll is not None: # This is from SICD version prior to 1.0, so handle manually. return cls._from_node_0_5(node, xml_ns, ns_key) else: return super(MatchInfoType, cls).from_node(node, xml_ns, ns_key=ns_key, kwargs=kwargs)
class ProductDisplayType(Serializable): """ """ _fields = ('PixelType', 'NumBands', 'DefaultBandDisplay', 'NonInteractiveProcessing', 'InteractiveProcessing', 'DisplayExtensions') _required = ('PixelType', 'NumBands', 'NonInteractiveProcessing', 'InteractiveProcessing') _collections_tags = { 'NonInteractiveProcessing': { 'array': False, 'child_tag': 'NonInteractiveProcessing' }, 'InteractiveProcessing': { 'array': False, 'child_tag': 'InteractiveProcessing' }, 'DisplayExtensions': { 'array': False, 'child_tag': 'DisplayExtension' } } # Descriptors PixelType = StringEnumDescriptor( 'PixelType', ('MONO8I', 'MONO8LU', 'MONO16I', 'RGB8LU', 'RGB24I'), _required, strict=DEFAULT_STRICT, docstring='Enumeration of the pixel type. Definition in ' 'Design and Exploitation document.') # type: str NumBands = IntegerDescriptor( 'NumBands', _required, strict=DEFAULT_STRICT, docstring= 'Number of bands contained in the image. Populate with the number of bands ' 'present after remapping. For example an 8-bit RGB image (RGBLU), this will ' 'be 3.') # type: int DefaultBandDisplay = IntegerDescriptor( 'DefaultBandDisplay', _required, strict=DEFAULT_STRICT, docstring='Indicates which band to display by default. ' 'Valid range = 1 to NumBands.') # type: int NonInteractiveProcessing = SerializableListDescriptor( 'NonInteractiveProcessing', NonInteractiveProcessingType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Non-interactive processing details.' ) # type: List[NonInteractiveProcessingType] InteractiveProcessing = SerializableListDescriptor( 'InteractiveProcessing', InteractiveProcessingType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Interactive processing details.' ) # type: List[InteractiveProcessingType] DisplayExtensions = ParametersDescriptor( 'DisplayExtensions', _collections_tags, _required, strict=DEFAULT_STRICT, docstring= 'Optional extensible parameters used to support profile-specific needs related to ' 'product display. Predefined filter types.' ) # type: ParametersCollection def __init__(self, PixelType=None, NumBands=1, DefaultBandDisplay=None, NonInteractiveProcessing=None, InteractiveProcessing=None, DisplayExtensions=None, **kwargs): """ Parameters ---------- PixelType : PixelTypeType NumBands : int DefaultBandDisplay : int|None NonInteractiveProcessing : List[NonInteractiveProcessingType] InteractiveProcessing : List[InteractiveProcessingType] DisplayExtensions : ParametersCollection|dict kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.PixelType = PixelType self.NumBands = NumBands self.DefaultBandDisplay = DefaultBandDisplay self.NonInteractiveProcessing = NonInteractiveProcessing self.InteractiveProcessing = InteractiveProcessing self.DisplayExtensions = DisplayExtensions super(ProductDisplayType, self).__init__(**kwargs) def get_pixel_size(self) -> int: """ Gets the raw size per pixel, in bytes. Returns ------- int """ if self.PixelType == 'MONO8I': return 1 elif self.PixelType == 'MONO8LU': return 1 elif self.PixelType == 'MONO16I': return 2 elif self.PixelType == 'RGB8LU': return 1 elif self.PixelType == 'RGB24I': return 3 else: raise ValueError('Got unhandled pixel type `{}`'.format( self.PixelType))
class MatchType(Serializable): """The is an array element for match information.""" _fields = ('TypeID', 'CurrentIndex', 'NumMatchCollections', 'MatchCollections') _required = ('TypeID', ) _collections_tags = { 'MatchCollections': { 'array': False, 'child_tag': 'MatchCollection' } } # descriptors TypeID = StringDescriptor( 'TypeID', _required, strict=DEFAULT_STRICT, docstring= 'The match type identifier. *Examples - "MULTI-IMAGE", "COHERENT" or "STEREO"*' ) # type: str CurrentIndex = IntegerDescriptor( 'CurrentIndex', _required, strict=DEFAULT_STRICT, docstring= 'Collection sequence index for the current collection. That is, which collection in the ' 'collection series (defined in MatchCollections) is this collection? ' '(1-based enumeration).') # type: int MatchCollections = SerializableListDescriptor( 'MatchCollections', MatchCollectionType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='The match collections.') # type: List[MatchCollectionType] def __init__(self, TypeID=None, CurrentIndex=None, MatchCollections=None, **kwargs): """ Parameters ---------- TypeID : str CurrentIndex : int MatchCollections : List[MatchCollectionType] kwargs : dict """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.TypeID = TypeID self.CurrentIndex = CurrentIndex self.MatchCollections = MatchCollections super(MatchType, self).__init__(**kwargs) @property def NumMatchCollections(self): """int: The number of match collections for this match type.""" if self.MatchCollections is None: return 0 else: return len(self.MatchCollections)
class FiducialInfoType(Serializable): _fields = ('NumberOfFiducialsInImage', 'NumberOfFiducialsInScene', 'LabelSource', 'Fiducials') _required = ('NumberOfFiducialsInImage', 'NumberOfFiducialsInScene', 'LabelSource', 'Fiducials') _collections_tags = { 'Fiducials': { 'array': False, 'child_tag': 'Fiducial' } } # descriptors NumberOfFiducialsInImage = IntegerDescriptor( 'NumberOfFiducialsInImage', _required, strict=DEFAULT_STRICT, docstring='Number of ground truthed objects in the image.' ) # type: int NumberOfFiducialsInScene = IntegerDescriptor( 'NumberOfFiducialsInScene', _required, strict=DEFAULT_STRICT, docstring='Number of ground truthed objects in the scene.' ) # type: int LabelSource = SerializableDescriptor( 'LabelSource', LabelSourceType, _required, strict=DEFAULT_STRICT, docstring='The source of the labels') # type: LabelSourceType Fiducials = SerializableListDescriptor( 'Fiducials', TheFiducialType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='The object collection') # type: List[TheFiducialType] def __init__(self, NumberOfFiducialsInImage=None, NumberOfFiducialsInScene=None, LabelSource=None, Fiducials=None, **kwargs): """ Parameters ---------- NumberOfFiducialsInImage : int NumberOfFiducialsInScene : int LabelSource : LabelSourceType Fiducials : None|List[TheFiducialType] kwargs Other keyword arguments """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.NumberOfFiducialsInImage = NumberOfFiducialsInImage self.NumberOfFiducialsInScene = NumberOfFiducialsInScene self.LabelSource = LabelSource self.Fiducials = Fiducials super(FiducialInfoType, self).__init__(**kwargs) def set_image_location_from_sicd(self, sicd, populate_in_periphery=False, include_out_of_range=False): """ Set the image location information with respect to the given SICD, assuming that the physical coordinates are populated. The `NumberOfFiducialsInImage` will be set, and `NumberOfFiducialsInScene` will be left unchanged. Parameters ---------- sicd : SICDType populate_in_periphery : bool Populate image information for objects on the periphery? include_out_of_range : bool Include the objects which are out of range (with no image location information)? """ def update_fiducial(temp_fid, in_image_count): status = temp_fid.set_image_location_from_sicd( sicd, populate_in_periphery=populate_in_periphery) use_fid = False if status == 0: raise ValueError('Fiducial already has image details set') if status == 1 or (status == 2 and populate_in_periphery): use_fid = True in_image_count += 1 return use_fid, in_image_count fid_in_image = 0 if include_out_of_range: # the fiducials list is just modified in place for the_fid in self.Fiducials: _, fid_in_image = update_fiducial(the_fid, fid_in_image) else: # the fiducials list is just modified in place fiducials = [] for the_fid in self.Fiducials: use_this_fid, fid_in_image = update_fiducial( the_fid, fid_in_image) if use_this_fid: fiducials.append(the_fid) self.Fiducials = fiducials self.NumberOfFiducialsInImage = fid_in_image
class PVPType(Serializable): _fields = ('RcvTime', 'RcvPos', 'RcvVel', 'RefPhi0', 'RefFreq', 'DFIC0', 'FICRate', 'FRCV1', 'FRCV2', 'DGRGC', 'SIGNAL', 'AmpSF', 'RcvAntenna', 'TxPulse', 'AddedPVP') _required = ('RcvTime', 'RcvPos', 'RcvVel', 'RefPhi0', 'RefFreq', 'DFIC0', 'FICRate', 'FRCV1', 'FRCV2') _collections_tags = {'AddedPVP': {'array': False, 'child_tag': 'AddedPVP'}} # descriptors RcvTime = SerializableDescriptor( 'RcvTime', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 RcvPos = SerializableDescriptor( 'RcvPos', PerVectorParameterXYZ, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterXYZ RcvVel = SerializableDescriptor( 'RcvVel', PerVectorParameterXYZ, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterXYZ RefPhi0 = SerializableDescriptor( 'RefPhi0', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 RefFreq = SerializableDescriptor( 'RefFreq', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 DFIC0 = SerializableDescriptor('DFIC0', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 FICRate = SerializableDescriptor( 'FICRate', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 FRCV1 = SerializableDescriptor('FRCV1', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 FRCV2 = SerializableDescriptor('FRCV2', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: PerVectorParameterF8 DGRGC = SerializableDescriptor( 'DGRGC', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, PerVectorParameterF8] SIGNAL = SerializableDescriptor( 'SIGNAL', PerVectorParameterI8, _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, PerVectorParameterI8] AmpSF = SerializableDescriptor( 'AmpSF', PerVectorParameterF8, _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, PerVectorParameterF8] RcvAntenna = SerializableDescriptor( 'RcvAntenna', RcvAntennaType, _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, RcvAntennaType] TxPulse = SerializableDescriptor( 'TxPulse', TxPulseType, _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, TxPulseType] AddedPVP = SerializableListDescriptor( 'AddedPVP', UserDefinedPVPType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, List[UserDefinedPVPType]] def __init__(self, RcvTime=None, RcvPos=None, RcvVel=None, RefPhi0=None, RefFreq=None, DFIC0=None, FICRate=None, FRCV1=None, FRCV2=None, DGRGC=None, SIGNAL=None, AmpSF=None, RcvAntenna=None, TxPulse=None, AddedPVP=None, **kwargs): """ Parameters ---------- RcvTime : PerVectorParameterF8 RcvPos : PerVectorParameterXYZ RcvVel : PerVectorParameterXYZ RefPhi0 : PerVectorParameterF8 RefFreq : PerVectorParameterF8 DFIC0 : PerVectorParameterF8 FICRate : PerVectorParameterF8 FRCV1 : PerVectorParameterF8 FRCV2 : PerVectorParameterF8 DGRGC : None|PerVectorParameterF8 SIGNAL : None|PerVectorParameterI8 AmpSF : None|PerVectorParameterF8 RcvAntenna : None|RcvAntennaType TxPulse : None|TxPulseType AddedPVP : None|List[UserDefinedPVPType] kwargs """ if '_xml_ns' in kwargs: self._xml_ns = kwargs['_xml_ns'] if '_xml_ns_key' in kwargs: self._xml_ns_key = kwargs['_xml_ns_key'] self.RcvTime = RcvTime self.RcvPos = RcvPos self.RcvVel = RcvVel self.RefPhi0 = RefPhi0 self.RefFreq = RefFreq self.DFIC0 = DFIC0 self.FICRate = FICRate self.FRCV1 = FRCV1 self.FRCV2 = FRCV2 self.DGRGC = DGRGC self.SIGNAL = SIGNAL self.AmpSF = AmpSF self.RcvAntenna = RcvAntenna self.TxPulse = TxPulse self.AddedPVP = AddedPVP super(PVPType, self).__init__(**kwargs) def get_size(self): """ Gets the size in bytes of each vector. Returns ------- int """ def get_num_words(obj): sz = getattr(obj, 'Size') if sz is not None: return sz sz = 0 # noinspection PyProtectedMember for fld in obj._fields: fld_val = getattr(obj, fld) if fld_val is not None: if fld_val.array: for arr_val in fld_val: sz += get_num_words(arr_val) else: sz += get_num_words(fld_val) return sz return get_num_words(self) * BYTES_PER_WORD def get_offset_size_format(self, field): """ Get the Offset (in bytes), Size (in bytes) for the given field, as well as the corresponding struct format string. Parameters ---------- field : str The desired field name. Returns ------- None|(int, int, str) """ def osf_tuple(val_in): return val_in.Offset * BYTES_PER_WORD, val_in.Size * BYTES_PER_WORD, homogeneous_dtype( val_in.Format).char # noinspection PyProtectedMember if field in self._fields[:-1]: val = getattr(self, field) if val is None: return None return osf_tuple(val) elif self.RcvAntenna and field in self.RcvAntenna._fields: val = getattr(self.RcvAntenna, field) if val is None: return None return osf_tuple(val) elif self.TxPulse and field in self.TxPulse._fields: val = getattr(self.TxPulse, field) if val is None: return None return osf_tuple(val) elif self.TxPulse and self.TxPulse.TxAntenna and field in self.TxPulse.TxAntenna._fields: val = getattr(self.TxPulse.TxAntenna, field) if val is None: return None return osf_tuple(val) else: if self.AddedPVP is None: return None for val in self.AddedPVP: if field == val.Name: return osf_tuple(val) return None def get_vector_dtype(self): """ Gets the dtype for the corresponding structured array for the full PVP set. Returns ------- numpy.dtype This will be a compound dtype for a structured array. """ names = [] formats = [] offsets = [] for field in self._fields: val = getattr(self, field) if val is None: continue elif field == "AddedPVP": for entry in val: names.append(entry.Name) formats.append(binary_format_string_to_dtype(entry.Format)) offsets.append(entry.Offset * BYTES_PER_WORD) elif field == 'RcvAntenna' or field == 'TxPulse': continue else: names.append(field) formats.append(binary_format_string_to_dtype(val.Format)) offsets.append(val.Offset * BYTES_PER_WORD) if self.RcvAntenna is not None: # noinspection PyProtectedMember for field in self.RcvAntenna._fields: val = getattr(self.RcvAntenna, field) if val is None: continue else: names.append(field) formats.append(binary_format_string_to_dtype(val.Format)) offsets.append(val.Offset * BYTES_PER_WORD) if self.TxPulse is not None: # noinspection PyProtectedMember for field in self.TxPulse._fields: val = getattr(self.TxPulse, field) if val is None: continue elif field == 'TxAntenna': continue else: names.append(field) formats.append(binary_format_string_to_dtype(val.Format)) offsets.append(val.Offset * BYTES_PER_WORD) if self.TxPulse.TxAntenna is not None: # noinspection PyProtectedMember for field in self.TxPulse.TxAntenna._fields: val = getattr(self.TxPulse.TxAntenna, field) if val is None: continue else: names.append(field) formats.append( binary_format_string_to_dtype(val.Format)) offsets.append(val.Offset * BYTES_PER_WORD) return numpy.dtype({ 'names': names, 'formats': formats, 'offsets': offsets })