Ejemplo n.º 1
0
    def __init__(self, file_name):
        """

        Parameters
        ----------
        file_name : str
        """

        # verify that the file is a tiff file
        self._tiff_details = TiffDetails(file_name)
        # verify that ImageDescription tiff tag exists
        if 'ImageDescription' not in self._tiff_details.tags:
            raise SarpyIOError('No "ImageDescription" tag in the tiff.')

        img_format = self._tiff_details.tags['ImageDescription']
        # verify that ImageDescription has a reasonable format
        try:
            self._img_desc_tags = json.loads(
                img_format)  # type: Dict[str, Any]
        except Exception as e:
            logging.error(
                'Failed deserializing the ImageDescription tag as json with error {}'
                .format(e))
            raise e
        # verify the file is not compressed
        self._tiff_details.check_compression()
        # verify the file is not tiled
        self._tiff_details.check_tiled()
Ejemplo n.º 2
0
    def __init__(self, radar_sat_details):
        """

        Parameters
        ----------
        radar_sat_details : str|RadarSatDetails
            file name or RadarSatDeatils object
        """

        if isinstance(radar_sat_details, string_types):
            radar_sat_details = RadarSatDetails(radar_sat_details)
        if not isinstance(radar_sat_details, RadarSatDetails):
            raise TypeError('The input argument for RadarSatReader must be a '
                            'filename or RadarSatDetails object')
        self._radar_sat_details = radar_sat_details
        # determine symmetry
        symmetry = self._radar_sat_details.get_symmetry()
        # get the datafiles
        data_files = self._radar_sat_details.get_data_file_names()
        # get the sicd metadata objects
        sicds = self._radar_sat_details.get_sicd_collection()
        readers = []
        for sicd, file_name in zip(sicds, data_files):
            # create one reader per file/sicd
            # NB: the files are implicitly listed in the same order as polarizations
            tiff_details = TiffDetails(file_name)
            readers.append(
                TiffReader(tiff_details, sicd_meta=sicd, symmetry=symmetry))
        self._readers = tuple(readers)  # type: Tuple[TiffReader]
        sicd_tuple = tuple(reader.sicd_meta for reader in readers)
        chipper_tuple = tuple(reader._chipper for reader in readers)
        super(RadarSatReader, self).__init__(sicd_tuple,
                                             chipper_tuple,
                                             is_sicd_type=True)
