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 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 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 TxRcvPolarizationType(Serializable): """ The transmit/receive polarization information. """ _fields = ('TxPolarization', 'RcvPolarization', 'RcvPolarizationOffset') _required = ('TxPolarization', 'RcvPolarization') _numeric_format = {'RcvPolarizationOffset': FLOAT_FORMAT} # Descriptor TxPolarization = StringEnumDescriptor( 'TxPolarization', POLARIZATION1_VALUES, _required, strict=DEFAULT_STRICT, docstring='Transmit polarization type.') # type: str RcvPolarization = StringEnumDescriptor( 'RcvPolarization', POLARIZATION1_VALUES, _required, strict=DEFAULT_STRICT, docstring='Receive polarization type.') # type: str RcvPolarizationOffset = FloatModularDescriptor( 'RcvPolarizationOffset', 180.0, _required, strict=DEFAULT_STRICT, docstring= 'Angle offset for the receive polarization defined at aperture center.' ) # type: float def __init__(self, TxPolarization=None, RcvPolarization=None, RcvPolarizationOffset=None, **kwargs): """ Parameters ---------- TxPolarization : str RcvPolarization : str RcvPolarizationOffset : None|float 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.TxPolarization = TxPolarization self.RcvPolarization = RcvPolarization self.RcvPolarizationOffset = RcvPolarizationOffset super(TxRcvPolarizationType, self).__init__(**kwargs) @classmethod def from_sicd_value(cls, str_in): """ Construct from the sicd style tx/rcv polarization string. Parameters ---------- str_in : str Returns ------- TxRcvPolarizationType """ tx, rcv = _extract_sicd_tx_rcv_pol(str_in) return cls(TxPolarization=tx, RcvPolarization=rcv)
class AngleMagnitudeType(Serializable, Arrayable): """ Represents a magnitude and angle. """ _fields = ('Angle', 'Magnitude') _required = ('Angle', 'Magnitude') _numeric_format = {key: FLOAT_FORMAT for key in _fields} _child_xml_ns_key = {'Angle': 'sicommon', 'Magnitude': 'sicommon'} # Descriptor Angle = FloatModularDescriptor( 'Angle', 180.0, _required, strict=DEFAULT_STRICT, docstring='The angle.') # type: float Magnitude = FloatDescriptor( 'Magnitude', _required, strict=DEFAULT_STRICT, bounds=(0.0, None), docstring='The magnitude.') # type: float def __init__(self, Angle=None, Magnitude=None, **kwargs): """ Parameters ---------- Angle : float Magnitude : float 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.Angle = Angle self.Magnitude = Magnitude super(AngleMagnitudeType, self).__init__(**kwargs) def get_array(self, dtype=numpy.float64): """ Gets an array representation of the class instance. Parameters ---------- dtype : str|numpy.dtype|numpy.number numpy data type of the return Returns ------- numpy.ndarray array of the form [Angle, Magnitude] """ return numpy.array([self.Angle, self.Magnitude], dtype=dtype) @classmethod def from_array(cls, array): """ Create from an array type entry. Parameters ---------- array: numpy.ndarray|list|tuple assumed [Angle, Magnitude] Returns ------- AngleMagnitudeType """ if array is None: return None if isinstance(array, (numpy.ndarray, list, tuple)): if len(array) < 2: raise ValueError(_len2_array_text.format(array)) return cls(Angle=array[0], Magnitude=array[1]) raise ValueError(_array_type_text.format(type(array)))
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))