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 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
def test_two_dim_poly_fit(self): coeffs = numpy.arange(9).reshape((3, 3)) y, x = numpy.meshgrid(numpy.arange(2, 6), numpy.arange(-2, 2)) z = polynomial.polyval2d(x, y, coeffs) t_coeffs, residuals, rank, sing_vals = two_dim_poly_fit(x, y, z, x_order=2, y_order=2) diff = (numpy.abs(coeffs - t_coeffs) < 1e-10) self.assertTrue(numpy.all(diff))
def _fit_timecoa_poly(proj_helper, bounds): """ Fit the TimeCOA in new pixel coordinates. Parameters ---------- proj_helper : ProjectionHelper bounds : numpy.ndarray The orthorectification pixel bounds of the form `(min row, max row, min col, max col)`. Returns ------- Poly2DType """ # what is the order of the sicd timecoapoly? in_poly = proj_helper.sicd.Grid.TimeCOAPoly use_order = max(in_poly.order1, in_poly.order2) if use_order == 0: # this is a constant polynomial, must be a spotlight collect return Poly2DType(Coefs=in_poly.get_array()) # create an ortho coordinate grid samples = use_order + 10 ortho_grid = numpy.zeros((samples, samples, 2), dtype=numpy.float64) ortho_grid[:, :, 1], ortho_grid[:, :, 0] = numpy.meshgrid( numpy.linspace(bounds[2], bounds[3], num=samples), numpy.linspace(bounds[0], bounds[1], num=samples)) # map to pixel grid coordinates pixel_grid = proj_helper.ortho_to_pixel(ortho_grid) pixel_rows_m = get_im_physical_coords(pixel_grid[:, :, 0], proj_helper.sicd.Grid, proj_helper.sicd.ImageData, 'row') pixel_cols_m = get_im_physical_coords(pixel_grid[:, :, 1], proj_helper.sicd.Grid, proj_helper.sicd.ImageData, 'col') # evaluate the sicd timecoapoly timecoa_values = proj_helper.sicd.Grid.TimeCOAPoly(pixel_rows_m, pixel_cols_m) # fit this at the ortho_grid coordinates sidd_timecoa_coeffs, residuals, rank, sing_values = two_dim_poly_fit( ortho_grid[:, :, 0] - bounds[0], ortho_grid[:, :, 1] - bounds[2], timecoa_values, x_order=use_order, y_order=use_order, x_scale=1e-3, y_scale=1e-3, rcond=1e-40) import logging logging.warning( 'The time_coa_fit details:\nroot mean square residuals = {}\nrank = {}\nsingular values = {}' .format(residuals, rank, sing_values)) return Poly2DType(Coefs=sidd_timecoa_coeffs)
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)))