Ejemplo n.º 1
0
    def _get_zero_doppler_data(hf, base_sicd):
        """
        Gets zero-doppler parameters.

        Parameters
        ----------
        hf : h5py.File
        base_sicd : SICDType

        Returns
        -------
        (numpy.ndarray, float, numpy.ndarray, numpy.ndarray)
            The azimuth zero-doppler time array, azimuth zero-doppler time spacing,
            grid range array, range zero doppler time array.
        """

        gp = hf['/science/LSAR/SLC/swaths']
        ds = gp['zeroDopplerTime']
        ref_time = _get_ref_time(ds.attrs['units'])
        zd_time = ds[:] + get_seconds(ref_time, base_sicd.Timeline.CollectStart, precision='ns')
        ss_az_s = gp['zeroDopplerTimeSpacing'][()]

        if base_sicd.SCPCOA.SideOfTrack == 'L':
            zd_time = zd_time[::-1]
            ss_az_s *= -1

        gp = hf['/science/LSAR/SLC/metadata/processingInformation/parameters']
        grid_r = gp['slantRange'][:]
        ds = gp['zeroDopplerTime']
        ref_time = _get_ref_time(ds.attrs['units'])
        grid_zd_time = ds[:] + get_seconds(ref_time, base_sicd.Timeline.CollectStart, precision='ns')

        return zd_time, ss_az_s, grid_r, grid_zd_time
Ejemplo n.º 2
0
        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)
Ejemplo n.º 3
0
 def get_position() -> PositionType:
     gp = hf['/science/LSAR/SLC/metadata/orbit']
     ref_time = _get_ref_time(gp['time'].attrs['units'])
     T = gp['time'][:] + get_seconds(ref_time, collect_start, precision='ns')
     Pos = gp['position'][:]
     Vel = gp['velocity'][:]
     P_x, P_y, P_z = fit_position_xvalidation(T, Pos, Vel, max_degree=8)
     return PositionType(ARPPoly=XYZPolyType(X=P_x, Y=P_y, Z=P_z))
Ejemplo n.º 4
0
    def _get_position(self):
        """
        Gets the Position.

        Returns
        -------
        PositionType
        """

        start_time = self._get_start_time()
        # get radar position state information
        state_vectors = self._findall('./sourceAttributes'
                                      '/orbitAndAttitude'
                                      '/orbitInformation'
                                      '/stateVector')
        # convert to relevant numpy arrays for polynomial fitting
        T = numpy.array([
            get_seconds(parse_timestring(state_vec.find('timeStamp').text),
                        start_time,
                        precision='us') for state_vec in state_vectors
        ],
                        dtype=numpy.float64)
        Pos = numpy.hstack((numpy.array([
            float(state_vec.find('xPosition').text)
            for state_vec in state_vectors
        ],
                                        dtype=numpy.float64)[:, numpy.newaxis],
                            numpy.array([
                                float(state_vec.find('yPosition').text)
                                for state_vec in state_vectors
                            ],
                                        dtype=numpy.float64)[:, numpy.newaxis],
                            numpy.array([
                                float(state_vec.find('zPosition').text)
                                for state_vec in state_vectors
                            ],
                                        dtype=numpy.float64)[:,
                                                             numpy.newaxis]))
        Vel = numpy.hstack((numpy.array([
            float(state_vec.find('xVelocity').text)
            for state_vec in state_vectors
        ],
                                        dtype=numpy.float64)[:, numpy.newaxis],
                            numpy.array([
                                float(state_vec.find('yVelocity').text)
                                for state_vec in state_vectors
                            ],
                                        dtype=numpy.float64)[:, numpy.newaxis],
                            numpy.array([
                                float(state_vec.find('zVelocity').text)
                                for state_vec in state_vectors
                            ],
                                        dtype=numpy.float64)[:,
                                                             numpy.newaxis]))
        P_x, P_y, P_z = fit_position_xvalidation(T, Pos, Vel, max_degree=8)

        return PositionType(ARPPoly=XYZPolyType(X=P_x, Y=P_y, Z=P_z))
Ejemplo n.º 5
0
 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
Ejemplo n.º 6
0
        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)
Ejemplo n.º 7
0
 def get_position():
     # type: () -> PositionType
     # fetch the state information
     times_str = hf['state_vector_time_utc'][:, 0]
     times = numpy.zeros((times_str.shape[0], ), dtype='float64')
     positions = numpy.zeros((times.size, 3), dtype='float64')
     velocities = numpy.zeros((times.size, 3), dtype='float64')
     for i, entry in enumerate(times_str):
         times[i] = get_seconds(_parse_time(entry), start_time, precision='us')
     positions[:, 0], positions[:, 1], positions[:, 2] = hf['posX'][:], hf['posY'][:], hf['posZ'][:]
     velocities[:, 0], velocities[:, 1], velocities[:, 2] = hf['velX'][:], hf['velY'][:], hf['velZ'][:]
     # fir the the position polynomial using cross validation
     P_x, P_y, P_z = fit_position_xvalidation(times, positions, velocities, max_degree=8)
     return PositionType(ARPPoly=XYZPolyType(X=P_x, Y=P_y, Z=P_z))
Ejemplo n.º 8
0
        def calculate_doppler_polys():
            # extract doppler centroid coefficients
            dc_estimate_coeffs = hf['dc_estimate_coeffs'][:]
            dc_time_str = hf['dc_estimate_time_utc'][:, 0]
            dc_zd_times = numpy.zeros((dc_time_str.shape[0], ), dtype='float64')
            for i, entry in enumerate(dc_time_str):
                dc_zd_times[i] = get_seconds(_parse_time(entry), start_time, precision='us')
            # create a sampled doppler centroid
            samples = 49  # copied from corresponding matlab, we just need enough for appropriate refitting
            # create doppler time samples
            diff_time_rg = first_pixel_time - zd_ref_time + \
                           numpy.linspace(0, number_of_range_samples/range_sampling_rate, samples)
            # doppler centroid samples definition
            dc_sample_array = numpy.zeros((samples, dc_zd_times.size), dtype='float64')
            for i, coeffs in enumerate(dc_estimate_coeffs):
                dc_sample_array[:, i] = polynomial.polyval(diff_time_rg, coeffs)
            # create arrays for range/azimuth from scp in meters
            azimuth_scp_m, range_scp_m = numpy.meshgrid(
                col_ss*(dc_zd_times - zd_time_scp)/ss_zd_s,
                (diff_time_rg + zd_ref_time - rg_time_scp)*speed_of_light/2)

            # fit the doppler centroid sample array
            x_order = min(3, range_scp_m.shape[0]-1)
            y_order = min(3, range_scp_m.shape[1]-1)

            t_dop_centroid_poly, residuals, rank, sing_values = two_dim_poly_fit(
                range_scp_m, azimuth_scp_m, dc_sample_array, x_order=x_order, y_order=y_order,
                x_scale=1e-3, y_scale=1e-3, rcond=1e-40)
            logger.info(
                'The dop_centroid_poly fit details:\n\troot mean square '
                'residuals = {}\n\trank = {}\n\tsingular values = {}'.format(
                    residuals, rank, sing_values))

            # define and fit the time coa array
            doppler_rate_sampled = polynomial.polyval(azimuth_scp_m, drate_ca_poly)
            time_coa = dc_zd_times + dc_sample_array/doppler_rate_sampled
            t_time_coa_poly, residuals, rank, sing_values = two_dim_poly_fit(
                range_scp_m, azimuth_scp_m, time_coa, x_order=x_order, y_order=y_order,
                x_scale=1e-3, y_scale=1e-3, rcond=1e-40)
            logger.info(
                'The time_coa_poly fit details:\n\troot mean square '
                'residuals = {}\n\trank = {}\n\tsingular values = {}'.format(
                    residuals, rank, sing_values))
            return t_dop_centroid_poly, t_time_coa_poly
