예제 #1
0
class J2KSubtype(Serializable):
    """
    The Jpeg 2000 subtype.
    """
    _fields = ('NumWaveletLevels', 'NumBands', 'LayerInfo')
    _required = ('NumWaveletLevels', 'NumBands')
    _collections_tags = {'LayerInfo': {'array': True, 'child_tag': 'Bitrate', 'size_attribute': 'numLayers'}}
    _numeric_format = {'LayerInfo': FLOAT_FORMAT}
    # Descriptor
    NumWaveletLevels = IntegerDescriptor(
        'NumWaveletLevels', _required, strict=DEFAULT_STRICT,
        docstring='')  # type: int
    NumBands = IntegerDescriptor(
        'NumBands', _required, strict=DEFAULT_STRICT,
        docstring='')  # type: int
    LayerInfo = FloatArrayDescriptor(
        'LayerInfo', _collections_tags, _required, strict=DEFAULT_STRICT,
        docstring='Original Layer Information. This is an array of bit rate target associated with each '
                  'layer. It may happen that the bit rate was not achieved due to data characteristics. '
                  '**Note -** for JPEG 2000 numerically loss-less quality, the bit rate for the final layer is '
                  'an expected value, based on performance.')  # type: Union[None, numpy.ndarray]

    def __init__(self, NumWaveletLevels=None, NumBands=None, LayerInfo=None, **kwargs):
        """

        Parameters
        ----------
        NumWaveletLevels : int
        NumBands : int
        LayerInfo : None|numpy.ndarray|list|tuple
        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.NumWaveletLevels = NumWaveletLevels
        self.NumBands = NumBands
        self.LayerInfo = LayerInfo
        super(J2KSubtype, self).__init__(**kwargs)
예제 #2
0
파일: Display.py 프로젝트: ngageoint/sarpy
class DRAHistogramOverridesType(Serializable):
    """
    Dynamic range adjustment overide parameters.
    """
    _fields = ('ClipMin', 'ClipMax')
    _required = ('ClipMin', 'ClipMax')
    # Descriptor
    ClipMin = IntegerDescriptor(
        'ClipMin',
        _required,
        strict=DEFAULT_STRICT,
        docstring=
        'Suggested override for the lower end-point of the display histogram in the '
        'ELT DRA application. Referred to as Pmin in SIPS documentation.'
    )  # type: int
    ClipMax = IntegerDescriptor(
        'ClipMax',
        _required,
        strict=DEFAULT_STRICT,
        docstring=
        'Suggested override for the upper end-point of the display histogram in the '
        'ELT DRA application. Referred to as Pmax in SIPS documentation.'
    )  # type: int

    def __init__(self, ClipMin=None, ClipMax=None, **kwargs):
        """

        Parameters
        ----------
        ClipMin : int
        ClipMax : int
        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.ClipMin = ClipMin
        self.ClipMax = ClipMax
        super(DRAHistogramOverridesType, self).__init__(**kwargs)
예제 #3
0
파일: Data.py 프로젝트: ngageoint/sarpy
class ArraySizeType(Serializable):
    """
    Parameters that define the array sizes.
    """

    _fields = ('NumVectors', 'NumSamples')
    _required = ('NumVectors', 'NumSamples')
    # descriptors
    NumVectors = IntegerDescriptor(
        'NumVectors',
        _required,
        strict=DEFAULT_STRICT,
        bounds=(1, None),
        docstring='Number of slow time vectors in the PHD array in this channel.'
    )  # type: int
    NumSamples = IntegerDescriptor(
        'NumSamples',
        _required,
        strict=DEFAULT_STRICT,
        bounds=(1, None),
        docstring=
        'Number of samples per vector in the PHD array in this channel.'
    )  # type: int

    def __init__(self, NumVectors=None, NumSamples=None, **kwargs):
        """

        Parameters
        ----------
        NumVectors : int
        NumSamples : int
        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.NumVectors = NumVectors
        self.NumSamples = NumSamples
        super(ArraySizeType, self).__init__(**kwargs)
예제 #4
0
class YDirectionType(Serializable):
    """The Y direction of the collect"""
    _fields = ('UVectECF', 'SampleSpacing', 'NumSamples', 'FirstSample')
    _required = _fields
    _numeric_format = {'SampleSpacing': FLOAT_FORMAT, }
    # descriptors
    UVectECF = UnitVectorDescriptor(
        'UVectECF', XYZType, _required, strict=DEFAULT_STRICT,
        docstring='The unit vector in the Y direction.')  # type: XYZType
    SampleSpacing = FloatDescriptor(
        'SampleSpacing', _required, strict=DEFAULT_STRICT,
        docstring='The collection sample spacing in the Y direction in meters.')  # type: float
    NumSamples = IntegerDescriptor(
        'NumSamples', _required, strict=DEFAULT_STRICT,
        docstring='The number of samples in the Y direction.')  # type: int
    FirstSample = IntegerDescriptor(
        'FirstSample', _required, strict=DEFAULT_STRICT,
        docstring='The first sample index.')  # type: int

    def __init__(self, UVectECF=None, SampleSpacing=None, NumSamples=None, FirstSample=None, **kwargs):
        """

        Parameters
        ----------
        UVectECF : XYZType|numpy.ndarray|list|tuple
        SampleSpacing : float
        NumSamples : int
        FirstSample : int
        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.UVectECF = UVectECF
        self.SampleSpacing = SampleSpacing
        self.NumSamples = NumSamples
        self.FirstSample = FirstSample
        super(YDirectionType, self).__init__(**kwargs)
예제 #5
0
파일: MatchInfo.py 프로젝트: kirkjens/sarpy
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)
예제 #6
0
class TxStepType(Serializable):
    """
    Transmit sequence step details.
    """

    _fields = ('WFIndex', 'TxPolarization', 'index')
    _required = ('index', )
    _set_as_attribute = ('index', )
    # descriptors
    WFIndex = IntegerDescriptor(
        'WFIndex', _required, strict=DEFAULT_STRICT,
        docstring='The waveform number for this step.')  # type: int
    TxPolarization = StringEnumDescriptor(
        'TxPolarization', POLARIZATION2_VALUES, _required, strict=DEFAULT_STRICT,
        docstring='Transmit signal polarization for this step.')  # type: str
    index = IntegerDescriptor(
        'index', _required, strict=DEFAULT_STRICT,
        docstring='The step index')  # type: int

    def __init__(self, WFIndex=None, TxPolarization=None, index=None, **kwargs):
        """

        Parameters
        ----------
        WFIndex : int
        TxPolarization : str
        index : int
        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.WFIndex = WFIndex
        self.TxPolarization = TxPolarization
        self.index = index
        super(TxStepType, self).__init__(**kwargs)
예제 #7
0
class IAYExtentType(Serializable):
    """
    Increasing sample index is in the +IAY direction.
    """

    _fields = ('SampleSpacing', 'FirstSample', 'NumSamples')
    _required = _fields
    _numeric_format = {'SampleSpacing': '0.17G'}
    # descriptors
    SampleSpacing = FloatDescriptor(
        'SampleSpacing', _required, strict=DEFAULT_STRICT, bounds=(0, None),
        docstring='Sample spacing, in meters.')  # type: float
    FirstSample = IntegerDescriptor(
        'FirstSample', _required, strict=DEFAULT_STRICT,
        docstring='Index of the first sample.')  # type: int
    NumSamples = IntegerDescriptor(
        'NumSamples', _required, strict=DEFAULT_STRICT, bounds=(1, None),
        docstring='Number of samples.')  # type: int

    def __init__(self, SampleSpacing=None, FirstSample=None, NumSamples=None, **kwargs):
        """

        Parameters
        ----------
        SampleSpacing : float
        FirstSample : int
        NumSamples : int
        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.SampleSpacing = SampleSpacing
        self.FirstSample = FirstSample
        self.NumSamples = NumSamples
        super(IAYExtentType, self).__init__(**kwargs)
예제 #8
0
파일: blocks.py 프로젝트: ngageoint/sarpy
class PredefinedFilterType(Serializable):
    """
    The predefined filter type.
    """
    _fields = ('DatabaseName', 'FilterFamily', 'FilterMember')
    _required = ()
    # Descriptor
    DatabaseName = StringEnumDescriptor(
        'DatabaseName', ('BILINEAR', 'CUBIC', 'LAGRANGE', 'NEAREST NEIGHBOR'),
        _required, strict=DEFAULT_STRICT,
        docstring='The filter name.')  # type: str
    FilterFamily = IntegerDescriptor(
        'FilterFamily', _required, strict=DEFAULT_STRICT,
        docstring='The filter family number.')  # type: int
    FilterMember = IntegerDescriptor(
        'FilterMember', _required, strict=DEFAULT_STRICT,
        docstring='The filter member number.')  # type: int

    def __init__(self, DatabaseName=None, FilterFamily=None, FilterMember=None, **kwargs):
        """

        Parameters
        ----------
        DatabaseName : None|str
        FilterFamily : None|int
        FilterMember : None|int
        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.DatabaseName = DatabaseName
        self.FilterFamily = FilterFamily
        self.FilterMember = FilterMember
        super(PredefinedFilterType, self).__init__(**kwargs)
예제 #9
0
class PositionalAccuracyType(Serializable):
    """
    Describes the horizontal and vertical point and regional information for the DED.
    """

    _fields = ('NumRegions', 'AbsoluteAccuracy', 'PointToPointAccuracy')
    _required = ('NumRegions', 'AbsoluteAccuracy', 'PointToPointAccuracy')
    # Descriptor
    NumRegions = IntegerDescriptor(
        'NumRegions',
        _required,
        strict=DEFAULT_STRICT,
        docstring='Number of positional accuracy regions.')  # type: int
    AbsoluteAccuracy = SerializableDescriptor(
        'AbsoluteAccuracy',
        AccuracyType,
        _required,
        strict=DEFAULT_STRICT,
        docstring='')  # type: AccuracyType
    PointToPointAccuracy = SerializableDescriptor(
        'PointToPointAccuracy',
        AccuracyType,
        _required,
        strict=DEFAULT_STRICT,
        docstring='')  # type: AccuracyType

    def __init__(self,
                 NumRegions=None,
                 AbsoluteAccuracy=None,
                 PointToPointAccuracy=None,
                 **kwargs):
        """

        Parameters
        ----------
        NumRegions : int
        AbsoluteAccuracy : AccuracyType
        PointToPointAccuracy : AccuracyType
        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.NumRegions = NumRegions
        self.AbsoluteAccuracy = AbsoluteAccuracy
        self.PointToPointAccuracy = PointToPointAccuracy
        super(PositionalAccuracyType, self).__init__(**kwargs)
