Beispiel #1
0
    def get_sicd_collection(self):
        """
        Gets the list of sicd objects, one per polarimetric entry.

        Returns
        -------
        Tuple[SICDType]
        """

        nitf, collection_info = self._get_collection_info()
        image_creation = self._get_image_creation()
        image_data, geo_data = self._get_image_and_geo_data()
        position = self._get_position()
        grid = self._get_grid()
        radar_collection = self._get_radar_collection()
        timeline = self._get_timeline()
        image_formation = self._get_image_formation(timeline, radar_collection)
        scpcoa = self._get_scpcoa()
        rma = self._get_rma_adjust_grid(scpcoa, grid, image_data, position,
                                        collection_info)
        radiometric = self._get_radiometric(image_data, grid)
        base_sicd = SICDType(CollectionInfo=collection_info,
                             ImageCreation=image_creation,
                             GeoData=geo_data,
                             ImageData=image_data,
                             Position=position,
                             Grid=grid,
                             RadarCollection=radar_collection,
                             Timeline=timeline,
                             ImageFormation=image_formation,
                             SCPCOA=scpcoa,
                             RMA=rma,
                             Radiometric=radiometric)
        if len(nitf) > 0:
            base_sicd._NITF = nitf
        self._update_geo_data(base_sicd)
        base_sicd.derive()  # derive all the fields
        # now, make one copy per polarimetric entry, as appropriate
        tx_pols, tx_rcv_pols = self._get_polarizations()
        sicd_list = []
        for i, entry in enumerate(tx_rcv_pols):
            this_sicd = base_sicd.copy()
            this_sicd.ImageFormation.RcvChanProc.ChanIndices = [
                i + 1,
            ]
            this_sicd.ImageFormation.TxRcvPolarizationProc = \
                this_sicd.RadarCollection.RcvChannels[i].TxRcvPolarization
            this_sicd.populate_rniirs(override=False)
            sicd_list.append(this_sicd)
        return tuple(sicd_list)
Beispiel #2
0
def validate_sicd_for_writing(sicd_meta: SICDType) -> SICDType:
    """
    Helper method which ensures the provided SICD structure provides enough
    information to support file writing, as well as ensures a few basic items
    are populated as appropriate.

    Parameters
    ----------
    sicd_meta : SICDType

    Returns
    -------
    SICDType
        This returns a deep copy of the provided SICD structure, with any
        necessary modifications.
    """

    if not isinstance(sicd_meta, SICDType):
        raise ValueError('sicd_meta is required to be an instance of SICDType, got {}'.format(type(sicd_meta)))
    if sicd_meta.ImageData is None:
        raise ValueError('The sicd_meta has un-populated ImageData, and nothing useful can be inferred.')
    if sicd_meta.ImageData.NumCols is None or sicd_meta.ImageData.NumRows is None:
        raise ValueError('The sicd_meta has ImageData with unpopulated NumRows or NumCols, '
                         'and nothing useful can be inferred.')
    if sicd_meta.ImageData.PixelType is None:
        logger.warning('The PixelType for sicd_meta is unset, so defaulting to RE32F_IM32F.')
        sicd_meta.ImageData.PixelType = 'RE32F_IM32F'

    sicd_meta = sicd_meta.copy()

    profile = '{} {}'.format(__title__, __version__)
    if sicd_meta.ImageCreation is None:
        sicd_meta.ImageCreation = ImageCreationType(
            Application=profile,
            DateTime=numpy.datetime64(datetime.now()),
            Profile=profile)
    else:
        sicd_meta.ImageCreation.Profile = profile
        if sicd_meta.ImageCreation.DateTime is None:
            sicd_meta.ImageCreation.DateTime = numpy.datetime64(datetime.now())
    return sicd_meta
