def update_timeline(sicd: SICDType, band_name: str) -> None: prf = band_dict[band_name]['PRF'] duration = sicd.Timeline.CollectDuration ipp_el = sicd.Timeline.IPP[0] ipp_el.IPPEnd = duration * prf ipp_el.TEnd = duration ipp_el.IPPPoly = Poly1DType(Coefs=(0, prf))
def strip_poly(arr): # strip worthless (all zero) highest order terms # find last non-zero index last_ind = arr.size for i in range(arr.size-1, -1, -1): if arr[i] != 0: break last_ind = i return Poly1DType(Coefs=arr[:last_ind])
def _get_timeline(self): """ Gets the Timeline metadata. Returns ------- TimelineType """ timeline = TimelineType(CollectStart=self._get_start_time()) pulse_parts = len( self._findall('./sourceAttributes/radarParameters/pulseBandwidth')) tx_pols, tx_rcv_polarizations = self._get_polarizations() if self.generation == 'RS2': pulse_rep_freq = float( self._find('./sourceAttributes' '/radarParameters' '/pulseRepetitionFrequency').text) elif self.generation == 'RCM': pulse_rep_freq = float( self._find('./sourceAttributes' '/radarParameters' '/prfInformation' '/pulseRepetitionFrequency').text) else: raise ValueError('unhandled generation {}'.format(self.generation)) pulse_rep_freq *= pulse_parts if pulse_parts == 2 and self._get_radar_mode().ModeType == 'STRIPMAP': # it's not completely clear why we need an additional factor of 2 for strip map pulse_rep_freq *= 2 lines_processed = [ float(entry.text) for entry in self._findall('./imageGenerationParameters' '/sarProcessingInformation' '/numberOfLinesProcessed') ] # there should be one entry of num_lines_processed for each transmit/receive polarization # and they should all be the same. Omit if this is not the case. if (len(lines_processed) == len(tx_rcv_polarizations)) and \ all(x == lines_processed[0] for x in lines_processed): num_lines_processed = lines_processed[0] * len(tx_pols) duration = num_lines_processed / pulse_rep_freq timeline.CollectDuration = duration timeline.IPP = [ IPPSetType(index=0, TStart=0, TEnd=duration, IPPStart=0, IPPEnd=int(num_lines_processed), IPPPoly=Poly1DType(Coefs=(0, pulse_rep_freq))), ] return timeline
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 get_rma() -> 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 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 check_switch_state(): # type: () -> Tuple[Poly1DType, Poly1DType, Poly1DType] if 'CSK' in self._satellite: if t_dop_rate_poly_rg[0] > 0: raise ValueError( 'Got unexpected state, use_sign = {} and dop_rate_poly_rg = {}'.format( use_sign, t_dop_rate_poly_rg)) return (Poly1DType(Coefs=t_dop_poly_az), Poly1DType(Coefs=t_dop_poly_rg), Poly1DType(Coefs=t_dop_rate_poly_rg)) elif 'KMP' in self._satellite: if (use_sign > 0 and t_dop_rate_poly_rg[0] > 0) or (use_sign < 0 and t_dop_rate_poly_rg[0] < 0): raise ValueError( 'Got unexpected state, use_sign = {} and dop_rate_poly_rg = {}'.format( use_sign, t_dop_rate_poly_rg)) return (Poly1DType(Coefs=t_dop_poly_az), Poly1DType(Coefs=t_dop_poly_rg), Poly1DType(Coefs=use_sign*t_dop_rate_poly_rg)) else: raise ValueError('Unhandled satellite type {}'.format(self._satellite))
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 _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
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)
def update_rma_and_grid(sicd: SICDType, band_name: str) -> None: rg_scp_time = rg_first_time + (ss_rg_s * sicd.ImageData.SCPPixel.Row) az_scp_time = az_first_time + (use_sign2 * ss_az_s * sicd.ImageData.SCPPixel.Col) r_ca_scp = rg_scp_time * speed_of_light / 2 sicd.RMA.INCA.R_CA_SCP = r_ca_scp # compute DRateSFPoly scp_ca_time = az_scp_time + ref_time_offset vel_poly = sicd.Position.ARPPoly.derivative(der_order=1, return_poly=True) vel_ca_vec = vel_poly(scp_ca_time) vel_ca_sq = numpy.sum(vel_ca_vec * vel_ca_vec) vel_ca = numpy.sqrt(vel_ca_sq) r_ca = numpy.array([r_ca_scp, 1.], dtype=numpy.float64) dop_rate_poly_rg_shifted = dop_rate_poly_rg.shift( rg_ref_time - rg_scp_time, alpha=ss_rg_s / row_ss, return_poly=False) drate_sf_poly = -(polynomial.polymul(dop_rate_poly_rg_shifted, r_ca) * speed_of_light / (2 * center_frequency * vel_ca_sq)) # update grid.row sicd.Grid.Row.SS = row_ss sicd.Grid.Row.ImpRespBW = row_bw sicd.Grid.Row.DeltaK1 = -0.5 * row_bw sicd.Grid.Row.DeltaK2 = 0.5 * row_bw # update grid.col col_ss = abs(vel_ca * ss_az_s * drate_sf_poly[0]) sicd.Grid.Col.SS = col_ss if self.mission_id == 'CSK': col_bw = min( band_dict[band_name] ['Azimuth Focusing Transition Bandwidth'] * ss_az_s, 1) / col_ss elif self.mission_id in ['CSG', 'KMPS']: col_bw = min( band_dict[band_name]['Azimuth Focusing Bandwidth'] * ss_az_s, 1) / col_ss else: raise ValueError('Got unhandled mission_id {}'.format( self.mission_id)) sicd.Grid.Col.ImpRespBW = col_bw # update inca sicd.RMA.INCA.DRateSFPoly = Poly2DType( Coefs=numpy.reshape(drate_sf_poly, (-1, 1))) sicd.RMA.INCA.TimeCAPoly = Poly1DType( Coefs=[scp_ca_time, use_sign2 * ss_az_s / col_ss]) # compute DopCentroidPoly & DeltaKCOAPoly dop_centroid_poly = numpy.zeros( (dop_poly_rg.order1 + 1, dop_poly_az.order1 + 1), dtype=numpy.float64) dop_centroid_poly[0, 0] = dop_poly_rg(rg_scp_time-rg_ref_time) + \ dop_poly_az(az_scp_time-az_ref_time) - \ 0.5*(dop_poly_rg[0] + dop_poly_az[0]) dop_poly_rg_shifted = dop_poly_rg.shift(rg_ref_time - rg_scp_time, alpha=ss_rg_s / row_ss) dop_poly_az_shifted = dop_poly_az.shift(az_ref_time - az_scp_time, alpha=ss_az_s / col_ss) dop_centroid_poly[1:, 0] = dop_poly_rg_shifted[1:] dop_centroid_poly[0, 1:] = dop_poly_az_shifted[1:] sicd.RMA.INCA.DopCentroidPoly = Poly2DType(Coefs=dop_centroid_poly) sicd.RMA.INCA.DopCentroidCOA = True sicd.Grid.Col.DeltaKCOAPoly = Poly2DType( Coefs=use_sign * dop_centroid_poly * ss_az_s / col_ss) # fit TimeCOAPoly sicd.Grid.TimeCOAPoly = fit_time_coa_polynomial( sicd.RMA.INCA, sicd.ImageData, sicd.Grid, dop_rate_poly_rg_shifted, poly_order=2) if csk_addin is not None: csk_addin.check_sicd(sicd, self.mission_id, h5_dict)
def check_switch_state() -> (int, Poly1DType): use_sign = 1 if t_dop_rate_poly_rg[0] < 0 else -1 return use_sign, Poly1DType(Coefs=use_sign * t_dop_rate_poly_rg)