예제 #10
0
파일: blocks.py 프로젝트: ngageoint/sarpy
class PredefinedLookupType(Serializable):
    """
    The predefined lookup table type. Allows for reference **either** by name, or family/member id number.
    """
    _fields = ('DatabaseName', 'RemapFamily', 'RemapMember')
    _required = ()
    # Descriptor
    DatabaseName = StringDescriptor(
        'DatabaseName', _required, strict=DEFAULT_STRICT,
        docstring='Database name of LUT to use.')  # type: str
    RemapFamily = IntegerDescriptor(
        'RemapFamily', _required, strict=DEFAULT_STRICT,
        docstring='The lookup family number.')  # type: int
    RemapMember = IntegerDescriptor(
        'RemapMember', _required, strict=DEFAULT_STRICT,
        docstring='The lookup member number.')  # type: int

    def __init__(self, DatabaseName=None, RemapFamily=None, RemapMember=None, **kwargs):
        """

        Parameters
        ----------
        DatabaseName : None|str
        RemapFamily : None|int
        RemapMember : None|int
        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.DatabaseName = DatabaseName
        self.RemapFamily = RemapFamily
        self.RemapMember = RemapMember
        super(PredefinedLookupType, self).__init__(**kwargs)
예제 #11
0
class InteractiveProcessingType(Serializable):
    """
    The interactive processing information.
    """
    _fields = (
        'GeometricTransform', 'SharpnessEnhancement', 'ColorSpaceTransform',
        'DynamicRangeAdjustment', 'TonalTransferCurve', 'band')
    _required = (
        'GeometricTransform', 'SharpnessEnhancement', 'DynamicRangeAdjustment', 'band')
    _set_as_attribute = ('band', )
    # Descriptor
    GeometricTransform = SerializableDescriptor(
        'GeometricTransform', GeometricTransformType, _required, strict=DEFAULT_STRICT,
        docstring='The geometric transform element is used to perform various geometric distortions '
                  'to each band of image data. These distortions include image '
                  'chipping, scaling, rotation, shearing, etc.')  # type: GeometricTransformType
    SharpnessEnhancement = SerializableDescriptor(
        'SharpnessEnhancement', SharpnessEnhancementType, _required, strict=DEFAULT_STRICT,
        docstring='Sharpness enhancement.')  # type: SharpnessEnhancementType
    ColorSpaceTransform = SerializableDescriptor(
        'ColorSpaceTransform', ColorSpaceTransformType, _required, strict=DEFAULT_STRICT,
        docstring='Color space transform.')  # type: ColorSpaceTransformType
    DynamicRangeAdjustment = SerializableDescriptor(
        'DynamicRangeAdjustment', DynamicRangeAdjustmentType, _required, strict=DEFAULT_STRICT,
        docstring='Specifies the recommended ELT DRA overrides.')  # type: DynamicRangeAdjustmentType
    TonalTransferCurve = SerializableDescriptor(
        'TonalTransferCurve', NewLookupTableType, _required, strict=DEFAULT_STRICT,
        docstring="The 1-D LUT element uses one or more 1-D LUTs to stretch or compress tone data "
                  "in valorous regions within a digital image's dynamic range. 1-D LUT can be "
                  "implemented using a Tonal Transfer Curve (TTC). There are 12 families of TTCs "
                  "- Range = [0, 11]. There are 64 members for each "
                  "family - Range=[0, 63].")  # type: NewLookupTableType
    band = IntegerDescriptor(
        'band', _required, strict=DEFAULT_STRICT,
        docstring='The image band to which this applies.')

    def __init__(self, GeometricTransform=None, SharpnessEnhancement=None,
                 ColorSpaceTransform=None, DynamicRangeAdjustment=None, band=1, **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.GeometricTransform = GeometricTransform
        self.SharpnessEnhancement = SharpnessEnhancement
        self.ColorSpaceTransform = ColorSpaceTransform
        self.DynamicRangeAdjustment = DynamicRangeAdjustment
        self.band = band
        super(InteractiveProcessingType, self).__init__(**kwargs)
예제 #12
0
class NonInteractiveProcessingType(Serializable):
    """
    The non-interactive processing information.
    """

    _fields = ('ProductGenerationOptions', 'RRDS', 'band')
    _required = ('ProductGenerationOptions', 'RRDS', 'band')
    _set_as_attribute = ('band', )
    # Descriptor
    ProductGenerationOptions = SerializableDescriptor(
        'ProductGenerationOptions',
        ProductGenerationOptionsType,
        _required,
        strict=DEFAULT_STRICT,
        docstring=
        'Performs several key actions on an image to prepare it for necessary additional processing to '
        'achieve the desired output product.'
    )  # type: ProductGenerationOptionsType
    RRDS = SerializableDescriptor(
        'RRDS',
        RRDSType,
        _required,
        strict=DEFAULT_STRICT,
        docstring=
        'Creates a set of sub-sampled versions of an image to provide processing chains '
        'with quick access to lower magnification values for faster computation '
        'speeds and performance.')  # type: RRDSType
    band = IntegerDescriptor(
        'band',
        _required,
        strict=DEFAULT_STRICT,
        docstring='The image band to which this applies.')  # type: int

    def __init__(self,
                 ProductGenerationOptions=None,
                 RRDS=None,
                 band=1,
                 **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.ProductGenerationOptions = ProductGenerationOptions
        self.RRDS = RRDS
        self.band = band
        super(NonInteractiveProcessingType, self).__init__(**kwargs)
예제 #13
0
class DigitalElevationDataType(Serializable):
    """
    This describes any Digital Elevation Data included with the SIDD product.
    """

    _fields = ('GeographicCoordinates', 'Geopositioning', 'PositionalAccuracy', 'NullValue')
    _required = ('GeographicCoordinates', 'Geopositioning', 'PositionalAccuracy')
    # Descriptor
    GeographicCoordinates = SerializableDescriptor(
        'GeographicCoordinates', GeographicCoordinatesType, _required, strict=DEFAULT_STRICT,
        docstring='Describes the Local Geographic Coordinate system linking row/column to the '
                  'absolute geographic coordinate (lat/lon)')  # type: GeographicCoordinatesType
    Geopositioning = SerializableDescriptor(
        'Geopositioning', GeopositioningType, _required, strict=DEFAULT_STRICT,
        docstring='Describes the absolute coordinate system to which the data is '
                  'referenced.')  # type: GeopositioningType
    PositionalAccuracy = SerializableDescriptor(
        'PositionalAccuracy', PositionalAccuracyType, _required, strict=DEFAULT_STRICT,
        docstring='Describes the horizontal and vertical point and regional information '
                  'for the DED.')  # type: PositionalAccuracyType
    NullValue = IntegerDescriptor(
        'NullValue', _required, strict=DEFAULT_STRICT,
        docstring='The value in the DEM corresponding to `No Value`.')  # type: Union[None, int]

    def __init__(self, GeographicCoordinates=None, Geopositioning=None, PositionalAccuracy=None,
                 NullValue=None, **kwargs):
        """

        Parameters
        ----------
        GeographicCoordinates : GeographicCoordinatesType
        Geopositioning : GeopositioningType
        PositionalAccuracy : PositionalAccuracyType
        NullValue : int
        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.GeographicCoordinates = GeographicCoordinates
        self.Geopositioning = Geopositioning
        self.PositionalAccuracy = PositionalAccuracy
        self.NullValue = NullValue
        super(DigitalElevationDataType, self).__init__(**kwargs)
예제 #14
0
class PerVectorParameterF8(Serializable):
    _fields = ('Offset', 'Size', 'Format')
    _required = ('Offset', )
    # descriptors
    Offset = IntegerDescriptor('Offset',
                               _required,
                               strict=DEFAULT_STRICT,
                               bounds=(0, None),
                               docstring='The offset value.')  # type: int

    def __init__(self, Offset=None, **kwargs):
        """

        Parameters
        ----------
        Offset : int
        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.Offset = Offset
        super(PerVectorParameterF8, self).__init__(**kwargs)

    @property
    def Size(self):
        """
        int: The size of the vector, constant value 1 here.
        """

        return 1

    @property
    def Format(self):
        """
        str: The format of the vector data, constant value 'F8' here.
        """

        return 'F8'
예제 #15
0
class DynamicRangeAdjustmentType(Serializable):
    """
    The dynamic range adjustment (DRA) parameters.
    """
    _fields = ('AlgorithmType', 'BandStatsSource', 'DRAParameters', 'DRAOverrides')
    _required = ('AlgorithmType', 'BandStatsSource', )
    # Descriptor
    AlgorithmType = StringEnumDescriptor(
        'AlgorithmType', ('AUTO', 'MANUAL', 'NONE'), _required, strict=DEFAULT_STRICT, default_value='NONE',
        docstring='Algorithm used for dynamic range adjustment.')  # type: str
    BandStatsSource = IntegerDescriptor(
        'BandStatsSource', _required, strict=DEFAULT_STRICT,
        docstring='')  # type: int
    DRAParameters = SerializableDescriptor(
        'DRAParameters', DRAParametersType, _required, strict=DEFAULT_STRICT,
        docstring='The dynamic range adjustment parameters.')  # type: DRAParametersType
    DRAOverrides = SerializableDescriptor(
        'DRAOverrides', DRAOverridesType, _required, strict=DEFAULT_STRICT,
        docstring='The dynamic range adjustment overrides.')  # type: DRAOverridesType

    def __init__(self, AlgorithmType='NONE', BandStatsSource=None, DRAParameters=None, DRAOverrides=None, **kwargs):
        """

        Parameters
        ----------
        AlgorithmType : str
        BandStatsSource : int
        DRAParameters : DRAParametersType
        DRAOverrides : DRAOverridesType
        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.AlgorithmType = AlgorithmType
        self.BandStatsSource = BandStatsSource
        self.DRAParameters = DRAParameters
        self.DRAOverrides = DRAOverrides
        super(DynamicRangeAdjustmentType, self).__init__(**kwargs)