Beispiel #3
0
    def _get_freq_specific_sicd(
            gp: h5pyGroup,
            base_sicd: SICDType) -> Tuple[SICDType, List[str], List[str], float]:
        """
        Gets the frequency specific sicd.

        Parameters
        ----------
        gp : h5py.Group
        base_sicd : SICDType

        Returns
        -------
        sicd: SICDType
        pol_names : numpy.ndarray
        pols : List[str]
        center_frequency : float
        """

        def update_grid() -> None:
            row_imp_resp_bw = 2*gp['processedRangeBandwidth'][()]/speed_of_light
            t_sicd.Grid.Row.SS = gp['slantRangeSpacing'][()]
            t_sicd.Grid.Row.ImpRespBW = row_imp_resp_bw
            t_sicd.Grid.Row.DeltaK1 = -0.5*row_imp_resp_bw
            t_sicd.Grid.Row.DeltaK2 = -t_sicd.Grid.Row.DeltaK1

        def update_timeline() -> None:
            prf = gp['nominalAcquisitionPRF'][()]
            t_sicd.Timeline.IPP[0].IPPEnd = prf*t_sicd.Timeline.CollectDuration
            t_sicd.Timeline.IPP[0].IPPPoly = [0, prf]

        def define_radar_collection() -> List[str]:
            tx_rcv_pol_t = []
            tx_pol = []
            for entry in pols:
                tx_rcv_pol_t.append('{}:{}'.format(entry[0], entry[1]))
                if entry[0] not in tx_pol:
                    tx_pol.append(entry[0])
            center_freq_t = gp['acquiredCenterFrequency'][()]
            bw = gp['acquiredRangeBandwidth'][()]
            tx_freq = (center_freq_t - 0.5*bw, center_freq_t + 0.5*bw)
            rcv_chans = [ChanParametersType(TxRcvPolarization=pol) for pol in tx_rcv_pol_t]
            if len(tx_pol) == 1:
                tx_sequence = None
                tx_pol = tx_pol[0]
            else:
                tx_sequence = [TxStepType(WFIndex=j+1, TxPolarization=pol) for j, pol in enumerate(tx_pol)]
                tx_pol = 'SEQUENCE'

            t_sicd.RadarCollection = RadarCollectionType(
                TxFrequency=tx_freq,
                RcvChannels=rcv_chans,
                TxPolarization=tx_pol,
                TxSequence=tx_sequence)
            return tx_rcv_pol_t

        def update_image_formation() -> float:
            center_freq_t = gp['processedCenterFrequency'][()]
            bw = gp['processedRangeBandwidth'][()]
            t_sicd.ImageFormation.TxFrequencyProc = (center_freq_t - 0.5*bw, center_freq_t + 0.5*bw)
            return center_freq_t

        pols = _get_string_list(gp['listOfPolarizations'][:])
        t_sicd = base_sicd.copy()

        update_grid()
        update_timeline()
        tx_rcv_pol = define_radar_collection()
        center_freq = update_image_formation()
        return t_sicd, pols, tx_rcv_pol, center_freq
