class ProcessingType(Serializable): """The transmit frequency range""" _fields = ('Type', 'Applied', 'Parameters') _required = ('Type', 'Applied') _collections_tags = {'Parameters': {'array': False, 'child_tag': 'Parameter'}} # descriptors Type = StringDescriptor( 'Type', _required, strict=DEFAULT_STRICT, docstring='The processing type identifier.') # type: str Applied = BooleanDescriptor( 'Applied', _required, strict=DEFAULT_STRICT, docstring='Indicates whether the given processing type has been applied.') # type: bool Parameters = ParametersDescriptor( 'Parameters', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='The parameters collection.') # type: ParametersCollection def __init__(self, Type=None, Applied=None, Parameters=None, **kwargs): """ Parameters ---------- Type : str Applied : bool Parameters : 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.Type = Type self.Applied = Applied self.Parameters = Parameters super(ProcessingType, self).__init__(**kwargs)
class AddedSupportArrayType(SupportArrayCore): """ Additional arrays (two-dimensional), where the content and format and units of each element are user defined. """ _fields = ( 'Identifier', 'ElementFormat', 'X0', 'Y0', 'XSS', 'YSS', 'NODATA', 'XUnits', 'YUnits', 'ZUnits', 'Parameters') _required = ( 'Identifier', 'ElementFormat', 'X0', 'Y0', 'XSS', 'YSS', 'XUnits', 'YUnits', 'ZUnits') _collections_tags = { 'Parameters': {'array': False, 'child_tag': 'Parameter'}} # descriptors XUnits = StringDescriptor( 'XUnits', _required, strict=DEFAULT_STRICT, docstring='The X units.') # type: str YUnits = StringDescriptor( 'YUnits', _required, strict=DEFAULT_STRICT, docstring='The Y units.') # type: str ZUnits = StringDescriptor( 'ZUnits', _required, strict=DEFAULT_STRICT, docstring='The Z units.') # type: str Parameters = ParametersDescriptor( 'Parameters', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Other necessary free-form parameters.') # type: Union[None, ParametersCollection] def __init__(self, Identifier=None, ElementFormat=None, X0=None, Y0=None, XSS=None, YSS=None, NODATA=None, XUnits=None, YUnits=None, ZUnits=None, Parameters=None, **kwargs): """ Parameters ---------- Identifier : str ElementFormat : str X0 : float Y0 : float XSS : float YSS : float NODATA : str XUnits : str YUnits : str ZUnits : str Parameters : 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.XUnits = XUnits self.YUnits = YUnits self.ZUnits = ZUnits self.Parameters = Parameters super(AddedSupportArrayType, self).__init__( Identifier=Identifier, ElementFormat=ElementFormat, X0=X0, Y0=Y0, XSS=XSS, YSS=YSS, NODATA=NODATA, **kwargs)
class BistaticType(Serializable): """ Error parameters for bistatic parameters. """ _fields = ('TxPlatform', 'RcvPlatform', 'AddedParameters') _required = ('TxPlatform', 'RcvPlatform') _collections_tags = { 'AddedParameters': { 'array': False, 'child_tag': 'Parameter' } } # descriptors TxPlatform = SerializableDescriptor( 'TxPlatform', PlatformType, _required, strict=DEFAULT_STRICT, docstring='Error statistics for the transmit platform.' ) # type: PlatformType RcvPlatform = SerializableDescriptor( 'RcvPlatform', PlatformType, _required, strict=DEFAULT_STRICT, docstring='Error statistics for the receive platform.' ) # type: PlatformType AddedParameters = ParametersDescriptor( 'AddedParameters', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Additional error parameters.') # type: ParametersCollection def __init__(self, TxPlatform=None, RcvPlatform=None, AddedParameters=None, **kwargs): """ Parameters ---------- TxPlatform : PlatformType RcvPlatform : PlatformType AddedParameters : 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.TxPlatform = TxPlatform self.RcvPlatform = RcvPlatform self.AddedParameters = AddedParameters super(BistaticType, self).__init__(**kwargs)
class ReceiveOnlyType(Serializable): """ Parameters for receive only collect type """ _fields = ('PosVelErr', 'ReceiveSensorType', 'AddedParameters') _required = ('PosVelErr', 'ReceiveSensorType') _collections_tags = { 'AddedParameters': { 'array': False, 'child_tag': 'Parameter' } } # descriptors PosVelErr = SerializableDescriptor( 'PosVelErr', PosVelErrType, _required, strict=DEFAULT_STRICT, docstring='Position and velocity error statistics for the sensor ' 'platform.') # type: PosVelErrType ReceiveSensor = SerializableDescriptor( 'ReceiveSensor', RadarSensorType, _required, strict=DEFAULT_STRICT, docstring='Receive sensor error statistics.') # type: RadarSensorType AddedParameters = ParametersDescriptor( 'AddedParameters', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Additional error parameters.') # type: ParametersCollection def __init__(self, PosVelErr=None, ReceiveSensor=None, AddedParameters=None, **kwargs): """ Parameters ---------- PosVelErr : PosVelErrType ReceiveSensor : RadarSensorType AddedParameters : 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.PosVelErr = PosVelErr self.ReceiveSensor = ReceiveSensor self.AddedParameters = AddedParameters super(ReceiveOnlyType, self).__init__(**kwargs)
class TargetInformationType(Serializable): """ Information about the target. """ _fields = ('Identifiers', 'Footprint', 'TargetInformationExtensions') _required = () _collections_tags = { 'Identifiers': {'array': False, 'child_tag': 'Identifier'}, 'Footprint': {'array': True, 'child_tag': 'Vertex'}, 'TargetInformationExtensions': {'array': False, 'child_tag': 'TargetInformationExtension'}} # Descriptors Identifiers = ParametersDescriptor( 'Identifiers', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Target may have one or more identifiers. Examples: names, BE numbers, etc. Use ' 'the "name" attribute to describe what this is.') # type: ParametersCollection Footprint = SerializableArrayDescriptor( 'Footprint', LatLonArrayElementType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Target footprint as defined by polygonal ' 'shape.') # type: Union[SerializableArray, List[LatLonArrayElementType]] TargetInformationExtensions = ParametersDescriptor( 'TargetInformationExtensions', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Generic extension. Could be used to indicate type of target, ' 'terrain, etc.') # type: ParametersCollection def __init__(self, Identifiers=None, Footprint=None, TargetInformationExtensions=None, **kwargs): """ Parameters ---------- Identifiers : None|ParametersCollection|dict Footprint : None|List[LatLonArrayElementType]|numpy.ndarray|list|tuple TargetInformationExtensions : 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.Identifiers = Identifiers self.Footprint = Footprint self.TargetInformationExtensions = TargetInformationExtensions super(TargetInformationType, self).__init__(**kwargs)
class MatchCollectionType(Serializable): """The match collection type.""" _fields = ('CoreName', 'MatchIndex', 'Parameters') _required = ('CoreName', ) _collections_tags = { 'Parameters': { 'array': False, 'child_tag': 'Parameter' } } # descriptors CoreName = StringDescriptor( 'CoreName', _required, strict=DEFAULT_STRICT, docstring='Unique identifier for the match type.') # type: str MatchIndex = IntegerDescriptor( 'MatchIndex', _required, strict=DEFAULT_STRICT, docstring='Collection sequence index for the match collection, assuming ' 'that this makes sense.') # type: int Parameters = ParametersDescriptor( 'Parameters', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='The match parameters.') # type: ParametersCollection def __init__(self, CoreName=None, MatchIndex=None, Parameters=None, **kwargs): """ Parameters ---------- CoreName : str MatchIndex : int Parameters : ParametersCollection|dict 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.CoreName = CoreName self.MatchIndex = MatchIndex self.Parameters = Parameters super(MatchCollectionType, self).__init__(**kwargs)
class MonostaticType(Serializable): """ Error parameters for monstatic collection. """ _fields = ('PosVelErr', 'RadarSensor', 'TropoError', 'IonoError', 'AddedParameters') _required = ('PosVelErr', 'RadarSensor') _collections_tags = {'AddedParameters': {'array': False, 'child_tag': 'Parameter'}} # descriptors PosVelErr = SerializableDescriptor( 'PosVelErr', PosVelErrType, _required, strict=DEFAULT_STRICT, docstring='Position and velocity error statistics for the sensor ' 'platform.') # type: PosVelErrType RadarSensor = SerializableDescriptor( 'RadarSensor', RadarSensorType, _required, strict=DEFAULT_STRICT, docstring='Radar sensor error statistics.') # type: RadarSensorType TropoError = SerializableDescriptor( 'TropoError', TropoErrorType, _required, strict=DEFAULT_STRICT, docstring='Troposphere delay error statistics.') # type: TropoErrorType IonoError = SerializableDescriptor( 'IonoError', IonoErrorType, _required, strict=DEFAULT_STRICT, docstring='Ionosphere delay error statistics.') # type: IonoErrorType AddedParameters = ParametersDescriptor( 'AddedParameters', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Additional error parameters.') # type: ParametersCollection def __init__(self, PosVelErr=None, RadarSensor=None, TropoError=None, IonoError=None, AddedParameters=None, **kwargs): """ Parameters ---------- PosVelErr : PosVelErrType RadarSensor : RadarSensorType TropoError : None|TropoErrorType IonoError : None|IonoErrorType AddedParameters : 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.PosVelErr = PosVelErr self.RadarSensor = RadarSensor self.TropoError = TropoError self.IonoError = IonoError self.AddedParameters = AddedParameters super(MonostaticType, self).__init__(PosVelErr=PosVelErr, RadarSensor=RadarSensor, **kwargs)
class GeographicInformationType(Serializable): """ Geographic information. """ _fields = ('CountryCodes', 'SecurityInfo', 'GeographicInfoExtensions') _required = () _collections_tags = { 'CountryCodes': {'array': False, 'child_tag': 'CountryCode'}, 'GeographicInfoExtensions': {'array': False, 'child_tag': 'GeographicInfoExtension'}} # descriptors CountryCodes = StringListDescriptor( 'CountryCodes', _required, strict=DEFAULT_STRICT, docstring="List of country codes for region covered by the image.") # type: List[str] SecurityInfo = StringDescriptor( 'SecurityInfo', _required, strict=DEFAULT_STRICT, docstring='Specifies classification level or special handling designators ' 'for this geographic region.') # type: Union[None, str] GeographicInfoExtensions = ParametersDescriptor( 'GeographicInfoExtensions', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Implementation specific geographic information.') # type: ParametersCollection def __init__(self, CountryCodes=None, SecurityInfo=None, GeographicInfoExtensions=None, **kwargs): """ Parameters ---------- CountryCodes : None|List[str] SecurityInfo : None|str GeographicInfoExtensions : None|ParametersCollection|dict 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.CountryCodes = CountryCodes self.SecurityInfo = SecurityInfo self.GeographicInfoExtensions = GeographicInfoExtensions super(GeographicInformationType, self).__init__(**kwargs)
class ErrorStatisticsType(Serializable): """Parameters used to compute error statistics within the SICD sensor model.""" _fields = ('CompositeSCP', 'Components', 'AdditionalParms') _required = () _collections_tags = {'AdditionalParms': {'array': False, 'child_tag': 'Parameter'}} # descriptors CompositeSCP = SerializableDescriptor( 'CompositeSCP', CompositeSCPErrorType, _required, strict=DEFAULT_STRICT, docstring='Composite error statistics for the scene center point. *Slant plane range (Rg)* and *azimuth (Az)* ' 'error statistics. Slant plane defined at *Scene Center Point, Center of Azimuth (SCP COA)*.' ) # type: CompositeSCPErrorType Components = SerializableDescriptor( 'Components', ErrorComponentsType, _required, strict=DEFAULT_STRICT, docstring='Error statistics by components.') # type: ErrorComponentsType AdditionalParms = ParametersDescriptor( 'AdditionalParms', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Any additional parameters.') # type: ParametersCollection def __init__(self, CompositeSCP=None, Components=None, AdditionalParms=None, **kwargs): """ Parameters ---------- CompositeSCP : CompositeSCPErrorType Components : ErrorComponentsType AdditionalParms : ParametersCollection|dict 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.CompositeSCP = CompositeSCP self.Components = Components self.AdditionalParms = AdditionalParms super(ErrorStatisticsType, self).__init__(**kwargs)
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 RadarCollectionType(Serializable): """The Radar Collection Type""" _fields = ( 'TxFrequency', 'RefFreqIndex', 'Waveform', 'TxPolarization', 'TxSequence', 'RcvChannels', 'Area', 'Parameters') _required = ('TxFrequency', 'TxPolarization', 'RcvChannels') _collections_tags = { 'Waveform': {'array': True, 'child_tag': 'WFParameters'}, 'TxSequence': {'array': True, 'child_tag': 'TxStep'}, 'RcvChannels': {'array': True, 'child_tag': 'ChanParameters'}, 'Parameters': {'array': False, 'child_tag': 'Parameter'}} # descriptors TxFrequency = SerializableDescriptor( 'TxFrequency', TxFrequencyType, _required, strict=DEFAULT_STRICT, docstring='The transmit frequency range.') # type: TxFrequencyType RefFreqIndex = IntegerDescriptor( 'RefFreqIndex', _required, strict=DEFAULT_STRICT, docstring='The reference frequency index, if applicable. If present and non-zero, ' 'all (most) RF frequency values are expressed as offsets from a reference ' 'frequency.') # type: int Waveform = SerializableArrayDescriptor( 'Waveform', WaveformParametersType, _collections_tags, _required, strict=DEFAULT_STRICT, minimum_length=1, docstring='Transmit and receive demodulation waveform parameters.' ) # type: Union[SerializableArray, List[WaveformParametersType]] TxPolarization = StringEnumDescriptor( 'TxPolarization', POLARIZATION1_VALUES, _required, strict=DEFAULT_STRICT, docstring='The transmit polarization.') # type: str TxSequence = SerializableArrayDescriptor( 'TxSequence', TxStepType, _collections_tags, _required, strict=DEFAULT_STRICT, minimum_length=1, docstring='The transmit sequence parameters array. If present, indicates the transmit signal steps through ' 'a repeating sequence of waveforms and/or polarizations. ' 'One step per Inter-Pulse Period.') # type: Union[SerializableArray, List[TxStepType]] RcvChannels = SerializableArrayDescriptor( 'RcvChannels', ChanParametersType, _collections_tags, _required, strict=DEFAULT_STRICT, minimum_length=1, docstring='Receive data channel parameters.') # type: Union[SerializableArray, List[ChanParametersType]] Area = SerializableDescriptor( 'Area', AreaType, _required, strict=DEFAULT_STRICT, docstring='The imaged area covered by the collection.') # type: AreaType Parameters = ParametersDescriptor( 'Parameters', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='A parameters collections.') # type: ParametersCollection def __init__(self, TxFrequency=None, RefFreqIndex=None, Waveform=None, TxPolarization=None, TxSequence=None, RcvChannels=None, Area=None, Parameters=None, **kwargs): """ Parameters ---------- TxFrequency : TxFrequencyType|numpy.ndarray|list|tuple RefFreqIndex : int Waveform : SerializableArray|List[WaveformParametersType] TxPolarization : str TxSequence : SerializableArray|List[TxStepType] RcvChannels : SerializableArray|List[ChanParametersType] Area : AreaType Parameters : ParametersCollection|dict 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.TxFrequency = TxFrequency self.RefFreqIndex = RefFreqIndex self.Waveform = Waveform self.TxPolarization = TxPolarization self.TxSequence = TxSequence self.RcvChannels = RcvChannels self.Area = Area self.Parameters = Parameters super(RadarCollectionType, self).__init__(**kwargs) def derive(self): """ Populates derived data in RadarCollection. Expected to be called by `SICD` parent. Returns ------- None """ self._derive_tx_polarization() if self.Area is not None: self.Area.derive() if self.Waveform is not None: for entry in self.Waveform: entry.derive() self._derive_tx_frequency() # call after waveform entry derive call self._derive_wf_params() def _derive_tx_polarization(self): def check_sequence(): unique_entries = set(entry.TxPolarization for entry in self.TxSequence) if len(unique_entries) == 1: self.TxPolarization = self.TxSequence[0].TxPolarization else: self.TxPolarization = 'SEQUENCE' # TxPolarization was optional prior to SICD 1.0. It may need to be derived. if self.TxSequence is not None: check_sequence() return if self.TxPolarization is not None: return # nothing to be done if self.RcvChannels is None: return # nothing to derive from if len(self.RcvChannels) > 1: # TxSequence may need to be derived from RCvChannels, for SICD before 1.0 or poorly formed if self.TxSequence is not None or self.RcvChannels is None or len(self.RcvChannels) < 2: return tx_pols = list(chan_param.get_transmit_polarization() for chan_param in self.RcvChannels) if len(tx_pols) > 1: self.TxSequence = [TxStepType(index=i+1, TxPolarization=tx_pol) for i, tx_pol in enumerate(tx_pols)] check_sequence() else: self.TxPolarization = tx_pols[0] else: self.TxPolarization = self.RcvChannels[0].get_transmit_polarization() def _derive_tx_frequency(self): if self.Waveform is None or self.Waveform.size == 0: return # nothing to be done if not(self.TxFrequency is None or self.TxFrequency.Min is None or self.TxFrequency.Max is None): return # no need to do anything if self.TxFrequency is None: self.TxFrequency = TxFrequencyType() if self.TxFrequency.Min is None: self.TxFrequency.Min = min( entry.TxFreqStart for entry in self.Waveform if entry.TxFreqStart is not None) if self.TxFrequency.Max is None: self.TxFrequency.Max = max( (entry.TxFreqStart + entry.TxRFBandwidth) for entry in self.Waveform if entry.TxFreqStart is not None and entry.TxRFBandwidth is not None) def _derive_wf_params(self): if self.TxFrequency is None or self.TxFrequency.Min is None or self.TxFrequency.Max is None: return # nothing that we can do if self.Waveform is None or self.Waveform.size != 1: return # nothing to be done entry = self.Waveform[0] # only true for single waveform definition if entry.TxFreqStart is None: entry.TxFreqStart = self.TxFrequency.Min if entry.TxRFBandwidth is None: entry.TxRFBandwidth = self.TxFrequency.Max - self.TxFrequency.Min 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.TxFrequency is not None: # noinspection PyProtectedMember self.TxFrequency._apply_reference_frequency(reference_frequency) if self.Waveform is not None: for entry in self.Waveform: # noinspection PyProtectedMember entry._apply_reference_frequency(reference_frequency) self.RefFreqIndex = 0 def get_polarization_abbreviation(self): """ Gets the polarization collection abbreviation for the suggested name. Returns ------- str """ if self.RcvChannels is None: pol_count = 0 else: pol_count = len(self.RcvChannels) if pol_count == 1: return 'S' elif pol_count == 2: return 'D' elif pol_count == 3: return 'T' elif pol_count > 3: return 'Q' else: return 'U' def _check_frequency(self): # type: () -> bool if self.RefFreqIndex is not None: return True if self.TxFrequency is not None and self.TxFrequency.Min is not None \ and self.TxFrequency.Min <= 0: self.log_validity_error( 'TxFrequency.Min is negative, but RefFreqIndex is not populated.') return False return True def _check_tx_sequence(self): # type: () -> bool cond = True if self.TxPolarization == 'SEQUENCE' and self.TxSequence is None: self.log_validity_error( 'TxPolarization is populated as "SEQUENCE", but TxSequence is not populated.') cond = False if self.TxSequence is not None: if self.TxPolarization != 'SEQUENCE': self.log_validity_error( 'TxSequence is populated, but TxPolarization is populated as {}'.format(self.TxPolarization)) cond = False tx_pols = list(set([entry.TxPolarization for entry in self.TxSequence])) if len(tx_pols) == 1: self.log_validity_error( 'TxSequence is populated, but the only unique TxPolarization ' 'among the entries is {}'.format(tx_pols[0])) cond = False return cond def _check_waveform_parameters(self): """ Validate the waveform parameters for consistency. Returns ------- bool """ def validate_entry(index, waveform): # type: (int, WaveformParametersType) -> bool this_cond = True try: if abs(waveform.TxRFBandwidth/(waveform.TxPulseLength*waveform.TxFMRate) - 1) > 1e-3: self.log_validity_error( 'The TxRFBandwidth, TxPulseLength, and TxFMRate parameters of Waveform ' 'entry {} are inconsistent'.format(index+1)) this_cond = False except (AttributeError, ValueError, TypeError): pass if waveform.RcvDemodType == 'CHIRP' and waveform.RcvFMRate != 0: self.log_validity_error( 'RcvDemodType == "CHIRP" and RcvFMRate != 0 in Waveform entry {}'.format(index+1)) this_cond = False if waveform.RcvDemodType == 'STRETCH' and \ waveform.RcvFMRate is not None and waveform.TxFMRate is not None and \ abs(waveform.RcvFMRate/waveform.TxFMRate - 1) > 1e-3: self.log_validity_warning( 'RcvDemodType = "STRETCH", RcvFMRate = {}, and TxFMRate = {} in ' 'Waveform entry {}. The RcvFMRate and TxFMRate should very likely ' 'be the same.'.format(waveform.RcvFMRate, waveform.TxFMRate, index+1)) if self.RefFreqIndex is None: if waveform.TxFreqStart <= 0: self.log_validity_error( 'TxFreqStart is negative in Waveform entry {}, but RefFreqIndex ' 'is not populated.'.format(index+1)) this_cond = False if waveform.RcvFreqStart is not None and waveform.RcvFreqStart <= 0: self.log_validity_error( 'RcvFreqStart is negative in Waveform entry {}, but RefFreqIndex ' 'is not populated.'.format(index + 1)) this_cond = False if waveform.TxPulseLength is not None and waveform.RcvWindowLength is not None and \ waveform.TxPulseLength > waveform.RcvWindowLength: self.log_validity_error( 'TxPulseLength ({}) is longer than RcvWindowLength ({}) in ' 'Waveform entry {}'.format(waveform.TxPulseLength, waveform.RcvWindowLength, index+1)) this_cond = False if waveform.RcvIFBandwidth is not None and waveform.ADCSampleRate is not None and \ waveform.RcvIFBandwidth > waveform.ADCSampleRate: self.log_validity_error( 'RcvIFBandwidth ({}) is longer than ADCSampleRate ({}) in ' 'Waveform entry {}'.format(waveform.RcvIFBandwidth, waveform.ADCSampleRate, index+1)) this_cond = False if waveform.RcvDemodType is not None and waveform.RcvDemodType == 'CHIRP' \ and waveform.TxRFBandwidth is not None and waveform.ADCSampleRate is not None \ and (waveform.TxRFBandwidth > waveform.ADCSampleRate): self.log_validity_error( 'RcvDemodType is "CHIRP" and TxRFBandwidth ({}) is larger than ADCSampleRate ({}) ' 'in Waveform entry {}'.format(waveform.TxRFBandwidth, waveform.ADCSampleRate, index+1)) this_cond = False if waveform.RcvWindowLength is not None and waveform.TxPulseLength is not None and \ waveform.TxFMRate is not None and waveform.RcvFreqStart is not None and \ waveform.TxFreqStart is not None and waveform.TxRFBandwidth is not None: freq_tol = (waveform.RcvWindowLength - waveform.TxPulseLength)*waveform.TxFMRate if waveform.RcvFreqStart >= waveform.TxFreqStart + waveform.TxRFBandwidth + freq_tol: self.log_validity_error( 'RcvFreqStart ({}), TxFreqStart ({}), and TxRfBandwidth ({}) parameters are inconsistent ' 'in Waveform entry {}'.format( waveform.RcvFreqStart, waveform.TxFreqStart, waveform.TxRFBandwidth, index + 1)) this_cond = False if waveform.RcvFreqStart <= waveform.TxFreqStart - freq_tol: self.log_validity_error( 'RcvFreqStart ({}) and TxFreqStart ({}) parameters are inconsistent ' 'in Waveform entry {}'.format(waveform.RcvFreqStart, waveform.TxFreqStart, index + 1)) this_cond = False return this_cond if self.Waveform is None or len(self.Waveform) < 1: return True cond = True # fetch min/max TxFreq observed wf_min_freq = None wf_max_freq = None for entry in self.Waveform: freq_start = entry.TxFreqStart freq_bw = entry.TxRFBandwidth if freq_start is not None: wf_min_freq = freq_start if wf_min_freq is None else \ min(wf_min_freq, freq_start) if entry.TxRFBandwidth is not None: wf_max_freq = freq_start + freq_bw if wf_max_freq is None else \ max(wf_max_freq, freq_start + freq_bw) if wf_min_freq is not None and self.TxFrequency is not None and self.TxFrequency.Min is not None: if abs(self.TxFrequency.Min/wf_min_freq - 1) > 1e-3: self.log_validity_error( 'The stated TxFrequency.Min is {}, but the minimum populated in a ' 'Waveform entry is {}'.format(self.TxFrequency.Min, wf_min_freq)) cond = False if wf_max_freq is not None and self.TxFrequency is not None and self.TxFrequency.Max is not None: if abs(self.TxFrequency.Max/wf_max_freq - 1) > 1e-3: self.log_validity_error( 'The stated TxFrequency.Max is {}, but the maximum populated in a ' 'Waveform entry is {}'.format(self.TxFrequency.Max, wf_max_freq)) cond = False for t_index, t_waveform in enumerate(self.Waveform): cond &= validate_entry(t_index, t_waveform) return cond def _basic_validity_check(self): valid = super(RadarCollectionType, self)._basic_validity_check() valid &= self._check_frequency() valid &= self._check_tx_sequence() valid &= self._check_waveform_parameters() return valid def permits_version_1_1(self): """ Does this value permit storage in SICD version 1.1? Returns ------- bool """ if self.RcvChannels is None: return True cond = True for entry in self.RcvChannels: cond &= entry.permits_version_1_1() return cond
class ExploitationFeaturesCollectionGeometryType(Serializable): """ Key geometry parameters independent of product processing. All values computed at the center time of the full collection. """ _fields = ('Azimuth', 'Slope', 'Squint', 'Graze', 'Tilt', 'DopplerConeAngle', 'Extensions') _required = () _collections_tags = { 'Extensions': { 'array': False, 'child_tag': 'Extension' } } _numeric_format = { 'Azimuth': FLOAT_FORMAT, 'Slope': FLOAT_FORMAT, 'Squint': FLOAT_FORMAT, 'Graze': FLOAT_FORMAT, 'Tilt': FLOAT_FORMAT, 'DopplerConeAngle': FLOAT_FORMAT } # Descriptor Azimuth = FloatDescriptor( 'Azimuth', _required, strict=DEFAULT_STRICT, bounds=(0.0, 360.0), docstring= 'Angle clockwise from north indicating the ETP line of sight vector.' ) # type: float Slope = FloatDescriptor( 'Slope', _required, strict=DEFAULT_STRICT, bounds=(0.0, 90.0), docstring= 'Angle between the ETP at scene center and the range vector perpendicular to ' 'the direction of motion.') # type: float Squint = FloatModularDescriptor( 'Squint', 180.0, _required, strict=DEFAULT_STRICT, docstring= 'Angle from the ground track to platform velocity vector at nadir. ' 'Left-look is positive, right-look is negative.') # type: float Graze = FloatDescriptor( 'Graze', _required, strict=DEFAULT_STRICT, bounds=(0.0, 90.0), docstring='Angle between the ETP and the line of sight vector.' ) # type: float Tilt = FloatModularDescriptor( 'Tilt', 180.0, _required, strict=DEFAULT_STRICT, docstring='Angle between the ETP and the cross range vector. ' 'Also known as the twist angle.') # type: float DopplerConeAngle = FloatDescriptor( 'DopplerConeAngle', _required, strict=DEFAULT_STRICT, bounds=(0.0, 180.0), docstring= 'The angle between the velocity vector and the radar line-of-sight vector. ' 'Also known as the slant plane squint angle.') # 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, Azimuth=None, Slope=None, Squint=None, Graze=None, Tilt=None, DopplerConeAngle=None, Extensions=None, **kwargs): """ Parameters ---------- Azimuth : None|float Slope : None|float Squint : None|float Graze : None|float Tilt : None|float DopplerConeAngle : 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.Azimuth = Azimuth self.Slope = Slope self.Squint = Squint self.Graze = Graze self.Tilt = Tilt self.DopplerConeAngle = DopplerConeAngle self.Extensions = Extensions super(ExploitationFeaturesCollectionGeometryType, self).__init__(**kwargs) @classmethod def from_calculator(cls, calculator): """ Create from an ExploitationCalculator object. Parameters ---------- calculator : ExploitationCalculator Returns ------- ExploitationFeaturesCollectionGeometryType """ if not isinstance(calculator, ExploitationCalculator): raise TypeError(_exp_calc_text.format(type(calculator))) return cls(Azimuth=calculator.AzimuthAngle, Slope=calculator.SlopeAngle, Graze=calculator.SlopeAngle, Tilt=calculator.TiltAngle, DopplerConeAngle=calculator.DopplerConeAngle, Squint=calculator.SquintAngle)
class ExploitationFeaturesCollectionPhenomenologyType(Serializable): """ Phenomenology related to both the geometry and the final product processing. All values computed at the center time of the full collection. """ _fields = ('Shadow', 'Layover', 'MultiPath', 'GroundTrack', 'Extensions') _required = () _collections_tags = { 'Extensions': { 'array': False, 'child_tag': 'Extension' } } _numeric_format = {'MultiPath': FLOAT_FORMAT, 'GroundTrack': FLOAT_FORMAT} # Descriptor Shadow = SerializableDescriptor( 'Shadow', AngleMagnitudeType, _required, strict=DEFAULT_STRICT, docstring='The phenomenon where vertical objects occlude radar ' 'energy.') # type: Union[None, AngleMagnitudeType] Layover = SerializableDescriptor( 'Layover', AngleMagnitudeType, _required, strict=DEFAULT_STRICT, docstring= 'The phenomenon where vertical objects appear as ground objects with ' 'the same range/range rate.') # type: Union[None, AngleMagnitudeType] MultiPath = FloatModularDescriptor( 'MultiPath', 180.0, _required, strict=DEFAULT_STRICT, docstring= 'This is a range dependent phenomenon which describes the energy from a ' 'single scatter returned to the radar via more than one path and results ' 'in a nominally constant direction in the ETP.' ) # type: Union[None, float] GroundTrack = FloatModularDescriptor( 'GroundTrack', 180.0, _required, strict=DEFAULT_STRICT, docstring= 'Counter-clockwise angle from increasing row direction to ground track ' 'at the center of the image.') # type: Union[None, 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, Shadow=None, Layover=None, MultiPath=None, GroundTrack=None, Extensions=None, **kwargs): """ Parameters ---------- Shadow : None|AngleMagnitudeType|numpy.ndarray|list|tuple Layover : None|AngleMagnitudeType|numpy.ndarray|list|tuple MultiPath : None|float GroundTrack : 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.Shadow = Shadow self.Layover = Layover self.MultiPath = MultiPath self.GroundTrack = GroundTrack self.Extensions = Extensions super(ExploitationFeaturesCollectionPhenomenologyType, self).__init__(**kwargs) @classmethod def from_calculator(cls, calculator): """ Create from an ExploitationCalculator object. Parameters ---------- calculator : ExploitationCalculator Returns ------- ExploitationFeaturesCollectionPhenomenologyType """ if not isinstance(calculator, ExploitationCalculator): raise TypeError(_exp_calc_text.format(type(calculator))) return cls(Shadow=calculator.Shadow, Layover=calculator.Layover, MultiPath=calculator.MultiPath, GroundTrack=calculator.GroundTrack)
class ProcessingModuleType(Serializable): """ Flexibly structured processing module definition to keep track of the name and any parameters associated with the algorithms used to produce the SIDD. """ _fields = ('ModuleName', 'name', 'ModuleParameters') _required = ('ModuleName', 'name', 'ModuleParameters') _set_as_attribute = ('name', ) _collections_tags = { 'ModuleParameters': {'array': False, 'child_tag': 'ModuleParameter'}} # Descriptor ModuleName = StringDescriptor( 'ModuleName', _required, strict=DEFAULT_STRICT, docstring='The module name.') # type: str name = StringDescriptor( 'name', _required, strict=DEFAULT_STRICT, docstring='The module identifier.') # type: str ModuleParameters = ParametersDescriptor( 'ModuleParameters', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Free form parameters.') # type: ParametersCollection def __init__(self, ModuleName=None, name=None, ModuleParameters=None, ProcessingModules=None, **kwargs): """ Parameters ---------- ModuleName : str name : str ModuleParameters : None|ParametersCollection|dict ProcessingModules : None|List[ProcessingModuleType] 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.ModuleName = ModuleName self.name = name self.ModuleParameters = ModuleParameters self._ProcessingModules = [] if ProcessingModules is None: pass elif isinstance(ProcessingModules, ProcessingModuleType): self.addProcessingModule(ProcessingModules) elif isinstance(ProcessingModules, (list, tuple)): for el in ProcessingModules: self.addProcessingModule(el) else: raise ('ProcessingModules got unexpected type {}'.format(type(ProcessingModules))) super(ProcessingModuleType, self).__init__(**kwargs) @property def ProcessingModules(self): """List[ProcessingModuleType]: list of ProcessingModules.""" return self._ProcessingModules def getProcessingModule(self, key): """ Get ProcessingModule(s) with name attribute == `key`. Parameters ---------- key : str Returns ------- List[ProcessingModuleType] """ return [entry for entry in self._ProcessingModules if entry.name == key] def addProcessingModule(self, value): """ Add the ProcessingModule to the list. Parameters ---------- value : ProcessingModuleType Returns ------- None """ if isinstance(value, ElementTree.Element): pm_key = self._child_xml_ns_key.get('ProcessingModules', self._xml_ns_key) value = ProcessingModuleType.from_node(value, self._xml_ns, ns_key=pm_key) elif isinstance(value, dict): value = ProcessingModuleType.from_dict(value) if isinstance(value, ProcessingModuleType): self._ProcessingModules.append(value) else: raise TypeError('Trying to set ProcessingModule 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() # parse the ModuleName mn_key = cls._child_xml_ns_key.get('ModuleName', ns_key) mn_node = find_first_child(node, 'ModuleName', xml_ns, mn_key) kwargs['ModuleName'] = get_node_value(mn_node) kwargs['name'] = mn_node.attrib.get('name', None) # parse the ProcessingModule children pm_key = cls._child_xml_ns_key.get('ProcessingModules', ns_key) kwargs['ProcessingModules'] = find_children(node, 'ProcessingModule', xml_ns, pm_key) return super(ProcessingModuleType, 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=()): exclude = exclude + ('ModuleName', 'name', 'ProcessingModules') node = super(ProcessingModuleType, self).to_node( doc, tag, ns_key=ns_key, parent=parent, check_validity=check_validity, strict=strict, exclude=exclude) # add the ModuleName and name children if self.ModuleName is not None: mn_key = self._child_xml_ns_key.get('ModuleName', ns_key) mn_tag = '{}:ModuleName'.format(mn_key) if mn_key is not None and mn_key != 'default' else 'ModuleName' mn_node = create_text_node(doc, mn_tag, self.ModuleName, parent=node) if self.name is not None: mn_node.attrib['name'] = self.name # add the ProcessingModule children pm_key = self._child_xml_ns_key.get('ProcessingModules', ns_key) for entry in self._ProcessingModules: entry.to_node(doc, tag, ns_key=pm_key, parent=node, strict=strict) return node def to_dict(self, check_validity=False, strict=DEFAULT_STRICT, exclude=()): out = super(ProcessingModuleType, self).to_dict(check_validity=check_validity, strict=strict, exclude=exclude) # slap on the GeoInfo children if len(self.ProcessingModules) > 0: out['ProcessingModules'] = [ entry.to_dict(check_validity=check_validity, strict=strict) for entry in self._ProcessingModules] return out
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 CreationInfoType(Serializable): """ Parameters that provide general information about the CPHD product generation. """ _fields = ('Application', 'DateTime', 'Site', 'Parameters') _required = ('DateTime', ) _collections_tags = { 'Parameters': { 'array': False, 'child_tag': 'Parameter' } } # descriptors Application = StringDescriptor( 'Application', _required, strict=DEFAULT_STRICT, docstring='Name and version of the application used to create the CPHD.' ) # type: str DateTime = DateTimeDescriptor( 'DateTime', _required, strict=DEFAULT_STRICT, numpy_datetime_units='us', docstring= 'Date and time the image creation application processed the image (UTC).' ) # type: numpy.datetime64 Site = StringDescriptor( 'Site', _required, strict=DEFAULT_STRICT, docstring='The creation site of this CPHD product.') # type: str Parameters = ParametersDescriptor( 'Parameters', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Additional parameters.' ) # type: Union[None, ParametersCollection] def __init__(self, Application=None, DateTime=None, Site=None, Parameters=None, **kwargs): """ Parameters ---------- Application : str DateTime : numpy.datetime64|datetime|date|str Site : str Profile : str 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.Application = Application self.DateTime = DateTime self.Site = Site self.Parameters = Parameters super(CreationInfoType, self).__init__(**kwargs)
class CollectionInfoType(Serializable): """General information about the collection.""" _collections_tags = { 'Parameters': {'array': False, 'child_tag': 'Parameter'}, 'CountryCodes': {'array': False, 'child_tag': 'CountryCode'}, } _fields = ( 'CollectorName', 'IlluminatorName', 'CoreName', 'CollectType', 'RadarMode', 'Classification', 'CountryCodes', 'Parameters') _required = ('CollectorName', 'CoreName', 'RadarMode', 'Classification') # other class variable _COLLECT_TYPE_VALUES = ('MONOSTATIC', 'BISTATIC') # descriptors CollectorName = StringDescriptor( 'CollectorName', _required, strict=DEFAULT_STRICT, docstring='Radar platform identifier. For Bistatic collections, list the Receive platform.') # type: str IlluminatorName = StringDescriptor( 'IlluminatorName', _required, strict=DEFAULT_STRICT, docstring='Radar platform identifier that provided the illumination. For Bistatic collections, ' 'list the transmit platform.') # type: str CoreName = StringDescriptor( 'CoreName', _required, strict=DEFAULT_STRICT, docstring='Collection and imaging data set identifier. Uniquely identifies imaging collections per ' 'Program Specific Implementation Doc.') # type: str CollectType = StringEnumDescriptor( 'CollectType', _COLLECT_TYPE_VALUES, _required, docstring="Collection type identifier. Monostatic collections include single platform collections with " "unique transmit and receive apertures.") # type: str RadarMode = SerializableDescriptor( 'RadarMode', RadarModeType, _required, strict=DEFAULT_STRICT, docstring='The radar mode.') # type: RadarModeType Classification = StringDescriptor( 'Classification', _required, strict=DEFAULT_STRICT, default_value='UNCLASSIFIED', docstring='Contains the human-readable banner. Contains classification, file control and handling, ' 'file releasing, and/or proprietary markings. Specified per Program Specific ' 'Implementation Document.') # type: str CountryCodes = StringListDescriptor( 'CountryCodes', _required, strict=DEFAULT_STRICT, docstring="List of country codes for region covered by the image.") # type: List[str] Parameters = ParametersDescriptor( 'Parameters', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Free form parameters object collection.') # type: ParametersCollection def __init__(self, CollectorName=None, IlluminatorName=None, CoreName=None, CollectType=None, RadarMode=None, Classification="UNCLASSIFIED", CountryCodes=None, Parameters=None, **kwargs): """ Parameters ---------- CollectorName : str IlluminatorName : str CoreName : str CollectType : str RadarMode : RadarModeType Classification : str CountryCodes : list|str Parameters : ParametersCollection|dict 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.CollectorName, self.IlluminatorName = CollectorName, IlluminatorName self.CoreName, self.CollectType = CoreName, CollectType self.RadarMode = RadarMode self.Classification = Classification self.CountryCodes, self.Parameters = CountryCodes, Parameters super(CollectionInfoType, self).__init__(**kwargs)
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 ProductCreationType(Serializable): """ Contains general information about product creation. """ _fields = ( 'ProcessorInformation', 'Classification', 'ProductName', 'ProductClass', 'ProductType', 'ProductCreationExtensions') _required = ( 'ProcessorInformation', 'Classification', 'ProductName', 'ProductClass') _collections_tags = {'ProductCreationExtensions': {'array': False, 'child_tag': 'ProductCreationExtension'}} # Descriptors ProcessorInformation = SerializableDescriptor( 'ProcessorInformation', ProcessorInformationType, _required, strict=DEFAULT_STRICT, docstring='Details regarding processor.') # type: ProcessorInformationType Classification = SerializableDescriptor( 'Classification', ProductClassificationType, _required, strict=DEFAULT_STRICT, docstring='The overall classification of the product.') # type: ProductClassificationType ProductName = StringDescriptor( 'ProductName', _required, strict=DEFAULT_STRICT, docstring='The output product name defined by the processor.') # type: str ProductClass = StringDescriptor( 'ProductClass', _required, strict=DEFAULT_STRICT, docstring='Class of product. Examples - :code:`Dynamic Image, Amplitude Change Detection, ' 'Coherent Change Detection`') # type: str ProductType = StringDescriptor( 'ProductType', _required, strict=DEFAULT_STRICT, docstring='Type of sub-product. Examples - :code:`Frame #, Reference, Match`. ' 'This field is only needed if there is a suite of associated ' 'products.') # type: Union[None, str] ProductCreationExtensions = ParametersDescriptor( 'ProductCreationExtensions', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Extensible parameters used to support profile-specific needs related to ' 'product creation.') # type: ParametersCollection def __init__(self, ProcessorInformation=None, Classification=None, ProductName=None, ProductClass=None, ProductType=None, ProductCreationExtensions=None, **kwargs): """ Parameters ---------- ProcessorInformation : ProcessorInformationType Classification : ProductClassificationType ProductName : str ProductClass : str ProductType : str ProductCreationExtensions : 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.ProcessorInformation = ProcessorInformation self.Classification = Classification self.ProductName = ProductName self.ProductClass = ProductClass self.ProductType = ProductType self.ProductCreationExtensions = ProductCreationExtensions super(ProductCreationType, self).__init__(**kwargs) @classmethod def from_sicd(cls, sicd, product_class): """ Generate from a SICD for the given product class. Parameters ---------- sicd : SICDType product_class : str Returns ------- ProductCreationType """ if not isinstance(sicd, SICDType): raise TypeError('Requires SICDType instance, got type {}'.format(type(sicd))) from sarpy.__about__ import __title__, __version__ proc_info = ProcessorInformationType( Application='{} {}'.format(__title__, __version__), ProcessingDateTime=numpy.datetime64(datetime.now()), Site='Unknown') classification = ProductClassificationType.from_sicd(sicd) return cls(ProcessorInformation=proc_info, Classification=classification, ProductName=product_class, ProductClass=product_class)
class ProductClassificationType(Serializable): """ The overall classification of the product. """ _fields = ( 'DESVersion', 'resourceElement', 'createDate', 'compliesWith', 'ISMCATCESVersion', 'classification', 'ownerProducer', 'SCIcontrols', 'SARIdentifier', 'disseminationControls', 'FGIsourceOpen', 'FGIsourceProtected', 'releasableTo', 'nonICmarkings', 'classifiedBy', 'compilationReason', 'derivativelyClassifiedBy', 'classificationReason', 'nonUSControls', 'derivedFrom', 'declassDate', 'declassEvent', 'declassException', 'typeOfExemptedSource', 'dateOfExemptedSource', 'SecurityExtensions') _required = ( 'DESVersion', 'createDate', 'classification', 'ownerProducer', 'compliesWith', 'ISMCATCESVersion') _collections_tags = {'SecurityExtensions': {'array': False, 'child_tag': 'SecurityExtension'}} _set_as_attribute = ( 'DESVersion', 'resourceElement', 'createDate', 'compliesWith', 'ISMCATCESVersion', 'classification', 'ownerProducer', 'SCIcontrols', 'SARIdentifier', 'disseminationControls', 'FGIsourceOpen', 'FGIsourceProtected', 'releasableTo', 'nonICmarkings', 'classifiedBy', 'compilationReason', 'derivativelyClassifiedBy', 'classificationReason', 'nonUSControls', 'derivedFrom', 'declassDate', 'declassEvent', 'declassException', 'typeOfExemptedSource', 'dateOfExemptedSource') _child_xml_ns_key = {the_field: 'ism' for the_field in _fields if the_field != 'SecurityExtensions'} # Descriptor DESVersion = IntegerDescriptor( 'DESVersion', _required, strict=DEFAULT_STRICT, default_value=13, docstring='The version number of the DES. Should there be multiple specified in an instance document ' 'the one at the root node is the one that will apply to the entire document.') # type: int createDate = StringDescriptor( 'createDate', _required, strict=DEFAULT_STRICT, docstring='This should be a date of format :code:`YYYY-MM-DD`, but this is not checked.') # type: str compliesWith = StringEnumDescriptor( 'compliesWith', ('USGov', 'USIC', 'USDOD', 'OtherAuthority'), _required, strict=DEFAULT_STRICT, default_value='USGov', docstring='The ISM rule sets with which the document may complies.') # type: Union[None, str] ISMCATCESVersion = StringDescriptor( 'ISMCATCESVersion', _required, strict=DEFAULT_STRICT, default_value='201903', docstring='') # type: Union[None, str] classification = StringEnumDescriptor( 'classification', ('U', 'C', 'R', 'S', 'TS'), _required, strict=DEFAULT_STRICT, docstring='') # type: str ownerProducer = StringDescriptor( 'ownerProducer', _required, strict=DEFAULT_STRICT, # default_value='USA', docstring='') # type: str SCIcontrols = StringDescriptor( 'SCIcontrols', _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, str] SARIdentifier = StringDescriptor( 'SARIdentifier', _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, str] disseminationControls = StringDescriptor( 'disseminationControls', _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, str] FGIsourceOpen = StringDescriptor( 'FGIsourceOpen', _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, str] FGIsourceProtected = StringDescriptor( 'FGIsourceProtected', _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, str] releasableTo = StringDescriptor( 'releasableTo', _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, str] nonICmarkings = StringDescriptor( 'nonICmarkings', _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, str] classifiedBy = StringDescriptor( 'classifiedBy', _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, str] compilationReason = StringDescriptor( 'compilationReason', _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, str] derivativelyClassifiedBy = StringDescriptor( 'derivativelyClassifiedBy', _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, str] classificationReason = StringDescriptor( 'classificationReason', _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, str] nonUSControls = StringDescriptor( 'nonUSControls', _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, str] derivedFrom = StringDescriptor( 'derivedFrom', _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, str] declassDate = StringDescriptor( 'declassDate', _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, str] declassEvent = StringDescriptor( 'declassEvent', _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, str] declassException = StringDescriptor( 'declassException', _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, str] typeOfExemptedSource = StringDescriptor( 'typeOfExemptedSource', _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, str] dateOfExemptedSource = StringDescriptor( 'dateOfExemptedSource', _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, str] SecurityExtensions = ParametersDescriptor( 'SecurityExtensions', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Extensible parameters used to support profile-specific needs related to ' 'product security.') # type: ParametersCollection def __init__(self, DESVersion=13, createDate=None, compliesWith='USGov', ISMCATCESVersion='201903', classification='U', ownerProducer='USA', SCIcontrols=None, SARIdentifier=None, disseminationControls=None, FGIsourceOpen=None, FGIsourceProtected=None, releasableTo=None, nonICmarkings=None, classifiedBy=None, compilationReason=None, derivativelyClassifiedBy=None, classificationReason=None, nonUSControls=None, derivedFrom=None, declassDate=None, declassEvent=None, declassException=None, typeOfExemptedSource=None, dateOfExemptedSource=None, SecurityExtensions=None, **kwargs): """ Parameters ---------- DESVersion : int createDate : str compliesWith : None|str ISMCATCESVersion : None|str classification : str ownerProducer : str SCIcontrols : None|str SARIdentifier : None|str disseminationControls : None|str FGIsourceOpen : None|str FGIsourceProtected : None|str releasableTo : None|str nonICmarkings : None|str classifiedBy : None|str compilationReason : None|str derivativelyClassifiedBy : None|str classificationReason : None|str nonUSControls : None|str derivedFrom : None|str declassDate : None|str declassEvent : None|str declassException : None|str typeOfExemptedSource : None|str dateOfExemptedSource : None|str SecurityExtensions : 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.DESVersion = DESVersion self.createDate = createDate self.compliesWith = compliesWith self.ISMCATCESVersion = ISMCATCESVersion self.classification = classification self.ownerProducer = ownerProducer self.SCIcontrols = SCIcontrols self.SARIdentifier = SARIdentifier self.disseminationControls = disseminationControls self.FGIsourceOpen = FGIsourceOpen self.FGIsourceProtected = FGIsourceProtected self.releasableTo = releasableTo self.nonICmarkings = nonICmarkings self.classifiedBy = classifiedBy self.compilationReason = compilationReason self.derivativelyClassifiedBy = derivativelyClassifiedBy self.classificationReason = classificationReason self.nonUSControls = nonUSControls self.derivedFrom = derivedFrom self.declassDate = declassDate self.declassEvent = declassEvent self.declassException = declassException self.typeOfExemptedSource = typeOfExemptedSource self.dateOfExemptedSource = dateOfExemptedSource self.SecurityExtensions = SecurityExtensions super(ProductClassificationType, self).__init__(**kwargs) @property def resourceElement(self): return 'true' @classmethod def from_sicd(cls, sicd, create_date=None): """ Extract best guess from SICD. Parameters ---------- sicd : SICDType create_date : str Returns ------- ProductClassificationType """ clas = extract_classification_from_sicd(sicd) if create_date is None: create_date = datetime.now().strftime('%Y-%m-%d') return cls(classification=clas, createDate=create_date)
class ChannelParametersType(Serializable): """ The CRSD data channel parameters """ _fields = ( 'Identifier', 'RefVectorIndex', 'RefFreqFixed', 'FrcvFixed', 'DemodFixed', 'F0Ref', 'Fs', 'BWInst', 'RcvPol', 'SignalNormal', 'RcvAntenna', 'SignalRefLevel', 'NoiseLevel', 'AddedParameters', 'SARImaging') _required = ( 'Identifier', 'RefVectorIndex', 'RefFreqFixed', 'FrcvFixed', 'DemodFixed', 'F0Ref', 'Fs', 'BWInst', 'RcvPol') _numeric_format = { 'F0Ref': FLOAT_FORMAT, 'Fs': FLOAT_FORMAT, 'BWInst': FLOAT_FORMAT} _collections_tags = { 'AddedParameters': {'array': False, 'child_tag': 'AddedParameters'}} # descriptors Identifier = StringDescriptor( 'Identifier', _required, strict=DEFAULT_STRICT, docstring='String that uniquely identifies this CRSD data channel.') # type: str RefVectorIndex = IntegerDescriptor( 'RefVectorIndex', _required, strict=DEFAULT_STRICT, bounds=(0, None), docstring='Index of the reference vector for the channel.') # type: int RefFreqFixed = BooleanDescriptor( 'RefFreqFixed', _required, strict=DEFAULT_STRICT, docstring='Flag to indicate a constant reference frequency is used for' ' the channel.') # type: bool FrcvFixed = BooleanDescriptor( 'FrcvFixed', _required, strict=DEFAULT_STRICT, docstring='Flag to indicate a constant receive band is saved for the' ' channel.') # type: bool DemodFixed = BooleanDescriptor( 'DemodFixed', _required, strict=DEFAULT_STRICT, docstring='Flag to indicate a constant demodulation is used for the' ' channel.') # type: bool F0Ref = FloatDescriptor( 'F0Ref', _required, strict=DEFAULT_STRICT, bounds=(0, None), docstring='Reference frequency for the reference signal vector.') # type: float Fs = FloatDescriptor( 'Fs', _required, strict=DEFAULT_STRICT, bounds=(0, None), docstring='Fast time sample rate for the signal array.') # type: float BWInst = FloatDescriptor( 'BWInst', _required, strict=DEFAULT_STRICT, bounds=(0, None), docstring='Nominal instantaneous bandwidth for the channel.') # type: float RcvPol = StringEnumDescriptor( 'RcvPol', POLARIZATION_TYPE, _required, strict=DEFAULT_STRICT, docstring='Receive polarization for the signal data processed to form the signal array.' ' Parameter describes the E-Field orientation of the signal.') # type: str SignalNormal = BooleanDescriptor( 'SignalNormal', _required, strict=DEFAULT_STRICT, docstring='Flag to indicate when all signal array vectors are normal.' ' Included if and only if the SIGNAL PVP is also included.') # type: Union[None, bool] RcvAntenna = SerializableDescriptor( 'RcvAntenna', RcvAntennaType, _required, strict=DEFAULT_STRICT, docstring='Antenna Phase Center and Antenna Pattern identifiers for the receive antenna' ' used to collect and form the signal array data.') # type: Union[None, RcvAntennaType] SignalRefLevel = SerializableDescriptor( 'SignalRefLevel', SignalRefLevelType, _required, strict=DEFAULT_STRICT, docstring='Signal power levels for a received CW signal with f = f_0_REF and polarization' ' matched to RcvPol of the channel.') # type: Union[None, SignalRefLevelType] NoiseLevel = SerializableDescriptor( 'NoiseLevel', NoiseLevelType, _required, strict=DEFAULT_STRICT, docstring='Thermal noise level in the CRSD signal vector for f_IC(v,t) =' ' f_0(v_CH_REF).') # type: Union[None, NoiseLevelType] AddedParameters = ParametersDescriptor( 'AddedParameters', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Additional free form parameters.') # type: Union[None, ParametersCollection] SARImaging = SerializableDescriptor( 'SARImaging', SARImagingType, _required, strict=DEFAULT_STRICT, docstring='Structure included for all SAR imaging collections.') # type: Union[None, SARImagingType] def __init__(self, Identifier=None, RefVectorIndex=None, RefFreqFixed=None, FrcvFixed=None, DemodFixed=None, F0Ref=None, Fs=None, BWInst=None, RcvPol=None, SignalNormal=None, RcvAntenna=None, SignalRefLevel=None, NoiseLevel=None, AddedParameters=None, SARImaging=None, **kwargs): """ Parameters ---------- Identifier : str RefVectorIndex : int RefFreqFixed : bool FrcvFixed : bool DemodFixed : bool F0Ref : float Fs : float BWInst : float RcvPol : str SignalNormal : None|bool RcvAntenna : None|RcvAntennaType SignalRefLevel : None|SignalRefLevelType NoiseLevel : None|NoiseLevelType AddedParameters : None|ParametersCollection SARImaging : None|SARImagingType 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.RefVectorIndex = RefVectorIndex self.RefFreqFixed = RefFreqFixed self.FrcvFixed = FrcvFixed self.DemodFixed = DemodFixed self.F0Ref = F0Ref self.Fs = Fs self.BWInst = BWInst self.RcvPol = RcvPol self.SignalNormal = SignalNormal self.RcvAntenna = RcvAntenna self.SignalRefLevel = SignalRefLevel self.NoiseLevel = NoiseLevel self.AddedParameters = AddedParameters self.SARImaging = SARImaging super(ChannelParametersType, self).__init__(**kwargs)
class WgtTypeType(Serializable): """ The weight type parameters of the direction parameters. """ _fields = ('WindowName', 'Parameters') _required = ('WindowName', ) _collections_tags = { 'Parameters': { 'array': False, 'child_tag': 'Parameter' } } # descriptors WindowName = StringDescriptor( 'WindowName', _required, strict=DEFAULT_STRICT, docstring= 'Type of aperture weighting applied in the spatial frequency domain (Krow) to yield ' 'the impulse response in the row direction. ' '*Example values - "UNIFORM", "TAYLOR", "UNKNOWN", "HAMMING"*' ) # type: str Parameters = ParametersDescriptor( 'Parameters', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Free form parameters list.') # type: ParametersCollection def __init__(self, WindowName=None, Parameters=None, **kwargs): """ Parameters ---------- WindowName : str Parameters : ParametersCollection|dict 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.WindowName = WindowName self.Parameters = Parameters super(WgtTypeType, self).__init__(**kwargs) def get_parameter_value(self, param_name, default=None): """ Gets the value (first value found) associated with a given parameter name. Returns `default` if not found. Parameters ---------- param_name : str the parameter name for which to search. default : None|str the default value to return if lookup fails. Returns ------- str the associated parameter value, or `default`. """ if self.Parameters is None: return default the_dict = self.Parameters.get_collection() if len(the_dict) == 0: return default if param_name is None: # get the first value - this is dumb, but appears a use case. Leaving undocumented. return list(the_dict.values())[0] return the_dict.get(param_name, default) @classmethod def from_node(cls, node, xml_ns, ns_key=None, kwargs=None): win_key = cls._child_xml_ns_key.get('WindowName', ns_key) win_name = find_first_child(node, 'WindowName', xml_ns, win_key) if win_name is None: # SICD 0.4 standard compliance, this could just be a space delimited string of the form # "<WindowName> <name1>=<value1> <name2>=<value2> ..." if kwargs is None: kwargs = {} values = node.text.strip().split() kwargs['WindowName'] = values[0] params = {} for entry in values[1:]: try: name, val = entry.split('=') params[name] = val except ValueError: continue kwargs['Parameters'] = params return cls.from_dict(kwargs) else: return super(WgtTypeType, cls).from_node(node, xml_ns, ns_key=ns_key, kwargs=kwargs)
class GeographicCoverageType(Serializable): """ The geographic coverage area for the product. """ _fields = ('GeoregionIdentifiers', 'Footprint', 'GeographicInfo') _required = ('Footprint', ) _collections_tags = { 'GeoregionIdentifiers': {'array': False, 'child_tag': 'GeoregionIdentifier'}, 'Footprint': {'array': True, 'child_tag': 'Vertex'}, 'SubRegions': {'array': False, 'child_tag': 'SubRegion'}} # Descriptors GeoregionIdentifiers = ParametersDescriptor( 'GeoregionIdentifiers', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Target may have one or more identifiers. Examples: names, BE numbers, etc. Use ' 'the "name" attribute to describe what this is.') # type: ParametersCollection Footprint = SerializableArrayDescriptor( 'Footprint', LatLonArrayElementType, _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Estimated ground footprint of the ' 'product.') # type: Union[None, SerializableArray, List[LatLonArrayElementType]] GeographicInfo = SerializableDescriptor( 'GeographicInfo', GeographicInformationType, _required, strict=DEFAULT_STRICT, docstring='') # type: Union[None, GeographicInformationType] def __init__(self, GeoregionIdentifiers=None, Footprint=None, SubRegions=None, GeographicInfo=None, **kwargs): """ Parameters ---------- GeoregionIdentifiers : None|ParametersCollection|dict Footprint : None|List[LatLonArrayElementType]|numpy.ndarray|list|tuple SubRegions : None|List[GeographicCoverageType] GeographicInfo : None|GeographicInformationType 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.GeoregionIdentifiers = GeoregionIdentifiers self.Footprint = Footprint self.GeographicInfo = GeographicInfo self._SubRegions = [] if SubRegions is None: pass elif isinstance(SubRegions, GeographicCoverageType): self.addSubRegion(SubRegions) elif isinstance(SubRegions, (list, tuple)): for el in SubRegions: self.addSubRegion(el) else: raise ('SubRegions got unexpected type {}'.format(type(SubRegions))) super(GeographicCoverageType, self).__init__(**kwargs) @property def SubRegions(self): """ List[GeographicCoverageType]: list of sub-regions. """ return self._SubRegions def addSubRegion(self, value): """ Add the given SubRegion to the SubRegions list. Parameters ---------- value : GeographicCoverageType Returns ------- None """ if isinstance(value, ElementTree.Element): value = GeographicCoverageType.from_node(value, self._xml_ns, ns_key=self._xml_ns_key) elif isinstance(value, dict): value = GeographicCoverageType.from_dict(value) if isinstance(value, GeographicCoverageType): self._SubRegions.append(value) else: raise TypeError('Trying to set SubRegion 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() kwargs['SubRegions'] = find_children(node, 'SubRegion', xml_ns, ns_key) return super(GeographicCoverageType, 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(GeographicCoverageType, self).to_node( doc, tag, ns_key=ns_key, parent=parent, check_validity=check_validity, strict=strict, exclude=exclude) # slap on the SubRegion children sub_key = self._child_xml_ns_key.get('SubRegions', ns_key) for entry in self._SubRegions: entry.to_node(doc, 'SubRegion', ns_key=sub_key, parent=node, strict=strict) return node def to_dict(self, check_validity=False, strict=DEFAULT_STRICT, exclude=()): out = super(GeographicCoverageType, self).to_dict(check_validity=check_validity, strict=strict, exclude=exclude) # slap on the SubRegion children if len(self.SubRegions) > 0: out['SubRegions'] = [ entry.to_dict(check_validity=check_validity, strict=strict) for entry in self._SubRegions] return out
class MonochromeDisplayRemapType(Serializable): """ This remap works by taking the input space and using the LUT to map it to a log space (for 8-bit only). From the log space the C0 and Ch fields are applied to get to display-ready density space. The density should then be rendered by the TTC and monitor comp. This means that the default DRA should not apply anything besides the clip points. If a different contrast/brightness is applied it should be done through modification of the clip points via DRA. """ _fields = ('RemapType', 'RemapLUT', 'RemapParameters') _required = ('RemapType', ) _collections_tags = { 'RemapParameters': { 'array': False, 'child_tag': 'RemapParameter' } } # Descriptor RemapType = StringDescriptor('RemapType', _required, strict=DEFAULT_STRICT, docstring='') # type: str RemapParameters = ParametersDescriptor( 'RemapParameters', _collections_tags, _required, strict=DEFAULT_STRICT, docstring= 'Textual remap parameter. Filled based upon remap type (for informational purposes only). ' 'For example, if the data is linlog encoded a RemapParameter could be used to describe any ' 'amplitude scaling that was performed prior to linlog encoding ' 'the data.') # type: Union[None, ParametersCollection] def __init__(self, RemapType=None, RemapLUT=None, RemapParameters=None, **kwargs): """ Parameters ---------- RemapType : str RemapLUT : None|numpy.ndarray RemapParameters : None|ParametersCollection|dict kwargs """ self._remap_lut = 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.RemapType = RemapType self.RemapLUT = RemapLUT self.RemapParameters = RemapParameters super(MonochromeDisplayRemapType, self).__init__(**kwargs) @property def RemapLUT(self): """ numpy.ndarray: the one dimensional Lookup table for remap to log amplitude for display, where the dtype must be `uint8`. Used during the "Product Generation Option" portion of the SIPS display chain. Required for 8-bit data, and not to be used for 16-bit data. """ return self._remap_lut @RemapLUT.setter def RemapLUT(self, value): if value is None: self._remap_lut = None return if isinstance(value, (tuple, list)): value = numpy.array(value, dtype=numpy.uint8) if not isinstance(value, numpy.ndarray) or value.dtype.name != 'uint8': raise ValueError( 'RemapLUT for class MonochromeDisplayRemapType must be a numpy.ndarray of dtype uint8.' ) if value.ndim != 1: raise ValueError( 'RemapLUT for class MonochromeDisplayRemapType must be a one-dimensional array.' ) self._remap_lut = value @classmethod def from_node(cls, node, xml_ns, ns_key=None, kwargs=None): if kwargs is None: kwargs = {} lut_key = cls._child_xml_ns_key.get('RemapLUT', ns_key) lut_node = find_first_child(node, 'RemapLUT', xml_ns, lut_key) if lut_node is not None: dim1 = int_func(lut_node.attrib['size']) arr = numpy.zeros((dim1, ), dtype=numpy.uint8) entries = get_node_value(lut_node).split() i = 0 for entry in entries: if len(entry) == 0: continue arr[i] = int(entry) i += 1 kwargs['RemapLUT'] = arr return super(MonochromeDisplayRemapType, cls).from_node(node, xml_ns, ns_key=ns_key, **kwargs) def to_node(self, doc, tag, ns_key=None, parent=None, check_validity=False, strict=DEFAULT_STRICT, exclude=()): node = super(MonochromeDisplayRemapType, self).to_node(doc, tag, ns_key=ns_key, parent=parent, check_validity=check_validity, strict=strict) if 'RemapLUT' in self._child_xml_ns_key: rtag = '{}:RemapLUT'.format(self._child_xml_ns_key['RemapLUT']) elif ns_key is not None: rtag = '{}:RemapLUT'.format(ns_key) else: rtag = 'RemapLUT' if self._remap_lut is not None: value = ' '.join('{0:d}'.format(entry) for entry in self._remap_lut) entry = create_text_node(doc, rtag, value, parent=node) entry.attrib['size'] = str(self._remap_lut.size) return node def to_dict(self, check_validity=False, strict=DEFAULT_STRICT, exclude=()): out = super(MonochromeDisplayRemapType, self).to_dict(check_validity=check_validity, strict=strict, exclude=exclude) if self.RemapLUT is not None: out['RemapLUT'] = self.RemapLUT.tolist() return out
class ExploitationFeaturesProductType(Serializable): """ Metadata regarding the product. """ _fields = ('Resolution', 'North', 'Extensions') _required = ('Resolution', ) _collections_tags = { 'Extensions': { 'array': False, 'child_tag': 'Extension' } } _numeric_format = {'North': '0.16G'} # Descriptor Resolution = SerializableDescriptor( 'Resolution', RowColDoubleType, _required, strict=DEFAULT_STRICT, docstring= 'Uniformly-weighted resolution projected into the Earth Tangent ' 'Plane (ETP).') # type: RowColDoubleType 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, North=None, Extensions=None, **kwargs): """ Parameters ---------- Resolution : RowColDoubleType|numpy.ndarray|list|tuple 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.North = North self.Extensions = Extensions super(ExploitationFeaturesProductType, self).__init__(**kwargs) @classmethod def from_sicd(cls, sicd): """ Parameters ---------- sicd : SICDType Returns ------- ExploitationFeaturesProductType """ if not isinstance(sicd, SICDType): raise TypeError('Requires SICDType instance, got type {}'.format( type(sicd))) row_ground, col_ground = sicd.get_ground_resolution() return cls(Resolution=(row_ground, col_ground))
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 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 ErrorStatisticsType(Serializable): """Parameters used to compute error statistics within the SICD sensor model.""" _fields = ('CompositeSCP', 'Components', 'Unmodeled', 'AdditionalParms') _required = () _collections_tags = { 'AdditionalParms': { 'array': False, 'child_tag': 'Parameter' } } # descriptors CompositeSCP = SerializableDescriptor( 'CompositeSCP', CompositeSCPErrorType, _required, strict=DEFAULT_STRICT, docstring= 'Composite error statistics for the scene center point. *Slant plane range (Rg)* and *azimuth (Az)* ' 'error statistics. Slant plane defined at *Scene Center Point, Center of Azimuth (SCP COA)*.' ) # type: Union[None, CompositeSCPErrorType] Components = SerializableDescriptor( 'Components', ErrorComponentsType, _required, strict=DEFAULT_STRICT, docstring='Error statistics by components.' ) # type: Union[None, ErrorComponentsType] Unmodeled = SerializableDescriptor( 'Unmodeled', UnmodeledType, _required, strict=DEFAULT_STRICT) # type: Union[None, UnmodeledType] AdditionalParms = ParametersDescriptor( 'AdditionalParms', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Any additional parameters.' ) # type: Union[None, ParametersCollection] def __init__(self, CompositeSCP=None, Components=None, Unmodeled=None, AdditionalParms=None, **kwargs): """ Parameters ---------- CompositeSCP : None|CompositeSCPErrorType Components : None|ErrorComponentsType Unmodeled : None|UnmodeledType AdditionalParms : 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.CompositeSCP = CompositeSCP self.Components = Components self.Unmodeled = Unmodeled self.AdditionalParms = AdditionalParms super(ErrorStatisticsType, self).__init__(**kwargs) def version_required(self): """ What SICD version is required? Returns ------- tuple """ if self.Unmodeled is None: return (1, 1, 0) else: return (1, 3, 0)
class ProductDisplayType(Serializable): """ """ _fields = ('PixelType', 'RemapInformation', 'MagnificationMethod', 'DecimationMethod', 'DRAHistogramOverrides', 'MonitorCompensationApplied', 'DisplayExtensions') _required = ('PixelType', ) _collections_tags = { '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 RemapInformation = SerializableDescriptor( 'RemapInformation', RemapChoiceType, _required, strict=DEFAULT_STRICT, docstring='Information regarding the encoding of the pixel data. ' 'Used for 8-bit pixel types.') # type: Union[None, RemapChoiceType] MagnificationMethod = StringEnumDescriptor( 'MagnificationMethod', ('NEAREST_NEIGHBOR', 'BILINEAR', 'LAGRANGE'), _required, strict=DEFAULT_STRICT, docstring='Recommended ELT magnification method for this data.' ) # type: Union[None, str] DecimationMethod = StringEnumDescriptor( 'DecimationMethod', ('NEAREST_NEIGHBOR', 'BILINEAR', 'BRIGHTEST_PIXEL', 'LAGRANGE'), _required, strict=DEFAULT_STRICT, docstring= 'Recommended ELT decimation method for this data. Also used as default for ' 'reduced resolution dataset generation (if applicable).' ) # type: Union[None, str] DRAHistogramOverrides = SerializableDescriptor( 'DRAHistogramOverrides', DRAHistogramOverridesType, _required, strict=DEFAULT_STRICT, docstring='Recommended ELT DRA overrides.' ) # type: Union[None, DRAHistogramOverridesType] MonitorCompensationApplied = SerializableDescriptor( 'MonitorCompensationApplied', MonitorCompensationAppliedType, _required, strict=DEFAULT_STRICT, docstring= 'Describes monitor compensation that may have been applied to the product ' 'during processing.' ) # type: Union[None, MonitorCompensationAppliedType] 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: Union[None, ParametersCollection] def __init__(self, PixelType=None, RemapInformation=None, MagnificationMethod=None, DecimationMethod=None, DRAHistogramOverrides=None, MonitorCompensationApplied=None, DisplayExtensions=None, **kwargs): """ Parameters ---------- PixelType : PixelTypeType RemapInformation : None|RemapChoiceType MagnificationMethod : None|str DecimationMethod : None|str DRAHistogramOverrides : None|DRAHistogramOverridesType MonitorCompensationApplied : None|MonitorCompensationAppliedType DisplayExtensions : 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.PixelType = PixelType self.RemapInformation = RemapInformation self.MagnificationMethod = MagnificationMethod self.DecimationMethod = DecimationMethod self.DRAHistogramOverrides = DRAHistogramOverrides self.MonitorCompensationApplied = MonitorCompensationApplied self.DisplayExtensions = DisplayExtensions super(ProductDisplayType, self).__init__(**kwargs)
class ProcessingEventType(Serializable): """ Processing event data. """ _fields = ('ApplicationName', 'AppliedDateTime', 'InterpolationMethod', 'Descriptors') _required = ('ApplicationName', 'AppliedDateTime') _collections_tags = { 'Descriptors': { 'array': False, 'child_tag': 'Descriptor' } } # Descriptor ApplicationName = StringDescriptor( 'ApplicationName', _required, strict=DEFAULT_STRICT, docstring='Application which applied a modification.') # type: str AppliedDateTime = DateTimeDescriptor( 'AppliedDateTime', _required, strict=DEFAULT_STRICT, numpy_datetime_units='us', docstring='Date and time defined in Coordinated Universal Time (UTC).' ) # type: numpy.datetime64 InterpolationMethod = StringDescriptor( 'InterpolationMethod', _required, strict=DEFAULT_STRICT, docstring='Type of interpolation applied to the data.' ) # type: Union[None, str] Descriptors = ParametersDescriptor( 'Descriptors', _collections_tags, _required, strict=DEFAULT_STRICT, docstring='Descriptors for the processing event.' ) # type: ParametersCollection def __init__(self, ApplicationName=None, AppliedDateTime=None, InterpolationMethod=None, Descriptors=None, **kwargs): """ Parameters ---------- ApplicationName : str AppliedDateTime : numpy.datetime64|str InterpolationMethod : None|str Descriptors : 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.ApplicationName = ApplicationName self.AppliedDateTime = numpy.datetime64( datetime.now()) if AppliedDateTime is None else AppliedDateTime self.InterpolationMethod = InterpolationMethod self.Descriptors = Descriptors super(ProcessingEventType, self).__init__(**kwargs)