예제 #16
0
class RcvChanProcType(Serializable):
    """The Received Processed Channels."""
    _fields = ('NumChanProc', 'PRFScaleFactor', 'ChanIndices')
    _required = ('NumChanProc', 'ChanIndices')
    _collections_tags = {
        'ChanIndices': {'array': False, 'child_tag': 'ChanIndex'}}
    _numeric_format = {'PRFScaleFactor': FLOAT_FORMAT}
    # descriptors
    NumChanProc = IntegerDescriptor(
        'NumChanProc', _required, strict=DEFAULT_STRICT,
        docstring='Number of receive data channels processed to form the image.')  # type: int
    PRFScaleFactor = FloatDescriptor(
        'PRFScaleFactor', _required, strict=DEFAULT_STRICT,
        docstring='Factor indicating the ratio of the effective PRF to the actual PRF.')  # type: float
    ChanIndices = IntegerListDescriptor(
        'ChanIndices', _collections_tags, _required, strict=DEFAULT_STRICT,
        docstring='Index of a data channel that was processed.')  # type: List[int]

    def __init__(self, NumChanProc=None, PRFScaleFactor=None, ChanIndices=None, **kwargs):
        """

        Parameters
        ----------
        NumChanProc : int
        PRFScaleFactor : float
        ChanIndices : List[int]
        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.NumChanProc = NumChanProc
        self.PRFScaleFactor = PRFScaleFactor
        self.ChanIndices = ChanIndices
        super(RcvChanProcType, self).__init__(**kwargs)
예제 #17
0
class CRSDHeader(CRSDHeaderBase):
    _fields = (
        'XML_BLOCK_SIZE', 'XML_BLOCK_BYTE_OFFSET', 'SUPPORT_BLOCK_SIZE', 'SUPPORT_BLOCK_BYTE_OFFSET',
        'PVP_BLOCK_SIZE', 'PVP_BLOCK_BYTE_OFFSET', 'SIGNAL_BLOCK_SIZE', 'SIGNAL_BLOCK_BYTE_OFFSET',
        'CLASSIFICATION', 'RELEASE_INFO')
    _required = (
        'XML_BLOCK_SIZE', 'XML_BLOCK_BYTE_OFFSET', 'PVP_BLOCK_SIZE', 'PVP_BLOCK_BYTE_OFFSET',
        'SIGNAL_BLOCK_SIZE', 'SIGNAL_BLOCK_BYTE_OFFSET', 'CLASSIFICATION', 'RELEASE_INFO')
    # descriptor
    XML_BLOCK_SIZE = IntegerDescriptor(
        'XML_BLOCK_SIZE', _required, strict=True,
        docstring='Size of the XML instance that describes the product in bytes. '
                  'Size does NOT include the 2 bytes of the section terminator.')  # type: int
    XML_BLOCK_BYTE_OFFSET = IntegerDescriptor(
        'XML_BLOCK_BYTE_OFFSET', _required, strict=True,
        docstring='Offset to the first byte of the XML block in bytes.')  # type: int
    SUPPORT_BLOCK_SIZE = IntegerDescriptor(
        'SUPPORT_BLOCK_SIZE', _required, strict=True,
        docstring='Size of the Support block in bytes. Note - If the Support block is omitted, this '
                  'is not included.')  # type: int
    SUPPORT_BLOCK_BYTE_OFFSET = IntegerDescriptor(
        'SUPPORT_BLOCK_BYTE_OFFSET', _required, strict=True,
        docstring='Offset to the first byte of the Support block in bytes. Note - If the Support '
                  'block is omitted, this is not included.')  # type: int
    PVP_BLOCK_SIZE = IntegerDescriptor(
        'PVP_BLOCK_SIZE', _required, strict=True,
        docstring='Size of the PVP block in bytes.')  # type: int
    PVP_BLOCK_BYTE_OFFSET = IntegerDescriptor(
        'PVP_BLOCK_BYTE_OFFSET', _required, strict=True,
        docstring='Offset to the first byte of the PVP block in bytes.')  # type: int
    SIGNAL_BLOCK_SIZE = IntegerDescriptor(
        'SIGNAL_BLOCK_SIZE', _required, strict=True,
        docstring='Size of the Signal block in bytes.')  # type: int
    SIGNAL_BLOCK_BYTE_OFFSET = IntegerDescriptor(
        'SIGNAL_BLOCK_BYTE_OFFSET', _required, strict=True,
        docstring='Offset to the first byte of the Signal block in bytes.')  # type: int
    CLASSIFICATION = StringDescriptor(
        'CLASSIFICATION', _required, strict=True, default_value='UNCLASSIFIED',
        docstring='Product classification information that is human-readable.')  # type: str
    RELEASE_INFO = StringDescriptor(
        'RELEASE_INFO', _required, strict=True, default_value='UNRESTRICTED',
        docstring='Product release information that is human-readable.')  # type: str

    def __init__(self, XML_BLOCK_SIZE=None, XML_BLOCK_BYTE_OFFSET=None,
                 SUPPORT_BLOCK_SIZE=None, SUPPORT_BLOCK_BYTE_OFFSET=None,
                 PVP_BLOCK_SIZE=None, PVP_BLOCK_BYTE_OFFSET=None,
                 SIGNAL_BLOCK_SIZE=None, SIGNAL_BLOCK_BYTE_OFFSET=None,
                 CLASSIFICATION='UNCLASSIFIED', RELEASE_INFO='UNRESTRICTED'):
        self.XML_BLOCK_SIZE = XML_BLOCK_SIZE
        self.XML_BLOCK_BYTE_OFFSET = XML_BLOCK_BYTE_OFFSET
        self.SUPPORT_BLOCK_SIZE = SUPPORT_BLOCK_SIZE
        self.SUPPORT_BLOCK_BYTE_OFFSET = SUPPORT_BLOCK_BYTE_OFFSET
        self.PVP_BLOCK_SIZE = PVP_BLOCK_SIZE
        self.PVP_BLOCK_BYTE_OFFSET = PVP_BLOCK_BYTE_OFFSET
        self.SIGNAL_BLOCK_SIZE = SIGNAL_BLOCK_SIZE
        self.SIGNAL_BLOCK_BYTE_OFFSET = SIGNAL_BLOCK_BYTE_OFFSET
        self.CLASSIFICATION = CLASSIFICATION
        self.RELEASE_INFO = RELEASE_INFO
        super(CRSDHeader, self).__init__()

    def to_string(self):
        """
        Forms a CRSD file header string (not including the section terminator) from populated attributes.
        """
        return ('CRSD/{}\n'.format(_CRSD_SPECIFICATION_VERSION)
                + ''.join(["{} := {}\n".format(f, getattr(self, f))
                           for f in self._fields if getattr(self, f) is not None]))
예제 #18
0
class FiducialInfoType(Serializable):
    _fields = ('NumberOfFiducialsInImage', 'NumberOfFiducialsInScene',
               'LabelSource', 'Fiducials')
    _required = ('NumberOfFiducialsInImage', 'NumberOfFiducialsInScene',
                 'LabelSource', 'Fiducials')
    _collections_tags = {
        'Fiducials': {
            'array': False,
            'child_tag': 'Fiducial'
        }
    }
    # descriptors
    NumberOfFiducialsInImage = IntegerDescriptor(
        'NumberOfFiducialsInImage',
        _required,
        strict=DEFAULT_STRICT,
        docstring='Number of ground truthed objects in the image.'
    )  # type: int
    NumberOfFiducialsInScene = IntegerDescriptor(
        'NumberOfFiducialsInScene',
        _required,
        strict=DEFAULT_STRICT,
        docstring='Number of ground truthed objects in the scene.'
    )  # type: int
    LabelSource = SerializableDescriptor(
        'LabelSource',
        LabelSourceType,
        _required,
        strict=DEFAULT_STRICT,
        docstring='The source of the labels')  # type: LabelSourceType
    Fiducials = SerializableListDescriptor(
        'Fiducials',
        TheFiducialType,
        _collections_tags,
        _required,
        strict=DEFAULT_STRICT,
        docstring='The object collection')  # type: List[TheFiducialType]

    def __init__(self,
                 NumberOfFiducialsInImage=None,
                 NumberOfFiducialsInScene=None,
                 LabelSource=None,
                 Fiducials=None,
                 **kwargs):
        """
        Parameters
        ----------
        NumberOfFiducialsInImage : int
        NumberOfFiducialsInScene : int
        LabelSource : LabelSourceType
        Fiducials : None|List[TheFiducialType]
        kwargs
            Other keyword arguments
        """

        if '_xml_ns' in kwargs:
            self._xml_ns = kwargs['_xml_ns']
        if '_xml_ns_key' in kwargs:
            self._xml_ns_key = kwargs['_xml_ns_key']
        self.NumberOfFiducialsInImage = NumberOfFiducialsInImage
        self.NumberOfFiducialsInScene = NumberOfFiducialsInScene
        self.LabelSource = LabelSource
        self.Fiducials = Fiducials
        super(FiducialInfoType, self).__init__(**kwargs)

    def set_image_location_from_sicd(self,
                                     sicd,
                                     populate_in_periphery=False,
                                     include_out_of_range=False):
        """
        Set the image location information with respect to the given SICD,
        assuming that the physical coordinates are populated. The `NumberOfFiducialsInImage`
        will be set, and `NumberOfFiducialsInScene` will be left unchanged.

        Parameters
        ----------
        sicd : SICDType
        populate_in_periphery : bool
            Populate image information for objects on the periphery?
        include_out_of_range : bool
            Include the objects which are out of range (with no image location information)?
        """
        def update_fiducial(temp_fid, in_image_count):
            status = temp_fid.set_image_location_from_sicd(
                sicd, populate_in_periphery=populate_in_periphery)
            use_fid = False
            if status == 0:
                raise ValueError('Fiducial already has image details set')
            if status == 1 or (status == 2 and populate_in_periphery):
                use_fid = True
                in_image_count += 1
            return use_fid, in_image_count

        fid_in_image = 0
        if include_out_of_range:
            # the fiducials list is just modified in place
            for the_fid in self.Fiducials:
                _, fid_in_image = update_fiducial(the_fid, fid_in_image)
        else:
            # the fiducials list is just modified in place
            fiducials = []
            for the_fid in self.Fiducials:
                use_this_fid, fid_in_image = update_fiducial(
                    the_fid, fid_in_image)
                if use_this_fid:
                    fiducials.append(the_fid)
            self.Fiducials = fiducials
        self.NumberOfFiducialsInImage = fid_in_image
예제 #19
0
class CollectionInfoType(Serializable):
    _fields = ('Name', 'ProgramName', 'Sponsor', 'Date', 'Location',
               'NumberOfSites')
    _required = ()
    # descriptors
    Name = StringDescriptor(
        'Name', _required,
        docstring="Name of the collection.")  # type: Optional[str]
    ProgramName = StringDescriptor(
        'StringDescriptor',
        _required,
        docstring="Name of the program that collected the data."
    )  # type: Optional[str]
    Sponsor = StringDescriptor(
        'Sponsor',
        _required,
        docstring="Sponsoring agency/organization of the data collection."
    )  # type: Optional[str]
    Date = SerializableDescriptor(
        'Date',
        DateRangeType,
        _required,
        strict=DEFAULT_STRICT,
        docstring="Begin and end dates of the data collection."
    )  # type: Optional[DateRangeType]
    Location = SerializableDescriptor(
        'Location',
        LocationType,
        _required,
        strict=DEFAULT_STRICT,
        docstring="General location of the data collection."
    )  # type: Optional[LocationType]
    NumberOfSites = IntegerDescriptor(
        'NumberOfSites',
        _required,
        strict=DEFAULT_STRICT,
        docstring="Number of different sites contained in the data collection."
    )  # type: Optional[int]

    def __init__(self,
                 Name=None,
                 ProgramName=None,
                 Sponsor=None,
                 Date=None,
                 Location=None,
                 NumberOfSites=None,
                 **kwargs):
        """
        Parameters
        ----------
        Name : None|str
        ProgramName : None|str
        Sponsor : None|str
        Date : None|DateRangeType|list|tuple
        Location : None|LocationType
        NumberOfSites : None|int
        kwargs
            Other keyword arguments
        """

        if '_xml_ns' in kwargs:
            self._xml_ns = kwargs['_xml_ns']
        if '_xml_ns_key' in kwargs:
            self._xml_ns_key = kwargs['_xml_ns_key']
        self.Name = Name
        self.ProgramName = ProgramName
        self.Sponsor = Sponsor
        self.Date = Date
        self.Location = Location
        self.NumberOfSites = NumberOfSites
        super(CollectionInfoType, self).__init__(**kwargs)
예제 #20
0
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))
예제 #21
0
class TheFiducialType(Serializable):
    _fields = ('Name', 'SerialNumber', 'FiducialType', 'DatasetFiducialNumber',
               'ImageLocation', 'GeoLocation', 'IPRWidth3dB', 'IPRWidth18dB',
               'IPRWidth3dB18dBRatio', 'PeakSideLobeRatio',
               'IntegratedSideLobeRatio', 'SlantPlane', 'GroundPlane',
               'ProjectionPerturbation')
    _required = ('FiducialType', 'ImageLocation', 'GeoLocation')
    # descriptors
    Name = StringDescriptor(
        'Name',
        _required,
        strict=DEFAULT_STRICT,
        docstring='Name of the fiducial.')  # type: Optional[str]
    SerialNumber = StringDescriptor(
        'SerialNumber',
        _required,
        strict=DEFAULT_STRICT,
        docstring='The serial number of the fiducial')  # type: Optional[str]
    FiducialType = StringDescriptor(
        'FiducialType',
        _required,
        strict=DEFAULT_STRICT,
        docstring='The type of fiducial')  # type: str
    DatasetFiducialNumber = IntegerDescriptor(
        'DatasetFiducialNumber',
        _required,
        docstring='Unique number of the fiducial within the selected dataset, '
        'defined by the RDE system')  # type: Optional[int]
    ImageLocation = SerializableDescriptor(
        'ImageLocation',
        ImageLocationType,
        _required,
        docstring='Center of the fiducial in the image'
    )  # type: Optional[ImageLocationType]
    GeoLocation = SerializableDescriptor(
        'GeoLocation',
        GeoLocationType,
        _required,
        docstring='Real physical location of the fiducial'
    )  # type: Optional[GeoLocationType]
    IPRWidth3dB = SerializableDescriptor(
        'IPRWidth3dB',
        RangeCrossRangeType,
        _required,
        docstring='The 3 dB impulse response width, in meters'
    )  # type: Optional[RangeCrossRangeType]
    IPRWidth18dB = SerializableDescriptor(
        'IPRWidth18dB',
        RangeCrossRangeType,
        _required,
        docstring='The 18 dB impulse response width, in meters'
    )  # type: Optional[RangeCrossRangeType]
    IPRWidth3dB18dBRatio = SerializableDescriptor(
        'IPRWidth3dB18dBRatio',
        RangeCrossRangeType,
        _required,
        docstring='Ratio of the 3 dB to 18 dB system impulse response width'
    )  # type: Optional[RangeCrossRangeType]
    PeakSideLobeRatio = SerializableDescriptor(
        'PeakSideLobeRatio',
        RangeCrossRangeType,
        _required,
        docstring=
        'Ratio of the peak sidelobe intensity to the peak mainlobe intensity, '
        'in dB')  # type: Optional[RangeCrossRangeType]
    IntegratedSideLobeRatio = SerializableDescriptor(
        'IntegratedSideLobeRatio',
        RangeCrossRangeType,
        _required,
        docstring='Ratio of all the energies in the sidelobes of the '
        'system impulse response to the energy in the mainlobe, '
        'in dB')  # type: Optional[RangeCrossRangeType]
    SlantPlane = SerializableDescriptor(
        'SlantPlane',
        PhysicalLocationType,
        _required,
        docstring='Center of the object in the slant plane'
    )  # type: Optional[PhysicalLocationType]
    GroundPlane = SerializableDescriptor(
        'GroundPlane',
        PhysicalLocationType,
        _required,
        docstring='Center of the object in the ground plane'
    )  # type: Optional[PhysicalLocationType]
    ProjectionPerturbation = SerializableDescriptor(
        'ProjectionPerturbation',
        ProjectionPerturbationType,
        _required,
        docstring='')  # type: Optional[ProjectionPerturbationType]

    def __init__(self,
                 Name=None,
                 SerialNumber=None,
                 FiducialType=None,
                 DatasetFiducialNumber=None,
                 ImageLocation=None,
                 GeoLocation=None,
                 IPRWidth3dB=None,
                 IPRWidth18dB=None,
                 IPRWidth3dB18dBRatio=None,
                 PeakSideLobeRatio=None,
                 IntegratedSideLobeRatio=None,
                 SlantPlane=None,
                 GroundPlane=None,
                 ProjectionPerturbation=None,
                 **kwargs):
        """
        Parameters
        ----------
        Name : str
        SerialNumber : None|str
        FiducialType : str
        DatasetFiducialNumber : None|int
        ImageLocation : ImageLocationType
        GeoLocation : GeoLocationType
        IPRWidth3dB : None|RangeCrossRangeType|numpy.ndarray|list|tuple
        IPRWidth18dB : None|RangeCrossRangeType|numpy.ndarray|list|tuple
        IPRWidth3dB18dBRatio : None|RangeCrossRangeType|numpy.ndarray|list|tuple
        PeakSideLobeRatio : None|RangeCrossRangeType|numpy.ndarray|list|tuple
        IntegratedSideLobeRatio : None|RangeCrossRangeType|numpy.ndarray|list|tuple
        SlantPlane : None|PhysicalLocationType
        GroundPlane : None|PhysicalLocationType
        ProjectionPerturbation : None|ProjectionPerturbationType
        kwargs
            Other keyword arguments
        """

        if '_xml_ns' in kwargs:
            self._xml_ns = kwargs['_xml_ns']
        if '_xml_ns_key' in kwargs:
            self._xml_ns_key = kwargs['_xml_ns_key']
        self.Name = Name
        self.SerialNumber = SerialNumber
        self.FiducialType = FiducialType
        self.DatasetFiducialNumber = DatasetFiducialNumber
        self.ImageLocation = ImageLocation
        self.GeoLocation = GeoLocation
        self.IPRWidth3dB = IPRWidth3dB
        self.IPRWidth18dB = IPRWidth18dB
        self.IPRWidth3dB18dBRatio = IPRWidth3dB18dBRatio
        self.PeakSideLobeRatio = PeakSideLobeRatio
        self.IntegratedSideLobeRatio = IntegratedSideLobeRatio
        self.SlantPlane = SlantPlane
        self.GroundPlane = GroundPlane
        self.ProjectionPerturbation = ProjectionPerturbation
        super(TheFiducialType, self).__init__(**kwargs)

    def set_image_location_from_sicd(self, sicd, populate_in_periphery=False):
        """
        Set the image location information with respect to the given SICD.

        Parameters
        ----------
        sicd : SICDType

        Returns
        -------
        int
            -1 - insufficient metadata to proceed
            0 - nothing to be done
            1 - successful
            2 - object in image periphery, not populating
            3 - object not in image field
        """

        if self.ImageLocation is not None or self.SlantPlane is not None:
            # no need to infer anything, it's already populated
            return 0

        if self.GeoLocation is None:
            logger.warning('GeoLocation is not populated,\n\t'
                           'so the image location can not be inferred')
            return -1

        if not sicd.can_project_coordinates():
            logger.warning(_no_projection_text)
            return -1

        image_location = ImageLocationType.from_geolocation(
            self.GeoLocation, sicd)
        # check bounding information
        rows = sicd.ImageData.NumRows
        cols = sicd.ImageData.NumCols
        center_pixel = image_location.CenterPixel.get_array(dtype='float64')

        if (0 < center_pixel[0] < rows - 1) and (0 < center_pixel[1] <
                                                 cols - 1):
            placement = 1
        elif (-3 < center_pixel[0] < rows + 2) and (-3 < center_pixel[1] <
                                                    cols + 2):
            placement = 2
        else:
            placement = 3

        if placement == 3 or (placement == 2 and not populate_in_periphery):
            return placement

        self.ImageLocation = image_location
        self.SlantPlane = PhysicalLocationType(Physical=image_location)
        return placement

    def set_geo_location_from_sicd(self,
                                   sicd,
                                   projection_type='HAE',
                                   **proj_kwargs):
        """
        Set the geographical location information with respect to the given SICD,
        assuming that the image coordinates are populated.

        .. Note::
            This assumes that the image coordinates are with respect to the given
            image (chip), and NOT including any sicd.ImageData.FirstRow/Col values,
            which will be added here.

        Parameters
        ----------
        sicd : SICDType
        projection_type : str
            The projection type selector, one of `['PLANE', 'HAE', 'DEM']`. Using `'DEM'`
            requires configuration for the DEM pathway described in
            :func:`sarpy.geometry.point_projection.image_to_ground_dem`.
        proj_kwargs
            The keyword arguments for the :func:`SICDType.project_image_to_ground_geo` method.
        """

        if self.GeoLocation is not None:
            # no need to infer anything, it's already populated
            return

        if self.ImageLocation is None:
            logger.warning('ImageLocation is not populated,\n\t'
                           'so the geographical location can not be inferred')
            return

        if not sicd.can_project_coordinates():
            logger.warning(_no_projection_text)
            return

        self.GeoLocation = GeoLocationType.from_image_location(
            self.ImageLocation,
            sicd,
            projection_type=projection_type,
            **proj_kwargs)
예제 #22
0
파일: Timeline.py 프로젝트: ngageoint/sarpy
class IPPSetType(Serializable):
    """
    The Inter-Pulse Parameter array element container.
    """

    # NOTE that this is simply defined as a child class ("Set") of the TimelineType in the SICD standard
    #   Defining it at root level clarifies the documentation, and giving it a more descriptive name is
    #   appropriate.
    _fields = ('TStart', 'TEnd', 'IPPStart', 'IPPEnd', 'IPPPoly', 'index')
    _required = _fields
    _set_as_attribute = ('index', )
    _numeric_format = {
        'TStart': FLOAT_FORMAT,
        'TEnd': FLOAT_FORMAT,
    }
    # descriptors
    TStart = FloatDescriptor(
        'TStart',
        _required,
        strict=DEFAULT_STRICT,
        docstring=
        'IPP start time relative to collection start time, i.e. offsets in seconds.'
    )  # type: float
    TEnd = FloatDescriptor(
        'TEnd',
        _required,
        strict=DEFAULT_STRICT,
        docstring=
        'IPP end time relative to collection start time, i.e. offsets in seconds.'
    )  # type: float
    IPPStart = IntegerDescriptor(
        'IPPStart',
        _required,
        strict=True,
        docstring='Starting IPP index for the period described.')  # type: int
    IPPEnd = IntegerDescriptor(
        'IPPEnd',
        _required,
        strict=True,
        docstring='Ending IPP index for the period described.')  # type: int
    IPPPoly = SerializableDescriptor(
        'IPPPoly',
        Poly1DType,
        _required,
        strict=DEFAULT_STRICT,
        docstring=
        'IPP index polynomial coefficients yield IPP index as a function of time.'
    )  # type: Poly1DType
    index = IntegerDescriptor(
        'index',
        _required,
        strict=DEFAULT_STRICT,
        docstring='The element array index.')  # type: int

    def __init__(self,
                 TStart=None,
                 TEnd=None,
                 IPPStart=None,
                 IPPEnd=None,
                 IPPPoly=None,
                 index=None,
                 **kwargs):
        """

        Parameters
        ----------
        TStart : float
        TEnd : float
        IPPStart : int
        IPPEnd : int
        IPPPoly : Poly1DType|numpy.ndarray|list|tuple
        index : int
        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.TStart, self.TEnd = TStart, TEnd
        self.IPPStart, self.IPPEnd = IPPStart, IPPEnd
        self.IPPPoly = IPPPoly
        self.index = index
        super(IPPSetType, self).__init__(**kwargs)

    def _basic_validity_check(self):
        condition = super(IPPSetType, self)._basic_validity_check()
        if self.TStart >= self.TEnd:
            self.log_validity_error('TStart ({}) >= TEnd ({})'.format(
                self.TStart, self.TEnd))
            condition = False

        if self.IPPStart >= self.IPPEnd:
            self.log_validity_error('IPPStart ({}) >= IPPEnd ({})'.format(
                self.IPPStart, self.IPPEnd))
            condition = False

        exp_ipp_start = self.IPPPoly(self.TStart)
        exp_ipp_end = self.IPPPoly(self.TEnd)
        if abs(exp_ipp_start - self.IPPStart) > 1:
            self.log_validity_error(
                'IPPStart populated as {}, inconsistent with value ({}) '
                'derived from IPPPoly and TStart'.format(
                    exp_ipp_start, self.IPPStart))
        if abs(exp_ipp_end - self.IPPEnd) > 1:
            self.log_validity_error(
                'IPPEnd populated as {}, inconsistent with value ({}) '
                'derived from IPPPoly and TEnd'.format(self.IPPEnd,
                                                       exp_ipp_end))
        return condition