Ejemplo n.º 9
0
    def _get_collection_times(hf):
        """
        Gets the collection start and end times, and inferred duration.

        Parameters
        ----------
        hf : h5py.File
            The h5py File object.

        Returns
        -------
        (numpy.datetime64, numpy.datetime64, float)
            Start and end times and duration
        """

        start = parse_timestring(_stringify(hf['/science/LSAR/identification/zeroDopplerStartTime'][()]), precision='ns')
        end = parse_timestring(_stringify(hf['/science/LSAR/identification/zeroDopplerEndTime'][()]), precision='ns')
        duration = get_seconds(end, start, precision='ns')
        return start, end, duration
Ejemplo n.º 10
0
    def _get_collection_times(hf: h5pyFile) -> Tuple[numpy.datetime64, numpy.datetime64, float]:
        """
        Gets the collection start and end times, and inferred duration.

        Parameters
        ----------
        hf : h5py.File
            The h5py File object.

        Returns
        -------
        start_time : numpy.datetime64
        end_time : numpy.datetime64
        duration : float
        """

        start_time = parse_timestring(_stringify(hf['/science/LSAR/identification/zeroDopplerStartTime'][()]), precision='ns')
        end_time = parse_timestring(_stringify(hf['/science/LSAR/identification/zeroDopplerEndTime'][()]), precision='ns')
        duration = get_seconds(end_time, start_time, precision='ns')
        return start_time, end_time, duration
Ejemplo n.º 11
0
def is_same_start_time(sicd1, sicd2):
    """
    Do the two SICD structures have the same start time with millisecond resolution?

    Parameters
    ----------
    sicd1 : sarpy.io.complex.sicd_elements.SICD.SICDType
    sicd2 : sarpy.io.complex.sicd_elements.SICD.SICDType

    Returns
    -------
    bool
    """

    if sicd1 is sicd2:
        return True

    try:
        return abs(
            get_seconds(sicd1.Timeline.CollectStart,
                        sicd2.Timeline.CollectStart,
                        precision='ms')) < 2e-3
    except AttributeError:
        return False
Ejemplo n.º 12
0
    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.º 13