Ejemplo n.º 3
0
class CapellaDetails(object):
    """
    Parses and converts the Cosmo Skymed metadata
    """

    __slots__ = ('_tiff_details', '_img_desc_tags')

    def __init__(self, file_name):
        """

        Parameters
        ----------
        file_name : str
        """

        # verify that the file is a tiff file
        self._tiff_details = TiffDetails(file_name)
        # verify that ImageDescription tiff tag exists
        if 'ImageDescription' not in self._tiff_details.tags:
            raise SarpyIOError('No "ImageDescription" tag in the tiff.')

        img_format = self._tiff_details.tags['ImageDescription']
        # verify that ImageDescription has a reasonable format
        try:
            self._img_desc_tags = json.loads(
                img_format)  # type: Dict[str, Any]
        except Exception as e:
            logging.error(
                'Failed deserializing the ImageDescription tag as json with error {}'
                .format(e))
            raise e
        # verify the file is not compressed
        self._tiff_details.check_compression()
        # verify the file is not tiled
        self._tiff_details.check_tiled()

    @property
    def file_name(self):
        """
        str: the file name
        """

        return self._tiff_details.file_name

    @property
    def tiff_details(self):
        # type: () -> TiffDetails
        """
        TiffDetails: The tiff details object.
        """

        return self._tiff_details

    def get_symmetry(self):
        # type: () -> Tuple[bool, bool, bool]
        """
        Gets the symmetry definition.

        Returns
        -------
        Tuple[bool, bool, bool]
        """

        pointing = self._img_desc_tags['collect']['radar']['pointing'].lower()
        if pointing == 'left':
            return False, False, False
        elif pointing == 'right':
            return False, True, False
        else:
            raise ValueError(
                'Got unhandled pointing value {}'.format(pointing))

    def get_sicd(self):
        """
        Get the SICD metadata for the image.

        Returns
        -------
        SICDType
        """
        def convert_string_dict(dict_in):
            # type: (dict) -> dict
            dict_out = OrderedDict()
            for key, val in dict_in.items():
                if isinstance(val, string_types):
                    dict_out[key] = val
                elif isinstance(val, int):
                    dict_out[key] = str(val)
                elif isinstance(val, float):
                    dict_out[key] = '{0:0.16G}'.format(val)
                else:
                    raise TypeError('Got unhandled type {}'.format(type(val)))
            return dict_out

        def extract_state_vector():
            # type: () -> (numpy.ndarray, numpy.ndarray, numpy.ndarray)
            vecs = collect['state']['state_vectors']
            times = numpy.zeros((len(vecs), ), dtype=numpy.float64)
            positions = numpy.zeros((len(vecs), 3), dtype=numpy.float64)
            velocities = numpy.zeros((len(vecs), 3), dtype=numpy.float64)
            for i, entry in enumerate(vecs):
                times[i] = get_seconds(parse_timestring(entry['time'],
                                                        precision='ns'),
                                       start_time,
                                       precision='ns')
                positions[i, :] = entry['position']
                velocities[i, :] = entry['velocity']
            return times, positions, velocities

        def get_collection_info():
            # type: () -> CollectionInfoType
            coll_name = collect['platform']
            start_dt = start_time.astype('datetime64[us]').astype(datetime)
            mode = collect['mode'].strip().lower()
            if mode == 'stripmap':
                radar_mode = RadarModeType(ModeType='STRIPMAP')
            elif mode == 'sliding_spotlight':
                radar_mode = RadarModeType(ModeType='DYNAMIC STRIPMAP')
            else:
                raise ValueError('Got unhandled radar mode {}'.format(mode))

            return CollectionInfoType(CollectorName=coll_name,
                                      CoreName='{}{}{}'.format(
                                          start_dt.strftime('%d%b%y').upper(),
                                          coll_name,
                                          start_dt.strftime('%H%M%S')),
                                      RadarMode=radar_mode,
                                      Classification='UNCLASSIFIED',
                                      CollectType='MONOSTATIC')

        def get_image_creation():
            # type: () -> ImageCreationType
            from sarpy.__about__ import __version__
            return ImageCreationType(
                Application=self._tiff_details.tags['Software'],
                DateTime=parse_timestring(
                    self._img_desc_tags['processing_time'], precision='us'),
                Profile='sarpy {}'.format(__version__),
                Site='Unknown')

        def get_image_data():
            # type: () -> ImageDataType
            img = collect['image']
            rows = int(
                img['columns'])  # capella uses flipped row/column definition?
            cols = int(img['rows'])
            if img['data_type'] == 'CInt16':
                pixel_type = 'RE16I_IM16I'
            else:
                raise ValueError('Got unhandled data_type {}'.format(
                    img['data_type']))

            scp_pixel = (int(0.5 * rows), int(0.5 * cols))
            if collect['radar']['pointing'] == 'left':
                scp_pixel = (rows - scp_pixel[0] - 1, cols - scp_pixel[1] - 1)

            return ImageDataType(NumRows=rows,
                                 NumCols=cols,
                                 FirstRow=0,
                                 FirstCol=0,
                                 PixelType=pixel_type,
                                 FullImage=(rows, cols),
                                 SCPPixel=scp_pixel)

        def get_geo_data():
            # type: () -> GeoDataType
            return GeoDataType(SCP=SCPType(
                ECF=collect['image']['center_pixel']['target_position']))

        def get_position():
            # type: () -> PositionType
            px, py, pz = fit_position_xvalidation(state_time,
                                                  state_position,
                                                  state_velocity,
                                                  max_degree=6)
            return PositionType(ARPPoly=XYZPolyType(X=px, Y=py, Z=pz))

        def get_grid():
            # type: () -> GridType

            img = collect['image']

            image_plane = 'OTHER'
            grid_type = 'PLANE'
            if self._img_desc_tags['product_type'] == 'SLC' and img[
                    'algorithm'] != 'backprojection':
                image_plane = 'SLANT'
                grid_type = 'RGZERO'

            coa_time = parse_timestring(img['center_pixel']['center_time'],
                                        precision='ns')
            row_imp_rsp_bw = 2 * bw / speed_of_light
            row = DirParamType(SS=img['pixel_spacing_column'],
                               ImpRespBW=row_imp_rsp_bw,
                               ImpRespWid=img['range_resolution'],
                               KCtr=2 * fc / speed_of_light,
                               DeltaK1=-0.5 * row_imp_rsp_bw,
                               DeltaK2=0.5 * row_imp_rsp_bw,
                               DeltaKCOAPoly=[
                                   [
                                       0.0,
                                   ],
                               ],
                               WgtType=WgtTypeType(
                                   WindowName=img['range_window']['name'],
                                   Parameters=convert_string_dict(
                                       img['range_window']['parameters'])))

            # get timecoa value
            timecoa_value = get_seconds(coa_time,
                                        start_time)  # TODO: constant?
            # find an approximation for zero doppler spacing - necessarily rough for backprojected images
            # find velocity at coatime
            arp_velocity = position.ARPPoly.derivative_eval(timecoa_value,
                                                            der_order=1)
            arp_speed = numpy.linalg.norm(arp_velocity)
            col_ss = img['pixel_spacing_row']
            dop_bw = img['processed_azimuth_bandwidth']
            # ss_zd_s = col_ss/arp_speed

            col = DirParamType(SS=col_ss,
                               ImpRespWid=img['azimuth_resolution'],
                               ImpRespBW=dop_bw / arp_speed,
                               KCtr=0,
                               WgtType=WgtTypeType(
                                   WindowName=img['azimuth_window']['name'],
                                   Parameters=convert_string_dict(
                                       img['azimuth_window']['parameters'])))

            # TODO: from Wade - account for numeric WgtFunct

            return GridType(ImagePlane=image_plane,
                            Type=grid_type,
                            TimeCOAPoly=[
                                [
                                    timecoa_value,
                                ],
                            ],
                            Row=row,
                            Col=col)

        def get_radar_colection():
            # type: () -> RadarCollectionType

            radar = collect['radar']
            freq_min = fc - 0.5 * bw
            return RadarCollectionType(
                TxPolarization=radar['transmit_polarization'],
                TxFrequency=TxFrequencyType(Min=freq_min, Max=freq_min + bw),
                Waveform=[
                    WaveformParametersType(
                        TxRFBandwidth=bw,
                        TxPulseLength=radar['pulse_duration'],
                        RcvDemodType='CHIRP',
                        ADCSampleRate=radar['sampling_frequency'],
                        TxFreqStart=freq_min)
                ],
                RcvChannels=[
                    ChanParametersType(TxRcvPolarization='{}:{}'.format(
                        radar['transmit_polarization'],
                        radar['receive_polarization']))
                ])

        def get_timeline():
            # type: () -> TimelineType
            prf = collect['radar']['prf'][0]['prf']
            return TimelineType(CollectStart=start_time,
                                CollectDuration=duration,
                                IPP=[
                                    IPPSetType(TStart=0,
                                               TEnd=duration,
                                               IPPStart=0,
                                               IPPEnd=duration * prf,
                                               IPPPoly=(0, prf)),
                                ])

        def get_image_formation():
            # type: () -> ImageFormationType

            radar = collect['radar']
            algo = collect['image']['algorithm'].upper()
            processings = None
            if algo == 'BACKPROJECTION':
                processings = [
                    ProcessingType(Type='Backprojected to DEM', Applied=True),
                ]
            if algo not in ('PFA', 'RMA', 'RGAZCOMP'):
                logging.warning(
                    'Image formation algorithm {} not one of the recognized SICD options, '
                    'being set to "OTHER".'.format(algo))
                algo = 'OTHER'

            return ImageFormationType(
                RcvChanProc=RcvChanProcType(NumChanProc=1, PRFScaleFactor=1),
                ImageFormAlgo=algo,
                TStartProc=0,
                TEndProc=duration,
                TxRcvPolarizationProc='{}:{}'.format(
                    radar['transmit_polarization'],
                    radar['receive_polarization']),
                TxFrequencyProc=TxFrequencyProcType(
                    MinProc=radar_collection.TxFrequency.Min,
                    MaxProc=radar_collection.TxFrequency.Max),
                STBeamComp='NO',
                ImageBeamComp='NO',
                AzAutofocus='NO',
                RgAutofocus='NO',
                Processings=processings)

        # TODO: From Wade - Radiometric is not suitable?

        # extract general use information
        collect = self._img_desc_tags['collect']
        start_time = parse_timestring(collect['start_timestamp'],
                                      precision='ns')
        end_time = parse_timestring(collect['stop_timestamp'], precision='ns')
        duration = get_seconds(end_time, start_time, precision='ns')
        state_time, state_position, state_velocity = extract_state_vector()
        bw = collect['radar']['pulse_bandwidth']
        fc = collect['radar']['center_frequency']

        # define the sicd elements
        collection_info = get_collection_info()
        image_creation = get_image_creation()
        image_data = get_image_data()
        geo_data = get_geo_data()
        position = get_position()
        grid = get_grid()
        radar_collection = get_radar_colection()
        timeline = get_timeline()
        image_formation = get_image_formation()

        sicd = SICDType(CollectionInfo=collection_info,
                        ImageCreation=image_creation,
                        ImageData=image_data,
                        GeoData=geo_data,
                        Position=position,
                        Grid=grid,
                        RadarCollection=radar_collection,
                        Timeline=timeline,
                        ImageFormation=image_formation)
        sicd.derive()

        # this would be a rough estimate - waiting for radiometric data
        # sicd.populate_rniirs(override=False)
        return sicd
