def computeImpGeoloc(in_productType, in_objPixc, in_indices, in_height): """ Refines geolocation for in_objPixc pixels corresponding to indices in_indices (in in_objPix) :param in_productType: type of product among "SP"=LakeSP and "TILE"=LakeTile :type in_productType: string :param in_objPixc: pixel cloud from which to compute improved geolocation :type in_objPixc: proc_pixc.PixelCloud or proc_pixc_sp.PixelCloudSP object :param in_indices: indices of pixels related to the same object :type in_indices: 1D-array of int :param in_height: new height of each point used for improved geoloc :type in_height: 1D-array of float :return out_lon_corr: improved longitude of pixels of in_indices :rtype: 1D-array of float :return out_lat_corr: improved latitude of pixels of in_indices :rtype: 1D-array of float :return out_lat_corr: improved latitude of pixels of in_indices :rtype: 1D-array of float """ logger = logging.getLogger("proc_pixc_vec") nb_pix = in_indices.size logger.debug("> %d PixC to deal with", nb_pix) # 1 - Prepare data for Damien's algo # 1.1 - Convert geodetic coordinates (lat, lon, height) to cartesian coordinates (x, y, z) x, y, z = my_geoloc.convert_llh2ecef(in_objPixc.latitude[in_indices], in_objPixc.longitude[in_indices], in_objPixc.height[in_indices], my_var.GEN_RAD_EARTH_EQ, my_var.GEN_RAD_EARTH_POLE) # 1.2 - Get position of associated along-track pixels (in cartesian coordinates) nadir_x = in_objPixc.nadir_x[in_indices] nadir_y = in_objPixc.nadir_y[in_indices] nadir_z = in_objPixc.nadir_z[in_indices] # 1.3 - Get velocity of associated along-track pixels (in cartesian coordinates) nadir_vx = in_objPixc.nadir_vx[in_indices] nadir_vy = in_objPixc.nadir_vy[in_indices] nadir_vz = in_objPixc.nadir_vz[in_indices] # 1.4 - Get distance from satellite to target point ri = in_objPixc.near_range + in_objPixc.range_index[in_indices] * my_var.GEN_RANGE_SPACING # 2 - Use Damien's algo # 2.1 - Init output vectors out_lat_corr = np.zeros(nb_pix) # Improved latitudes out_lon_corr = np.zeros(nb_pix) # Improved longitudes out_height_corr = np.zeros(nb_pix) # Improved heights # 2.2 - Improve geolocation p_final, p_final_llh, h_mu, (iter_grad,nfev_minimize_scalar) = my_geoloc.pointcloud_height_geoloc_vect(np.transpose(np.array([x, y, z])), in_objPixc.height[in_indices], np.transpose(np.array([nadir_x, nadir_y, nadir_z])), np.transpose(np.array([nadir_vx, nadir_vy, nadir_vz])), ri, in_height, recompute_Doppler=True, recompute_R=True, verbose=False, max_iter_grad=1, height_goal=1.e-3, safe_flag=True) # 2.3 - Save output variables out_lat_corr, out_lon_corr, out_height_corr = np.transpose(p_final_llh) # 2.4 - Return output between 0 and 360 degrees (pixel cloud format) return my_tools.convert_to_0_360(out_lon_corr), out_lat_corr, out_height_corr
def taylor_improved_geoloc(self): """ Improve the height of noisy point (in object sensor) """ nb_pix = self.pixcvec.height.size # Convert geodetic coordinates (lat, lon, height) to cartesian coordinates (x, y, z) x, y, z = geoloc.convert_llh2ecef(self.pixcvec.latitude, self.pixcvec.longitude, self.pixcvec.height, GEN_RAD_EARTH_EQ, GEN_RAD_EARTH_POLE) # Get position of associated along-track pixels (in cartesian coordinates) nadir_x = self.sensor.nadir_x nadir_y = self.sensor.nadir_y nadir_z = self.sensor.nadir_z # Get velocity of associated along-track pixels (in cartesian coordinates) nadir_vx = self.sensor.nadir_vx nadir_vy = self.sensor.nadir_vy nadir_vz = self.sensor.nadir_vz # Get distance from satellite to target point ri = self.pixcvec.near_range + self.pixcvec.range_idx * self.pixcvec.range_spacing # Init output vectors self.out_lat_corr = np.zeros(nb_pix) # Improved latitudes self.out_lon_corr = np.zeros(nb_pix) # Improved longitudes self.out_height_corr = np.zeros(nb_pix) # Improved heights # need to remap illumnation time to nearest sensor index # TODO replace this by a call to a get_sensor_index or equivalent function # that either interpolates the sensor or does something more efficient f = interpolate.interp1d(self.sensor.time, range(len(self.sensor.time))) sensor_s = (np.rint(f(self.pixc.illumination_time))).astype(int) # Loop over each pixel (could be vectorized) # vectorisation h_noisy = self.pixcvec.height nadir_x_vect = np.zeros(nb_pix) nadir_y_vect = np.zeros(nb_pix) nadir_z_vect = np.zeros(nb_pix) nadir_vx_vect = np.zeros(nb_pix) nadir_vy_vect = np.zeros(nb_pix) nadir_vz_vect = np.zeros(nb_pix) for i in np.arange(nb_pix): ind_sensor = sensor_s[i] nadir_x_vect[i] = nadir_x[ind_sensor] nadir_y_vect[i] = nadir_y[ind_sensor] nadir_z_vect[i] = nadir_z[ind_sensor] nadir_vx_vect[i] = nadir_vx[ind_sensor] nadir_vy_vect[i] = nadir_vy[ind_sensor] nadir_vz_vect[i] = nadir_vz[ind_sensor] # improuve height with vectorised pixel p_final, p_final_llh, h_mu, ( iter_grad, nfev_minimize_scalar) = geoloc.pointcloud_height_geoloc_vect( np.transpose(np.array([x, y, z])), h_noisy, np.transpose( np.array([nadir_x_vect, nadir_y_vect, nadir_z_vect])), np.transpose( np.array([nadir_vx_vect, nadir_vy_vect, nadir_vz_vect])), ri, self.new_height, recompute_doppler=True, recompute_range=True, verbose=False, max_iter_grad=1, height_goal=1.e-3) self.out_lat_corr, self.out_lon_corr, self.out_height_corr = np.transpose( p_final_llh)
def swotlib_improved_geoloc(self): """ wrapper for functions that use the actual geolocation in swotlib """ # import python/swotlib-only stuff import swot.proc.geolocate import swot.proc.base_classes import swot.multilook.multilook as ml import swot.refloc.refloc #print ("got here", self.sensor) # make swot.proc sensor file from damiens version sensor = swot.proc.base_classes.TVP()#Sensor() sensor.time = np.array(self.sensor.time, dtype=np.double) sensor.x = np.array(self.sensor.nadir_x, dtype=np.double) sensor.y = np.array(self.sensor.nadir_y, dtype=np.double) sensor.z = np.array(self.sensor.nadir_z, dtype=np.double) sensor.vx = np.array(self.sensor.nadir_vx, dtype=np.double) sensor.vy = np.array(self.sensor.nadir_vy, dtype=np.double) sensor.vz = np.array(self.sensor.nadir_vz, dtype=np.double) sensor.ref_leverarm_x = np.array(self.sensor.ref_leverarm_x, dtype=np.double) sensor.ref_leverarm_y = np.array(self.sensor.ref_leverarm_y, dtype=np.double) sensor.ref_leverarm_z = np.array(self.sensor.ref_leverarm_z, dtype=np.double) sensor.sec_leverarm_x = np.array(self.sensor.sec_leverarm_x, dtype=np.double) sensor.sec_leverarm_y = np.array(self.sensor.sec_leverarm_y, dtype=np.double) sensor.sec_leverarm_z = np.array(self.sensor.sec_leverarm_z, dtype=np.double) # #sensor.baseline_left_x = np.array(self.sensor.baseline_left_x,dtype=np.double) #sensor.baseline_left_y = np.array(self.sensor.baseline_left_y,dtype=np.double) #sensor.baseline_left_z = np.array(self.sensor.baseline_left_z, dtype=np.double) #sensor.baseline_right_x = np.array(self.sensor.baseline_right_x, dtype=np.double) #sensor.baseline_right_y = np.array(self.sensor.baseline_right_y, dtype=np.double) #sensor.baseline_right_z = np.array(self.sensor.baseline_right_z ,dtype=np.double) #print ("#########sensor:",sensor.x) # get the azimuth looks azimuth_looks = int(np.nanmedian(self.pixc.num_rare_looks)) #print ('#########az_looks:',azimuth_looks) line_to_sensor = np.arange(len(sensor.x)) # fake these so we dont have to read them in and mess with the interface #sensor.time = np.array(line_to_sensor,dtype=np.double) #lat, lon, height = geoloc.convert_ecef2llh( # sensor.x, sensor.y, sensor.z, GEN_RAD_EARTH_EQ, GEN_RAD_EARTH_POLE) #sensor.latitude = np.zeros(np.shape(sensor.x)) #sensor.longitude = np.zeros(np.shape(sensor.x)) #sensor.altitude = np.zeros(np.shape(sensor.x)) #sensor.heading = np.zeros(np.shape(sensor.x)) rare_line_to_sensor = ml.boxcar_downsample( line_to_sensor[np.newaxis].T, azimuth_looks, 1, agg_type='sample') # get the swath side swath_side = 'Left' swath_side_int = 1 if self.pixc.tile_ref.endswith('R'): swath_side = 'Right' swath_side_int = -1 # make a refloc object attributes = {}#pixc.attributes attributes['nr_pixels'] = self.pixc.nr_pixels attributes['nr_lines'] = self.pixc.nr_lines attributes['wavelength'] = self.pixc.wavelength attributes['range_spacing'] = self.pixc.range_spacing attributes['near_range'] = self.pixc.near_range attributes['swath_side_flag'] = swath_side_int refloc = swot.refloc.refloc.refloc_from_sensor( sensor, attributes, rare_line_to_sensor) # set xyz image # Convert geodetic coordinates (lat, lon, height) to cartesian coordinates (x, y, z) x, y, z = geoloc.convert_llh2ecef( self.pixcvec.latitude, self.pixcvec.longitude, self.pixcvec.height, GEN_RAD_EARTH_EQ, GEN_RAD_EARTH_POLE) # X = np.zeros((attributes['nr_lines'],attributes['nr_pixels'])) Y = np.zeros((attributes['nr_lines'],attributes['nr_pixels'])) Z = np.zeros((attributes['nr_lines'],attributes['nr_pixels'])) X[self.pixcvec.azimuth_idx,self.pixcvec.range_idx] = x Y[self.pixcvec.azimuth_idx,self.pixcvec.range_idx] = y Z[self.pixcvec.azimuth_idx,self.pixcvec.range_idx] = z refloc.set_xyz(X,Y,Z) # set s_image use_illumination_time = True if use_illumination_time: # use the s_image in the pixc file s_image = np.zeros((attributes['nr_lines'],attributes['nr_pixels'])) #### OLD WAY #~ sensor_s = [np.argmin(abs(self.sensor.time #~ - self.pixc.illumination_time[k])) #~ for k in range(len(self.pixc.illumination_time))] f = interpolate.interp1d(self.sensor.time,range(len(self.sensor.time))) sensor_s = (np.rint(f(self.pixc.illumination_time))).astype(np.double) s_image[self.pixc.azimuth_index,self.pixc.range_index] = sensor_s[:] refloc.set_s_prof(s_image) else: # recompute s-image using pixc geoloc as refloc refloc.compute_s_prof(0, attributes['nr_lines']) #refloc.compute_s_prof(0, attributes['nr_lines']) # make H_new as a 2d image H_new = np.zeros((attributes['nr_lines'],attributes['nr_pixels'])) H_new[self.pixcvec.azimuth_idx,self.pixcvec.range_idx] = self.new_height[:] # finally call the function that does the work #llh = swot.proc.geolocate.height_constrained_geoloc_grad_search ( # refloc, # sensor, # H_new, # self.pixc.wavelength, # swath_side_int, # maxiter=10) xyz = swot.proc.geolocate.fixed_height_geolocation ( refloc, sensor, H_new, self.pixc.wavelength) llh = swot.proc.geolocate.xyz2llh(xyz) # map to outputs lat = np.squeeze(llh[0,:,:]) lon = np.squeeze(llh[1,:,:]) height = np.squeeze(llh[2,:,:]) msk = np.zeros((attributes['nr_lines'],attributes['nr_pixels'])) msk[self.pixcvec.azimuth_idx,self.pixcvec.range_idx] = 1 self.OUT_lat_corr = lat[msk==1] self.OUT_lon_corr = lon[msk==1] self.OUT_height_corr = height[msk==1]
def aggregate_wse(self, pixc, mask, use_improved_geoloc=True): """ Aggregate water surface elevation and associated uncertainties """ LOGGER.info("aggregating wse") pixc_height = pixc['pixel_cloud']['height'] pixc_num_rare_looks = pixc['pixel_cloud']['eff_num_rare_looks'] pixc_num_med_looks = pixc['pixel_cloud']['eff_num_medium_looks'] pixc_power_plus_y = pixc['pixel_cloud']['power_plus_y'] pixc_power_minus_y = pixc['pixel_cloud']['power_minus_y'] pixc_dh_dphi = pixc['pixel_cloud']['dheight_dphase'] pixc_dlat_dphi = pixc['pixel_cloud']['dlatitude_dphase'] pixc_dlon_dphi = pixc['pixel_cloud']['dlongitude_dphase'] pixc_phase_noise_std = pixc['pixel_cloud']['phase_noise_std'] pixc_height_std = np.abs(pixc_phase_noise_std * pixc_dh_dphi) # set bad pix height std to high number to deweight # instead of giving infs/nans bad_num = 1.0e5 pixc_height_std[pixc_height_std<=0] = bad_num pixc_height_std[np.isinf(pixc_height_std)] = bad_num pixc_height_std[np.isnan(pixc_height_std)] = bad_num looks_to_efflooks = pixc['pixel_cloud'].looks_to_efflooks if use_improved_geoloc: # Flatten ifgram with improved geoloc and height target_xyz = geoloc.convert_llh2ecef( pixc['pixel_cloud']['improved_latitude'], pixc['pixel_cloud']['improved_longitude'], pixc['pixel_cloud']['improved_height'], GEN_RAD_EARTH_EQ, GEN_RAD_EARTH_POLE) else: # Flatten ifgram with original geoloc and improved height target_xyz = geoloc.convert_llh2ecef( pixc['pixel_cloud']['latitude'], pixc['pixel_cloud']['longitude'], pixc['pixel_cloud']['improved_height'], GEN_RAD_EARTH_EQ, GEN_RAD_EARTH_POLE) pixc_ifgram = pixc['pixel_cloud']['interferogram'] tvp_plus_y_antenna_xyz = (pixc['tvp']['plus_y_antenna_x'], pixc['tvp']['plus_y_antenna_y'], pixc['tvp']['plus_y_antenna_z']) tvp_minus_y_antenna_xyz = (pixc['tvp']['minus_y_antenna_x'], pixc['tvp']['minus_y_antenna_y'], pixc['tvp']['minus_y_antenna_z']) pixc_tvp_index = ag.get_sensor_index(pixc) pixc_wavelength = pixc.wavelength flat_ifgram = ag.flatten_interferogram(pixc_ifgram, tvp_plus_y_antenna_xyz, tvp_minus_y_antenna_xyz, target_xyz, pixc_tvp_index, pixc_wavelength) self.wse = np.ma.masked_all((self.size_y, self.size_x)) self.wse_u = np.ma.masked_all((self.size_y, self.size_x)) self.wse_qual = np.ma.ones((self.size_y, self.size_x)) self.n_wse_pix = np.ma.zeros((self.size_y, self.size_x)) for i in range(0, self.size_y): for j in range(0, self.size_x): good = mask[self.proj_mapping[i][j]] if np.any(good): grid_height = ag.height_with_uncerts( pixc_height[self.proj_mapping[i][j]], good, pixc_num_rare_looks[self.proj_mapping[i][j]], pixc_num_med_looks[self.proj_mapping[i][j]], flat_ifgram[self.proj_mapping[i][j]], pixc_power_minus_y[self.proj_mapping[i][j]], pixc_power_plus_y[self.proj_mapping[i][j]], looks_to_efflooks, pixc_dh_dphi[self.proj_mapping[i][j]], pixc_dlat_dphi[self.proj_mapping[i][j]], pixc_dlon_dphi[self.proj_mapping[i][j]], pixc_height_std[self.proj_mapping[i][j]], method=self.height_agg_method) self.wse[i][j] = grid_height[0] self.wse_u[i][j] = grid_height[2] self.n_wse_pix[i][j] = ag.simple(good, metric='sum') # TODO: more complex qual handling self.wse_qual[i][j] = np.logical_or( self.wse_u[i][j] >= WSE_BAD_UNCERT, self.n_wse_pix[i][j] <= BAD_NUM_PIXELS) self.apply_wse_corrections()
def taylor_improved_geoloc(self): """ Improve the height of noisy point (in object sensor) """ LOGGER.info("doing taylor improved geolocation") nb_pix = self.pixc['pixel_cloud']['height'].size # Convert geodetic coordinates (lat, lon, height) to cartesian coordinates (x, y, z) x, y, z = geoloc.convert_llh2ecef(self.pixc['pixel_cloud']['latitude'], self.pixc['pixel_cloud']['longitude'], self.pixc['pixel_cloud']['height'], GEN_RAD_EARTH_EQ, GEN_RAD_EARTH_POLE) # Get position of associated along-track pixels (in cartesian coordinates) nadir_x = self.pixc['tvp']['x'] nadir_y = self.pixc['tvp']['y'] nadir_z = self.pixc['tvp']['z'] # Get velocity of associated along-track pixels (in cartesian coordinates) nadir_vx = self.pixc['tvp']['vx'] nadir_vy = self.pixc['tvp']['vy'] nadir_vz = self.pixc['tvp']['vz'] # Get distance from satellite to target point ri = self.pixc.near_range + (self.pixc['pixel_cloud']['range_index'] * self.pixc.nominal_slant_range_spacing) # Init output vectors self.out_lat_corr = np.zeros(nb_pix) # Improved latitudes self.out_lon_corr = np.zeros(nb_pix) # Improved longitudes self.out_height_corr = np.zeros(nb_pix) # Improved heights # Remap illumnation time to nearest sensor index sensor_s = ag.get_sensor_index(self.pixc) # Loop over each pixel (could be vectorized) h_noisy = self.pixc['pixel_cloud']['height'] nadir_x_vect = np.zeros(nb_pix) nadir_y_vect = np.zeros(nb_pix) nadir_z_vect = np.zeros(nb_pix) nadir_vx_vect = np.zeros(nb_pix) nadir_vy_vect = np.zeros(nb_pix) nadir_vz_vect = np.zeros(nb_pix) for i in np.arange(nb_pix): ind_sensor = sensor_s[i] nadir_x_vect[i] = nadir_x[ind_sensor] nadir_y_vect[i] = nadir_y[ind_sensor] nadir_z_vect[i] = nadir_z[ind_sensor] nadir_vx_vect[i] = nadir_vx[ind_sensor] nadir_vy_vect[i] = nadir_vy[ind_sensor] nadir_vz_vect[i] = nadir_vz[ind_sensor] # improve height with vectorised pixel p_final, p_final_llh, h_mu, (iter_grad, nfev_minimize_scalar) = \ geoloc.pointcloud_height_geoloc_vect(np.transpose(np.array([x, y, z])), h_noisy, np.transpose(np.array( [nadir_x_vect, nadir_y_vect, nadir_z_vect])), np.transpose(np.array( [nadir_vx_vect, nadir_vy_vect, nadir_vz_vect])), ri, self.new_height, recompute_doppler=True, recompute_range=True, verbose=False, max_iter_grad=1, height_goal=1.e-3) self.out_lat_corr, self.out_lon_corr, self.out_height_corr = np.transpose( p_final_llh)