0
    def get_sicd(self):
        """
        Gets the SICD structure.

        Returns
        -------
        Tuple[SICDType, tuple, tuple]
            The sicd structure, the data size argument, and the symmetry argument.
        """
        def get_collection_info():
            # type: () -> CollectionInfoType
            return CollectionInfoType(
                CollectorName=_stringify(hf['satellite_name'][()]),
                CoreName=_stringify(hf['product_name'][()]),
                CollectType='MONOSTATIC',
                Classification='UNCLASSIFIED',
                RadarMode=RadarModeType(
                    ModeType=_stringify(hf['acquisition_mode'][()]).upper(),
                    ModeID=_stringify(hf['product_type'][()])))

        def get_image_creation():
            # type: () -> ImageCreationType
            from sarpy.__about__ import __version__
            return ImageCreationType(
                Application='ICEYE_P_{}'.format(hf['processor_version'][()]),
                DateTime=_parse_time(hf['processing_time'][()]),
                Site='Unknown',
                Profile='sarpy {}'.format(__version__))

        def get_image_data():
            # type: () -> ImageDataType

            samp_prec = _stringify(hf['sample_precision'][()])
            if samp_prec.upper() == 'INT16':
                pixel_type = 'RE16I_IM16I'
            elif samp_prec.upper() == 'FLOAT32':
                pixel_type = 'RE32F_IM32F'
            else:
                raise ValueError(
                    'Got unhandled sample precision {}'.format(samp_prec))

            num_rows = int_func(number_of_range_samples)
            num_cols = int_func(number_of_azimuth_samples)
            scp_row = int_func(coord_center[0]) - 1
            scp_col = int_func(coord_center[1]) - 1
            if 0 < scp_col < num_rows - 1:
                if look_side == 'left':
                    scp_col = num_cols - scp_col - 1
            else:
                # early ICEYE processing bug led to nonsensical SCP
                scp_col = int_func(num_cols / 2.0)

            return ImageDataType(PixelType=pixel_type,
                                 NumRows=num_rows,
                                 NumCols=num_cols,
                                 FirstRow=0,
                                 FirstCol=0,
                                 FullImage=(num_rows, num_cols),
                                 SCPPixel=(scp_row, scp_col))

        def get_geo_data():
            # type: () -> GeoDataType
            # NB: the remainder will be derived.
            return GeoDataType(SCP=SCPType(
                LLH=[coord_center[2], coord_center[3], avg_scene_height]))

        def get_timeline():
            # type: () -> TimelineType

            acq_prf = hf['acquisition_prf'][()]
            return TimelineType(CollectStart=start_time,
                                CollectDuration=duration,
                                IPP=[
                                    IPPSetType(index=0,
                                               TStart=0,
                                               TEnd=duration,
                                               IPPStart=0,
                                               IPPEnd=int_func(
                                                   round(acq_prf * duration)),
                                               IPPPoly=[0, acq_prf]),
                                ])

        def get_position():
            # type: () -> PositionType
            # fetch the state information
            times_str = hf['state_vector_time_utc'][:, 0]
            times = numpy.zeros((times_str.shape[0], ), dtype='float64')
            positions = numpy.zeros((times.size, 3), dtype='float64')
            velocities = numpy.zeros((times.size, 3), dtype='float64')
            for i, entry in enumerate(times_str):
                times[i] = get_seconds(_parse_time(entry),
                                       start_time,
                                       precision='us')
            positions[:, 0], positions[:, 1], positions[:, 2] = hf[
                'posX'][:], hf['posY'][:], hf['posZ'][:]
            velocities[:, 0], velocities[:, 1], velocities[:, 2] = hf[
                'velX'][:], hf['velY'][:], hf['velZ'][:]
            # fir the the position polynomial using cross validation
            P_x, P_y, P_z = fit_position_xvalidation(times,
                                                     positions,
                                                     velocities,
                                                     max_degree=8)
            return PositionType(ARPPoly=XYZPolyType(X=P_x, Y=P_y, Z=P_z))

        def get_radar_collection():
            # type : () -> RadarCollection
            return RadarCollectionType(
                TxPolarization=tx_pol,
                TxFrequency=TxFrequencyType(Min=min_freq, Max=max_freq),
                Waveform=[
                    WaveformParametersType(
                        TxFreqStart=min_freq,
                        TxRFBandwidth=tx_bandwidth,
                        TxPulseLength=hf['chirp_duration'][()],
                        ADCSampleRate=hf['range_sampling_rate'][()],
                        RcvDemodType='CHIRP',
                        RcvFMRate=0,
                        index=1)
                ],
                RcvChannels=[
                    ChanParametersType(TxRcvPolarization=polarization, index=1)
                ])

        def get_image_formation():
            # type: () -> ImageFormationType
            return ImageFormationType(
                TxRcvPolarizationProc=polarization,
                ImageFormAlgo='RMA',
                TStartProc=0,
                TEndProc=duration,
                TxFrequencyProc=TxFrequencyProcType(MinProc=min_freq,
                                                    MaxProc=max_freq),
                STBeamComp='NO',
                ImageBeamComp='SV',
                AzAutofocus='NO',
                RgAutofocus='NO',
                RcvChanProc=RcvChanProcType(NumChanProc=1,
                                            PRFScaleFactor=1,
                                            ChanIndices=[
                                                1,
                                            ]),
            )

        def get_radiometric():
            # type: () -> RadiometricType
            return RadiometricType(BetaZeroSFPoly=[
                [
                    float(hf['calibration_factor'][()]),
                ],
            ])

        def calculate_drate_sf_poly():
            r_ca_coeffs = numpy.array([r_ca_scp, 1], dtype='float64')
            dop_rate_coeffs = hf['doppler_rate_coeffs'][:]
            # Prior to ICEYE 1.14 processor, absolute value of Doppler rate was
            # provided, not true Doppler rate. Doppler rate should always be negative
            if dop_rate_coeffs[0] > 0:
                dop_rate_coeffs *= -1
            dop_rate_poly = Poly1DType(Coefs=dop_rate_coeffs)
            # now adjust to create
            t_drate_ca_poly = dop_rate_poly.shift(t_0=zd_ref_time -
                                                  rg_time_scp,
                                                  alpha=2 / speed_of_light,
                                                  return_poly=False)
            return t_drate_ca_poly, -polynomial.polymul(
                t_drate_ca_poly, r_ca_coeffs) * speed_of_light / (
                    2 * center_freq * vm_ca_sq)

        def calculate_doppler_polys():
            # extract doppler centroid coefficients
            dc_estimate_coeffs = hf['dc_estimate_coeffs'][:]
            dc_time_str = hf['dc_estimate_time_utc'][:, 0]
            dc_zd_times = numpy.zeros((dc_time_str.shape[0], ),
                                      dtype='float64')
            for i, entry in enumerate(dc_time_str):
                dc_zd_times[i] = get_seconds(_parse_time(entry),
                                             start_time,
                                             precision='us')
            # create a sampled doppler centroid
            samples = 49  # copied from corresponding matlab, we just need enough for appropriate refitting
            # create doppler time samples
            diff_time_rg = first_pixel_time - zd_ref_time + \
                           numpy.linspace(0, number_of_range_samples/range_sampling_rate, samples)
            # doppler centroid samples definition
            dc_sample_array = numpy.zeros((samples, dc_zd_times.size),
                                          dtype='float64')
            for i, coeffs in enumerate(dc_estimate_coeffs):
                dc_sample_array[:,
                                i] = polynomial.polyval(diff_time_rg, coeffs)
            # create arrays for range/azimuth from scp in meters
            azimuth_scp_m, range_scp_m = numpy.meshgrid(
                col_ss * (dc_zd_times - zd_time_scp) / ss_zd_s,
                (diff_time_rg + zd_ref_time - rg_time_scp) * speed_of_light /
                2)

            # fit the doppler centroid sample array
            x_order = min(3, range_scp_m.shape[0] - 1)
            y_order = min(3, range_scp_m.shape[1] - 1)

            t_dop_centroid_poly, residuals, rank, sing_values = two_dim_poly_fit(
                range_scp_m,
                azimuth_scp_m,
                dc_sample_array,
                x_order=x_order,
                y_order=y_order,
                x_scale=1e-3,
                y_scale=1e-3,
                rcond=1e-40)
            logging.info(
                'The dop_centroid_poly fit details:\nroot mean square '
                'residuals = {}\nrank = {}\nsingular values = {}'.format(
                    residuals, rank, sing_values))

            # define and fit the time coa array
            doppler_rate_sampled = polynomial.polyval(azimuth_scp_m,
                                                      drate_ca_poly)
            time_coa = dc_zd_times + dc_sample_array / doppler_rate_sampled
            t_time_coa_poly, residuals, rank, sing_values = two_dim_poly_fit(
                range_scp_m,
                azimuth_scp_m,
                time_coa,
                x_order=x_order,
                y_order=y_order,
                x_scale=1e-3,
                y_scale=1e-3,
                rcond=1e-40)
            logging.info(
                'The time_coa_poly fit details:\nroot mean square '
                'residuals = {}\nrank = {}\nsingular values = {}'.format(
                    residuals, rank, sing_values))
            return t_dop_centroid_poly, t_time_coa_poly

        def get_rma():
            # type: () -> RMAType
            dop_centroid_poly = Poly2DType(Coefs=dop_centroid_poly_coeffs)
            dop_centroid_coa = True
            if collect_info.RadarMode.ModeType == 'SPOTLIGHT':
                dop_centroid_poly = None
                dop_centroid_coa = None
            # NB: DRateSFPoly is defined as a function of only range - reshape appropriately
            inca = INCAType(
                R_CA_SCP=r_ca_scp,
                FreqZero=center_freq,
                DRateSFPoly=Poly2DType(
                    Coefs=numpy.reshape(drate_sf_poly_coefs, (-1, 1))),
                DopCentroidPoly=dop_centroid_poly,
                DopCentroidCOA=dop_centroid_coa,
                TimeCAPoly=Poly1DType(Coefs=time_ca_poly_coeffs))
            return RMAType(RMAlgoType='OMEGA_K', INCA=inca)

        def get_grid():
            # type: () -> GridType
            time_coa_poly = Poly2DType(Coefs=time_coa_poly_coeffs)
            if collect_info.RadarMode.ModeType == 'SPOTLIGHT':
                time_coa_poly = Poly2DType(Coefs=[
                    [
                        float(time_coa_poly_coeffs[0, 0]),
                    ],
                ])

            row_win = _stringify(hf['window_function_range'][()])
            if row_win == 'NONE':
                row_win = 'UNIFORM'
            row = DirParamType(SS=row_ss,
                               Sgn=-1,
                               KCtr=2 * center_freq / speed_of_light,
                               ImpRespBW=2 * tx_bandwidth / speed_of_light,
                               DeltaKCOAPoly=Poly2DType(Coefs=[[
                                   0,
                               ]]),
                               WgtType=WgtTypeType(WindowName=row_win))
            col_win = _stringify(hf['window_function_azimuth'][()])
            if col_win == 'NONE':
                col_win = 'UNIFORM'
            col = DirParamType(
                SS=col_ss,
                Sgn=-1,
                KCtr=0,
                ImpRespBW=col_imp_res_bw,
                WgtType=WgtTypeType(WindowName=col_win),
                DeltaKCOAPoly=Poly2DType(Coefs=dop_centroid_poly_coeffs *
                                         ss_zd_s / col_ss))
            return GridType(Type='RGZERO',
                            ImagePlane='SLANT',
                            TimeCOAPoly=time_coa_poly,
                            Row=row,
                            Col=col)

        def correct_scp():
            scp_pixel = sicd.ImageData.SCPPixel.get_array()
            scp_ecf = sicd.project_image_to_ground(scp_pixel,
                                                   projection_type='HAE')
            sicd.update_scp(scp_ecf, coord_system='ECF')

        with h5py.File(self._file_name, 'r') as hf:
            # some common use variables
            look_side = _stringify(hf['look_side'][()])
            coord_center = hf['coord_center'][:]
            avg_scene_height = float(hf['avg_scene_height'][()])
            start_time = _parse_time(hf['acquisition_start_utc'][()])
            end_time = _parse_time(hf['acquisition_end_utc'][()])
            duration = get_seconds(end_time, start_time, precision='us')

            center_freq = float(hf['carrier_frequency'][()])
            tx_bandwidth = float(hf['chirp_bandwidth'][()])
            min_freq = center_freq - 0.5 * tx_bandwidth
            max_freq = center_freq + 0.5 * tx_bandwidth

            pol_temp = _stringify(hf['polarization'][()])
            tx_pol = pol_temp[0]
            rcv_pol = pol_temp[1]
            polarization = tx_pol + ':' + rcv_pol

            first_pixel_time = float(hf['first_pixel_time'][()])
            near_range = first_pixel_time * speed_of_light / 2
            number_of_range_samples = float(hf['number_of_range_samples'][()])
            number_of_azimuth_samples = float(
                hf['number_of_azimuth_samples'][()])
            range_sampling_rate = float(hf['range_sampling_rate'][()])
            row_ss = speed_of_light / (2 * range_sampling_rate)

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

            # calculate some zero doppler parameters
            ss_zd_s = float(hf['azimuth_time_interval'][()])
            if look_side == 'left':
                ss_zd_s *= -1
                zero_doppler_left = _parse_time(hf['zerodoppler_end_utc'][()])
            else:
                zero_doppler_left = _parse_time(
                    hf['zerodoppler_start_utc'][()])
            dop_bw = hf['total_processed_bandwidth_azimuth'][()]
            zd_time_scp = get_seconds(zero_doppler_left, start_time, precision='us') + \
                          image_data.SCPPixel.Col*ss_zd_s
            zd_ref_time = first_pixel_time + number_of_range_samples / (
                2 * range_sampling_rate)
            vel_scp = position.ARPPoly.derivative_eval(zd_time_scp,
                                                       der_order=1)
            vm_ca_sq = numpy.sum(vel_scp * vel_scp)
            rg_time_scp = first_pixel_time + image_data.SCPPixel.Row / range_sampling_rate
            r_ca_scp = rg_time_scp * speed_of_light / 2
            # calculate the doppler rate sf polynomial
            drate_ca_poly, drate_sf_poly_coefs = calculate_drate_sf_poly()

            # calculate some doppler dependent grid parameters
            col_ss = float(
                numpy.sqrt(vm_ca_sq) * abs(ss_zd_s) * drate_sf_poly_coefs[0])
            col_imp_res_bw = dop_bw * abs(ss_zd_s) / col_ss
            time_ca_poly_coeffs = [zd_time_scp, ss_zd_s / col_ss]

            # calculate the doppler polynomials
            dop_centroid_poly_coeffs, time_coa_poly_coeffs = calculate_doppler_polys(
            )

            # finish definition of sicd elements
            rma = get_rma()
            grid = get_grid()
            sicd = SICDType(CollectionInfo=collect_info,
                            ImageCreation=image_creation,
                            ImageData=image_data,
                            GeoData=geo_data,
                            Timeline=timeline,
                            Position=position,
                            RadarCollection=radar_collection,
                            ImageFormation=image_formation,
                            Radiometric=radiometric,
                            RMA=rma,
                            Grid=grid)
        # adjust the scp location
        correct_scp()
        # derive sicd fields
        sicd.derive()
        # TODO: RNIIRS?
        data_size = (image_data.NumCols, image_data.NumRows)
        symmetry = (True, False,
                    True) if look_side == 'left' else (False, False, True)
        return sicd, data_size, symmetry