예제 #23
0
class ParametersType(Serializable):
    """
    Channel dependent parameters.
    """

    _fields = ('SRP_Index', 'NomTOARateSF', 'FxCtrNom', 'BWSavedNom',
               'TOASavedNom', 'TxAnt_Index', 'RcvAnt_Index', 'TWAnt_Index')
    _required = ('SRP_Index', 'NomTOARateSF', 'FxCtrNom', 'BWSavedNom',
                 'TOASavedNom')
    _numeric_format = {
        'NomTOARateSF': FLOAT_FORMAT,
        'FxCtrNom': FLOAT_FORMAT,
        'BWSavedNom': FLOAT_FORMAT,
        'TOASavedNom': FLOAT_FORMAT
    }
    # descriptors
    SRP_Index = IntegerDescriptor(
        'SRP_Index',
        _required,
        strict=DEFAULT_STRICT,
        docstring='Index to identify the SRP position function used for the '
        'channel.')  # type: int
    NomTOARateSF = FloatDescriptor(
        'NomTOARateSF',
        _required,
        strict=DEFAULT_STRICT,
        docstring=
        'Scale factor to indicate the fraction of the Doppler spectrum '
        'that is clear.')  # type: float
    FxCtrNom = FloatDescriptor(
        'FxCtrNom',
        _required,
        strict=DEFAULT_STRICT,
        docstring=
        'Nominal center transmit frequency associated with the channel (Hz). '
        'For DomainType = TOA, FxCtrNom is the center frequency for all '
        'vectors.')  # type: float
    BWSavedNom = FloatDescriptor(
        'BWSavedNom',
        _required,
        strict=DEFAULT_STRICT,
        docstring='Nominal transmit bandwidth associated with the channel (Hz). '
        'For DomainType = TOA, BWSavedNom is the bandwidth saved for all '
        'vectors.')  # type: float
    TOASavedNom = FloatDescriptor(
        'TOASavedNom',
        _required,
        strict=DEFAULT_STRICT,
        docstring=
        'Nominal span in TOA saved for the channel. For DomainType = FX, '
        'TOASavedNom is the bandwidth saved for all '
        'vectors.')  # type: float
    TxAnt_Index = IntegerDescriptor(
        'TxAnt_Index',
        _required,
        strict=DEFAULT_STRICT,
        docstring=
        'Indicates the Transmit Antenna pattern for data collected to form '
        'the CPHD channel.')  # type: Union[None, int]
    RcvAnt_Index = IntegerDescriptor(
        'RcvAnt_Index',
        _required,
        strict=DEFAULT_STRICT,
        docstring=
        'Indicates the Receive Antenna pattern for data collected to form '
        'the CPHD channel.')  # type: Union[None, int]
    TWAnt_Index = IntegerDescriptor(
        'TWAnt_Index',
        _required,
        strict=DEFAULT_STRICT,
        docstring=
        'Indicates the T wo-way Antenna pattern for data collected to form '
        'the CPHD channel.')  # type: Union[None, int]

    def __init__(self,
                 SRP_Index=None,
                 NomTOARateSF=None,
                 FxCtrNom=None,
                 BWSavedNom=None,
                 TOASavedNom=None,
                 TxAnt_Index=None,
                 RcvAnt_Index=None,
                 TWAnt_Index=None,
                 **kwargs):
        """

        Parameters
        ----------
        SRP_Index : int
        NomTOARateSF : float
        FxCtrNom : float
        BWSavedNom : float
        TOASavedNom : float
        TxAnt_Index : None|int
        RcvAnt_Index : None|int
        TWAnt_Index : None|int
        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.SRP_Index = SRP_Index
        self.NomTOARateSF = NomTOARateSF
        self.FxCtrNom = FxCtrNom
        self.BWSavedNom = BWSavedNom
        self.TOASavedNom = TOASavedNom
        self.TxAnt_Index = TxAnt_Index
        self.RcvAnt_Index = RcvAnt_Index
        self.TWAnt_Index = TWAnt_Index
        super(ParametersType, self).__init__(**kwargs)
예제 #24
0
class ImageInfoType(Serializable):
    _fields = ('DataFilename', 'ClassificationMarkings', 'Filetype',
               'DataCheckSum', 'DataSize', 'DataPlane', 'DataDomain',
               'DataType', 'BitsPerSample', 'DataFormat', 'DataByteOrder',
               'NumPixels', 'ImageCollectionDate', 'ZuluOffset',
               'SensorReferencePoint', 'SensorCalibrationFactor',
               'DataCalibrated', 'Resolution', 'PixelSpacing', 'WeightingType',
               'OverSamplingFactor', 'IPRWidth3dB', 'ImageQualityDescription',
               'ImageHeading', 'ImageCorners', 'SlantPlane', 'GroundPlane',
               'SceneCenterReferenceLine', 'ProjectionPerturbation')
    _required = ('DataFilename', 'ClassificationMarkings', 'DataCheckSum',
                 'DataPlane', 'DataDomain', 'DataType', 'DataFormat',
                 'NumPixels', 'ImageCollectionDate', 'SensorReferencePoint',
                 'DataCalibrated', 'Resolution', 'PixelSpacing',
                 'WeightingType', 'ImageCorners')
    _numeric_format = {
        'ImageHeading': '0.17G',
        'SensorCalibrationFactor': '0.17G',
        'SceneCenterReferenceLine': '0.17G',
    }
    # descriptors
    DataFilename = StringDescriptor(
        'DataFilename',
        _required,
        docstring='The base file name to which this information pertains'
    )  # type: str
    ClassificationMarkings = SerializableDescriptor(
        'ClassificationMarkings',
        ClassificationMarkingsType,
        _required,
        docstring='The classification information'
    )  # type: ClassificationMarkingsType
    Filetype = StringDescriptor(
        'Filetype', _required,
        docstring='The image file type')  # type: Optional[str]
    DataCheckSum = StringDescriptor(
        'DataCheckSum',
        _required,
        docstring='The 32 character (hexidecimal digest) MD5 checksum of the '
        'full image file')  # type: str
    DataSize = IntegerDescriptor(
        'DataSize', _required,
        docstring='The image size in bytes')  # type: Optional[int]
    DataPlane = StringEnumDescriptor('DataPlane', {'Slant', 'Ground'},
                                     _required,
                                     default_value='Slant',
                                     docstring='The image plane.')  # type: str
    DataDomain = StringEnumDescriptor(
        'DataDomain',
        {
            'Image',
        },
        _required,  # todo: values
        docstring='The image data domain')  # type: str
    DataType = StringEnumDescriptor(
        'DataType', {'Magnitude/Phase', 'In-phase/Quadrature'},
        _required,
        docstring='The image data type')  # type: str
    BitsPerSample = IntegerDescriptor(
        'BitsPerSample', _required,
        docstring='The number of bits per sample')  # type: Optional[int]
    DataFormat = StringDescriptor(
        'DataFormat', _required,
        docstring='The image data format')  # type: str
    DataByteOrder = StringEnumDescriptor(
        'DataByteOrder', {'Big-Endian', 'Little-Endian'},
        _required,
        docstring='The image data byte order.')  # type: Optional[str]
    NumPixels = SerializableDescriptor(
        'NumPixels',
        NumPixelsType,
        _required,
        docstring='The number of image pixels')  # type: NumPixelsType
    ImageCollectionDate = DateTimeDescriptor(
        'ImageCollectionDate',
        _required,
        docstring='The date/time of the image collection in UTC'
    )  # type: Optional[numpy.datetime64]
    ZuluOffset = StringDescriptor(
        'ZuluOffset', _required,
        docstring='The local time offset from UTC')  # type: Optional[str]
    SensorReferencePoint = StringEnumDescriptor(
        'DataPlane', {'Left', 'Right', 'Top', 'Bottom'},
        _required,
        docstring='Description of the sensor location relative to the scene.'
    )  # type: Optional[str]
    SensorCalibrationFactor = FloatDescriptor(
        'SensorCalibrationFactor',
        _required,
        docstring=
        'Multiplicative factor used to scale raw image data to the return '
        'of a calibrated reference reflector or active source'
    )  # type: Optional[float]
    DataCalibrated = BooleanDescriptor(
        'DataCalibrated', _required,
        docstring='Has the data been calibrated?')  # type: bool
    Resolution = SerializableDescriptor(
        'Resolution',
        RangeCrossRangeType,
        _required,
        docstring='Resolution (intrinsic) of the sensor system/mode in meters.'
    )  # type: RangeCrossRangeType
    PixelSpacing = SerializableDescriptor(
        'PixelSpacing',
        RangeCrossRangeType,
        _required,
        docstring='Pixel spacing of the image in meters.'
    )  # type: RangeCrossRangeType
    WeightingType = SerializableDescriptor(
        'WeightingType',
        StringRangeCrossRangeType,
        _required,
        docstring='Weighting function applied to the image during formation.'
    )  # type: StringRangeCrossRangeType
    OverSamplingFactor = SerializableDescriptor(
        'OverSamplingFactor',
        RangeCrossRangeType,
        _required,
        docstring='The factor by which the pixel space is oversampled.'
    )  # type: Optional[RangeCrossRangeType]
    IPRWidth3dB = SerializableDescriptor(
        'IPRWidth3dB',
        RangeCrossRangeType,
        _required,
        docstring='The 3 dB system impulse response with, in meters'
    )  # type: Optional[RangeCrossRangeType]
    ImageQualityDescription = StringDescriptor(
        'ImageQualityDescription',
        _required,
        docstring='General description of image quality'
    )  # type: Optional[str]
    ImageHeading = FloatDescriptor(
        'ImageHeading',
        _required,
        docstring='Image heading relative to True North, in degrees'
    )  # type: Optional[float]
    ImageCorners = SerializableDescriptor(
        'ImageCorners',
        ImageCornerType,
        _required,
        docstring='The image corners')  # type: ImageCornerType
    SlantPlane = SerializableDescriptor(
        'SlantPlane',
        PixelSpacingType,
        _required,
        docstring='The slant plane pixel spacing'
    )  # type: Optional[PixelSpacingType]
    GroundPlane = SerializableDescriptor(
        'GroundPlane',
        PixelSpacingType,
        _required,
        docstring='The ground plane pixel spacing'
    )  # type: Optional[PixelSpacingType]
    SceneCenterReferenceLine = FloatDescriptor(
        'SceneCenterReferenceLine',
        _required,
        docstring='The ideal line (heading) at the intersection of the radar '
        'line-of-sight with the horizontal reference plane '
        'created by the forward motion of the aircraft, '
        'in degrees')  # type: Optional[float]
    ProjectionPerturbation = SerializableDescriptor(
        'ProjectionPerturbation',
        ProjectionPerturbationType,
        _required,
        docstring='')  # type: Optional[ProjectionPerturbationType]

    def __init__(self,
                 DataFilename=None,
                 ClassificationMarkings=None,
                 FileType=None,
                 DataCheckSum=None,
                 DataSize=None,
                 DataPlane='Slant',
                 DataDomain=None,
                 DataType=None,
                 BitsPerSample=None,
                 DataFormat=None,
                 DataByteOrder=None,
                 NumPixels=None,
                 ImageCollectionDate=None,
                 ZuluOffset=None,
                 SensorReferencePoint=None,
                 SensorCalibrationFactor=None,
                 DataCalibrated=None,
                 Resolution=None,
                 PixelSpacing=None,
                 WeightingType=None,
                 OverSamplingFactor=None,
                 IPRWidth3dB=None,
                 ImageQualityDescription=None,
                 ImageHeading=None,
                 ImageCorners=None,
                 SlantPlane=None,
                 GroundPlane=None,
                 SceneCenterReferenceLine=None,
                 ProjectionPerturbation=None,
                 **kwargs):
        """
        Parameters
        ----------
        DataFilename : str
        ClassificationMarkings : ClassificationMarkingsType
        FileType : str
        DataCheckSum : str
        DataSize : int
        DataPlane : str
        DataDomain : None|str
        DataType : None|str
        BitsPerSample : None|int
        DataFormat : None|str
        DataByteOrder : None|str
        NumPixels : NumPixelsType|numpy.ndarray|list|tuple
        ImageCollectionDate : numpy.datetime64|datetime|date|str
        ZuluOffset : None|str
        SensorReferencePoint : None|str
        SensorCalibrationFactor : None|float
        DataCalibrated : bool
        Resolution : RangeCrossRangeType|numpy.ndarray|list|tuple
        PixelSpacing : RangeCrossRangeType|numpy.ndarray|list|tuple
        WeightingType : StringRangeCrossRangeType
        OverSamplingFactor : None|RangeCrossRangeType
        IPRWidth3dB : None|RangeCrossRangeType|numpy.ndarray|list|tuple
        ImageQualityDescription : None|str
        ImageHeading : None|float
        ImageCorners : ImageCornerType
        SlantPlane : None|PixelSpacingType
        GroundPlane : None|PixelSpacingType
        SceneCenterReferenceLine : None|float
        ProjectionPerturbation : None|ProjectionPerturbationType
        kwargs
            Other keyword arguments
        """

        if '_xml_ns' in kwargs:
            self._xml_ns = kwargs['_xml_ns']
        if '_xml_ns_key' in kwargs:
            self._xml_ns_key = kwargs['_xml_ns_key']

        self.DataFilename = DataFilename

        if ClassificationMarkings is None:
            self.ClassificationMarkings = ClassificationMarkingsType()
        else:
            self.ClassificationMarkings = ClassificationMarkings

        self.Filetype = FileType
        self.DataCheckSum = DataCheckSum
        self.DataSize = DataSize
        self.DataPlane = DataPlane
        self.DataDomain = DataDomain
        self.DataType = DataType

        self.BitsPerSample = BitsPerSample
        self.DataFormat = DataFormat
        self.DataByteOrder = DataByteOrder
        self.NumPixels = NumPixels
        self.ImageCollectionDate = ImageCollectionDate
        self.ZuluOffset = ZuluOffset

        self.SensorReferencePoint = SensorReferencePoint
        self.SensorCalibrationFactor = SensorCalibrationFactor
        self.DataCalibrated = DataCalibrated
        self.Resolution = Resolution
        self.PixelSpacing = PixelSpacing
        self.WeightingType = WeightingType
        self.OverSamplingFactor = OverSamplingFactor
        self.IPRWidth3dB = IPRWidth3dB

        self.ImageQualityDescription = ImageQualityDescription
        self.ImageHeading = ImageHeading
        self.ImageCorners = ImageCorners
        self.SlantPlane = SlantPlane
        self.GroundPlane = GroundPlane
        self.SceneCenterReferenceLine = SceneCenterReferenceLine
        self.ProjectionPerturbation = ProjectionPerturbation
        super(ImageInfoType, self).__init__(**kwargs)

    @classmethod
    def from_sicd(cls,
                  sicd,
                  base_file_name,
                  file_type='NITF02.10',
                  md5_checksum=None):
        """
        Construct the ImageInfo from the sicd object and given image file name.

        Parameters
        ----------
        sicd : SICDType
        base_file_name : str
        file_type : str
            The file type. This should probably always be NITF02.10 for now.
        md5_checksum : None|str
            The md5 checksum of the full image file.

        Returns
        -------
        ImageInfoType
        """

        pixel_type = sicd.ImageData.PixelType
        if pixel_type == 'RE32F_IM32F':
            data_type = 'In-phase/Quadrature'
            bits_per_sample = 32
            data_format = 'float'
        elif pixel_type == 'RE16I_IM16I':
            data_type = 'In-phase/Quadrature'
            bits_per_sample = 16
            data_format = 'integer'
        elif pixel_type == 'AMP8I_PHS8I':
            data_type = 'Magnitude/Phase'
            bits_per_sample = 8
            data_format = 'unsigned integer'
        else:
            raise ValueError('Unhandled')

        data_cal = sicd.Radiometric is not None

        icps = ImageCornerType(UpperLeft=sicd.GeoData.ImageCorners.FRFC,
                               UpperRight=sicd.GeoData.ImageCorners.FRLC,
                               LowerRight=sicd.GeoData.ImageCorners.LRLC,
                               LowerLeft=sicd.GeoData.ImageCorners.LRFC)

        if sicd.Grid.ImagePlane == 'SLANT':
            data_plane = 'Slant'
        elif sicd.Grid.ImagePlane == 'Ground':
            data_plane = 'Ground'
        else:
            data_plane = None

        has_perturb = False
        proj_perturb = None
        coa = sicd.coa_projection
        if coa is not None:
            delta_arp = coa.delta_arp
            if numpy.any(delta_arp != 0):
                has_perturb = True
            else:
                delta_arp = None

            delta_varp = coa.delta_varp
            if numpy.any(delta_varp != 0):
                has_perturb = True
            else:
                delta_varp = None

            delta_range = coa.delta_range
            if delta_range != 0:
                has_perturb = True
            else:
                delta_range = None

            if has_perturb:
                proj_perturb = ProjectionPerturbationType(
                    CoordinateFrame='ECF',
                    DeltaArp=delta_arp,
                    DeltaVarp=delta_varp,
                    DeltaRange=delta_range)

        return ImageInfoType(
            DataFilename=base_file_name,
            ClassificationMarkings=ClassificationMarkingsType(
                Classification=sicd.CollectionInfo.Classification),
            FileType=file_type,
            DataCheckSum=md5_checksum,
            DataPlane=data_plane,
            DataType=data_type,
            DataCalibrated=data_cal,
            BitsPerSample=bits_per_sample,
            DataDomain='Image',
            DataFormat=data_format,
            DataByteOrder='Big-Endian',
            NumPixels=(sicd.ImageData.NumRows, sicd.ImageData.NumCols),
            ImageCollectionDate=sicd.Timeline.CollectStart,
            SensorReferencePoint='Top',
            Resolution=(sicd.Grid.Row.ImpRespWid, sicd.Grid.Col.ImpRespWid),
            PixelSpacing=(sicd.Grid.Row.SS, sicd.Grid.Col.SS),
            WeightingType=StringRangeCrossRangeType(
                Range=sicd.Grid.Row.WgtType.WindowName,
                CrossRange=sicd.Grid.Col.WgtType.WindowName),
            ImageHeading=sicd.SCPCOA.AzimAng,
            ImageCorners=icps,
            ProjectionPerturbation=proj_perturb)
예제 #25
0
파일: CPHD.py 프로젝트: kirkjens/sarpy
class CPHDHeader(CPHDHeaderBase):
    _fields = ('XML_DATA_SIZE', 'XML_BYTE_OFFSET', 'VB_DATA_SIZE',
               'VB_BYTE_OFFSET', 'CPHD_DATA_SIZE', 'CPHD_BYTE_OFFSET',
               'CLASSIFICATION', 'RELEASE_INFO')
    _required = ('XML_DATA_SIZE', 'XML_BYTE_OFFSET', 'VB_DATA_SIZE',
                 'VB_BYTE_OFFSET', 'CPHD_DATA_SIZE', 'CPHD_BYTE_OFFSET')
    # descriptor
    XML_DATA_SIZE = IntegerDescriptor(
        'XML_DATA_SIZE',
        _required,
        strict=True,
        docstring=
        'Size of the XML Metadata in bytes. Does not include the 2 bytes '
        'of the section terminator.')  # type: int
    XML_BYTE_OFFSET = IntegerDescriptor(
        'XML_BYTE_OFFSET',
        _required,
        strict=True,
        docstring='Offset to the first byte of the XML Metadata in bytes.'
    )  # type: int
    VB_DATA_SIZE = IntegerDescriptor(
        'VB_DATA_SIZE',
        _required,
        strict=True,
        docstring='Size of the Vector Based Metadata in bytes.')  # type: int
    VB_BYTE_OFFSET = IntegerDescriptor(
        'VB_BYTE_OFFSET',
        _required,
        strict=True,
        docstring=
        'Offset to the first byte of the Vector Based Metadata in bytes.'
    )  # type: int
    CPHD_DATA_SIZE = IntegerDescriptor(
        'CPHD_DATA_SIZE',
        _required,
        strict=True,
        docstring='Size of the Compensated PHD arrays in bytes.')  # type: int
    CPHD_BYTE_OFFSET = IntegerDescriptor(
        'CPHD_BYTE_OFFSET',
        _required,
        strict=True,
        docstring='Offset to the first byte of the CPHD data in bytes.'
    )  # type: int
    CLASSIFICATION = StringDescriptor(
        'CLASSIFICATION',
        _required,
        strict=True,
        default_value='UNCLASSIFIED',
        docstring=
        'Product classification information that is the human-readable banner.'
    )  # type: str
    RELEASE_INFO = StringDescriptor(
        'RELEASE_INFO',
        _required,
        strict=True,
        default_value='UNRESTRICTED',
        docstring='Product release information.')  # type: str

    def __init__(self,
                 XML_DATA_SIZE=None,
                 XML_BYTE_OFFSET=None,
                 VB_DATA_SIZE=None,
                 VB_BYTE_OFFSET=None,
                 CPHD_DATA_SIZE=None,
                 CPHD_BYTE_OFFSET=None,
                 CLASSIFICATION='UNCLASSIFIED',
                 RELEASE_INFO='UNRESTRICTED'):
        self.XML_DATA_SIZE = XML_DATA_SIZE
        self.XML_BYTE_OFFSET = XML_BYTE_OFFSET
        self.VB_DATA_SIZE = VB_DATA_SIZE
        self.VB_BYTE_OFFSET = VB_BYTE_OFFSET
        self.CPHD_DATA_SIZE = CPHD_DATA_SIZE
        self.CPHD_BYTE_OFFSET = CPHD_BYTE_OFFSET
        self.CLASSIFICATION = CLASSIFICATION
        self.RELEASE_INFO = RELEASE_INFO
        super(CPHDHeader, self).__init__()
예제 #26
0
class NumPixelsType(Serializable, Arrayable):
    """A row and column attribute container - used as indices into array(s)."""
    _fields = ('NumRows', 'NumCols')
    _required = _fields
    NumRows = IntegerDescriptor('NumRows',
                                _required,
                                strict=True,
                                docstring='The number of rows.')  # type: int
    NumCols = IntegerDescriptor(
        'NumCols', _required, strict=True,
        docstring='The number of columns.')  # type: int

    def __init__(self, NumRows=None, NumCols=None, **kwargs):
        """
        Parameters
        ----------
        NumRows : int
        NumCols : int
        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.NumRows, self.NumCols = NumRows, NumCols
        super(NumPixelsType, self).__init__(**kwargs)

    def get_array(self, dtype=numpy.int64):
        """
        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 [NumRows, NumCols]
        """

        return numpy.array([self.NumRows, self.NumCols], dtype=dtype)

    @classmethod
    def from_array(cls, array):
        """
        Create from an array type entry.

        Parameters
        ----------
        array: numpy.ndarray|list|tuple
            assumed [NumRows, NumCols]

        Returns
        -------
        NumPixelsType
        """
        if array is None:
            return None
        if isinstance(array, (numpy.ndarray, list, tuple)):
            if len(array) < 2:
                raise ValueError(
                    'Expected array to be of length 2, and received {}'.format(
                        array))
            return cls(NumRows=array[0], NumCols=array[1])
        raise ValueError(
            'Expected array to be numpy.ndarray, list, or tuple, got {}'.
            format(type(array)))