Beispiel #4
0
    def _get_pol_specific_sicd(
            hf: h5pyFile,
            ds: h5pyDataset,
            base_sicd: SICDType,
            pol_name: str,
            freq_name: str,
            j: int,
            pol: str,
            r_ca_sampled: numpy.ndarray,
            zd_time: numpy.ndarray,
            grid_zd_time: numpy.ndarray,
            grid_r: numpy.ndarray,
            doprate_sampled: numpy.ndarray,
            dopcentroid_sampled: numpy.ndarray,
            center_freq: float,
            ss_az_s: float,
            dop_bw: float,
            beta0,
            gamma0,
            sigma0) -> Tuple[SICDType, Tuple[int, ...], numpy.dtype]:
        """
        Gets the frequency/polarization specific sicd.

        Parameters
        ----------
        hf : h5py.File
        ds : h5py.Dataset
        base_sicd : SICDType
        pol_name : str
        freq_name : str
        j : int
        pol : str
        r_ca_sampled : numpy.ndarray
        zd_time : numpy.ndarray
        grid_zd_time : numpy.ndarray
        grid_r : numpy.ndarray
        doprate_sampled : numpy.ndarray
        dopcentroid_sampled : numpy.ndarray
        center_freq : float
        ss_az_s : float
        dop_bw : float

        Returns
        -------
        sicd: SICDType
        shape : Tuple[int, ...]
        numpy.dtype
        """

        def define_image_data() -> None:
            if dtype.name in ('float32', 'complex64'):
                pixel_type = 'RE32F_IM32F'
            elif dtype.name == 'int16':
                pixel_type = 'RE16I_IM16I'
            else:
                raise ValueError('Got unhandled dtype {}'.format(dtype))
            t_sicd.ImageData = ImageDataType(
                PixelType=pixel_type,
                NumRows=shape[1],
                NumCols=shape[0],
                FirstRow=0,
                FirstCol=0,
                SCPPixel=[0.5*shape[0], 0.5*shape[1]],
                FullImage=[shape[1], shape[0]])

        def update_image_formation() -> None:
            t_sicd.ImageFormation.RcvChanProc.ChanIndices = [j, ]
            t_sicd.ImageFormation.TxRcvPolarizationProc = pol

        def update_inca_and_grid() -> Tuple[numpy.ndarray, numpy.ndarray]:
            t_sicd.RMA.INCA.R_CA_SCP = r_ca_sampled[t_sicd.ImageData.SCPPixel.Row]
            scp_ca_time = zd_time[t_sicd.ImageData.SCPPixel.Col]

            # compute DRateSFPoly
            # velocity at scp ca time
            vel_ca = t_sicd.Position.ARPPoly.derivative_eval(scp_ca_time, der_order=1)
            # squared magnitude
            vm_ca_sq = numpy.sum(vel_ca*vel_ca)
            # polynomial coefficient for function representing range as a function of range distance from SCP
            r_ca_poly = numpy.array([t_sicd.RMA.INCA.R_CA_SCP, 1], dtype=numpy.float64)
            # closest Doppler rate polynomial to SCP
            min_ind = numpy.argmin(numpy.absolute(grid_zd_time - scp_ca_time))
            # define range coordinate grid
            coords_rg_m = grid_r - t_sicd.RMA.INCA.R_CA_SCP
            # determine dop_rate_poly coordinates
            dop_rate_poly = polynomial.polyfit(coords_rg_m, -doprate_sampled[min_ind, :], 4)  # why fourth order?
            t_sicd.RMA.INCA.FreqZero = center_freq
            t_sicd.RMA.INCA.DRateSFPoly = Poly2DType(Coefs=numpy.reshape(
                -numpy.convolve(dop_rate_poly, r_ca_poly)*speed_of_light/(2*center_freq*vm_ca_sq), (-1, 1)))

            # update Grid.Col parameters
            t_sicd.Grid.Col.SS = numpy.sqrt(vm_ca_sq)*abs(ss_az_s)*t_sicd.RMA.INCA.DRateSFPoly.Coefs[0, 0]
            t_sicd.Grid.Col.ImpRespBW = min(abs(dop_bw*ss_az_s), 1)/t_sicd.Grid.Col.SS
            t_sicd.RMA.INCA.TimeCAPoly = [scp_ca_time, ss_az_s/t_sicd.Grid.Col.SS]

            #TimeCOAPoly/DopCentroidPoly/DeltaKCOAPoly
            coords_az_m = (grid_zd_time - scp_ca_time)*t_sicd.Grid.Col.SS/ss_az_s

            # cerate the 2d grids
            coords_rg_2d_t, coords_az_2d_t = numpy.meshgrid(coords_rg_m, coords_az_m, indexing='xy')

            coefs, residuals, rank, sing_values = two_dim_poly_fit(
                coords_rg_2d_t, coords_az_2d_t, dopcentroid_sampled,
                x_order=3, y_order=3, x_scale=1e-3, y_scale=1e-3, rcond=1e-40)
            logger.info(
                'The dop_centroid_poly fit details:\n\t'
                'root mean square residuals = {}\n\t'
                'rank = {}\n\t'
                'singular values = {}'.format(residuals, rank, sing_values))
            t_sicd.RMA.INCA.DopCentroidPoly = Poly2DType(Coefs=coefs)
            t_sicd.Grid.Col.DeltaKCOAPoly = Poly2DType(Coefs=coefs*ss_az_s/t_sicd.Grid.Col.SS)

            timeca_sampled = numpy.outer(grid_zd_time, numpy.ones((grid_r.size, )))
            time_coa_sampled = timeca_sampled + (dopcentroid_sampled/doprate_sampled)
            coefs, residuals, rank, sing_values = two_dim_poly_fit(
                coords_rg_2d_t, coords_az_2d_t, time_coa_sampled,
                x_order=3, y_order=3, x_scale=1e-3, y_scale=1e-3, rcond=1e-40)
            logger.info(
                'The time_coa_poly fit details:\n\t'
                'root mean square residuals = {}\n\t'
                'rank = {}\n\t'
                'singular values = {}'.format(residuals, rank, sing_values))
            t_sicd.Grid.TimeCOAPoly = Poly2DType(Coefs=coefs)

            return coords_rg_2d_t, coords_az_2d_t

        def define_radiometric() -> None:
            def get_poly(ds: h5pyDataset, name: str) -> Optional[Poly2DType]:
                array = ds[:]
                fill = ds.attrs['_FillValue']
                boolc = (array != fill)

                if numpy.any(boolc):
                    array = array[boolc]
                    if numpy.any(array != array[0]):
                        coefs, residuals, rank, sing_values = two_dim_poly_fit(
                            coords_rg_2d[boolc], coords_az_2d[boolc], array,
                            x_order=3, y_order=3, x_scale=1e-3, y_scale=1e-3, rcond=1e-40)
                        logger.info(
                            'The {} fit details:\n\t'
                            'root mean square residuals = {}\n\t'
                            'rank = {}\n\t'
                            'singular values = {}'.format(name, residuals, rank, sing_values))
                    else:
                        # it's constant, so just use a constant polynomial
                        coefs = [[array[0], ], ]
                        logger.info('The {} values are constant'.format(name))
                    return Poly2DType(Coefs=coefs)
                else:
                    logger.warning('No non-trivial values for {} provided.'.format(name))
                    return None

            beta0_poly = get_poly(beta0, 'beta0')
            gamma0_poly = get_poly(gamma0, 'gamma0')
            sigma0_poly = get_poly(sigma0, 'sigma0')

            nesz = hf['/science/LSAR/SLC/metadata/calibrationInformation/frequency{}/{}/nes0'.format(freq_name,
                                                                                                     pol_name)][:]
            noise_samples = nesz - (10 * numpy.log10(sigma0_poly.Coefs[0, 0]))

            coefs, residuals, rank, sing_values = two_dim_poly_fit(
                coords_rg_2d, coords_az_2d, noise_samples,
                x_order=3, y_order=3, x_scale=1e-3, y_scale=1e-3, rcond=1e-40)
            logger.info(
                'The noise_poly fit details:\n\t'
                'root mean square residuals = {}\n\t'
                'rank = {}\n\t'
                'singular values = {}'.format(
                    residuals, rank, sing_values))
            t_sicd.Radiometric = RadiometricType(
                BetaZeroSFPoly=beta0_poly,
                GammaZeroSFPoly=gamma0_poly,
                SigmaZeroSFPoly=sigma0_poly,
                NoiseLevel=NoiseLevelType_(
                    NoiseLevelType='ABSOLUTE', NoisePoly=Poly2DType(Coefs=coefs)))

        def update_geodata() -> None:
            ecf = point_projection.image_to_ground(
                [t_sicd.ImageData.SCPPixel.Row, t_sicd.ImageData.SCPPixel.Col], t_sicd)
            t_sicd.GeoData.SCP = SCPType(ECF=ecf)  # LLH will be populated

        t_sicd = base_sicd.copy()
        shape = ds.shape
        dtype = ds.dtype

        define_image_data()
        update_image_formation()
        coords_rg_2d, coords_az_2d = update_inca_and_grid()
        define_radiometric()
        update_geodata()
        t_sicd.derive()
        t_sicd.populate_rniirs(override=False)
        return t_sicd, shape, dtype