Ejemplo n.º 14
0
    def _get_rma_adjust_grid(self, scpcoa, grid, image_data, position,
                             collection_info):
        """
        Gets the RMA metadata, and adjust the Grid.Col metadata.

        Parameters
        ----------
        scpcoa : SCPCOAType
        grid : GridType
        image_data : ImageDataType
        position : PositionType
        collection_info : CollectionInfoType

        Returns
        -------
        RMAType
        """

        look = scpcoa.look
        start_time = self._get_start_time()
        center_freq = self._get_center_frequency()
        doppler_bandwidth = float(
            self._find('./imageGenerationParameters'
                       '/sarProcessingInformation'
                       '/totalProcessedAzimuthBandwidth').text)
        zero_dop_last_line = parse_timestring(
            self._find('./imageGenerationParameters'
                       '/sarProcessingInformation'
                       '/zeroDopplerTimeLastLine').text)
        zero_dop_first_line = parse_timestring(
            self._find('./imageGenerationParameters'
                       '/sarProcessingInformation'
                       '/zeroDopplerTimeFirstLine').text)
        if look > 1:  # SideOfTrack == 'L'
            # we explicitly want negative time order
            if zero_dop_first_line < zero_dop_last_line:
                zero_dop_first_line, zero_dop_last_line = zero_dop_last_line, zero_dop_first_line
        else:
            # we explicitly want positive time order
            if zero_dop_first_line > zero_dop_last_line:
                zero_dop_first_line, zero_dop_last_line = zero_dop_last_line, zero_dop_first_line
        col_spacing_zd = get_seconds(zero_dop_last_line,
                                     zero_dop_first_line,
                                     precision='us') / (image_data.NumCols - 1)
        # zero doppler time of SCP relative to collect start
        time_scp_zd = get_seconds(zero_dop_first_line, start_time, precision='us') + \
            image_data.SCPPixel.Col*col_spacing_zd
        if self.generation == 'RS2':
            near_range = float(
                self._find('./imageGenerationParameters'
                           '/sarProcessingInformation'
                           '/slantRangeNearEdge').text)
        elif self.generation == 'RCM':
            near_range = float(
                self._find('./sceneAttributes'
                           '/imageAttributes'
                           '/slantRangeNearEdge').text)
        else:
            raise ValueError('unhandled generation {}'.format(self.generation))

        inca = INCAType(R_CA_SCP=near_range +
                        (image_data.SCPPixel.Row * grid.Row.SS),
                        FreqZero=center_freq)
        # doppler rate calculations
        velocity = position.ARPPoly.derivative_eval(time_scp_zd, 1)
        vel_ca_squared = numpy.sum(velocity * velocity)
        # polynomial representing range as a function of range distance from SCP
        r_ca = numpy.array([inca.R_CA_SCP, 1], dtype=numpy.float64)
        # doppler rate coefficients
        if self.generation == 'RS2':
            doppler_rate_coeffs = numpy.array([
                float(entry) for entry in self._find(
                    './imageGenerationParameters'
                    '/dopplerRateValues'
                    '/dopplerRateValuesCoefficients').text.split()
            ],
                                              dtype=numpy.float64)
            doppler_rate_ref_time = float(
                self._find('./imageGenerationParameters'
                           '/dopplerRateValues'
                           '/dopplerRateReferenceTime').text)
        elif self.generation == 'RCM':
            doppler_rate_coeffs = numpy.array([
                float(entry) for entry in self._find(
                    './dopplerRate'
                    '/dopplerRateEstimate'
                    '/dopplerRateCoefficients').text.split()
            ],
                                              dtype=numpy.float64)
            doppler_rate_ref_time = float(
                self._find('./dopplerRate'
                           '/dopplerRateEstimate'
                           '/dopplerRateReferenceTime').text)
        else:
            raise ValueError('unhandled generation {}'.format(self.generation))

        # the doppler_rate_coeffs represents a polynomial in time, relative to
        #   doppler_rate_ref_time.
        # to construct the doppler centroid polynomial, we need to change scales
        #   to a polynomial in space, relative to SCP.
        doppler_rate_poly = Poly1DType(Coefs=doppler_rate_coeffs)
        alpha = 2.0 / speed_of_light
        t_0 = doppler_rate_ref_time - alpha * inca.R_CA_SCP
        dop_rate_scaled_coeffs = doppler_rate_poly.shift(t_0,
                                                         alpha,
                                                         return_poly=False)
        # DRateSFPoly is then a scaled multiple of this scaled poly and r_ca above
        coeffs = -numpy.convolve(dop_rate_scaled_coeffs, r_ca) / (
            alpha * center_freq * vel_ca_squared)
        inca.DRateSFPoly = Poly2DType(
            Coefs=numpy.reshape(coeffs, (coeffs.size, 1)))

        # modify a few of the other fields
        ss_scale = numpy.sqrt(vel_ca_squared) * inca.DRateSFPoly[0, 0]
        grid.Col.SS = col_spacing_zd * ss_scale
        grid.Col.ImpRespBW = -look * doppler_bandwidth / ss_scale
        inca.TimeCAPoly = Poly1DType(Coefs=[time_scp_zd, 1. / ss_scale])

        # doppler centroid
        if self.generation == 'RS2':
            doppler_cent_coeffs = numpy.array([
                float(entry) for entry in self._find(
                    './imageGenerationParameters'
                    '/dopplerCentroid'
                    '/dopplerCentroidCoefficients').text.split()
            ],
                                              dtype=numpy.float64)
            doppler_cent_ref_time = float(
                self._find('./imageGenerationParameters'
                           '/dopplerCentroid'
                           '/dopplerCentroidReferenceTime').text)
            doppler_cent_time_est = parse_timestring(
                self._find('./imageGenerationParameters'
                           '/dopplerCentroid'
                           '/timeOfDopplerCentroidEstimate').text)
        elif self.generation == 'RCM':
            doppler_cent_coeffs = numpy.array([
                float(entry) for entry in self._find(
                    './dopplerCentroid'
                    '/dopplerCentroidEstimate'
                    '/dopplerCentroidCoefficients').text.split()
            ],
                                              dtype=numpy.float64)
            doppler_cent_ref_time = float(
                self._find('./dopplerCentroid'
                           '/dopplerCentroidEstimate'
                           '/dopplerCentroidReferenceTime').text)
            doppler_cent_time_est = parse_timestring(
                self._find('./dopplerCentroid'
                           '/dopplerCentroidEstimate'
                           '/timeOfDopplerCentroidEstimate').text)
        else:
            raise ValueError('unhandled generation {}'.format(self.generation))

        doppler_cent_poly = Poly1DType(Coefs=doppler_cent_coeffs)
        alpha = 2.0 / speed_of_light
        t_0 = doppler_cent_ref_time - alpha * inca.R_CA_SCP
        scaled_coeffs = doppler_cent_poly.shift(t_0, alpha, return_poly=False)
        inca.DopCentroidPoly = Poly2DType(
            Coefs=numpy.reshape(scaled_coeffs, (scaled_coeffs.size, 1)))
        # adjust doppler centroid for spotlight, we need to add a second
        # dimension to DopCentroidPoly
        if collection_info.RadarMode.ModeType == 'SPOTLIGHT':
            doppler_cent_est = get_seconds(doppler_cent_time_est,
                                           start_time,
                                           precision='us')
            doppler_cent_col = (doppler_cent_est -
                                time_scp_zd) / col_spacing_zd
            dop_poly = numpy.zeros((scaled_coeffs.shape[0], 2),
                                   dtype=numpy.float64)
            dop_poly[:, 0] = scaled_coeffs
            dop_poly[0, 1] = -look * center_freq * alpha * numpy.sqrt(
                vel_ca_squared) / inca.R_CA_SCP
            # dopplerCentroid in native metadata was defined at specific column,
            # which might not be our SCP column.  Adjust so that SCP column is correct.
            dop_poly[0, 0] = dop_poly[0, 0] - (dop_poly[0, 1] *
                                               doppler_cent_col * grid.Col.SS)
            inca.DopCentroidPoly = Poly2DType(Coefs=dop_poly)

        grid.Col.DeltaKCOAPoly = Poly2DType(
            Coefs=inca.DopCentroidPoly.get_array() * col_spacing_zd /
            grid.Col.SS)
        # compute grid.Col.DeltaK1/K2 from DeltaKCOAPoly
        coeffs = grid.Col.DeltaKCOAPoly.get_array()[:, 0]
        # get roots
        roots = polynomial.polyroots(coeffs)
        # construct range bounds (in meters)
        range_bounds = (
            numpy.array([0, image_data.NumRows - 1], dtype=numpy.float64) -
            image_data.SCPPixel.Row) * grid.Row.SS
        possible_ranges = numpy.copy(range_bounds)
        useful_roots = ((roots > numpy.min(range_bounds)) &
                        (roots < numpy.max(range_bounds)))
        if numpy.any(useful_roots):
            possible_ranges = numpy.concatenate(
                (possible_ranges, roots[useful_roots]), axis=0)
        azimuth_bounds = (
            numpy.array([0, (image_data.NumCols - 1)], dtype=numpy.float64) -
            image_data.SCPPixel.Col) * grid.Col.SS
        coords_az_2d, coords_rg_2d = numpy.meshgrid(azimuth_bounds,
                                                    possible_ranges)
        possible_bounds_deltak = grid.Col.DeltaKCOAPoly(
            coords_rg_2d, coords_az_2d)
        grid.Col.DeltaK1 = numpy.min(
            possible_bounds_deltak) - 0.5 * grid.Col.ImpRespBW
        grid.Col.DeltaK2 = numpy.max(
            possible_bounds_deltak) + 0.5 * grid.Col.ImpRespBW
        # Wrapped spectrum
        if (grid.Col.DeltaK1 < -0.5 / grid.Col.SS) or (grid.Col.DeltaK2 >
                                                       0.5 / grid.Col.SS):
            grid.Col.DeltaK1 = -0.5 / abs(grid.Col.SS)
            grid.Col.DeltaK2 = -grid.Col.DeltaK1
        time_coa_poly = fit_time_coa_polynomial(inca,
                                                image_data,
                                                grid,
                                                dop_rate_scaled_coeffs,
                                                poly_order=2)
        if collection_info.RadarMode.ModeType == 'SPOTLIGHT':
            # using above was convenience, but not really sensible in spotlight mode
            grid.TimeCOAPoly = Poly2DType(Coefs=[
                [
                    time_coa_poly.Coefs[0, 0],
                ],
            ])
            inca.DopCentroidPoly = None
        elif collection_info.RadarMode.ModeType == 'STRIPMAP':
            # fit TimeCOAPoly for grid
            grid.TimeCOAPoly = time_coa_poly
            inca.DopCentroidCOA = True
        else:
            raise ValueError('unhandled ModeType {}'.format(
                collection_info.RadarMode.ModeType))
        return RMAType(RMAlgoType='OMEGA_K', INCA=inca)