예제 #27
0
class FullImageType(Serializable, Arrayable):
    """
    The full image product attributes.
    """

    _fields = ('NumRows', 'NumCols')
    _required = _fields
    # descriptors
    NumRows = IntegerDescriptor(
        'NumRows',
        _required,
        strict=True,
        docstring=
        'Number of rows in the original full image product. May include zero pixels.'
    )  # type: int
    NumCols = IntegerDescriptor(
        'NumCols',
        _required,
        strict=True,
        docstring=
        'Number of columns in the original full image product. May include zero pixels.'
    )  # type: int

    def __init__(self, NumRows=None, NumCols=None, **kwargs):
        """

        Parameters
        ----------
        NumRows : int
        NumCols : int
        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.NumRows, self.NumCols = NumRows, NumCols
        super(FullImageType, self).__init__(**kwargs)

    def get_array(self, dtype=numpy.int64):
        """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 `[X,Y,Z]`
        """

        return numpy.array([self.NumRows, self.NumCols], dtype=dtype)

    @classmethod
    def from_array(cls, array):
        """
        Create from an array type entry.

        Parameters
        ----------
        array: numpy.ndarray|list|tuple
            assumed `[NumRows, NumCols]`

        Returns
        -------
        FullImageType
        """

        if isinstance(array, (numpy.ndarray, list, tuple)):
            if len(array) < 2:
                raise ValueError(
                    'Expected array to be of length 2, and received {}'.format(
                        array))
            return cls(NumRows=array[0], NumCols=array[1])
        raise ValueError(
            'Expected array to be numpy.ndarray, list, or tuple, got {}'.
            format(type(array)))
예제 #28
0
class ImageDataType(Serializable):
    """The image pixel data."""
    _collections_tags = {
        'AmpTable': {
            'array': True,
            'child_tag': 'Amplitude'
        },
        'ValidData': {
            'array': True,
            'child_tag': 'Vertex'
        },
    }
    _fields = ('PixelType', 'AmpTable', 'NumRows', 'NumCols', 'FirstRow',
               'FirstCol', 'FullImage', 'SCPPixel', 'ValidData')
    _required = ('PixelType', 'NumRows', 'NumCols', 'FirstRow', 'FirstCol',
                 'FullImage', 'SCPPixel')
    _numeric_format = {'AmpTable': FLOAT_FORMAT}
    _PIXEL_TYPE_VALUES = ("RE32F_IM32F", "RE16I_IM16I", "AMP8I_PHS8I")
    # descriptors
    PixelType = StringEnumDescriptor(
        'PixelType',
        _PIXEL_TYPE_VALUES,
        _required,
        strict=True,
        docstring=
        "The PixelType attribute which specifies the interpretation of the file data."
    )  # type: str
    AmpTable = FloatArrayDescriptor(
        'AmpTable',
        _collections_tags,
        _required,
        strict=DEFAULT_STRICT,
        minimum_length=256,
        maximum_length=256,
        docstring="The amplitude look-up table. This is required if "
        "`PixelType == 'AMP8I_PHS8I'`")  # type: numpy.ndarray
    NumRows = IntegerDescriptor(
        'NumRows',
        _required,
        strict=True,
        docstring='The number of Rows in the product. May include zero rows.'
    )  # type: int
    NumCols = IntegerDescriptor(
        'NumCols',
        _required,
        strict=True,
        docstring='The number of Columns in the product. May include zero rows.'
    )  # type: int
    FirstRow = IntegerDescriptor(
        'FirstRow',
        _required,
        strict=DEFAULT_STRICT,
        docstring='Global row index of the first row in the product. '
        'Equal to 0 in full image product.')  # type: int
    FirstCol = IntegerDescriptor(
        'FirstCol',
        _required,
        strict=DEFAULT_STRICT,
        docstring='Global column index of the first column in the product. '
        'Equal to 0 in full image product.')  # type: int
    FullImage = SerializableDescriptor(
        'FullImage',
        FullImageType,
        _required,
        strict=DEFAULT_STRICT,
        docstring='Original full image product.')  # type: FullImageType
    SCPPixel = SerializableDescriptor(
        'SCPPixel',
        RowColType,
        _required,
        strict=DEFAULT_STRICT,
        docstring=
        'Scene Center Point pixel global row and column index. Should be located near the '
        'center of the full image.')  # type: RowColType
    ValidData = SerializableArrayDescriptor(
        'ValidData',
        RowColArrayElement,
        _collections_tags,
        _required,
        strict=DEFAULT_STRICT,
        minimum_length=3,
        docstring=
        'Indicates the full image includes both valid data and some zero filled pixels. '
        'Simple polygon encloses the valid data (may include some zero filled pixels for simplification). '
        'Vertices in clockwise order.'
    )  # type: Union[SerializableArray, List[RowColArrayElement]]

    def __init__(self,
                 PixelType=None,
                 AmpTable=None,
                 NumRows=None,
                 NumCols=None,
                 FirstRow=None,
                 FirstCol=None,
                 FullImage=None,
                 SCPPixel=None,
                 ValidData=None,
                 **kwargs):
        """

        Parameters
        ----------
        PixelType : str
        AmpTable : numpy.ndarray|list|tuple
        NumRows : int
        NumCols : int
        FirstRow : int
        FirstCol : int
        FullImage : FullImageType|numpy.ndarray|list|tuple
        SCPPixel : RowColType|numpy.ndarray|list|tuple
        ValidData : SerializableArray|List[RowColArrayElement]|numpy.ndarray|list|tuple
        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.AmpTable = AmpTable
        self.NumRows, self.NumCols = NumRows, NumCols
        self.FirstRow, self.FirstCol = FirstRow, FirstCol
        self.FullImage = FullImage
        self.SCPPixel = SCPPixel
        self.ValidData = ValidData
        super(ImageDataType, self).__init__(**kwargs)

    def _check_valid_data(self):
        if self.ValidData is None:
            return True
        if len(self.ValidData) < 2:
            return True

        value = True
        valid_data = self.ValidData.get_array(dtype='float64')
        lin_ring = LinearRing(coordinates=valid_data)
        area = lin_ring.get_area()
        if area == 0:
            self.log_validity_error('ValidData encloses no area.')
            value = False
        elif area > 0:
            self.log_validity_error(
                "ValidData must be traversed in clockwise direction.")
            value = False
        for i, entry in enumerate(valid_data):
            if not (
                (self.FirstRow <= entry[0] <= self.FirstRow + self.NumRows) and
                (self.FirstCol <= entry[1] <= self.FirstCol + self.NumCols)):
                self.log_validity_warning(
                    'ValidData entry {} is not contained in the image bounds'.
                    format(i))
                value = False
        return value

    def _basic_validity_check(self):
        condition = super(ImageDataType, self)._basic_validity_check()
        if (self.PixelType == 'AMP8I_PHS8I') and (self.AmpTable is None):
            self.log_validity_error(
                "We have `PixelType='AMP8I_PHS8I'` and `AmpTable` is not defined for ImageDataType."
            )
            condition = False
        if (self.PixelType != 'AMP8I_PHS8I') and (self.AmpTable is not None):
            self.log_validity_error(
                "We have `PixelType != 'AMP8I_PHS8I'` and `AmpTable` is defined for ImageDataType."
            )
            condition = False
        if (self.ValidData is not None) and (len(self.ValidData) < 3):
            self.log_validity_error(
                "We have `ValidData` defined with fewer than 3 entries.")
            condition = False
        condition &= self._check_valid_data()
        return condition

    def get_valid_vertex_data(self, dtype=numpy.int64):
        """
        Gets an array of `[row, col]` indices defining the valid data. If this is not viable, then `None`
        will be returned.

        Parameters
        ----------
        dtype : object
            the data type for the array

        Returns
        -------
        numpy.ndarray|None
        """

        if self.ValidData is None:
            return None
        out = numpy.zeros((self.ValidData.size, 2), dtype=dtype)
        for i, entry in enumerate(self.ValidData):
            out[i, :] = entry.get_array(dtype=dtype)
        return out

    def get_full_vertex_data(self, dtype=numpy.int64):
        """
        Gets an array of `[row, col]` indices defining the full vertex data. If this is not viable, then `None`
        will be returned.

        Parameters
        ----------
        dtype : object
            the data type for the array

        Returns
        -------
        numpy.ndarray|None
        """

        if self.NumRows is None or self.NumCols is None:
            return None
        return numpy.array(
            [[0, 0], [0, self.NumCols - 1],
             [self.NumRows - 1, self.NumCols - 1], [self.NumRows - 1, 0]],
            dtype=dtype)

    def get_pixel_size(self) -> int:
        """
        Gets the size per pixel, in bytes.

        Returns
        -------
        int
        """

        if self.PixelType == "RE32F_IM32F":
            return 8
        elif self.PixelType == "RE16I_IM16I":
            return 4
        elif self.PixelType == "AMP8I_PHS8I":
            return 2
        else:
            raise ValueError('Got unhandled pixel type `{}`'.format(
                self.PixelType))