Ejemplo n.º 4
0
class CapellaDetails(object):
    """
    Parses and converts the Cosmo Skymed metadata
    """

    __slots__ = ('_tiff_details', '_img_desc_tags')

    def __init__(self, file_name):
        """

        Parameters
        ----------
        file_name : str
        """

        # verify that the file is a tiff file
        self._tiff_details = TiffDetails(file_name)
        # verify that ImageDescription tiff tag exists
        if 'ImageDescription' not in self._tiff_details.tags:
            raise SarpyIOError('No "ImageDescription" tag in the tiff.')

        img_format = self._tiff_details.tags['ImageDescription']
        # verify that ImageDescription has a reasonable format
        try:
            self._img_desc_tags = json.loads(
                img_format)  # type: Dict[str, Any]
        except Exception as e:
            msg = 'Failed deserializing the ImageDescription tag as json with error {}'.format(
                e)
            logger.info(msg)
            raise SarpyIOError(msg)

        # verify the file is not compressed
        self._tiff_details.check_compression()
        # verify the file is not tiled
        self._tiff_details.check_tiled()

    @property
    def file_name(self):
        """
        str: the file name
        """

        return self._tiff_details.file_name

    @property
    def tiff_details(self):
        # type: () -> TiffDetails
        """
        TiffDetails: The tiff details object.
        """

        return self._tiff_details

    def get_symmetry(self):
        # type: () -> Tuple[bool, bool, bool]
        """
        Gets the symmetry definition.

        Returns
        -------
        Tuple[bool, bool, bool]
        """

        pointing = self._img_desc_tags['collect']['radar']['pointing'].lower()
        if pointing == 'left':
            return True, False, True
        elif pointing == 'right':
            return False, False, True
        else:
            raise ValueError(
                'Got unhandled pointing value {}'.format(pointing))

    def get_sicd(self):
        """
        Get the SICD metadata for the image.

        Returns
        -------
        SICDType
        """
        def convert_string_dict(dict_in):
            # type: (dict) -> dict
            dict_out = OrderedDict()
            for key, val in dict_in.items():
                if isinstance(val, str):
                    dict_out[key] = val
                elif isinstance(val, int):
                    dict_out[key] = str(val)
                elif isinstance(val, float):
                    dict_out[key] = '{0:0.17G}'.format(val)
                else:
                    raise TypeError('Got unhandled type {}'.format(type(val)))
            return dict_out

        def extract_state_vector():
            # type: () -> (numpy.ndarray, numpy.ndarray, numpy.ndarray)
            vecs = collect['state']['state_vectors']
            times = numpy.zeros((len(vecs), ), dtype=numpy.float64)
            positions = numpy.zeros((len(vecs), 3), dtype=numpy.float64)
            velocities = numpy.zeros((len(vecs), 3), dtype=numpy.float64)
            for i, entry in enumerate(vecs):
                times[i] = get_seconds(parse_timestring(entry['time'],
                                                        precision='ns'),
                                       start_time,
                                       precision='ns')
                positions[i, :] = entry['position']
                velocities[i, :] = entry['velocity']
            return times, positions, velocities

        def get_radar_parameter(name):
            if name in radar:
                return radar[name]
            if len(radar_time_varying) > 0:
                element = radar_time_varying[0]
                if name in element:
                    return element[name]
            raise ValueError(
                'Unable to determine radar parameter `{}`'.format(name))

        def get_collection_info():
            # type: () -> CollectionInfoType
            coll_name = collect['platform']
            mode = collect['mode'].strip().lower()
            if mode == 'stripmap':
                radar_mode = RadarModeType(ModeType='STRIPMAP', ModeID=mode)
            elif mode == 'spotlight':
                radar_mode = RadarModeType(ModeType='SPOTLIGHT', ModeID=mode)
            elif mode == 'sliding_spotlight':
                radar_mode = RadarModeType(ModeType='DYNAMIC STRIPMAP',
                                           ModeID=mode)
            else:
                raise ValueError('Got unhandled radar mode {}'.format(mode))

            return CollectionInfoType(CollectorName=coll_name,
                                      CoreName=collect['collect_id'],
                                      RadarMode=radar_mode,
                                      Classification='UNCLASSIFIED',
                                      CollectType='MONOSTATIC')

        def get_image_creation():
            # type: () -> ImageCreationType
            from sarpy.__about__ import __version__
            return ImageCreationType(
                Application=self._tiff_details.tags['Software'],
                DateTime=parse_timestring(
                    self._img_desc_tags['processing_time'], precision='us'),
                Profile='sarpy {}'.format(__version__),
                Site='Unknown')

        def get_image_data():
            # type: () -> ImageDataType
            rows = int(
                img['columns'])  # capella uses flipped row/column definition?
            cols = int(img['rows'])
            if img['data_type'] == 'CInt16':
                pixel_type = 'RE16I_IM16I'
            else:
                raise ValueError('Got unhandled data_type {}'.format(
                    img['data_type']))

            scp_pixel = (int(0.5 * rows), int(0.5 * cols))
            if radar['pointing'] == 'left':
                scp_pixel = (rows - scp_pixel[0] - 1, cols - scp_pixel[1] - 1)

            return ImageDataType(NumRows=rows,
                                 NumCols=cols,
                                 FirstRow=0,
                                 FirstCol=0,
                                 PixelType=pixel_type,
                                 FullImage=(rows, cols),
                                 SCPPixel=scp_pixel)

        def get_geo_data():
            # type: () -> GeoDataType
            return GeoDataType(SCP=SCPType(
                ECF=img['center_pixel']['target_position']))

        def get_position():
            # type: () -> PositionType
            px, py, pz = fit_position_xvalidation(state_time,
                                                  state_position,
                                                  state_velocity,
                                                  max_degree=8)
            return PositionType(ARPPoly=XYZPolyType(X=px, Y=py, Z=pz))

        def get_grid():
            # type: () -> GridType

            def get_weight(window_dict):
                window_name = window_dict['name']
                if window_name.lower() == 'rectangular':
                    return WgtTypeType(WindowName='UNIFORM'), None
                elif window_name.lower() == 'avci-nacaroglu':
                    return WgtTypeType(
                        WindowName=window_name.upper(),
                        Parameters=convert_string_dict(window_dict['parameters'])), \
                           avci_nacaroglu_window(64, alpha=window_dict['parameters']['alpha'])
                else:
                    return WgtTypeType(WindowName=window_name,
                                       Parameters=convert_string_dict(
                                           window_dict['parameters'])), None

            image_plane = 'SLANT'
            grid_type = 'RGZERO'

            coa_time = parse_timestring(img['center_pixel']['center_time'],
                                        precision='ns')
            row_bw = img.get('processed_range_bandwidth', bw)
            row_imp_rsp_bw = 2 * row_bw / speed_of_light
            row_wgt, row_wgt_funct = get_weight(img['range_window'])
            row = DirParamType(SS=img['image_geometry']['delta_range_sample'],
                               Sgn=-1,
                               ImpRespBW=row_imp_rsp_bw,
                               ImpRespWid=img['range_resolution'],
                               KCtr=2 * fc / speed_of_light,
                               DeltaK1=-0.5 * row_imp_rsp_bw,
                               DeltaK2=0.5 * row_imp_rsp_bw,
                               DeltaKCOAPoly=[
                                   [
                                       0.0,
                                   ],
                               ],
                               WgtFunct=row_wgt_funct,
                               WgtType=row_wgt)

            # get timecoa value
            timecoa_value = get_seconds(coa_time, start_time)
            # find an approximation for zero doppler spacing - necessarily rough for backprojected images
            col_ss = img['pixel_spacing_row']
            dop_bw = img['processed_azimuth_bandwidth']

            col_wgt, col_wgt_funct = get_weight(img['azimuth_window'])
            col = DirParamType(SS=col_ss,
                               Sgn=-1,
                               ImpRespWid=img['azimuth_resolution'],
                               ImpRespBW=dop_bw * abs(ss_zd_s) / col_ss,
                               KCtr=0,
                               WgtFunct=col_wgt_funct,
                               WgtType=col_wgt)

            # TODO:
            #   column deltakcoa poly - it's in there at ["image"]["frequency_doppler_centroid_polynomial"]

            return GridType(ImagePlane=image_plane,
                            Type=grid_type,
                            TimeCOAPoly=[
                                [
                                    timecoa_value,
                                ],
                            ],
                            Row=row,
                            Col=col)

        def get_radar_collection():
            # type: () -> RadarCollectionType

            freq_min = fc - 0.5 * bw
            return RadarCollectionType(
                TxPolarization=radar['transmit_polarization'],
                TxFrequency=(freq_min, freq_min + bw),
                Waveform=[
                    WaveformParametersType(
                        TxRFBandwidth=bw,
                        TxPulseLength=get_radar_parameter('pulse_duration'),
                        RcvDemodType='CHIRP',
                        ADCSampleRate=radar['sampling_frequency'],
                        TxFreqStart=freq_min)
                ],
                RcvChannels=[
                    ChanParametersType(TxRcvPolarization='{}:{}'.format(
                        radar['transmit_polarization'],
                        radar['receive_polarization']))
                ])

        def get_timeline():
            # type: () -> TimelineType
            prf = radar['prf'][0]['prf']
            return TimelineType(CollectStart=start_time,
                                CollectDuration=duration,
                                IPP=[
                                    IPPSetType(TStart=0,
                                               TEnd=duration,
                                               IPPStart=0,
                                               IPPEnd=duration * prf,
                                               IPPPoly=(0, prf)),
                                ])

        def get_image_formation():
            # type: () -> ImageFormationType

            algo = img['algorithm'].upper()
            processings = None
            if algo == 'BACKPROJECTION':
                processings = [
                    ProcessingType(Type='Backprojected to DEM', Applied=True),
                ]
            else:
                logger.warning('Got unexpected algorithm, the results for the '
                               'sicd struture might be unexpected')

            if algo not in ('PFA', 'RMA', 'RGAZCOMP'):
                logger.warning(
                    'Image formation algorithm {} not one of the recognized SICD options, '
                    'being set to "OTHER".'.format(algo))
                algo = 'OTHER'

            return ImageFormationType(
                RcvChanProc=RcvChanProcType(NumChanProc=1, PRFScaleFactor=1),
                ImageFormAlgo=algo,
                TStartProc=0,
                TEndProc=duration,
                TxRcvPolarizationProc='{}:{}'.format(
                    radar['transmit_polarization'],
                    radar['receive_polarization']),
                TxFrequencyProc=(radar_collection.TxFrequency.Min,
                                 radar_collection.TxFrequency.Max),
                STBeamComp='NO',
                ImageBeamComp='NO',
                AzAutofocus='NO',
                RgAutofocus='NO',
                Processings=processings)

        def get_rma():
            # type: () -> RMAType
            img_geometry = img['image_geometry']
            near_range = img_geometry['range_to_first_sample']
            center_time = parse_timestring(img['center_pixel']['center_time'],
                                           precision='us')
            first_time = parse_timestring(img_geometry['first_line_time'],
                                          precision='us')
            zd_time_scp = get_seconds(center_time, first_time, 'us')
            r_ca_scp = near_range + image_data.SCPPixel.Row * grid.Row.SS
            time_ca_poly = numpy.array(
                [zd_time_scp, -look * ss_zd_s / grid.Col.SS], dtype='float64')

            timecoa_value = get_seconds(center_time, start_time)
            arp_velocity = position.ARPPoly.derivative_eval(timecoa_value,
                                                            der_order=1)
            vm_ca = numpy.linalg.norm(arp_velocity)
            inca = INCAType(R_CA_SCP=r_ca_scp,
                            FreqZero=fc,
                            TimeCAPoly=time_ca_poly,
                            DRateSFPoly=[
                                [1 / (vm_ca * ss_zd_s / grid.Col.SS)],
                            ])

            return RMAType(RMAlgoType='RG_DOP', INCA=inca)

        def get_radiometric():
            # type: () -> Union[None, RadiometricType]
            if img['radiometry'].lower() != 'beta_nought':
                logger.warning('Got unrecognized Capella radiometry {},\n\t'
                               'skipping the radiometric metadata'.format(
                                   img['radiometry']))
                return None

            return RadiometricType(BetaZeroSFPoly=[
                [
                    img['scale_factor']**2,
                ],
            ])

        def add_noise():
            if sicd.Radiometric is None:
                return

            nesz_raw = numpy.array(img['nesz_polynomial']['coefficients'],
                                   dtype='float64')
            test_value = polynomial.polyval(rma.INCA.R_CA_SCP, nesz_raw)
            if abs(test_value - img['nesz_peak']) > 100:
                # this polynomial reversed in early versions, so reverse if evaluated results are nonsense
                nesz_raw = nesz_raw[::-1]
            nesz_poly_raw = Poly2DType(Coefs=numpy.reshape(nesz_raw, (-1, 1)))
            noise_coeffs = nesz_poly_raw.shift(-rma.INCA.R_CA_SCP,
                                               1,
                                               0,
                                               1,
                                               return_poly=False)
            # this is in nesz units, so shift to absolute units
            noise_coeffs[0] -= 10 * numpy.log10(
                sicd.Radiometric.SigmaZeroSFPoly[0, 0])
            sicd.Radiometric.NoiseLevel = NoiseLevelType_(
                NoiseLevelType='ABSOLUTE', NoisePoly=noise_coeffs)

        # extract general use information
        collect = self._img_desc_tags['collect']
        img = collect['image']
        radar = collect['radar']
        radar_time_varying = radar.get('time_varying_parameters', [])

        start_time = parse_timestring(collect['start_timestamp'],
                                      precision='ns')
        end_time = parse_timestring(collect['stop_timestamp'], precision='ns')
        duration = get_seconds(end_time, start_time, precision='ns')
        state_time, state_position, state_velocity = extract_state_vector()
        bw = get_radar_parameter('pulse_bandwidth')
        fc = get_radar_parameter('center_frequency')
        ss_zd_s = img['image_geometry']['delta_line_time']
        look = -1 if radar['pointing'] == 'right' else 1

        # define the sicd elements
        collection_info = get_collection_info()
        image_creation = get_image_creation()
        image_data = get_image_data()
        geo_data = get_geo_data()
        position = get_position()
        grid = get_grid()
        radar_collection = get_radar_collection()
        timeline = get_timeline()
        image_formation = get_image_formation()
        rma = get_rma()
        radiometric = get_radiometric()

        sicd = SICDType(CollectionInfo=collection_info,
                        ImageCreation=image_creation,
                        ImageData=image_data,
                        GeoData=geo_data,
                        Position=position,
                        Grid=grid,
                        RadarCollection=radar_collection,
                        Timeline=timeline,
                        ImageFormation=image_formation,
                        RMA=rma,
                        Radiometric=radiometric)
        sicd.derive()

        add_noise()
        sicd.populate_rniirs(override=False)
        return sicd