Ejemplo n.º 15
0
Archivo: csk.py Proyecto: LordHui/sarpy
    def _get_band_specific_sicds(self, base_sicd, h5_dict, band_dict, shape_dict):
        # type: (SICDType, dict, dict, dict) -> Dict[str, SICDType]

        az_ref_time, rg_ref_time, dop_poly_az, dop_poly_rg, dop_rate_poly_rg = self._get_dop_poly_details(h5_dict)
        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')

        def update_scp_prelim(sicd, band_name):
            # type: (SICDType, str) -> None
            LLH = band_dict[band_name]['Centre Geodetic Coordinates']
            sicd.GeoData = GeoDataType(SCP=SCPType(LLH=LLH))  # EarthModel & ECF will be populated

        def update_image_data(sicd, band_name):
            # type: (SICDType, str) -> Tuple[float, float, float, float]

            cols, rows = shape_dict[band_name]
            t_az_first_time = band_dict[band_name]['Zero Doppler Azimuth First Time']
            # zero doppler time of first column
            t_ss_az_s = band_dict[band_name]['Line Time Interval']
            if base_sicd.SCPCOA.SideOfTrack == 'L':
                # we need to reverse time order
                t_ss_az_s *= -1
                t_az_first_time = band_dict[band_name]['Zero Doppler Azimuth Last 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,
                                           PixelType='RE16I_IM16I',
                                           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

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

        def update_radar_collection(sicd, band_name, ind):
            # type: (SICDType, str, int) -> None
            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]['Reference Dechirping Time']
            win_length = band_dict[band_name]['Echo Sampling Window Length']
            rcv_fm_rate = 0 if numpy.isnan(ref_dechirp_time) else ref_dechirp_time  # TODO: is this the correct value?
            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 = TxFrequencyType(Min=fr_min,
                                                               Max=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 = TxFrequencyProcType(MinProc=fr_min,
                                                                      MaxProc=fr_max)
            sicd.ImageFormation.TxRcvPolarizationProc = sicd.RadarCollection.RcvChannels[ind].TxRcvPolarization

        def update_rma_and_grid(sicd, band_name):
            # type: (SICDType, str) -> None
            rg_scp_time = rg_first_time + (ss_rg_s*sicd.ImageData.SCPPixel.Row)
            az_scp_time = az_first_time + (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 = vel_ca*ss_az_s*drate_sf_poly[0]
            sicd.Grid.Col.SS = col_ss
            col_bw = min(band_dict[band_name]['Azimuth Focusing Bandwidth'] * abs(ss_az_s), 1) / col_ss
            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, 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=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)

        def update_radiometric(sicd, band_name):
            # type: (SICDType, str) -> None
            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)
                if h5_dict['Calibration Constant Compensation Flag'] == 0:
                    rsf = h5_dict['Rescaling Factor']
                    cal = band_dict[band_name]['Calibration Constant']
                    sf /= cal*(rsf**2)
                sicd.Radiometric = RadiometricType(BetaZeroSFPoly=Poly2DType(Coefs=[[sf, ], ]))

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

        out = {}
        for i, bd_name in enumerate(band_dict):
            t_sicd = base_sicd.copy()
            update_scp_prelim(t_sicd, bd_name)  # set preliminary value for SCP (required for projection)
            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 = update_image_data(t_sicd, bd_name)
            update_timeline(t_sicd, bd_name)
            update_radar_collection(t_sicd, bd_name, i)
            update_rma_and_grid(t_sicd, bd_name)
            update_radiometric(t_sicd, bd_name)
            update_geodata(t_sicd)
            t_sicd.derive()
            t_sicd.populate_rniirs(override=False)
            out[bd_name] = t_sicd
        return out