예제 #29
0
class WaveformParametersType(Serializable):
    """
    Transmit and receive demodulation waveform parameters.
    """

    _fields = (
        'TxPulseLength', 'TxRFBandwidth', 'TxFreqStart', 'TxFMRate', 'RcvDemodType', 'RcvWindowLength',
        'ADCSampleRate', 'RcvIFBandwidth', 'RcvFreqStart', 'RcvFMRate', 'index')
    _required = ()
    _set_as_attribute = ('index', )
    _numeric_format = {
        'TxPulseLength': FLOAT_FORMAT, 'TxRFBandwidth': '0.17E', 'TxFreqStart': '0.17E',
        'TxFMRate': '0.17E', 'RcvWindowLength': FLOAT_FORMAT, 'ADCSampleRate': '0.17E',
        'RcvIFBandwidth': '0.17E', 'RcvFreqStart': '0.17E', 'RcvFMRate': '0.17E'}

    # descriptors
    TxPulseLength = FloatDescriptor(
        'TxPulseLength', _required, strict=DEFAULT_STRICT,
        docstring='Transmit pulse length in seconds.')  # type: float
    TxRFBandwidth = FloatDescriptor(
        'TxRFBandwidth', _required, strict=DEFAULT_STRICT,
        docstring='Transmit RF bandwidth of the transmit pulse in Hz.')  # type: float
    TxFreqStart = FloatDescriptor(
        'TxFreqStart', _required, strict=DEFAULT_STRICT,
        docstring='Transmit Start frequency for Linear FM waveform in Hz, may be relative '
                  'to reference frequency.')  # type: float
    TxFMRate = FloatDescriptor(
        'TxFMRate', _required, strict=DEFAULT_STRICT,
        docstring='Transmit FM rate for Linear FM waveform in Hz/second.')  # type: float
    RcvWindowLength = FloatDescriptor(
        'RcvWindowLength', _required, strict=DEFAULT_STRICT,
        docstring='Receive window duration in seconds.')  # type: float
    ADCSampleRate = FloatDescriptor(
        'ADCSampleRate', _required, strict=DEFAULT_STRICT,
        docstring='Analog-to-Digital Converter sampling rate in samples/second.')  # type: float
    RcvIFBandwidth = FloatDescriptor(
        'RcvIFBandwidth', _required, strict=DEFAULT_STRICT,
        docstring='Receive IF bandwidth in Hz.')  # type: float
    RcvFreqStart = FloatDescriptor(
        'RcvFreqStart', _required, strict=DEFAULT_STRICT,
        docstring='Receive demodulation start frequency in Hz, may be relative to reference frequency.')  # type: float
    index = IntegerDescriptor(
        'index', _required, strict=False, docstring="The array index.")  # type: int

    def __init__(self, TxPulseLength=None, TxRFBandwidth=None, TxFreqStart=None, TxFMRate=None,
                 RcvDemodType=None, RcvWindowLength=None, ADCSampleRate=None, RcvIFBandwidth=None,
                 RcvFreqStart=None, RcvFMRate=None, index=None, **kwargs):
        """

        Parameters
        ----------
        TxPulseLength : float
        TxRFBandwidth : float
        TxFreqStart : float
        TxFMRate : float
        RcvDemodType : str
        RcvWindowLength : float
        ADCSampleRate : float
        RcvIFBandwidth : float
        RcvFreqStart : float
        RcvFMRate : float
        index : int
        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._RcvFMRate = None
        self.TxPulseLength, self.TxRFBandwidth = TxPulseLength, TxRFBandwidth
        self.TxFreqStart, self.TxFMRate = TxFreqStart, TxFMRate
        self.RcvWindowLength = RcvWindowLength
        self.ADCSampleRate = ADCSampleRate
        self.RcvIFBandwidth = RcvIFBandwidth
        self.RcvFreqStart = RcvFreqStart
        # NB: self.RcvDemodType is read only.
        if RcvDemodType == 'CHIRP' and RcvFMRate is None:
            self.RcvFMRate = 0.0
        else:
            self.RcvFMRate = RcvFMRate
        self.index = index
        super(WaveformParametersType, self).__init__(**kwargs)

    @property
    def RcvDemodType(self):  # type: () -> Union[None, str]
        """
        str: READ ONLY. Receive demodulation used when Linear FM waveform is
        used on transmit. This value is derived form the value of `RcvFMRate`.

        * `None` - `RcvFMRate` is `None`.

        * `'CHIRP'` - `RcvFMRate=0`.

        * `'STRETCH'` - `RcvFMRate` is non-zero.
        """

        if self._RcvFMRate is None:
            return None
        elif self._RcvFMRate == 0:
            return 'CHIRP'
        else:
            return 'STRETCH'

    @property
    def RcvFMRate(self):  # type: () -> Union[None, float]
        """
        float: Receive FM rate in Hz/sec. Also, determines the value of `RcvDemodType`. **Optional.**
        """
        return self._RcvFMRate

    @RcvFMRate.setter
    def RcvFMRate(self, value):
        if value is None:
            self._RcvFMRate = None
        else:
            try:
                self._RcvFMRate = parse_float(value, 'RcvFMRate', self)
            except Exception as e:
                logger.error(
                    'Failed parsing value {} for field RCVFMRate of type "float",\n\t'
                    'with error {} - {}.\n\t'
                    'The value has been set to None.'.format(value, type(e), e))
                self._RcvFMRate = None

    def _basic_validity_check(self):
        valid = super(WaveformParametersType, self)._basic_validity_check()
        return valid

    def derive(self):
        """
        Populate derived data in `WaveformParametersType`.

        Returns
        -------
        None
        """

        if self.TxPulseLength is not None and self.TxFMRate is not None and self.TxRFBandwidth is None:
            self.TxRFBandwidth = self.TxPulseLength*self.TxFMRate
        if self.TxPulseLength is not None and self.TxRFBandwidth is not None and self.TxFMRate is None:
            self.TxFMRate = self.TxRFBandwidth/self.TxPulseLength
        if self.TxFMRate is not None and self.TxRFBandwidth is not None and self.TxPulseLength is None:
            self.TxPulseLength = self.TxRFBandwidth/self.TxFMRate

    def _apply_reference_frequency(self, reference_frequency):
        if self.TxFreqStart is not None:
            self.TxFreqStart += reference_frequency
        if self.RcvFreqStart is not None:
            self.RcvFreqStart += reference_frequency
예제 #30
0
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