Beispiel #5
0
    def _get_band_specific_sicds(self, base_sicd: SICDType, h5_dict: dict,
                                 band_dict: dict, shape_dict: dict,
                                 pixeltype_dict: dict) -> Dict[str, SICDType]:
        def update_scp_prelim(sicd: SICDType, band_name: str) -> None:
            if self._mission_id in ['CSK', 'KMPS']:
                LLH = band_dict[band_name]['Centre Geodetic Coordinates']
            elif self._mission_id == 'CSG':
                LLH = h5_dict['Scene Centre Geodetic Coordinates']
            else:
                raise ValueError(_unhandled_id_text.format(self._mission_id))
            sicd.GeoData = GeoDataType(
                SCP=SCPType(LLH=LLH))  # EarthModel & ECF will be populated

        def update_image_data(
                sicd: SICDType,
                band_name: str) -> (float, float, float, float, int):
            cols, rows = shape_dict[band_name]
            # zero doppler time of first/last columns
            t_az_first_time = band_dict[band_name][
                'Zero Doppler Azimuth First Time']
            t_az_last_time = band_dict[band_name][
                'Zero Doppler Azimuth Last Time']
            t_ss_az_s = band_dict[band_name]['Line Time Interval']
            t_use_sign2 = 1
            if h5_dict['Look Side'].upper() == 'LEFT':
                t_use_sign2 = -1
                t_az_first_time, t_az_last_time = t_az_last_time, t_az_first_time
            # zero doppler time of first row
            t_rg_first_time = band_dict[band_name][
                'Zero Doppler Range First Time']
            # row spacing in range time (seconds)
            t_ss_rg_s = band_dict[band_name]['Column Time Interval']

            sicd.ImageData = ImageDataType(NumRows=rows,
                                           NumCols=cols,
                                           FirstRow=0,
                                           FirstCol=0,
                                           FullImage=(rows, cols),
                                           PixelType=pixeltype_dict[band_name],
                                           SCPPixel=RowColType(
                                               Row=int(rows / 2),
                                               Col=int(cols / 2)))
            return t_rg_first_time, t_ss_rg_s, t_az_first_time, t_ss_az_s, t_use_sign2

        def check_switch_state() -> (int, Poly1DType):
            use_sign = 1 if t_dop_rate_poly_rg[0] < 0 else -1
            return use_sign, Poly1DType(Coefs=use_sign * t_dop_rate_poly_rg)

        def update_timeline(sicd: SICDType, band_name: str) -> None:
            prf = band_dict[band_name]['PRF']
            duration = sicd.Timeline.CollectDuration
            ipp_el = sicd.Timeline.IPP[0]
            ipp_el.IPPEnd = duration * prf
            ipp_el.TEnd = duration
            ipp_el.IPPPoly = Poly1DType(Coefs=(0, prf))

        def update_radar_collection(sicd: SICDType, band_name: str) -> None:
            ind = None
            for the_chan_index, chan in enumerate(
                    sicd.RadarCollection.RcvChannels):
                if chan.TxRcvPolarization == polarization:
                    ind = the_chan_index
                    break
            if ind is None:
                raise ValueError(
                    'Failed to find receive channel for polarization {}'.
                    format(polarization))

            chirp_length = band_dict[band_name]['Range Chirp Length']
            chirp_rate = abs(band_dict[band_name]['Range Chirp Rate'])
            sample_rate = band_dict[band_name]['Sampling Rate']
            ref_dechirp_time = band_dict[band_name].get(
                'Reference Dechirping Time', 0)  # TODO: is this right?
            win_length = band_dict[band_name]['Echo Sampling Window Length']
            rcv_fm_rate = 0 if numpy.isnan(ref_dechirp_time) else chirp_rate
            band_width = chirp_length * chirp_rate
            fr_min = center_frequency - 0.5 * band_width
            fr_max = center_frequency + 0.5 * band_width
            sicd.RadarCollection.TxFrequency = (fr_min, fr_max)
            sicd.RadarCollection.Waveform = [
                WaveformParametersType(index=0,
                                       TxPulseLength=chirp_length,
                                       TxRFBandwidth=band_width,
                                       TxFreqStart=fr_min,
                                       TxFMRate=chirp_rate,
                                       ADCSampleRate=sample_rate,
                                       RcvFMRate=rcv_fm_rate,
                                       RcvWindowLength=win_length /
                                       sample_rate),
            ]
            sicd.ImageFormation.RcvChanProc.ChanIndices = [
                ind + 1,
            ]
            sicd.ImageFormation.TxFrequencyProc = (fr_min, fr_max)

        def update_rma_and_grid(sicd: SICDType, band_name: str) -> None:
            rg_scp_time = rg_first_time + (ss_rg_s *
                                           sicd.ImageData.SCPPixel.Row)
            az_scp_time = az_first_time + (use_sign2 * ss_az_s *
                                           sicd.ImageData.SCPPixel.Col)
            r_ca_scp = rg_scp_time * speed_of_light / 2
            sicd.RMA.INCA.R_CA_SCP = r_ca_scp
            # compute DRateSFPoly
            scp_ca_time = az_scp_time + ref_time_offset
            vel_poly = sicd.Position.ARPPoly.derivative(der_order=1,
                                                        return_poly=True)
            vel_ca_vec = vel_poly(scp_ca_time)
            vel_ca_sq = numpy.sum(vel_ca_vec * vel_ca_vec)
            vel_ca = numpy.sqrt(vel_ca_sq)
            r_ca = numpy.array([r_ca_scp, 1.], dtype=numpy.float64)
            dop_rate_poly_rg_shifted = dop_rate_poly_rg.shift(
                rg_ref_time - rg_scp_time,
                alpha=ss_rg_s / row_ss,
                return_poly=False)
            drate_sf_poly = -(polynomial.polymul(dop_rate_poly_rg_shifted,
                                                 r_ca) * speed_of_light /
                              (2 * center_frequency * vel_ca_sq))
            # update grid.row
            sicd.Grid.Row.SS = row_ss
            sicd.Grid.Row.ImpRespBW = row_bw
            sicd.Grid.Row.DeltaK1 = -0.5 * row_bw
            sicd.Grid.Row.DeltaK2 = 0.5 * row_bw
            # update grid.col
            col_ss = abs(vel_ca * ss_az_s * drate_sf_poly[0])
            sicd.Grid.Col.SS = col_ss
            if self.mission_id == 'CSK':
                col_bw = min(
                    band_dict[band_name]
                    ['Azimuth Focusing Transition Bandwidth'] * ss_az_s,
                    1) / col_ss
            elif self.mission_id in ['CSG', 'KMPS']:
                col_bw = min(
                    band_dict[band_name]['Azimuth Focusing Bandwidth'] *
                    ss_az_s, 1) / col_ss
            else:
                raise ValueError('Got unhandled mission_id {}'.format(
                    self.mission_id))
            sicd.Grid.Col.ImpRespBW = col_bw
            # update inca
            sicd.RMA.INCA.DRateSFPoly = Poly2DType(
                Coefs=numpy.reshape(drate_sf_poly, (-1, 1)))
            sicd.RMA.INCA.TimeCAPoly = Poly1DType(
                Coefs=[scp_ca_time, use_sign2 * ss_az_s / col_ss])
            # compute DopCentroidPoly & DeltaKCOAPoly
            dop_centroid_poly = numpy.zeros(
                (dop_poly_rg.order1 + 1, dop_poly_az.order1 + 1),
                dtype=numpy.float64)
            dop_centroid_poly[0, 0] = dop_poly_rg(rg_scp_time-rg_ref_time) + \
                dop_poly_az(az_scp_time-az_ref_time) - \
                0.5*(dop_poly_rg[0] + dop_poly_az[0])
            dop_poly_rg_shifted = dop_poly_rg.shift(rg_ref_time - rg_scp_time,
                                                    alpha=ss_rg_s / row_ss)
            dop_poly_az_shifted = dop_poly_az.shift(az_ref_time - az_scp_time,
                                                    alpha=ss_az_s / col_ss)
            dop_centroid_poly[1:, 0] = dop_poly_rg_shifted[1:]
            dop_centroid_poly[0, 1:] = dop_poly_az_shifted[1:]
            sicd.RMA.INCA.DopCentroidPoly = Poly2DType(Coefs=dop_centroid_poly)
            sicd.RMA.INCA.DopCentroidCOA = True
            sicd.Grid.Col.DeltaKCOAPoly = Poly2DType(
                Coefs=use_sign * dop_centroid_poly * ss_az_s / col_ss)
            # fit TimeCOAPoly
            sicd.Grid.TimeCOAPoly = fit_time_coa_polynomial(
                sicd.RMA.INCA,
                sicd.ImageData,
                sicd.Grid,
                dop_rate_poly_rg_shifted,
                poly_order=2)

            if csk_addin is not None:
                csk_addin.check_sicd(sicd, self.mission_id, h5_dict)

        def update_radiometric(sicd: SICDType, band_name: str) -> None:
            if self.mission_id in ['KMPS', 'CSG']:
                # TODO: skipping for now - strange results for flag == 77. Awaiting gidance - see Wade.
                return
            if h5_dict['Range Spreading Loss Compensation Geometry'] != 'NONE':
                slant_range = h5_dict['Reference Slant Range']
                exp = h5_dict['Reference Slant Range Exponent']
                sf = slant_range**(2 * exp)
                rsf = h5_dict['Rescaling Factor']
                sf /= rsf * rsf
                if h5_dict.get('Calibration Constant Compensation Flag',
                               None) == 0:
                    cal = band_dict[band_name]['Calibration Constant']
                    sf /= cal
                sicd.Radiometric = RadiometricType(BetaZeroSFPoly=Poly2DType(
                    Coefs=[
                        [
                            sf,
                        ],
                    ]))

        def update_geodata(sicd: SICDType) -> None:
            scp_pixel = [
                sicd.ImageData.SCPPixel.Row, sicd.ImageData.SCPPixel.Col
            ]
            ecf = sicd.project_image_to_ground(scp_pixel,
                                               projection_type='HAE')
            sicd.update_scp(ecf, coord_system='ECF')

            SCP = sicd.GeoData.SCP.ECF.get_array(dtype='float64')
            scp_time = sicd.RMA.INCA.TimeCAPoly[0]
            ca_pos = sicd.Position.ARPPoly(scp_time)
            RG = SCP - ca_pos
            sicd.RMA.INCA.R_CA_SCP = numpy.linalg.norm(RG)

        out = {}
        center_frequency = h5_dict['Radar Frequency']
        # relative times in csk are wrt some reference time - for sicd they should be relative to start time
        collect_start = parse_timestring(h5_dict['Scene Sensing Start UTC'],
                                         precision='ns')
        ref_time = parse_timestring(h5_dict['Reference UTC'], precision='ns')
        ref_time_offset = get_seconds(ref_time, collect_start, precision='ns')

        for bd_name in band_dict:
            polarization = self._parse_pol(
                self._get_polarization(h5_dict, band_dict, bd_name))
            az_ref_time, rg_ref_time, t_dop_poly_az, t_dop_poly_rg, t_dop_rate_poly_rg = \
                self._get_dop_poly_details(h5_dict, band_dict, bd_name)
            dop_poly_az = Poly1DType(Coefs=t_dop_poly_az)
            dop_poly_rg = Poly1DType(Coefs=t_dop_poly_rg)

            t_sicd = base_sicd.copy()
            t_sicd.ImageFormation.TxRcvPolarizationProc = polarization

            row_bw = band_dict[bd_name][
                'Range Focusing Bandwidth'] * 2 / speed_of_light
            row_ss = band_dict[bd_name]['Column Spacing']
            rg_first_time, ss_rg_s, az_first_time, ss_az_s, use_sign2 = update_image_data(
                t_sicd, bd_name)
            use_sign, dop_rate_poly_rg = check_switch_state()
            update_timeline(t_sicd, bd_name)
            update_radar_collection(t_sicd, bd_name)
            update_rma_and_grid(t_sicd, bd_name)
            update_radiometric(t_sicd, bd_name)

            update_scp_prelim(
                t_sicd, bd_name
            )  # set preliminary value for SCP (required for projection)
            update_geodata(t_sicd)
            t_sicd.derive()
            # t_sicd.populate_rniirs(override=False)
            out[bd_name] = t_sicd
        return out