Ejemplo n.º 16
0
        def get_grid():
            # type: () -> GridType

            def get_weight(window_dict):
                window_name = window_dict['name']
                if window_name.lower() == 'rectangular':
                    return WgtTypeType(WindowName='UNIFORM')
                else:
                    # TODO: what is the proper interpretation for the avci-nacaroglu window?
                    return WgtTypeType(WindowName=window_name,
                                       Parameters=convert_string_dict(
                                           window_dict['parameters']))

            img = collect['image']
            img_geometry = img['image_geometry']
            if img_geometry.get('type', None) == 'slant_plane':
                image_plane = 'SLANT'
            else:
                image_plane = 'OTHER'

            grid_type = 'PLANE'
            if self._img_desc_tags['product_type'] == 'SLC' and img[
                    'algorithm'] != 'backprojection':
                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'],
                               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,
                                   ],
                               ],
                               WgtType=get_weight(img['range_window']))

            # get timecoa value
            timecoa_value = get_seconds(
                coa_time, start_time)  # TODO: this is not generally correct
            # 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,
                               Sgn=-1,
                               ImpRespWid=img['azimuth_resolution'],
                               ImpRespBW=dop_bw / arp_speed,
                               KCtr=0,
                               WgtType=get_weight(img['azimuth_window']))

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

            return GridType(ImagePlane=image_plane,
                            Type=grid_type,
                            TimeCOAPoly=[
                                [
                                    timecoa_value,
                                ],
                            ],
                            Row=row,
                            Col=col)
