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 update_inca_and_grid(): t_sicd.RMA.INCA.R_CA_SCP = r_ca_sampled[t_sicd.ImageData.SCPPixel.Row] scp_ca_time = zd_time[t_sicd.ImageData.SCPPixel.Col] # compute DRateSFPoly # velocity at scp ca time vel_ca = t_sicd.Position.ARPPoly.derivative_eval(scp_ca_time, der_order=1) # squared magnitude vm_ca_sq = numpy.sum(vel_ca*vel_ca) # polynomial coefficient for function representing range as a function of range distance from SCP r_ca_poly = numpy.array([t_sicd.RMA.INCA.R_CA_SCP, 1], dtype=numpy.float64) # closest Doppler rate polynomial to SCP min_ind = numpy.argmin(numpy.absolute(grid_zd_time - scp_ca_time)) # define range coordinate grid coords_rg_m = grid_r - t_sicd.RMA.INCA.R_CA_SCP # determine dop_rate_poly coordinates dop_rate_poly = polynomial.polyfit(coords_rg_m, -doprate_sampled[min_ind, :], 4) # why fourth order? t_sicd.RMA.INCA.FreqZero = center_freq t_sicd.RMA.INCA.DRateSFPoly = Poly2DType(Coefs=numpy.reshape( -numpy.convolve(dop_rate_poly, r_ca_poly)*speed_of_light/(2*center_freq*vm_ca_sq), (-1, 1))) # update Grid.Col parameters t_sicd.Grid.Col.SS = numpy.sqrt(vm_ca_sq)*abs(ss_az_s)*t_sicd.RMA.INCA.DRateSFPoly.Coefs[0, 0] t_sicd.Grid.Col.ImpRespBW = min(abs(dop_bw*ss_az_s), 1)/t_sicd.Grid.Col.SS t_sicd.RMA.INCA.TimeCAPoly = [scp_ca_time, ss_az_s/t_sicd.Grid.Col.SS] #TimeCOAPoly/DopCentroidPoly/DeltaKCOAPoly coords_az_m = (grid_zd_time - scp_ca_time)*t_sicd.Grid.Col.SS/ss_az_s # cerate the 2d grids coords_rg_2d_t, coords_az_2d_t = numpy.meshgrid(coords_rg_m, coords_az_m, indexing='xy') coefs, residuals, rank, sing_values = two_dim_poly_fit( coords_rg_2d_t, coords_az_2d_t, dopcentroid_sampled, x_order=3, y_order=3, x_scale=1e-3, y_scale=1e-3, rcond=1e-40) logger.info( 'The dop_centroid_poly fit details:\n\t' 'root mean square residuals = {}\n\t' 'rank = {}\n\t' 'singular values = {}'.format(residuals, rank, sing_values)) t_sicd.RMA.INCA.DopCentroidPoly = Poly2DType(Coefs=coefs) t_sicd.Grid.Col.DeltaKCOAPoly = Poly2DType(Coefs=coefs*ss_az_s/t_sicd.Grid.Col.SS) timeca_sampled = numpy.outer(grid_zd_time, numpy.ones((grid_r.size, ))) time_coa_sampled = timeca_sampled + (dopcentroid_sampled/doprate_sampled) coefs, residuals, rank, sing_values = two_dim_poly_fit( coords_rg_2d_t, coords_az_2d_t, time_coa_sampled, x_order=3, y_order=3, x_scale=1e-3, y_scale=1e-3, rcond=1e-40) logger.info( 'The time_coa_poly fit details:\n\t' 'root mean square residuals = {}\n\t' 'rank = {}\n\t' 'singular values = {}'.format(residuals, rank, sing_values)) t_sicd.Grid.TimeCOAPoly = Poly2DType(Coefs=coefs) return coords_rg_2d_t, coords_az_2d_t
def get_poly(ds, name): array = ds[:] fill = ds.attrs['_FillValue'] boolc = (array != fill) if numpy.any(boolc): array = array[boolc] if numpy.any(array != array[0]): coefs, residuals, rank, sing_values = two_dim_poly_fit( coords_rg_2d[boolc], coords_az_2d[boolc], array, x_order=3, y_order=3, x_scale=1e-3, y_scale=1e-3, rcond=1e-40) logging.info( 'The {} fit details:\nroot mean square residuals = {}\nrank = {}\nsingular values = {}' .format(name, residuals, rank, sing_values)) else: # it's constant, so just use a constant polynomial coefs = [ [ array[0], ], ] logging.info('The {} values are constant'.format(name)) return Poly2DType(Coefs=coefs) else: logging.warning( 'No non-trivial values for {} provided.'.format(name)) return None
def fit_time_coa_polynomial(inca, image_data, grid, dop_rate_scaled_coeffs, poly_order=2): """ Parameters ---------- inca : sarpy.io.complex.sicd_elements.RMA.INCAType image_data : sarpy.io.complex.sicd_elements.ImageData.ImageDataType grid : sarpy.io.complex.sicd_elements.Grid.GridType dop_rate_scaled_coeffs : numpy.ndarray the dop rate polynomial relative to physical coordinates - the is a common construct in converting metadata for csk/sentinel/radarsat poly_order : int the degree of the polynomial to fit. Returns ------- Poly2DType """ grid_samples = poly_order + 8 coords_az = get_im_physical_coords( numpy.linspace(0, image_data.NumCols - 1, grid_samples, dtype='float64'), grid, image_data, 'col') coords_rg = get_im_physical_coords( numpy.linspace(0, image_data.NumRows - 1, grid_samples, dtype='float64'), grid, image_data, 'row') coords_az_2d, coords_rg_2d = numpy.meshgrid(coords_az, coords_rg) time_ca_sampled = inca.TimeCAPoly(coords_az_2d) dop_centroid_sampled = inca.DopCentroidPoly(coords_rg_2d, coords_az_2d) doppler_rate_sampled = polynomial.polyval(coords_rg_2d, dop_rate_scaled_coeffs) time_coa_sampled = time_ca_sampled + dop_centroid_sampled / doppler_rate_sampled coefs, residuals, rank, sing_values = two_dim_poly_fit( coords_rg_2d, coords_az_2d, time_coa_sampled, x_order=poly_order, y_order=poly_order, x_scale=1e-3, y_scale=1e-3, rcond=1e-40) logging.info('The time_coa_fit details:\nroot mean square residuals = {}\nrank = {}\nsingular values = {}'.format(residuals, rank, sing_values)) return Poly2DType(Coefs=coefs)
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 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 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 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.17E}'.format(coefficient)} out = WgtTypeType(WindowName=weight_name, Parameters=params) if weight_name != 'HAMMING': logger.warning( 'Got unexpected weight scheme {} for {}.\n\t' 'The weighting will not be properly populated.'.format( weight_name, direction)) return out if re.sub( ' ', '', h5_dict['Projection ID']).upper() == 'SLANTRANGE/AZIMUTH': image_plane = 'SLANT' gr_type = 'RGZERO' else: image_plane = 'GROUND' gr_type = 'PLANE' # 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 define_radiometric(): def get_poly(ds, name): array = ds[:] fill = ds.attrs['_FillValue'] boolc = (array != fill) if numpy.any(boolc): array = array[boolc] if numpy.any(array != array[0]): coefs, residuals, rank, sing_values = two_dim_poly_fit( coords_rg_2d[boolc], coords_az_2d[boolc], array, x_order=3, y_order=3, x_scale=1e-3, y_scale=1e-3, rcond=1e-40) logger.info( 'The {} fit details:\n\t' 'root mean square residuals = {}\n\t' 'rank = {}\n\t' 'singular values = {}'.format(name, residuals, rank, sing_values)) else: # it's constant, so just use a constant polynomial coefs = [[array[0], ], ] logger.info('The {} values are constant'.format(name)) return Poly2DType(Coefs=coefs) else: logger.warning('No non-trivial values for {} provided.'.format(name)) return None beta0_poly = get_poly(beta0, 'beta0') gamma0_poly = get_poly(gamma0, 'gamma0') sigma0_poly = get_poly(sigma0, 'sigma0') nesz = hf['/science/LSAR/SLC/metadata/calibrationInformation/frequency{}/{}/nes0'.format(freq_name, pol_name)][:] noise_samples = nesz - (10 * numpy.log10(sigma0_poly.Coefs[0, 0])) coefs, residuals, rank, sing_values = two_dim_poly_fit( coords_rg_2d, coords_az_2d, noise_samples, x_order=3, y_order=3, x_scale=1e-3, y_scale=1e-3, rcond=1e-40) logger.info( 'The noise_poly fit details:\n\t' 'root mean square residuals = {}\n\t' 'rank = {}\n\t' 'singular values = {}'.format( residuals, rank, sing_values)) t_sicd.Radiometric = RadiometricType( BetaZeroSFPoly=beta0_poly, GammaZeroSFPoly=gamma0_poly, SigmaZeroSFPoly=sigma0_poly, NoiseLevel=NoiseLevelType_( NoiseLevelType='ABSOLUTE', NoisePoly=Poly2DType(Coefs=coefs)))
def update_radiometric(sicd, band_name): # type: (SICDType, str) -> None if 'KMP' in self._satellite: # TODO: skipping for now - strange results for kompsat 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 _get_grid_row(self): """ Gets the Grid.Row metadata. Returns ------- DirParamType """ center_freq = self._get_center_frequency() if self.generation == 'RS2': row_ss = float( self._find('./imageAttributes' '/rasterAttributes' '/sampledPixelSpacing').text) elif self.generation == 'RCM': row_ss = float( self._find('./imageReferenceAttributes' '/rasterAttributes' '/sampledPixelSpacing').text) else: raise ValueError('unhandled generation {}'.format(self.generation)) row_irbw = 2 * float( self._find('./imageGenerationParameters' '/sarProcessingInformation' '/totalProcessedRangeBandwidth').text) / speed_of_light row_wgt_type = WgtTypeType( WindowName=self._find('./imageGenerationParameters' '/sarProcessingInformation' '/rangeWindow/windowName').text.upper()) if row_wgt_type.WindowName == 'KAISER': row_wgt_type.Parameters = { 'BETA': self._find('./imageGenerationParameters' '/sarProcessingInformation' '/rangeWindow/windowCoefficient').text } return DirParamType(SS=row_ss, ImpRespBW=row_irbw, Sgn=-1, KCtr=2 * center_freq / speed_of_light, DeltaKCOAPoly=Poly2DType(Coefs=((0, ), )), WgtType=row_wgt_type)
def update_radiometric(sicd: SICDType, band_name: str) -> None: if self.mission_id in ['KMPS', 'CSG']: # TODO: skipping for now - strange results for flag == 77. Awaiting gidance - see Wade. return if h5_dict['Range Spreading Loss Compensation Geometry'] != 'NONE': slant_range = h5_dict['Reference Slant Range'] exp = h5_dict['Reference Slant Range Exponent'] sf = slant_range**(2 * exp) rsf = h5_dict['Rescaling Factor'] sf /= rsf * rsf if h5_dict.get('Calibration Constant Compensation Flag', None) == 0: cal = band_dict[band_name]['Calibration Constant'] sf /= cal sicd.Radiometric = RadiometricType(BetaZeroSFPoly=Poly2DType( Coefs=[ [ sf, ], ]))
def 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)
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 _get_radiometric(self, image_data, grid): """ Gets the Radiometric metadata. Parameters ---------- image_data : ImageDataType grid : GridType Returns ------- RadiometricType """ def perform_radiometric_fit(component_file): comp_struct = _parse_xml(component_file, without_ns=(self.generation != 'RS2')) comp_values = numpy.array([ float(entry) for entry in comp_struct.find('./gains').text.split() ], dtype=numpy.float64) comp_values = 1. / (comp_values * comp_values ) # adjust for sicd convention if numpy.all(comp_values == comp_values[0]): return numpy.array([ [ comp_values[0], ], ], dtype=numpy.float64) else: # fit a 1-d polynomial in range coords_rg = (numpy.arange(image_data.NumRows) - image_data.SCPPixel.Row) * grid.Row.SS if self.generation == 'RCM': # the rows are sub-sampled start = int(comp_struct.find('./pixelFirstLutValue').text) num_vs = int(comp_struct.find('./numberOfValues').text) t_step = int(comp_struct.find('./stepSize').text) if t_step > 0: rng_indices = numpy.arange(start, num_vs, t_step) else: rng_indices = numpy.arange(start, -1, t_step) coords_rg = coords_rg[rng_indices] return numpy.atleast_2d( polynomial.polyfit(coords_rg, comp_values, 3)) base_path = os.path.dirname(self.file_name) if self.generation == 'RS2': beta_file = os.path.join( base_path, self._find('./imageAttributes' '/lookupTable' '[@incidenceAngleCorrection="Beta Nought"]').text) sigma_file = os.path.join( base_path, self._find('./imageAttributes' '/lookupTable' '[@incidenceAngleCorrection="Sigma Nought"]').text) gamma_file = os.path.join( base_path, self._find('./imageAttributes' '/lookupTable' '[@incidenceAngleCorrection="Gamma"]').text) elif self.generation == 'RCM': beta_file = os.path.join( base_path, 'calibration', self._find('./imageReferenceAttributes' '/lookupTableFileName' '[@sarCalibrationType="Beta Nought"]').text) sigma_file = os.path.join( base_path, 'calibration', self._find('./imageReferenceAttributes' '/lookupTableFileName' '[@sarCalibrationType="Sigma Nought"]').text) gamma_file = os.path.join( base_path, 'calibration', self._find('./imageReferenceAttributes' '/lookupTableFileName' '[@sarCalibrationType="Gamma"]').text) else: raise ValueError('unhandled generation {}'.format(self.generation)) if not os.path.isfile(beta_file): logging.error( msg="Beta calibration information should be located in file {}, " "which doesn't exist.".format(beta_file)) return None # perform beta, sigma, gamma fit beta_zero_sf_poly = perform_radiometric_fit(beta_file) sigma_zero_sf_poly = perform_radiometric_fit(sigma_file) gamma_zero_sf_poly = perform_radiometric_fit(gamma_file) # construct noise poly noise_level = None if self.generation == 'RS2': # noise is in the main product.xml beta0_element = self._find( './sourceAttributes/radarParameters' '/referenceNoiseLevel[@incidenceAngleCorrection="Beta Nought"]' ) elif self.generation == 'RCM': noise_file = os.path.join( base_path, 'calibration', self._find( './imageReferenceAttributes/noiseLevelFileName').text) noise_root = _parse_xml(noise_file, without_ns=True) noise_levels = noise_root.findall('./referenceNoiseLevel') beta0s = [ entry for entry in noise_levels if entry.find('sarCalibrationType').text.startswith('Beta') ] beta0_element = beta0s[0] if len(beta0s) > 0 else None else: raise ValueError('unhandled generation {}'.format(self.generation)) if beta0_element is not None: noise_level = NoiseLevelType_(NoiseLevelType='ABSOLUTE') pfv = float(beta0_element.find('pixelFirstNoiseValue').text) step = float(beta0_element.find('stepSize').text) beta0s = numpy.array([ float(x) for x in beta0_element.find('noiseLevelValues').text.split() ]) range_coords = grid.Row.SS * (numpy.arange(len(beta0s)) * step + pfv - image_data.SCPPixel.Row) noise_poly = polynomial.polyfit( range_coords, beta0s - 10 * numpy.log10( polynomial.polyval(range_coords, beta_zero_sf_poly[:, 0])), 2) noise_level.NoisePoly = Poly2DType( Coefs=numpy.atleast_2d(noise_poly)) return RadiometricType(BetaZeroSFPoly=beta_zero_sf_poly, SigmaZeroSFPoly=sigma_zero_sf_poly, GammaZeroSFPoly=gamma_zero_sf_poly, NoiseLevel=noise_level)
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)