Ejemplo n.º 17
0
Archivo: csk.py Proyecto: LordHui/sarpy
    def _get_base_sicd(self, h5_dict, band_dict):
        # type: (dict, dict) -> SICDType

        def get_collection_info():  # type: () -> CollectionInfoType
            mode_type = 'STRIPMAP' if h5_dict['Acquisition Mode'] in \
                                      ['HIMAGE', 'PINGPONG', 'WIDEREGION', 'HUGEREGION'] else 'DYNAMIC STRIPMAP'
            return CollectionInfoType(Classification='UNCLASSIFIED',
                                      CollectorName=h5_dict['Satellite ID'],
                                      CoreName=str(h5_dict['Programmed Image ID']),
                                      CollectType='MONOSTATIC',
                                      RadarMode=RadarModeType(ModeID=h5_dict['Multi-Beam ID'],
                                                              ModeType=mode_type))

        def get_image_creation():  # type: () -> ImageCreationType
            from sarpy.__about__ import __version__
            return ImageCreationType(
                DateTime=parse_timestring(h5_dict['Product Generation UTC'], precision='ns'),
                Profile='sarpy {}'.format(__version__))

        def get_grid():  # type: () -> GridType
            if h5_dict['Projection ID'] == 'SLANT RANGE/AZIMUTH':
                image_plane = 'SLANT'
                gr_type = 'RGZERO'
            else:
                image_plane = 'GROUND'
                gr_type = None
            # Row
            row_window_name = h5_dict['Range Focusing Weighting Function'].rstrip().upper()
            row_params = None
            if row_window_name == 'HAMMING':
                row_params = {'COEFFICIENT': '{0:15f}'.format(h5_dict['Range Focusing Weighting Coefficient'])}
            row = DirParamType(Sgn=-1,
                               KCtr=2*center_frequency/speed_of_light,
                               DeltaKCOAPoly=Poly2DType(Coefs=[[0, ], ]),
                               WgtType=WgtTypeType(WindowName=row_window_name, Parameters=row_params))
            # Col
            col_window_name = h5_dict['Azimuth Focusing Weighting Function'].rstrip().upper()
            col_params = None
            if col_window_name == 'HAMMING':
                col_params = {'COEFFICIENT': '{0:15f}'.format(h5_dict['Azimuth Focusing Weighting Coefficient'])}
            col = DirParamType(Sgn=-1,
                               KCtr=0,
                               WgtType=WgtTypeType(WindowName=col_window_name, Parameters=col_params))
            return GridType(ImagePlane=image_plane, Type=gr_type, Row=row, Col=col)

        def get_timeline():  # type: () -> TimelineType
            return TimelineType(CollectStart=collect_start,
                                CollectDuration=duration,
                                IPP=[IPPSetType(index=0, TStart=0, TEnd=0, IPPStart=0, IPPEnd=0), ])  # NB: IPPEnd must be set, but will be replaced

        def get_position():  # type: () -> PositionType
            T = h5_dict['State Vectors Times']  # in seconds relative to ref time
            T += ref_time_offset
            Pos = h5_dict['ECEF Satellite Position']
            Vel = h5_dict['ECEF Satellite Velocity']
            P_x, P_y, P_z = fit_position_xvalidation(T, Pos, Vel, max_degree=8)
            return PositionType(ARPPoly=XYZPolyType(X=P_x, Y=P_y, Z=P_z))

        def get_radar_collection():
            # type: () -> RadarCollectionType
            tx_pols = []
            chan_params = []
            for i, bdname in enumerate(band_dict):
                pol = band_dict[bdname]['Polarisation']
                tx_pols.append(pol[0])
                chan_params.append(ChanParametersType(TxRcvPolarization=self._parse_pol(pol), index=i))
            if len(tx_pols) == 1:
                return RadarCollectionType(RcvChannels=chan_params, TxPolarization=tx_pols[0])
            else:
                return RadarCollectionType(RcvChannels=chan_params,
                                           TxPolarization='SEQUENCE',
                                           TxSequence=[TxStepType(TxPolarization=pol,
                                                                  index=i+1) for i, pol in enumerate(tx_pols)])

        def get_image_formation():
            # type: () -> ImageFormationType
            return ImageFormationType(ImageFormAlgo='RMA',
                                      TStartProc=0,
                                      TEndProc=duration,
                                      STBeamComp='SV',
                                      ImageBeamComp='SV',
                                      AzAutofocus='NO',
                                      RgAutofocus='NO',
                                      RcvChanProc=RcvChanProcType(NumChanProc=1,
                                                                  PRFScaleFactor=1))

        def get_rma():
            # type: () -> RMAType
            inca = INCAType(FreqZero=center_frequency)
            return RMAType(RMAlgoType='OMEGA_K',
                           INCA=inca)

        def get_scpcoa():
            # type: () -> SCPCOAType
            return SCPCOAType(SideOfTrack=h5_dict['Look Side'][0:1].upper())

        # some common use parameters
        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')
        collect_end = parse_timestring(h5_dict['Scene Sensing Stop UTC'], precision='ns')
        duration = get_seconds(collect_end, collect_start, precision='ns')
        ref_time = parse_timestring(h5_dict['Reference UTC'], precision='ns')
        ref_time_offset = get_seconds(ref_time, collect_start, precision='ns')

        # assemble our pieces
        collection_info = get_collection_info()
        image_creation = get_image_creation()
        grid = get_grid()
        timeline = get_timeline()
        position = get_position()
        radar_collection = get_radar_collection()
        image_formation = get_image_formation()
        rma = get_rma()
        scpcoa = get_scpcoa()

        return SICDType(CollectionInfo=collection_info,
                        ImageCreation=image_creation,
                        Grid=grid,
                        Timeline=timeline,
                        Position=position,
                        RadarCollection=radar_collection,
                        ImageFormation=image_formation,
                        RMA=rma,
                        SCPCOA=scpcoa)
Ejemplo n.º 18
0
    def _get_band_specific_sicds(self, base_sicd, h5_dict, band_dict,
                                 shape_dict, dtype_dict):
        # type: (SICDType, dict, dict, dict, dict) -> Dict[str, SICDType]

        def update_scp_prelim(sicd, band_name):
            # type: (SICDType, 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 mission id {}'.format(
                    self._mission_id))
            sicd.GeoData = GeoDataType(
                SCP=SCPType(LLH=LLH))  # EarthModel & ECF will be populated

        def update_image_data(sicd, band_name):
            # type: (SICDType, str) -> Tuple[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=dtype_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():
            # type: () -> Tuple[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, band_name):
            # type: (SICDType, 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, band_name, ind):
            # type: (SICDType, str, int) -> None
            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 = TxFrequencyType(Min=fr_min,
                                                               Max=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 = TxFrequencyProcType(
                MinProc=fr_min, MaxProc=fr_max)
            sicd.ImageFormation.TxRcvPolarizationProc = sicd.RadarCollection.RcvChannels[
                ind].TxRcvPolarization

        def update_rma_and_grid(sicd, band_name):
            # type: (SICDType, 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, band_name):
            # type: (SICDType, 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):  # type: (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 i, bd_name in enumerate(band_dict):
            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()
            update_scp_prelim(
                t_sicd, bd_name
            )  # set preliminary value for SCP (required for projection)
            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, i)
            update_rma_and_grid(t_sicd, bd_name)
            update_radiometric(t_sicd, bd_name)
            update_geodata(t_sicd)
            t_sicd.derive()
            # t_sicd.populate_rniirs(override=False)
            out[bd_name] = t_sicd
        return out
Ejemplo n.º 19
0
    def _get_base_sicd(self, h5_dict, band_dict):
        # type: (dict, dict) -> SICDType

        def get_collection_info():  # type: () -> (dict, CollectionInfoType)
            acq_mode = h5_dict['Acquisition Mode'].upper()
            if self.mission_id == 'CSK':
                if acq_mode in ['HIMAGE', 'PINGPONG']:
                    mode_type = 'STRIPMAP'
                elif acq_mode in ['WIDEREGION', 'HUGEREGION']:
                    # scansar, processed as stripmap
                    mode_type = 'STRIPMAP'
                elif acq_mode in ['ENHANCED SPOTLIGHT', 'SMART']:
                    mode_type = 'DYNAMIC STRIPMAP'
                else:
                    logging.warning(
                        'Got unexpected acquisition mode {}'.format(acq_mode))
                    mode_type = 'DYNAMIC STRIPMAP'
            elif self.mission_id == 'KMPS':
                if acq_mode in ['STANDARD', 'ENHANCED STANDARD']:
                    mode_type = 'STRIPMAP'
                elif acq_mode in ['WIDE SWATH', 'ENHANCED WIDE SWATH']:
                    # scansar, processed as stripmap
                    mode_type = 'STRIPMAP'
                elif acq_mode in [
                        'HIGH RESOLUTION', 'ENHANCED HIGH RESOLUTION',
                        'ULTRA HIGH RESOLUTION'
                ]:
                    # "spotlight"
                    mode_type = 'DYNAMIC STRIPMAP'
                else:
                    logging.warning(
                        'Got unexpected acquisition mode {}'.format(acq_mode))
                    mode_type = 'DYNAMIC STRIPMAP'
            elif self.mission_id == 'CSG':
                if acq_mode.startswith('SPOTLIGHT'):
                    mode_type = 'DYNAMIC STRIPMAP'
                elif acq_mode in ['STRIPMAP', 'QUADPOL']:
                    mode_type = "STRIPMAP"
                else:
                    logging.warning(
                        'Got unhandled acquisition mode {}, setting to DYNAMIC STRIPMAP'
                        .format(acq_mode))
                    mode_type = 'DYNAMIC STRIPMAP'
            else:
                raise ValueError('Unhandled mission id {}'.format(
                    self._mission_id))

            start_time_dt = collect_start.astype('datetime64[s]').astype(
                datetime)
            date_str = start_time_dt.strftime('%d%b%y').upper()
            time_str = start_time_dt.strftime('%H%M%S') + 'Z'
            core_name = '{}_{}_{}'.format(date_str, self.mission_id, time_str)
            collect_info = CollectionInfoType(
                Classification='UNCLASSIFIED',
                CollectorName=h5_dict['Satellite ID'],
                CoreName=core_name,
                CollectType='MONOSTATIC',
                RadarMode=RadarModeType(ModeID=h5_dict['Multi-Beam ID'],
                                        ModeType=mode_type))
            return collect_info

        def get_image_creation():  # type: () -> ImageCreationType
            from sarpy.__about__ import __version__
            return ImageCreationType(
                DateTime=parse_timestring(h5_dict['Product Generation UTC'],
                                          precision='ns'),
                Site=h5_dict['Processing Centre'],
                Application='L0: `{}`, L1: `{}`'.format(
                    h5_dict.get('L0 Software Version', 'NONE'),
                    h5_dict.get('L1A Software Version', 'NONE')),
                Profile='sarpy {}'.format(__version__))

        def get_grid():  # type: () -> GridType
            def get_wgt_type(weight_name, coefficient, direction):
                if weight_name == 'GENERAL_COSINE':
                    # probably only for kompsat?
                    weight_name = 'HAMMING'
                    coefficient = 1 - coefficient
                if coefficient is None:
                    params = None
                else:
                    params = {'COEFFICIENT': '{0:0.16G}'.format(coefficient)}
                out = WgtTypeType(WindowName=weight_name, Parameters=params)
                if weight_name != 'HAMMING':
                    logging.warning(
                        'Got unexpected weight scheme {} for {}. The weighting will '
                        'not be properly populated.'.format(
                            weight_name, direction))
                return out

            if h5_dict['Projection ID'] == 'SLANT RANGE/AZIMUTH':
                image_plane = 'SLANT'
                gr_type = 'RGZERO'
            else:
                image_plane = 'GROUND'
                gr_type = None
            # Row
            row_window_name = h5_dict[
                'Range Focusing Weighting Function'].rstrip().upper()
            row_coefficient = h5_dict.get(
                'Range Focusing Weighting Coefficient', None)
            row_weight = get_wgt_type(row_window_name, row_coefficient, 'Row')
            row = DirParamType(Sgn=-1,
                               KCtr=2 * center_frequency / speed_of_light,
                               DeltaKCOAPoly=Poly2DType(Coefs=[
                                   [
                                       0,
                                   ],
                               ]),
                               WgtType=row_weight)
            # Col
            col_window_name = h5_dict[
                'Azimuth Focusing Weighting Function'].rstrip().upper()
            col_coefficient = h5_dict.get(
                'Azimuth Focusing Weighting Coefficient', None)
            col_weight = get_wgt_type(col_window_name, col_coefficient, 'Col')
            col = DirParamType(Sgn=-1, KCtr=0, WgtType=col_weight)
            return GridType(ImagePlane=image_plane,
                            Type=gr_type,
                            Row=row,
                            Col=col)

        def get_timeline():  # type: () -> TimelineType
            # NB: IPPEnd must be set, but will be replaced
            return TimelineType(CollectStart=collect_start,
                                CollectDuration=duration,
                                IPP=[
                                    IPPSetType(index=0,
                                               TStart=0,
                                               TEnd=0,
                                               IPPStart=0,
                                               IPPEnd=0),
                                ])

        def get_position():  # type: () -> PositionType
            T = h5_dict[
                'State Vectors Times']  # in seconds relative to ref time
            T += ref_time_offset
            Pos = h5_dict['ECEF Satellite Position']
            Vel = h5_dict['ECEF Satellite Velocity']
            P_x, P_y, P_z = fit_position_xvalidation(T, Pos, Vel, max_degree=8)
            return PositionType(ARPPoly=XYZPolyType(X=P_x, Y=P_y, Z=P_z))

        def get_radar_collection():
            # type: () -> RadarCollectionType
            tx_pols = []
            chan_params = []
            for i, bdname in enumerate(band_dict):
                if 'Polarisation' in band_dict[bdname]:
                    pol = band_dict[bdname]['Polarisation']
                elif 'Polarization' in h5_dict:
                    pol = h5_dict['Polarization']
                else:
                    raise ValueError(
                        'Failed finding polarization for file {}\nmission id {}'
                        .format(self._file_name, self._mission_id))
                tx_pols.append(pol[0])
                chan_params.append(
                    ChanParametersType(TxRcvPolarization=self._parse_pol(pol),
                                       index=i))
            if len(tx_pols) == 1:
                return RadarCollectionType(RcvChannels=chan_params,
                                           TxPolarization=tx_pols[0])
            else:
                return RadarCollectionType(RcvChannels=chan_params,
                                           TxPolarization='SEQUENCE',
                                           TxSequence=[
                                               TxStepType(TxPolarization=pol,
                                                          index=i + 1)
                                               for i, pol in enumerate(tx_pols)
                                           ])

        def get_image_formation():
            # type: () -> ImageFormationType
            return ImageFormationType(ImageFormAlgo='RMA',
                                      TStartProc=0,
                                      TEndProc=duration,
                                      STBeamComp='NO',
                                      ImageBeamComp='SV',
                                      AzAutofocus='NO',
                                      RgAutofocus='NO',
                                      RcvChanProc=RcvChanProcType(
                                          NumChanProc=1, PRFScaleFactor=1))

        def get_rma():
            # type: () -> RMAType
            inca = INCAType(FreqZero=center_frequency)
            return RMAType(RMAlgoType='OMEGA_K', INCA=inca)

        def get_scpcoa():
            # type: () -> SCPCOAType
            return SCPCOAType(SideOfTrack=h5_dict['Look Side'][0:1].upper())

        # some common use parameters
        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')
        collect_end = parse_timestring(h5_dict['Scene Sensing Stop UTC'],
                                       precision='ns')
        duration = get_seconds(collect_end, collect_start, precision='ns')
        ref_time = parse_timestring(h5_dict['Reference UTC'], precision='ns')
        ref_time_offset = get_seconds(ref_time, collect_start, precision='ns')

        # assemble our pieces
        collection_info = get_collection_info()
        image_creation = get_image_creation()
        grid = get_grid()
        timeline = get_timeline()
        position = get_position()
        radar_collection = get_radar_collection()
        image_formation = get_image_formation()
        rma = get_rma()
        scpcoa = get_scpcoa()
        sicd = SICDType(CollectionInfo=collection_info,
                        ImageCreation=image_creation,
                        Grid=grid,
                        Timeline=timeline,
                        Position=position,
                        RadarCollection=radar_collection,
                        ImageFormation=image_formation,
                        RMA=rma,
                        SCPCOA=scpcoa)
        return sicd
Ejemplo n.º 20
0
    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
Ejemplo n.º 21
0
        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)