def compute_near_range(IN_attributes, layer, cycle_number=0): if IN_attributes.height_model == 'reference_height': count, height_tot = 0, 0 fields_count = layer.GetLayerDefn().GetFieldCount() for ind, polygon_index in enumerate(layer): for i in range(fields_count): if layer.GetLayerDefn().GetFieldDefn(i).GetName() == IN_attributes.height_name: if polygon_index.GetField(str(IN_attributes.height_name)) is not None : height_tot += np.float(polygon_index.GetField(str(IN_attributes.height_name))) count +=1 if count != 0: hmean = height_tot/count near_range = np.mean(np.sqrt((IN_attributes.alt - hmean + (IN_attributes.nr_cross_track ** 2) / (2 * GEN_APPROX_RAD_EARTH)) ** 2 + IN_attributes.nr_cross_track ** 2)) else: near_range = 0 if IN_attributes.height_model == 'gaussian': near_range = np.mean(np.sqrt((IN_attributes.alt + (IN_attributes.nr_cross_track ** 2) / (2 * GEN_APPROX_RAD_EARTH)) ** 2 + IN_attributes.nr_cross_track ** 2)) if IN_attributes.height_model == 'polynomial': near_range = np.mean(np.sqrt((IN_attributes.alt + (IN_attributes.nr_cross_track ** 2) / (2 * GEN_APPROX_RAD_EARTH)) ** 2 + IN_attributes.nr_cross_track ** 2)) if IN_attributes.height_model == 'reference_file': near_range = np.mean(np.sqrt((IN_attributes.alt + (IN_attributes.nr_cross_track ** 2) / (2 * GEN_APPROX_RAD_EARTH)) ** 2 + IN_attributes.nr_cross_track ** 2)) if IN_attributes.height_model == None: hmean = IN_attributes.height_model_a + IN_attributes.height_model_a * \ np.sin(2*np.pi * (np.mean(IN_attributes.orbit_time) + cycle_number * IN_attributes.cycle_duration) - IN_attributes.height_model_t0) / IN_attributes.height_model_period near_range = np.mean(np.sqrt((IN_attributes.alt - hmean + (IN_attributes.nr_cross_track ** 2) / (2 * GEN_APPROX_RAD_EARTH)) ** 2 + IN_attributes.nr_cross_track ** 2)) my_api.printInfo("[write_polygons] [reproject_shapefile] Near_range = %d" % (near_range)) return near_range
def calc_delta_jitter(IN_orbit_heading, IN_lat, IN_orbit_jitter): """ Calculate the jitter :param IN_orbit_heading: the orbit headings :type IN_orbit_heading: 1D-array of float :param IN_lat: the orbit latitudes :type IN_lat: 1D-array of float :param IN_orbit_jitter : :type IN_orbit_jitter : :return: the values of delta jitter :rtype: 1D-array of float """ # Random jitter of +/- random_jitter orbit_jitter = [0, int(np.random.normal(0, IN_orbit_jitter)) ][IN_orbit_jitter != 0] if orbit_jitter > IN_orbit_jitter: orbit_jitter = IN_orbit_jitter elif orbit_jitter < -IN_orbit_jitter: orbit_jitter = -IN_orbit_jitter my_api.printInfo( "[mathematical_function] [calc_delta_jitter] orbit_jitter = %.6f" % orbit_jitter) return (np.cos(IN_orbit_heading) * orbit_jitter) / ( GEN_APPROX_RAD_EARTH * np.cos(np.mean(IN_lat) * DEG2RAD))
def calculate_tropo_error_map(self, latmin): my_api.printInfo("Computing map tropo_error field on %d x %d image" % (self.azmax - self.azmin, self.rmax - self.rmin)) ds = nc.Dataset(self.tropo_error_map_file, 'r') delta_wtc_MEAN = ds.variables['delta_wtc_MEAN'][:] delta_wtc_STD = ds.variables['delta_wtc_STD'][:] latitude = ds.variables['latitude'][:] f = scipy.interpolate.interp1d(latitude, delta_wtc_MEAN, kind='linear') delta_wtc_MEAN_local = f(latmin) f = scipy.interpolate.interp1d(latitude, delta_wtc_STD, kind='linear') delta_wtc_STD_local = f(latmin) my_api.printInfo( "%f cm mean biais and %f cm stv estimated at latitude %f" % (delta_wtc_MEAN_local, delta_wtc_STD_local, latmin)) self.tropo_map_rg_az = height_model.generate_2d_profile_gaussian( 1, self.azmin, self.azmax + 1, 1, self.rmin, self.rmax + 1, delta_wtc_STD_local * 0.01, lcorr=self.tropo_error_correlation) + delta_wtc_MEAN_local * 0.01
def run_postprocessing(self): """ Run post-processing """ my_api.printInfo("") my_api.printInfo("") my_api.printInfo("[sisimp_processing] POST-PROCESSING...") my_api.printInfo("[sisimp_processing] Nothing to do...") my_api.printInfo("")
def write_swath_polygons(IN_attributes): """ Write swath polygons shapefile for currently processed orbit :param IN_attributes :type IN_attributes """ IN_attributes.sisimp_filenames.footprint_file = IN_attributes.sisimp_filenames.footprint_file.replace( '.shp', '_' + str(IN_attributes.tile_number) + '.shp') my_api.printInfo( "[sisimp_function] [write_swath_polygons] == write_swath_polygons : %s ==" % IN_attributes.sisimp_filenames.footprint_file) shpDriver = ogr.GetDriverByName(str("ESRI Shapefile")) # 1 - Delete output file if already exists if os.path.exists(IN_attributes.sisimp_filenames.footprint_file): shpDriver.DeleteDataSource( IN_attributes.sisimp_filenames.footprint_file) # 2 - Create output file dataSource = shpDriver.CreateDataSource( IN_attributes.sisimp_filenames.footprint_file) srs = osr.SpatialReference() srs.ImportFromEPSG(4326) # WGS84 layer = dataSource.CreateLayer(str( os.path.basename( IN_attributes.sisimp_filenames.footprint_file).split('.')[0]), srs, geom_type=ogr.wkbMultiPolygon) layer.CreateField(ogr.FieldDefn(str('Swath'), ogr.OFTString)) layerDefn = layer.GetLayerDefn() for swath, tile_coords in IN_attributes.tile_coords.items(): feature = ogr.Feature(layerDefn) geom = ogr.Geometry(ogr.wkbPolygon) ring = ogr.Geometry(ogr.wkbLinearRing) for point in tile_coords: ring.AddPoint(point[0], point[1]) ring.CloseRings() geom.AddGeometry(ring) geom = geom.ConvexHull() feature.SetField(str("Swath"), str(swath)) feature.SetGeometry(geom) layer.CreateFeature(feature) dataSource.Destroy()
def get_roll_file_associated_to_orbit_and_cycle(self, orbit_number, cycle_number, delta_time=0): root_name = "GLOBAL_swot292_c" file_name = os.path.join( self.In_repository, root_name + str(cycle_number).zfill(2) + "_p" + str(orbit_number).zfill(3)) + ".nc" my_api.printInfo("Roll file used : %s " % file_name) self.read_roll_file(file_name, delta_time=delta_time)
def __init__(self, IN_azimuth_index, IN_range_index, IN_mission_start_time, IN_cycle_duration, IN_cycle_num, IN_pass_num, IN_tile_ref, IN_nb_pix_range, IN_nb_pix_azimuth): """ Constructor of the pixel cloud vector attribute product :param IN_azimuth_index: azimuth indices :type IN_azimuth_index: 1D-array of int :param IN_range_index: range indices :type IN_range_index: 1D-array of int :param IN_mission_start_time: mission start time :type IN_mission_start_time: string (yyyy-mm-dd) :param IN_cycle_duration: number of seconds in a cycle :type IN_cycle_duration: int :param IN_cycle_num: cycle number :type IN_cycle_num: int :param IN_pass_num: pass number :type IN_pass_num: int :param IN_tile_ref: tile reference :type IN_tile_ref: string :param IN_nb_pix_range: number of pixels in range of the interferogram :type IN_nb_pix_range: int :param IN_nb_pix_azimuth: number of pixels in azimuth of the interferogram :type IN_nb_pix_azimuth: int + nb_water_pix(int) : number of water pixels, i.e. pixels in azimuth_index, ..., crosstrack vectors + latitude_vectorproc(1D-array) : improved latitude values + longitude_vectorproc(1D-array) : improved longitude values + height_vectorproc(1D-array) : improved height values + river_tag(1D-array): reach ID associated to each pixel + pattern(str): filename pattern """ my_api.printInfo("[l2_hr_pixc_vec_river] == INIT ==") self.azimuth_index = IN_azimuth_index self.range_index = IN_range_index self.nb_water_pix = IN_azimuth_index.size self.latitude_vectorproc = None self.longitude_vectorproc = None self.height_vectorproc = None self.river_tag = None self.mission_start_time = IN_mission_start_time self.cycle_duration = IN_cycle_duration self.cycle_num = IN_cycle_num self.pass_num = IN_pass_num self.tile_ref = IN_tile_ref self.nb_pix_range = IN_nb_pix_range self.nb_pix_azimuth = IN_nb_pix_azimuth self.nb_pix_river = 0 # Number of PixC associated to river self.pixc_river_idx = None # Indices of pixels in the L2_HR_PIXC product associated to a river
def read_parameter(IN_rdf_reader, IN_instrument_name, IN_instrument_default_value, read_type): try: OUT_instrument_param = read_type( IN_rdf_reader.getValue(IN_instrument_name)) my_api.printInfo("[sisimp_processing] [read_parameter] %s : %s" % (IN_instrument_name, str(OUT_instrument_param))) except: OUT_instrument_param = IN_instrument_default_value my_api.printInfo( "[sisimp_processing] [read_parameter] Default value for %s : %s" % (IN_instrument_name, str(OUT_instrument_param))) return OUT_instrument_param
def calculate_tropo_error_gaussian(self): my_api.printInfo( "Computing random tropo_error field on %d x %d image" % (self.azmax - self.azmin, self.rmax - self.rmin)) self.tropo_map_rg_az = height_model.generate_2d_profile_gaussian( 1, self.azmin, self.azmax + 1, 1, self.rmin, self.rmax + 1, self.tropo_error_stdv, lcorr=self.tropo_error_correlation) + self.tropo_error_mean
def coords_from_labels(matrix): nb_col, nb_line = matrix.shape labels_coords = {} processing = np.round(np.linspace(0, nb_col, 11), 0) for i in range(nb_col): if i in processing: my_api.printInfo( "[my_tools] [coords_from_labels] Processing %d %%" % (int(100 * (i + 1) / nb_col))) for j in range(nb_line): val = matrix[i, j] labels_coords.setdefault(val, []).append((i, j)) return labels_coords
def calc_delta_h(IN_angles, IN_noise_height, IN_height_bias_std, seed=None): """ Calculate the delta h values and add noise :param IN_angles : the angles :type IN_angles: 1D-array of int :param IN_noise_height : :type IN_noise_height : :param IN_height_bias_std : :type IN_height_bias_std : :return OUT_noisy_h: the noisy height values :rtype OUT_noisy_h: 1D-array of float """ np.random.seed(seed) if (IN_angles.size != 0) and (np.max(IN_angles * RAD2DEG) > np.max( IN_noise_height[:, 0])): my_api.printInfo( "One or more incidence angles are greater than the max value defined in the noise file ! Values higher than {0} degrees will be set to the maximum value defined in the file." .format(np.max(IN_noise_height[:, 0]))) OUT_noisy_h = 0 if (IN_noise_height[:, 1] < 1.e-5).any( ) and not IN_height_bias_std < 1.e-5: # Case noise file as one or more zeros OUT_noisy_h = np.random.normal(0, IN_height_bias_std) elif not (IN_noise_height[:, 1] < 1.e-5).any( ) and IN_height_bias_std < 1.e-5: # Case height bias equals zero stdv = np.interp(IN_angles * RAD2DEG, IN_noise_height[:, 0], IN_noise_height[:, 1]) stdv[np.isnan(stdv)] = 0. OUT_noisy_h = np.random.normal(0, stdv) elif (IN_noise_height[:, 1] < 1.e-5).any( ) and IN_height_bias_std < 1.e-5: # Case both are equals to zero OUT_noisy_h = 0. else: # Case none are equals to zero stdv = np.interp(IN_angles * RAD2DEG, IN_noise_height[:, 0], IN_noise_height[:, 1]) stdv[np.isnan(stdv)] = 0. OUT_noisy_h = np.random.normal( 0, IN_height_bias_std) + np.random.normal(0, stdv) return OUT_noisy_h
def get_tiles_from_orbit(my_attributes, orbit_number): # Retrieve the tile database (pass_number/tile_number/nadir_lon/nadir_lat/nadir_heading) tile_db = my_attributes.tile_database # Subset the tile DB to the portion related to the orbit number #tile_db_orbit = tile_db[np.where(tile_db[:,0] == IN_orbit_number)[0],:] tmp_orbit_number = orbit_number - 331 # Pass 1 in tile database file = pass 332 in last KML file (sept2015-v2) if tmp_orbit_number < 1: tmp_orbit_number += 584 tile_db_orbit = tile_db[np.where(tile_db[:, 0] == tmp_orbit_number)[0], :] # Compute the indices of nadir_lat_min and nadir_lat_max nadir_lat_argmin = int(np.argmin(my_attributes.lat * RAD2DEG)) nadir_lat_argmax = int(np.argmax(my_attributes.lat * RAD2DEG)) # Get long and lat in degrees, associated to nadir_min_lat nadir_lat_deg_min = my_attributes.lat[nadir_lat_argmin] * RAD2DEG nadir_lon_deg_min = my_attributes.lon[nadir_lat_argmin] * RAD2DEG # Get long and lat in degrees, associated to nadir_max_lat nadir_lat_deg_max = my_attributes.lat[nadir_lat_argmax] * RAD2DEG nadir_lon_deg_max = my_attributes.lon[nadir_lat_argmax] * RAD2DEG # Construct the kd-tree for quick nearest-neighbor lookup tree = cKDTree(tile_db_orbit[:, 2:4]) # Retrieve index of tile_db_orbit the nearest of nadir_min_lat ind_min = tree.query([nadir_lat_deg_min, nadir_lon_deg_min]) # Retrieve index of tile_db_orbit the nearest of nadir_max_lat ind_max = tree.query([nadir_lat_deg_max, nadir_lon_deg_max]) tile_db_orbit_cropped = tile_db_orbit[ max(0, min(ind_max[1], ind_min[1]) - 1):min(len(tile_db_orbit), max(ind_max[1], ind_min[1]) + 2), :] vect_lat_lon_db_cropped = np.zeros( [max(0, tile_db_orbit_cropped.shape[0] - 1), 2]) for i in range(max(0, tile_db_orbit_cropped.shape[0] - 1)): vect_lat_lon_db_cropped[ i, 0] = tile_db_orbit_cropped[i + 1, 2] - tile_db_orbit_cropped[i, 2] vect_lat_lon_db_cropped[ i, 1] = tile_db_orbit_cropped[i + 1, 3] - tile_db_orbit_cropped[i, 3] nb_az_traj = max(nadir_lat_argmax, nadir_lat_argmin) - min( nadir_lat_argmax, nadir_lat_argmin) + 1 tile_values = np.zeros(nb_az_traj, int) for i in range( min(nadir_lat_argmax, nadir_lat_argmin) - 1, max(nadir_lat_argmax, nadir_lat_argmin) + 1): dist = np.abs( ((my_attributes.lat[i] * RAD2DEG - tile_db_orbit_cropped[:-1, 2]) * vect_lat_lon_db_cropped[:, 0] + (my_attributes.lon[i] * RAD2DEG - tile_db_orbit_cropped[:-1, 3]) * vect_lat_lon_db_cropped[:, 1]) / np.sqrt(vect_lat_lon_db_cropped[:, 0]**2 + vect_lat_lon_db_cropped[:, 1]**2)) tile_values[i] = tile_db_orbit_cropped[np.argmin(dist), 1] tile_list = np.unique(tile_values) my_api.printInfo( "[my_tiling] [get_tiles_from_orbit] Simulation over tiles number: %s" % str(tile_list)) return tile_values, tile_list
def read_orbit(IN_filename, IN_cycle_number, IN_attributes): """ Read the orbit from IN_filename. Store lon,lat,alt,heading + few data :param IN_filename: full path of the orbit file :type IN_filename: string :param IN_cycle_number: cycle number :type IN_cycle_number = int :param IN_attributes :type IN_attributes :param OUT_attributes :type OUT_attributes """ my_api.printInfo("[sisimp_function] [read_orbit] == read_orbit ==") my_api.printInfo("[sisimp_function] [read_orbit] Orbit file = %s" % IN_filename) OUT_attributes = IN_attributes # Read the orbit file ds = Dataset(IN_filename) lon1 = ds.variables['longitude'][:] * DEG2RAD lat1 = ds.variables['latitude'][:] * DEG2RAD alt1 = ds.variables['altitude'][:] heading1 = ds.variables['heading'][:] * DEG2RAD if "start_mission_time" in ds.ncattrs(): OUT_attributes.mission_start_time = ds.getncattr( 'start_mission_time') # Mission start time elif "mission start time" in ds.ncattrs(): OUT_attributes.mission_start_time = ds.getncattr( 'mission start time') # Mission start time OUT_attributes.cycle_duration = ds.getncattr('repeat_cycle_period') OUT_attributes.azimuth_spacing = ds.getncattr('azimuth_spacing') # Add 2 points margin to avoid problems in azr_from_lonlat (interpolation) n = len(lat1) + 2 lat = np.zeros(n) lon = np.zeros(n) alt = np.zeros(n) heading = np.zeros(n) lat[1:-1], lon[1:-1], alt[1:-1], heading[1:-1] = [ lat1, lon1, alt1, heading1 ] sign = [-1, 1][lat1[-1] < lat1[0]] lat[0] = lat[1] + sign * 70000.0 / GEN_APPROX_RAD_EARTH * sin(heading1[0]) lat[-1] = lat[-2] - sign * 70000.0 / GEN_APPROX_RAD_EARTH * sin( heading1[-1]) x = (lat[1] - lat[0]) / (lat[2] - lat[1]) lon[0] = lon[1] - x * (lon[2] - lon[1]) alt[0] = alt[1] - x * (alt[2] - alt[1]) heading[0] = heading[1] - x * (heading[2] - heading[1]) x = (lat[-2] - lat[-1]) / (lat[-3] - lat[-2]) lon[-1] = lon[-2] - x * (lon[-3] - lon[-2]) alt[-1] = alt[-2] - x * (alt[-3] - alt[-2]) heading[-1] = heading[-2] - x * (heading[-3] - heading[-2]) # Add lon noise my_api.printDebug( "[sisimp_function] [read_orbit] lon[0] before orbit jitter = %.6f" % (lon[0])) lon = lon + math_fct.calc_delta_jitter(heading, lat, IN_attributes.orbit_jitter) my_api.printDebug( "[sisimp_function] [read_orbit] lon[0] after orbit jitter = %.6f" % (lon[0])) # !!! Do not forget that indices 0 and -1 correspond to fake values, just used for extrapolations # Variable name ended with _init will be use to linear_exptrap OUT_attributes.lon = OUT_attributes.lon_init = lon OUT_attributes.lat = OUT_attributes.lat_init = lat OUT_attributes.alt = alt OUT_attributes.heading = OUT_attributes.heading_init = heading OUT_attributes.cosphi_init = np.cos(lon) OUT_attributes.sinphi_init = np.sin(lon) OUT_attributes.costheta_init = np.cos(np.pi / 2 - lat) OUT_attributes.sintheta_init = np.sin(np.pi / 2 - lat) OUT_attributes.cospsi_init = np.cos(heading) OUT_attributes.sinpsi_init = np.sin(heading) ratio = (lat[1] - lat[0]) / (lat[2] - lat[1]) orbit_time = np.zeros(n) orbit_time[1:-1] = np.array(ds.variables['time']) + ( IN_cycle_number - 1) * OUT_attributes.cycle_duration orbit_time[0] = ratio * (orbit_time[1] - orbit_time[2]) + orbit_time[1] orbit_time[-1] = ratio * (orbit_time[-2] - orbit_time[-3]) + orbit_time[-2] OUT_attributes.orbit_time = orbit_time x = np.zeros(n) x[1:-1] = np.array(ds.variables['x']) x[0] = ratio * (x[1] - x[2]) + x[1] x[-1] = ratio * (x[-2] - x[-3]) + x[-2] OUT_attributes.x = x y = np.zeros(n) y[1:-1] = np.array(ds.variables['y']) y[0] = ratio * (y[1] - y[2]) + y[1] y[-1] = ratio * (y[-2] - y[-3]) + y[-2] OUT_attributes.y = y z = np.zeros(n) z[1:-1] = np.array(ds.variables['z']) z[0] = ratio * (z[1] - z[2]) + z[1] z[-1] = ratio * (z[-2] - z[-3]) + z[-2] OUT_attributes.z = z my_api.printDebug( "[sisimp_function] [read_orbit] Nb points on nadir track = %d" % (len(OUT_attributes.orbit_time))) return OUT_attributes
def compute_pixels_in_water(IN_fshp_reproj, IN_pixc_vec_only, IN_attributes): """ Compute the position of the radar pixels that are inside a water body Method: use the GDAL rasterize function to mark the pixels that are contained in some polygons. This is very fast. Then we extract the pixels that are marked (value=1) and write them in an text file for check with qgis Important note: only polygons in one swath (left or right) must be in fshp_reproj :param IN_fshp_reproj: full path of the shapefile with polygons in radar projection :type IN_fshp_reproj: string :param IN_pixc_vec_only: if set, deal only with polygons with field RIV_FLAG != 0 :type IN_pixc_vec_only: boolean :param IN_attributes: :type IN_attributes: :return OUT_burn_data: the radar pixels that are inside a water body :rtype OUT_burn_data: 2D-array of int (0=land 1=water) :rettun OUT_height_data : the height pixels that are inside a water body :rtype OUT_height_data : 2D-array of int (height of each water body pixel) """ if IN_pixc_vec_only: my_api.printInfo("[write_polygons] [compute_pixels_in_water] == compute_pixels_in_water / river polygons only ==") else: my_api.printInfo("[write_polygons] [compute_pixels_in_water] == compute_pixels_in_water / all polygons ==") # 1 - Read the reprojected shapefile layer, da_shapefile = my_shp.open_shp(IN_fshp_reproj) if IN_pixc_vec_only: layer.SetAttributeFilter(str("RIV_FLAG != '0'")) my_api.printInfo("[write_polygons] [compute_pixels_in_water] compute_pixels_in_water / river pixels only - %d features to deal with" % layer.GetFeatureCount()) # Create a GDAL raster in memory nx = len(IN_attributes.lon) ny = IN_attributes.nb_pix_range cover = np.zeros((ny, nx), dtype='float64') cover_height = np.zeros((ny, nx), dtype='float64') cover_code = np.zeros((ny, nx), dtype='float64') cover_ind_lac = np.zeros((ny, nx), dtype='int') # Create 2 raster band if heights value come from shapefile #~ nb_rasterBand = [1, 2][IN_attributes.height_model == "reference_height" or IN_attributes.height_model == "gaussian" or IN_attributes.height_model == "polynomial"] nb_rasterBand = 4 ds = gdal.GetDriverByName(str('MEM')).Create('', nx, ny, nb_rasterBand, GDT_Float32) ds.SetGeoTransform([-0.5, 1, 0, -0.5, 0, 1]) ds.GetRasterBand(1).WriteArray(cover) # Burn with a value 1 the pixels that are in a polygon gdal.RasterizeLayer(ds, [1], layer, None, None, burn_values=[1]) #~ # , options=['ALL_TOUCHED=TRUE']) # Convert the radar pixels touching water in lon-lat OUT_burn_data = ds.GetRasterBand(1).ReadAsArray() # Analyse value in shapefile OUT_height_data = None OUT_code_data = None OUT_ind_lac_data = None #not used, commented to improve speed if IN_attributes.height_model == "reference_height": ds.GetRasterBand(2).WriteArray(cover_height) # Burn with height value pixels in the associated polygon gdal.RasterizeLayer(ds, [2], layer, None, options=["ATTRIBUTE=HEIGHT"]) # Get height pixels in lon-lat OUT_height_data = ds.GetRasterBand(2).ReadAsArray() if IN_attributes.height_model == "gaussian" or IN_attributes.height_model == "polynomial": ds.GetRasterBand(3).WriteArray(cover_code) # Burn with height value pixels in the associated polygon gdal.RasterizeLayer(ds, [3], layer, None, options=["ATTRIBUTE=CODE"]) # Get height pixels in lon-lat OUT_code_data = ds.GetRasterBand(3).ReadAsArray().astype(int) ds.GetRasterBand(4).WriteArray(cover_ind_lac) gdal.RasterizeLayer(ds, [4], layer, None, options=["ATTRIBUTE=IND_LAC"]) OUT_ind_lac_data = ds.GetRasterBand(4).ReadAsArray().astype(int) # Close the raster ds = None if not IN_pixc_vec_only: my_api.printInfo("[write_polygons] [compute_pixels_in_water] Compute lakes labels") nb_lakes = len(IN_attributes.liste_lacs) if nb_lakes > 100 : # Quick way to compute labels for a large amount of lakes labels_coords = my_tools.coords_from_labels(OUT_ind_lac_data) for i, lake in enumerate(IN_attributes.liste_lacs): if lake.num in labels_coords: lake.set_pixels_coods(np.array(labels_coords[lake.num]).transpose()) else : # lakes without pixels lake.set_pixels_coods([[], []]) else : for lake in IN_attributes.liste_lacs: lake.compute_pixels_in_given_lac(OUT_ind_lac_data) return OUT_burn_data, OUT_height_data, OUT_code_data, OUT_ind_lac_data, IN_attributes
def write_file_asShp(self, IN_output_file): """ Write the pixel cloud vector attribute for rivers file as a shapefile :param IN_output_file: output file full path :type IN_output_file: string """ if self.nb_pix_river == 0: my_api.printInfo( "[l2_hr_pixc_vec_river] [write_file_asShp] == write_file_asShp ==" ) my_api.printInfo( "[l2_hr_pixc_vec_river] [write_file_asShp] NO river pixels => NO PIXCVecRiver shapefile generated" ) else: my_api.printInfo( "[l2_hr_pixc_vec_river] [write_file_asShp] == write_file_asShp : %s ==" % IN_output_file) # 1 - Initialisation du fichier de sortie # 1.1 - Driver shpDriver = ogr.GetDriverByName(str("ESRI Shapefile")) # 1.2 - Creation du fichier if os.path.exists(IN_output_file): shpDriver.DeleteDataSource(IN_output_file) outDataSource = shpDriver.CreateDataSource(IN_output_file) # 1.3 - Creation de la couche srs = osr.SpatialReference() srs.ImportFromEPSG(4326) # WGS84 outLayer = outDataSource.CreateLayer(str( os.path.basename(IN_output_file).split(".")[0]), srs, geom_type=ogr.wkbPoint) # 1.4 - Creation des attributs outLayer.CreateField(ogr.FieldDefn(str('az_index'), ogr.OFTInteger)) outLayer.CreateField(ogr.FieldDefn(str('r_index'), ogr.OFTInteger)) tmpField = ogr.FieldDefn(str('lat2'), ogr.OFTReal) tmpField.SetWidth(15) tmpField.SetPrecision(6) outLayer.CreateField(tmpField) tmpField = ogr.FieldDefn(str('long2'), ogr.OFTReal) tmpField.SetWidth(15) tmpField.SetPrecision(6) outLayer.CreateField(tmpField) tmpField = ogr.FieldDefn(str('wse2'), ogr.OFTReal) tmpField.SetWidth(15) tmpField.SetPrecision(6) outLayer.CreateField(tmpField) outLayer.CreateField(ogr.FieldDefn(str('node_id'), ogr.OFTString)) outLayerDefn = outLayer.GetLayerDefn() # 2 - On traite point par point for indp in self.pixc_river_idx: # 2.1 - On cree l'objet dans le format de la couche de sortie outFeature = ogr.Feature(outLayerDefn) # 2.2 - On lui assigne le point point = ogr.Geometry(ogr.wkbPoint) point.AddPoint(self.longitude_vectorproc[indp], self.latitude_vectorproc[indp]) outFeature.SetGeometry(point) # 2.3 - On lui assigne les attributs outFeature.SetField(str('az_index'), int(self.azimuth_index[indp])) outFeature.SetField(str('r_index'), int(self.range_index[indp])) outFeature.SetField(str('lat2'), float(self.latitude_vectorproc[indp])) outFeature.SetField(str('long2'), float(self.longitude_vectorproc[indp])) outFeature.SetField(str('wse2'), float(self.height_vectorproc[indp])) outFeature.SetField(str('node_id'), str(self.river_tag[indp])) # 2.4 - On ajoute l'objet dans la couche de sortie outLayer.CreateFeature(outFeature) # 3 - Destroy the data sources to free resources outDataSource.Destroy()
def write_water_pixels_realPixC(IN_water_pixels, IN_swath, IN_cycle_number, IN_orbit_number, IN_attributes): """ Check what pixels are marked as water and write their position. Real PixC files (Version 08/2018) are produced. Associated shapefiles are also produced if asked. :param IN_water_pixels: 2D-array of water pixels vs land pixels :type IN_water_pixels: 2D-array of int :param IN_swath: Left or Right swath :type IN_swath: string :param IN_cycle_number: cycle number :type IN_cycle_number: int :param IN_orbit_number: orbit number :type IN_orbit_number: int :param IN_attributes: :type IN_attributes: """ my_api.printInfo("[write_polygons] [write_water_pixels_realPixC] == write_water_pixels_realPixC ==") ################################ # Variables for PixC main file # ################################ # Print number of water pixels size_of_tabs = np.count_nonzero(IN_water_pixels) my_api.printInfo("[write_polygons] [write_water_pixels_realPixC] Nb water pixels: %d" %(size_of_tabs)) # 1 - Get range and azimuth indices of all water pixels ind = np.nonzero(IN_water_pixels) # Get indices 1=lake and 2=river (remove 0=land) r, az = [ind[0], ind[1]] # Range index #az = ind[1] # Azimuth index river_flag = IN_water_pixels[ind] # 1=lake and 2=river # Dark Water # Check if dark water is simulated or not if IN_attributes.dark_water.lower() == "yes": # Simulate dark water if water pixel are present # TODO: integrer dans le if suivant après quand ça marche pour éviter les répétitions if size_of_tabs != 0.: rmin, rmax, azmin, azmax = r.min(), r.max(), az.min(), az.max() # Simulate dark_water dw_mask = dark_water.dark_water_simulation(1, azmin, azmax+1, 1, rmin, rmax+1, IN_attributes.dw_pourcent, IN_attributes.dw_seed, lcorr=IN_attributes.dw_correlation_length) # Get water extent indice_r = np.array(ind[0]-rmin) indice_az = np.array(ind[1]-azmin) # Randomly classify or erase dark water regions # Randomly erase DW regions in DW mask dw_mask = dark_water.dark_water_non_detected_simulation(dw_mask, 1, azmin, azmax+1, 1, rmin, rmax+1, IN_attributes.dw_detected_percent, IN_attributes.dw_seed, scale_factor=IN_attributes.scale_factor_non_detected_dw) # Reshape dark_water to water extent dw_mask = dw_mask[indice_az, indice_r] # Update IN_water_pixels with the deleted water pixels # Check if dw pixels are deleted = dw_mask pixels set to 2 if np.where(dw_mask == 2)[0].size > 0: my_api.printInfo("[write_polygons] [write_water_pixels_realPixC] Nb detected dark water pixels : %d" % np.where(dw_mask == 1)[0].size) my_api.printInfo("[write_polygons] [write_water_pixels_realPixC] Nb non detected dark water pixels : %d" % np.where(dw_mask == 2)[0].size) # Update river_flag and IN_water_pixels with the deleted water pixels river_flag[np.where(dw_mask == 2)] = 0 IN_water_pixels[ind] = river_flag # Delete the corresponding pixels in the dw mask to update indices values dw_mask = np.delete(dw_mask, np.where(dw_mask == 2)) # Update size of tabs etc... because water pixels were deleted size_of_tabs = np.count_nonzero(IN_water_pixels) my_api.printInfo("[write_polygons] [write_water_pixels_realPixC] Nb water pixels: %d" % size_of_tabs) ind = np.nonzero(IN_water_pixels) r, az = [ind[0], ind[1]] river_flag = IN_water_pixels[ind] # Build the classification array with water flag Dark_water flag classification_tab = np.ones(size_of_tabs) * IN_attributes.water_flag # Classification as water # Locate DW pixels dark_water_loc = np.where(dw_mask == 1) # Update classification value for dark water pixels with DW flag classification_tab[dark_water_loc] = IN_attributes.darkwater_flag else: classification_tab = np.ones(size_of_tabs) * IN_attributes.water_flag else: classification_tab = np.ones(size_of_tabs) * IN_attributes.water_flag my_api.printInfo("[write_polygons] [write_water_pixels_realPixC] No Dark Water will be simulated") if IN_attributes.height_model_a_tab is not None: height_flag = IN_attributes.height_model_a_tab[ind] if IN_attributes.code is not None: code_flag = IN_attributes.code[ind] # 2 - Compute radar variables for water pixels ri = IN_attributes.near_range + r * IN_attributes.range_sampling # Radar-to-ground distance Hi = IN_attributes.alt[az] # Altitude angles = np.arccos(Hi/ri) # Look angles pixel_area = IN_attributes.azimuth_spacing * IN_attributes.range_sampling / np.sin(angles) # Pixel area # 3 - Build cross-track distance array # Compute theorical cross-track distance for water pixels sign = [-1, 1][IN_swath.lower() == 'right'] y = sign * np.sqrt((ri + Hi) * (ri - Hi) / (1. + Hi / GEN_APPROX_RAD_EARTH)) elevation_tab = np.zeros(len(az)) processing = np.round(np.linspace(0, len(IN_attributes.liste_lacs), 11), 0) for i, lac in enumerate(IN_attributes.liste_lacs): if i in processing: my_api.printInfo("[write_polygons] [write_water_pixels_realPixC] Processing %d%%" % (int(100 * (i + 1) / len(IN_attributes.liste_lacs)))) if lac.nb_pix > 0 : #~ indice = np.logical_and(np.isin(r, lac.pixels[0]), np.isin(az, lac.pixels[1])) def merge(a,b): return a*100000+b titi = merge(lac.pixels[0], lac.pixels[1]) toto = merge(r, az) indice = np.isin(toto,titi) lon, lat = math_fct.lonlat_from_azy(az, ri, IN_attributes, IN_swath, IN_unit="deg", h=lac.hmean) elevation_tab[indice] = lac.compute_h(lat[indice], lon[indice]) # 4.1 - Compute noise over height if IN_attributes.dark_water.lower() == "yes": noise_seed = int(str(time.time()).split('.')[1]) delta_h = np.zeros(elevation_tab.shape) water_pixels = np.where(classification_tab == IN_attributes.water_flag) dw_pixels = np.where(classification_tab == IN_attributes.darkwater_flag) delta_h[water_pixels] = math_fct.calc_delta_h(angles[water_pixels], IN_attributes.noise_height, IN_attributes.height_bias_std, seed=noise_seed) delta_h[dw_pixels] = math_fct.calc_delta_h(angles[dw_pixels], IN_attributes.dw_detected_noise_height, IN_attributes.height_bias_std, seed=noise_seed) else: delta_h = math_fct.calc_delta_h(angles, IN_attributes.noise_height, IN_attributes.height_bias_std) # 4.2 Add residual roll error try: if IN_attributes.roll_repo is not None: my_api.printInfo("[write_polygons] [write_water_pixels_realPixC] Applying roll residual error") roll = Roll_module(IN_attributes.roll_repo) roll.get_roll_file_associated_to_orbit_and_cycle(IN_orbit_number, IN_cycle_number) roll.interpolate_roll_on_sensor_grid(IN_attributes.orbit_time) # Apply roll for each pixel roll.interpolate_roll_on_pixelcloud(IN_attributes.orbit_time, IN_attributes.orbit_time[az], y) delta_h_roll = roll.roll1_err_cloud delta_h += delta_h_roll else: my_api.printInfo("[write_polygons] [write_water_pixels_realPixC] No roll error applied") except: my_api.printInfo("[write_polygons] [write_water_pixels_realPixC] No roll error applied") # 4.3 Add tropospheric delay tropo = Tropo_module(IN_attributes.tropo_model, min(r), max(r), min(az), max(az), \ IN_attributes.tropo_error_stdv, IN_attributes.tropo_error_mean, IN_attributes.tropo_error_correlation, \ IN_attributes.tropo_error_map_file) if IN_attributes.tropo_map_rg_az is None: if tropo.model == 'gaussian': my_api.printInfo("[write_polygons] [write_water_pixels_realPixC] Applying wet tropo gaussian model") tropo.calculate_tropo_error_gaussian(IN_attributes.tropo_error_stdv, IN_attributes.tropo_error_mean, IN_attributes.tropo_error_correlation) tropo.apply_tropo_error_on_pixels(az, r) tropo_2d_field = tropo.tropo_2d_field delta_h += tropo_2d_field if tropo.model == 'map': my_api.printInfo("[write_polygons] [write_water_pixels_realPixC] Applying wet tropo map gaussian model") tropo.calculate_tropo_error_map(np.mean(IN_attributes.lat), IN_attributes.tropo_error_map_file, IN_attributes.tropo_error_correlation) tropo.apply_tropo_error_on_pixels(az, r) tropo_2d_field = tropo.tropo_2d_field delta_h += tropo_2d_field else : tropo.tropo_map_rg_az = IN_attributes.tropo_map_rg_az tropo.apply_tropo_error_on_pixels(az, r) tropo_2d_field = tropo.tropo_2d_field delta_h += tropo_2d_field # 5.3 - Compute final noisy heights (elevation + thermal noise + roll error + height model) elevation_tab_noisy = elevation_tab + delta_h # 7 - Build velocity arrays nb_pix_nadir = IN_attributes.x.size # Nb pixels at nadir # Init velocity arrays vx = np.zeros(nb_pix_nadir) vy = np.zeros(nb_pix_nadir) vz = np.zeros(nb_pix_nadir) # Compute first value vx[0], vy[0], vz[0] = [(IN_attributes.x[1] - IN_attributes.x[0]), (IN_attributes.y[1] - IN_attributes.y[0]), (IN_attributes.z[1] - IN_attributes.z[0])] / (IN_attributes.orbit_time[1] - IN_attributes.orbit_time[0]) # Compute last value vx[-1], vy[-1], vz[-1] = [(IN_attributes.x[-1] - IN_attributes.x[-2]), (IN_attributes.y[-1] - IN_attributes.y[-2]), (IN_attributes.z[-1] - IN_attributes.z[-2])] / (IN_attributes.orbit_time[-1] - IN_attributes.orbit_time[-2]) # Compute middle values for indp in range(1, nb_pix_nadir-1): vx[indp], vy[indp], vz[indp] = [(IN_attributes.x[indp+1] - IN_attributes.x[indp-1]), (IN_attributes.y[indp+1] - IN_attributes.y[indp-1]), (IN_attributes.z[indp+1] - IN_attributes.z[indp-1])] / (IN_attributes.orbit_time[indp+1] - IN_attributes.orbit_time[indp-1]) # Convert nadir latitudes/longitudes in degrees nadir_lat_deg = IN_attributes.lat * RAD2DEG nadir_lon_deg = IN_attributes.lon * RAD2DEG # Remove 1st and last values because just here for extrapolators (cf. read_orbit) nadir_alt = IN_attributes.alt nadir_heading = IN_attributes.heading lon_noisy, lat_noisy = math_fct.lonlat_from_azy(az, ri, IN_attributes, IN_swath, h=elevation_tab+delta_h) lon_noisy *= RAD2DEG # Conversion in degrees lat_noisy *= RAD2DEG # Conversion in degrees ###################### # Write output files # ###################### # Cut arrays in order to write real PixC files # Tiles correspond to theoretical tiles, with 60km length at nadir if IN_attributes.lat.size != 0: my_api.printInfo("[write_polygons] [write_water_pixels_realPixC] == Dealing with tile number %03d" % IN_attributes.tile_number) # Get azimuth indices corresponding to this integer value of latitude nadir_az = np.arange(1, len(IN_attributes.alt)-1) az_min = np.sort(nadir_az)[0] # Min azimuth index, to remove from tile azimuth indices vector my_api.printInfo("[write_polygons] [write_water_pixels_realPixC] = %d pixels in azimuth (index %d put to 0)" % (nadir_az.size, az_min)) # Get overlapping pixels du to tilling process nb_pix_overlap_begin = IN_attributes.nb_pix_overlap_begin nb_pix_overlap_end = IN_attributes.nb_pix_overlap_end # Get pixel indices of water pixels corresponding to this latitude interval az_indices = np.where((az >= min(nadir_az) + nb_pix_overlap_begin -1 ) & (az <= max(nadir_az) - nb_pix_overlap_end +1 ))[0] nb_pix = az_indices.size # Number of water pixels for this latitude interval my_api.printInfo("[write_polygons] [write_water_pixels_realPixC] = %d water pixels" % nb_pix) if az_indices.size != 0: # Write water pixels at this latitude sub_az, sub_r = [az[az_indices], r[az_indices]] my_api.printInfo("[write_polygons] [write_water_pixels_realPixC] Min r ind = %d - Max r ind = %d" % (np.min(sub_r), np.max(sub_r))) my_api.printInfo("[write_polygons] [write_water_pixels_realPixC] Min az ind = %d - Max az ind = %d" % (np.min(sub_az), np.max(sub_az))) # Get output filename # Left / right swath flag left_or_right = IN_swath.upper()[0] # General tile reference tile_ref = "%03d%s" % (IN_attributes.tile_number, left_or_right) sub_az = sub_az - az_min - nb_pix_overlap_begin + 1 # remove first and last orbit point, added in read_orbit if nb_pix_overlap_begin == 0: nb_pix_overlap_begin = 1 nb_pix_overlap_end = nb_pix_overlap_end - nb_pix_overlap_begin if nb_pix_overlap_end == 0: nb_pix_overlap_end = 1 tile_nadir_lat_deg = nadir_lat_deg[nb_pix_overlap_begin:-nb_pix_overlap_end] tile_nadir_lon_deg = nadir_lon_deg[nb_pix_overlap_begin:-nb_pix_overlap_end] tile_orbit_time = IN_attributes.orbit_time[nb_pix_overlap_begin:-nb_pix_overlap_end] tile_nadir_alt = nadir_alt[nb_pix_overlap_begin:-nb_pix_overlap_end] tile_nadir_heading = nadir_heading[nb_pix_overlap_begin:-nb_pix_overlap_end] tile_x = IN_attributes.x[nb_pix_overlap_begin:-nb_pix_overlap_end] tile_y = IN_attributes.y[nb_pix_overlap_begin:-nb_pix_overlap_end] tile_z = IN_attributes.z[nb_pix_overlap_begin:-nb_pix_overlap_end] tile_vx = vx[nb_pix_overlap_begin:-nb_pix_overlap_end] tile_vy = vy[nb_pix_overlap_begin:-nb_pix_overlap_end] tile_vz = vz[nb_pix_overlap_begin:-nb_pix_overlap_end] nadir_az_size = tile_nadir_lat_deg.size tile_coords = compute_tile_coords(IN_attributes, IN_swath, nadir_az_size, nb_pix_overlap_begin) IN_attributes.tile_coords[left_or_right] = tile_coords # Init L2_HR_PIXC object my_pixc = proc_real_pixc.l2_hr_pixc(sub_az, sub_r, classification_tab[az_indices], pixel_area[az_indices], lat_noisy[az_indices], lon_noisy[az_indices], elevation_tab_noisy[az_indices], y[az_indices], tile_orbit_time, tile_nadir_lat_deg, tile_nadir_lon_deg, tile_nadir_alt, tile_nadir_heading, tile_x, tile_y, tile_z, tile_vx, tile_vy, tile_vz, IN_attributes.near_range, IN_attributes.mission_start_time, IN_attributes.cycle_duration, IN_cycle_number, IN_orbit_number, tile_ref, IN_attributes.nb_pix_range, nadir_az_size, IN_attributes.azimuth_spacing, IN_attributes.range_sampling, IN_attributes.near_range, tile_coords) # Update filenames with tile ref IN_attributes.sisimp_filenames.updateWithTileRef(tile_ref, IN_attributes.orbit_time[nadir_az[0]], IN_attributes.orbit_time[nadir_az[-1]]) # Write main file my_pixc.write_pixc_file(IN_attributes.sisimp_filenames.pixc_file+".nc", compress=True) # Write annotation file my_pixc.write_annotation_file(IN_attributes.sisimp_filenames.file_annot_file, IN_attributes.sisimp_filenames.pixc_file+".nc") # Write shapefiles if asked if IN_attributes.create_shapefile: my_pixc.write_pixc_asShp(IN_attributes.sisimp_filenames.pixc_file+"_pixc.shp") my_pixc.write_tvp_asShp(IN_attributes.sisimp_filenames.pixc_file+"_tvp.shp") # Write PIXCVec files if asked if IN_attributes.create_pixc_vec_river: # Init PIXCVec product my_pixc_vec = proc_real_pixc_vec_river.l2_hr_pixc_vec_river(sub_az, sub_r, IN_attributes.mission_start_time, IN_attributes.cycle_duration, IN_cycle_number, IN_orbit_number, tile_ref, IN_attributes.nb_pix_range, nadir_az.size) # Set improved geoloc lon_no_noisy, lat_no_noisy = math_fct.lonlat_from_azy(az, ri, IN_attributes, IN_swath, h=elevation_tab) my_pixc_vec.set_vectorproc(lat_no_noisy[az_indices], lon_no_noisy[az_indices], elevation_tab[az_indices]) # Compute river_flag my_pixc_vec.set_river_lake_tag(river_flag[az_indices]-1) # -1 to have 0=lake and 1=river # Write PIXCVec file my_pixc_vec.write_file(IN_attributes.sisimp_filenames.pixc_vec_river_file+".nc", compress=True) # Write as shapefile if asked if IN_attributes.create_shapefile: my_pixc_vec.write_file_asShp(IN_attributes.sisimp_filenames.pixc_vec_river_file+".shp") else: my_api.printInfo("[write_polygons] [write_water_pixels_realPixC] No output data file to write")
def reproject_shapefile(IN_filename, IN_swath, IN_driver, IN_attributes, IN_cycle_number): """ Read the water polygon shapefile and compute polygons in radar coordinates. Save the reprojected polygons in a new shapefile and return its name. Compute the part of water bodies polygons that is in the swath. This is needed to avoid folding of one swath on the other one due to left-range ambiguity caused by the transformation in azimuth-range. :param IN_filename: full path of the given shapefile :type IN_filename: string :param IN_swath: the name of the swath :type IN_swath: string ("Left" or "Right") :param IN_driver: OGR driver :type IN_driver: - :param IN_attributes: :type IN_attributes: :param IN_cycle_number: :type IN_cycle_number: :return OUT_file/Getname: full path of the shapefile with the water body polygons in radar coordinates :rtype OUT_filename: string :return OUT_swath_polygons :rtype OUT_swath_polygons """ my_api.printInfo("[write_polygons] [reproject_shapefile] == reproject_shapefile ==") # 1 - Make swath polygons swath_polygon = make_swath_polygon(IN_swath, IN_attributes) # 2 - Select water bodies polygons in the swath layer, da_shapefile = my_shp.open_shp(IN_filename, swath_polygon) # Compute near_range (assuming height is nul, should be done differrently to handle totpography) IN_attributes.near_range = compute_near_range(IN_attributes, layer, cycle_number = IN_cycle_number) layer.ResetReading() #~ IN_attributes.near_range = np.amin(np.sqrt((IN_attributes.alt + (IN_attributes.nr_cross_track ** 2) / (2 * GEN_APPROX_RAD_EARTH)) ** 2 + IN_attributes.nr_cross_track ** 2)) nb_features = layer.GetFeatureCount() my_api.printInfo("[write_polygons] [reproject_shapefile] There are %d feature(s) crossing %s swath" % (nb_features, IN_swath)) sys.stdout.flush() # Exit if no feature to deal with if nb_features == 0: return None, IN_attributes # 3 - Create the output shapefile swath_t = '%s_swath' % IN_swath OUT_filename = os.path.join(IN_attributes.out_dir, os.path.splitext(os.path.split(IN_filename)[1])[0] + '_tmp_radarproj_%s.shp' % swath_t) if os.path.exists(OUT_filename): IN_driver.DeleteDataSource(OUT_filename) dataout = IN_driver.CreateDataSource(OUT_filename) if dataout is None: my_api.printError("[write_polygons] [reproject_shapefile] Could not create file") layerout = dataout.CreateLayer(str(os.path.splitext(os.path.split(OUT_filename)[1])[0]), None, geom_type=ogr.wkbPolygon) # Create necessary output fields layerout.CreateField(ogr.FieldDefn(str('RIV_FLAG'), ogr.OFTInteger)) layerout.CreateField(ogr.FieldDefn(str('HEIGHT'), ogr.OFTReal)) layerout.CreateField(ogr.FieldDefn(str('CODE'), ogr.OFTInteger64)) layerout.CreateField(ogr.FieldDefn(str('IND_LAC'), ogr.OFTInteger64)) floutDefn = layerout.GetLayerDefn() feature_out = ogr.Feature(floutDefn) # 4 - Convert coordinates for each water body polygon range_tab = [] liste_lac = [] indmax = 0 nb_lakes = layer.GetFeatureCount() processing = np.round(np.linspace(0, nb_lakes, 11), 0) for ind, polygon_index in enumerate(layer): if ind in processing : my_api.printInfo("[write_polygons] [reproject_shapefile] Processing %d %%" %( int(100 * (ind+1)/nb_lakes) ) ) geom = polygon_index.GetGeometryRef() if geom is not None: # Test geom.IsValid() not necessary # 4.1 - Fill RIV_FLAG flag if IN_attributes.compute_pixc_vec_river: riv_flag = polygon_index.GetField(str("RIV_FLAG")) else: riv_flag = 0 # 4.2 - Create the output polygon in radar projection # 4.2.1 - Init output geometry geom_out = ogr.Geometry(ogr.wkbPolygon) # 4.2.2 - Compute the zone resulting of the intersection between polygon and swath intersection = geom.Intersection(swath_polygon) # 4.2.3 - Convert polygons coordinates add_ring = False # Oversample the polygon to correctly reconstruct it in SAR geometry intersection.Segmentize(0.01) for ring in all_linear_rings(intersection): npoints = ring.GetPointCount() if npoints == 0: continue # ignore polygons completely outside the swath points = np.transpose(np.array(ring.GetPoints())) lon, lat = points[0], points[1] x_c, y_c, zone_number, zone_letter = utm.from_latlon(lat[0], lon[0]) latlon = pyproj.Proj(init="epsg:4326") utm_proj = pyproj.Proj("+proj=utm +zone={}{} +ellps=WGS84 +datum=WGS84 +units=m +no_defs".format(zone_number, zone_letter)) X, Y = pyproj.transform(latlon, utm_proj, lon, lat) ring_xy = ogr.Geometry(ogr.wkbLinearRing) for i in range(len(X)): ring_xy.AddPoint(X[i], Y[i]) poly_xy = ogr.Geometry(ogr.wkbPolygon) poly_xy.AddGeometry(ring_xy) # area in ha area = poly_xy.GetArea()/10000. layerDefn = layer.GetLayerDefn() lon = lon * DEG2RAD lat = lat * DEG2RAD lac = None if IN_attributes.height_model is None: lac = Constant_Lac(ind+1, IN_attributes, lat, IN_cycle_number) if IN_attributes.height_model == 'reference_height': lac = Reference_height_Lac(ind+1, polygon_index, layerDefn, IN_attributes) if IN_attributes.height_model == 'gaussian': if area > IN_attributes.height_model_min_area: my_api.printInfo(str("Gaussian model applied for big water body of size %f ha" % area)) lac = Gaussian_Lac(ind+1, IN_attributes, lat * RAD2DEG, lon * RAD2DEG, IN_cycle_number) else: lac = Constant_Lac(ind+1, IN_attributes, lat* RAD2DEG, IN_cycle_number) if IN_attributes.height_model == 'polynomial': if area > IN_attributes.height_model_min_area: my_api.printInfo(str("Polynomial model applied for big water body of size %f ha" % area)) lac = Polynomial_Lac(ind+1, IN_attributes, lat* RAD2DEG, lon* RAD2DEG, IN_cycle_number) else: lac = Constant_Lac(ind+1, IN_attributes, lat* RAD2DEG, IN_cycle_number) if IN_attributes.height_model == "reference_file": if IN_attributes.trueheight_file is not None: lac = Height_in_file_Lac(ind+1, IN_attributes) else: lac = Constant_Lac(ind+1, IN_attributes, lat, IN_cycle_number) lac.set_hmean(np.mean(lac.compute_h(lat* RAD2DEG, lon* RAD2DEG))) if IN_attributes.height_model == 'polynomial' and area > IN_attributes.height_model_min_area: az, r = azr_from_lonlat(lon, lat, IN_attributes, heau=lac.compute_h(lat* RAD2DEG, lon* RAD2DEG)) else: az, r = azr_from_lonlat(lon, lat, IN_attributes, heau=lac.hmean) range_tab = np.concatenate((range_tab, r), -1) npoints = len(az) if len(az) != len(lon): my_api.printDebug("[write_polygons] [reproject_shapefile] Ignore polygons crossing the swath") continue # Ignore polygons crossing the swath for p in range(npoints): # no fonction ring.SetPoints() ring.SetPoint(p, az[p], r[p]) ring.CloseRings() add_ring = True # Add the reprojected ring to the output geometry geom_out.AddGeometry(ring) # 4.2.4 - Add Output geometry if add_ring: # Add the output reprojected polygon to the output feature feature_out.SetGeometry(geom_out) # Set the RIV_FLAG field feature_out.SetField(str("RIV_FLAG"), riv_flag) # Set the HEIGHT field height_from_shp = False layerDefn = layer.GetLayerDefn() for i in range(layerDefn.GetFieldCount()): if IN_attributes.height_model == 'polynomial' or IN_attributes.height_model == 'gaussian': feature_out.SetField(str("CODE"), polygon_index.GetField("code")) if not height_from_shp: IN_attributes.height_model_a_tab = None feature_out.SetField(str("IND_LAC"), ind+1) #~ # Not used, commented to improve speed if IN_attributes.height_model == 'reference_height': feature_out.SetField(str("HEIGHT"), lac.height) # Add the output feature to the output layer layerout.CreateFeature(feature_out) liste_lac.append(lac) indmax += 1 dataout.Destroy() safe_flag_layover = True if (safe_flag_layover) and (IN_attributes.height_model == 'reference_height'): liste_lac = intersect(OUT_filename, OUT_filename, indmax, IN_attributes) + liste_lac IN_attributes.liste_lacs = liste_lac return OUT_filename, IN_attributes
def run_processing(self): """Main process, computations are done here""" my_api.printInfo("") my_api.printInfo("") my_api.printInfo("[sisimp_processing] PROCESSING...") my_api.printInfo("") for elem in self.my_attributes.orbit_list: # Process per element in orbit list = triplet (cycle_number, orbit_number, orbit_file) my_api.printInfo( "########################################################") my_api.printInfo( "[sisimp_processing] >>> CYCLE %03d and ORBIT %03d <<<" % (elem[0], elem[1])) my_api.printInfo( "########################################################") my_api.printInfo("") # 1 - Read orbit file self.my_attributes = sisimp_fct.read_orbit(elem[2], elem[0], self.my_attributes) my_api.printInfo("") # 2 - Init SISIMP filenames object self.my_attributes.sisimp_filenames = my_names.sisimpFilenames( self.my_attributes.out_dir, self.my_attributes.mission_start_time, self.my_attributes.cycle_duration, elem[0], elem[1]) ## loop over tile tile_values, tile_list = tiling.get_tiles_from_orbit( self.my_attributes, elem[1]) pre_tiling = True if pre_tiling: tropo = tropo_module.Tropo_module(self.my_attributes.tropo_model, 0, self.my_attributes.nb_pix_range, 0, len(tile_values), \ self.my_attributes.tropo_error_stdv, self.my_attributes.tropo_error_mean, self.my_attributes.tropo_error_correlation, \ self.my_attributes.tropo_error_map_file) tropo.generate_tropo_field_over_pass( min(self.my_attributes.lat)) for tile_number in tile_list: time = my_timer.Timer() time.start() my_api.printInfo( "========================================================" ) my_api.printInfo( "[sisimp_processing] Processing tile %d " % (tile_number)) my_api.printInfo( "========================================================" ) self.my_new_attributes = tiling.crop_orbit( self.my_attributes, tile_values, tile_number, tropo.tropo_map_rg_az) # 3 - Process right swath self.my_new_attributes = sisimp_fct.make_pixel_cloud( "Right", elem[0], elem[1], self.my_new_attributes) my_api.printInfo("") my_api.printInfo("[sisimp_processing] %s " % (time.stop())) my_api.printInfo("") time = my_timer.Timer() time.start() # 4 - Process left swath self.my_new_attributes = sisimp_fct.make_pixel_cloud( "Left", elem[0], elem[1], self.my_new_attributes) my_api.printInfo("") my_api.printInfo("[sisimp_processing] %s " % (time.stop())) my_api.printInfo("") # 5 - Write swath polygons shapefile sisimp_fct.write_swath_polygons(self.my_new_attributes) my_api.printInfo("") my_api.printInfo("") else: # 3 - Process right swath self.my_attributes.tile_number = 0 self.my_attributes = sisimp_fct.make_pixel_cloud( "Right", elem[0], elem[1], self.my_attributes) my_api.printInfo("") # 4 - Process left swath self.my_attributes = sisimp_fct.make_pixel_cloud( "Left", elem[0], elem[1], self.my_attributes) my_api.printInfo("") # 5 - Write swath polygons shapefile sisimp_fct.write_swath_polygons(self.my_attributes) my_api.printInfo("") my_api.printInfo("")
def __init__(self): """Constructor, initializes the module and read the command file""" my_api.printInfo("[sisimp_processing] == INIT ==") self.my_attributes = orbitAttributes()
def crop_orbit(my_attributes, tile_values, tile_number, tropo_map_rg_az): my_new_attributes = deepcopy(my_attributes) my_api.printInfo( "[my_tiling] [crop_orbit] == Dealing with tile number %03d" % tile_number) nadir_az = np.where(tile_values == tile_number)[0] my_api.printInfo( "[my_tiling] [crop_orbit] nadir az contains %d pixels with %d and %d min and max value " % (nadir_az.size, min(nadir_az), max(nadir_az))) nb_pix_overlap_begin = 50 nb_pix_overlap_end = 50 if min(nadir_az) > nb_pix_overlap_begin: add_nadir = np.arange( min(nadir_az) - 1 - nb_pix_overlap_begin, min(nadir_az) - 1) nadir_az = np.concatenate((nadir_az, add_nadir)) else: nb_pix_overlap_begin = min(nadir_az) add_nadir = np.arange(0, min(nadir_az) - 1) nadir_az = np.concatenate((nadir_az, add_nadir)) nadir_az = np.sort(nadir_az) if max(nadir_az) < len(my_attributes.orbit_time) - 1 - nb_pix_overlap_end: add_nadir = np.arange( max(nadir_az) + 1, max(nadir_az) + 1 + nb_pix_overlap_end) nadir_az = np.concatenate((nadir_az, add_nadir)) else: nb_pix_overlap_end = len(my_attributes.orbit_time) - 1 - max(nadir_az) add_nadir = np.arange( max(nadir_az) + 1, max(nadir_az) + 1 + nb_pix_overlap_end) nadir_az = np.concatenate((nadir_az, add_nadir)) my_api.printInfo("[my_tiling] [crop_orbit] nadir az contains %d pixels " % nadir_az.size) my_api.printInfo( "[my_tiling] [crop_orbit] Tile contains %d and %d of overlaping azimuth pixel in the begining and the end of the tile" % (nb_pix_overlap_begin, nb_pix_overlap_end)) nadir_az = np.sort(nadir_az) my_new_attributes.nb_pix_overlap_begin = nb_pix_overlap_begin my_new_attributes.nb_pix_overlap_end = nb_pix_overlap_end # Get azimuth indices corresponding to this integer value of latitude az_min = np.sort(nadir_az)[ 0] # Min azimuth index, to remove from tile azimuth indices vector az_max = np.sort(nadir_az)[ -1] # Min azimuth index, to remove from tile azimuth indices vector my_api.printInfo( "[my_tiling] [crop_orbit] = %d pixels in azimuth (index %d put to 0)" % (nadir_az.size, az_min)) # Cropping orbit to only simulate tile area my_new_attributes.orbit_time = (my_attributes.orbit_time[nadir_az]) my_new_attributes.x = my_attributes.x[nadir_az] my_new_attributes.y = my_attributes.y[nadir_az] my_new_attributes.z = my_attributes.z[nadir_az] my_new_attributes.lon = (my_attributes.lon[nadir_az]) my_new_attributes.lon_init = (my_attributes.lon[nadir_az]) my_new_attributes.lat = (my_attributes.lat[nadir_az]) my_new_attributes.lat_init = (my_new_attributes.lat_init[nadir_az]) my_new_attributes.heading = (my_attributes.heading[nadir_az]) my_new_attributes.heading_init = (my_attributes.heading[nadir_az]) my_new_attributes.alt = (my_attributes.alt[nadir_az]) my_new_attributes.cosphi_init = my_attributes.cosphi_init[nadir_az] my_new_attributes.sinphi_init = my_attributes.sinphi_init[nadir_az] my_new_attributes.costheta_init = my_attributes.costheta_init[nadir_az] my_new_attributes.sintheta_init = my_attributes.sintheta_init[nadir_az] my_new_attributes.cospsi_init = my_attributes.cospsi_init[nadir_az] my_new_attributes.sinpsi_init = my_attributes.sinpsi_init[nadir_az] my_new_attributes.tile_number = tile_number if tropo_map_rg_az is None: my_api.printInfo("[my_tiling] [crop_orbit] = Tropo field not applied") my_new_attributes.tropo_map_rg_az = None else: my_new_attributes.tropo_map_rg_az = tropo_map_rg_az[az_min:az_max, :] return my_new_attributes
def run_preprocessing(self, IN_paramFile): """ Preprocessing, commonly used to perform some checking, read the configuration and initialize structures that will be used during the processing. :param IN_paramFile: parameter filename ; file in RDF format (<key> = <value>) :type IN_paramFile: string """ my_api.printInfo("") my_api.printInfo("") my_api.printInfo("[sisimp_processing] PRE-PROCESSING...") my_api.printInfo("") # Init param parameters = None run_directory_for_orbits = None path_to_orbit_file = None # Read param file try: # Get the parameters parameters = my_rdf.myRdfReader(IN_paramFile) # Directory of orbit files (computed by select_orbit_cnes) run_directory_for_orbits = os.path.expandvars( parameters.getValue("Run directory for orbits")) my_tools.testDir(run_directory_for_orbits) # Shapefile of water bodies self.my_attributes.shapefile_path = os.path.expandvars( parameters.getValue("Shapefile path")) # Output directory self.my_attributes.out_dir = os.path.expandvars( str(parameters.getValue("Output directory"))) # Create output dir if doesn't exist if os.path.exists(self.my_attributes.out_dir): if not os.path.isdir(self.my_attributes.out_dir): my_api.exitWithError("ERROR = %s is not a directory" % self.my_attributes.out_dir) else: os.makedirs(self.my_attributes.out_dir) # Cross-over residual roll error try: self.my_attributes.roll_repo = str( parameters.getValue("roll_repository_name")) my_api.printInfo("[sisimp_processing] Roll repository : %s " % self.my_attributes.roll_repo) except: my_api.printInfo( "[sisimp_processing] roll_repo_name not set, roll error won't be applied" ) # Orbit parameters self.my_attributes.multi_orbit_option = read_parameter( parameters, "Multiple orbit", my_var.MULTIPLE_ORBIT, str).lower() if self.my_attributes.multi_orbit_option not in [ 'no', 'yes', 'passplan' ]: self.my_attributes.multi_orbit_option = 'yes' if self.my_attributes.multi_orbit_option == 'no': try: self.my_attributes.orbit_number = int( parameters.getValue("Orbit")) my_api.printInfo("[sisimp_processing] Orbit number : %d" % self.my_attributes.orbit_number) except: my_api.exitWithError( "Multiple orbit = no => Orbit number should be set") try: self.my_attributes.cycle_number = int( parameters.getValue("Cycle number")) my_api.printInfo("[sisimp_processing] Orbit number : %d" % self.my_attributes.orbit_number) except: my_api.printInfo( "[sisimp_processing] Multiple orbit = no => Cycle number should be set. Set to default value : 1" ) self.my_attributes.cycle_number = 1 if self.my_attributes.multi_orbit_option == 'passplan': try: self.my_attributes.passplan_path = str( parameters.getValue("Passplan path")) my_api.printInfo("[sisimp_processing] Passplan path : %s" % self.my_attributes.passplan_path) except: try: self.my_attributes.passplan_path = os.path.join( run_directory_for_orbits, "passplan.txt") except: my_api.exitWithError( "Multiple orbit = passplan => no passplan in orbit repo" ) # Simulation parameters self.my_attributes.swath_width = read_parameter( parameters, "Swath width", my_var.SWATH_WIDTH, float) self.my_attributes.nr_cross_track = read_parameter( parameters, "NR cross track", my_var.NR_CROSS_TRACK, float) self.my_attributes.sensor_wavelength = read_parameter( parameters, "Sensor wavelength", my_var.SENSOR_WAVELENGTH, float) self.my_attributes.range_sampling = read_parameter( parameters, "Range sampling", my_var.RANGE_SAMPLING, float) self.my_attributes.nb_pix_range = read_parameter( parameters, "Number of pixels in range", my_var.NB_PIX_RANGE, int) self.my_attributes.orbit_jitter = read_parameter( parameters, "Orbit jitter", my_var.ORBIT_JITTER, float) # Height model parameter self.my_attributes.height_model = read_parameter( parameters, "Height model", my_var.HEIGHT_MODEL, str) # True height file try: self.my_attributes.trueheight_file = os.path.expandvars( parameters.getValue("True height file")) my_api.printInfo("[sisimp_processing] True height file : %s" % self.my_attributes.trueheight_file) except: self.my_attributes.trueheight_file = None my_api.printInfo( "[sisimp_processing] True height file not set, True height model won't be applied" ) # Dark water self.my_attributes.dark_water = read_parameter( parameters, "Dark water", 'No', str) self.my_attributes.dw_pourcent = read_parameter( parameters, "Dark water percentage", my_var.DW_PERCENT, float) self.my_attributes.darkwater_flag = read_parameter( parameters, "Dark water flag", my_var.DARKWATER_FLAG, int) self.my_attributes.dw_seed = read_parameter( parameters, "Dark water seed", None, float) self.my_attributes.scale_factor_non_detected_dw = read_parameter( parameters, "Scale factor non detected dw", my_var.SCALE_FACTOR_NON_DETECTED_DW, float) self.my_attributes.dw_detected_percent = read_parameter( parameters, "Dark water detected percentage", my_var.DW_DETECTED_PERCENT, float) self.my_attributes.dw_detected_noise_factor = read_parameter( parameters, "Dark water detected noise factor", my_var.DW_DETECTED_NOISE_FACTOR, float) self.my_attributes.dw_correlation_length = read_parameter( parameters, "Dark water correlation length", my_var.DW_CORRELATION_LENGTH, int) # Water flag self.my_attributes.water_flag = read_parameter( parameters, "Water flag", my_var.WATER_FLAG, float) # Noise parameters self.my_attributes.height_bias_std = read_parameter( parameters, "Height bias std", my_var.HEIGHT_BIAS_STD, float) self.my_attributes.noise_multiplier_factor = read_parameter( parameters, "Noise multiplier factor", my_var.NOISE_MULTIPLIER_FACTOR, float) self.my_attributes.geolocalisation_improvement = read_parameter( parameters, "Geolocalisation improvement", my_var.GEOLOCATION_IMPROVEMENT, str) # Tropo model self.my_attributes.tropo_model = read_parameter( parameters, "Tropo model", None, str) self.my_attributes.tropo_error_correlation = read_parameter( parameters, "Tropo error correlation", None, int) if self.my_attributes.tropo_model == 'gaussian': self.my_attributes.tropo_error_stdv = read_parameter( parameters, "Tropo error stdv", None, float) self.my_attributes.tropo_error_mean = read_parameter( parameters, "Tropo error mean", None, float) self.my_attributes.tropo_error_map_file = None elif self.my_attributes.tropo_model == 'map': self.my_attributes.tropo_error_stdv = None self.my_attributes.tropo_error_mean = None self.my_attributes.tropo_error_map_file = os.path.expandvars( parameters.getValue("Tropo error map file")) else: self.my_attributes.tropo_error_stdv = None self.my_attributes.tropo_error_mean = None self.my_attributes.tropo_error_map_file = None # Height model parameters # More complex model self.my_attributes.height_model = read_parameter( parameters, "Height model", None, str) if self.my_attributes.height_model is None: my_api.printInfo( "[sisimp_processing] Height only given by a simple model A/t0/T" ) # Simple model self.my_attributes.height_model_a = read_parameter( parameters, "Constant height model A", my_var.HEIGHT_MODEL_A, float) self.my_attributes.height_model_t0 = read_parameter( parameters, "Constant height model t0", my_var.HEIGHT_MODEL_t0, float) self.my_attributes.height_model_period = read_parameter( parameters, "Constant height model period", my_var.HEIGHT_MODEL_PERIOD, float) else: if self.my_attributes.height_model in [ "polynomial", "gaussian" ]: # Simple model self.my_attributes.height_model_a = read_parameter( parameters, "Constant height model A", my_var.HEIGHT_MODEL_A, float) self.my_attributes.height_model_t0 = read_parameter( parameters, "Constant height model t0", my_var.HEIGHT_MODEL_t0, float) self.my_attributes.height_model_period = read_parameter( parameters, "Constant height model period", my_var.HEIGHT_MODEL_PERIOD, float) # Specific attributes self.my_attributes.height_model_min_area = read_parameter( parameters, "Height 2d model min area", my_var.HEIGHT_MODEL_MIN_AREA, float) # Only for gaussian model if self.my_attributes.height_model == "gaussian": self.my_attributes.height_model_stdv = read_parameter( parameters, "Height 2d model stdv", my_var.HEIGHT_MODEL_STDV, float) elif self.my_attributes.height_model == "reference_height": self.my_attributes.height_name = read_parameter( parameters, "Height shp attribute name", "HEIGHT", str) elif self.my_attributes.height_model == "reference_file": # True height file self.my_attributes.trueheight_file = os.path.expandvars( parameters.getValue("True height file")) if self.my_attributes.trueheight_file is None: my_api.exitWithError("True height file not filled") my_tools.testFile(self.my_attributes.trueheight_file, IN_extent=".nc") else: my_api.exitWithError( "Height model value UNKNOWN => should be one of polynomial / gaussian / reference_height / reference_file" ) except IOError: my_api.exitWithError( "[sisimp_processing/run_preprocessing] Parameter file not found = %s" % IN_paramFile) # Check input shapefile # Check if all needed files of shapefile are there file_missing = False if not os.path.isfile(self.my_attributes.shapefile_path + ".dbf"): my_api.printError("The file " + self.my_attributes.shapefile_path + ".dbf is missing.") file_missing = True if not os.path.isfile(self.my_attributes.shapefile_path + ".shp"): my_api.printError("The file " + self.my_attributes.shapefile_path + ".shp is missing.") file_missing = True if not os.path.isfile(self.my_attributes.shapefile_path + ".shx"): my_api.printError("The file " + self.my_attributes.shapefile_path + ".shx is missing.") file_missing = True if file_missing: raise IOError( "One or several shapefile files are missing, check logs to know which one" ) # Loading shapefile wb_layer, da_shape_file = my_shp.open_shp( self.my_attributes.shapefile_path + ".shp") # Check if the informations in the shapefile are right shp_srs = wb_layer.GetSpatialRef() lonlat_srs = osr.SpatialReference() lonlat_srs.ImportFromEPSG(4326) if not lonlat_srs.IsSame(shp_srs): raise IOError( "This is not a shapefile in lon/lat WGS84 projection") # Name of height variable if used if self.my_attributes.height_model == "reference_height": field_names = [field.name for field in wb_layer.schema] if self.my_attributes.height_name not in field_names: my_api.exitWithError( "%s attribute not found in %s; reference_height model option can't be applied" % (self.my_attributes.height_name, self.my_attributes.shapefile_path + ".shp")) # Load the noise tab try: self.my_attributes.noise_height = np.loadtxt(os.path.expandvars( parameters.getValue("Noise file path")), skiprows=1) self.my_attributes.noise_height[:, 1] = self.my_attributes.noise_multiplier_factor * self.my_attributes.noise_height[:, 1] self.my_attributes.dw_detected_noise_height = np.loadtxt( os.path.expandvars(parameters.getValue("Noise file path")), skiprows=1) self.my_attributes.dw_detected_noise_height[:, 1] = self.my_attributes.dw_detected_noise_factor * self.my_attributes.noise_height[:, 1] except IOError: my_api.exitWithError("Noise file not found") # Load the tile database file try: archive = zipfile.ZipFile( os.path.expandvars(parameters.getValue("Tile database path")), "r") imgfile = archive.open("tiles_full.txt") self.my_attributes.tile_database = np.loadtxt(imgfile, skiprows=1) except IOError: my_api.exitWithError("Tile database not found ") # Orbit processing # For loop on orbit_file generated if self.my_attributes.multi_orbit_option == 'yes' or self.my_attributes.multi_orbit_option == 'passplan': try: # Retrieve all orbit files for path, subdirs, files in ( os.walk(run_directory_for_orbits)): for file in files: file_name = os.path.join(path, file) if len( re.findall("cycle_[0-9]+_pass_[0-9]+", file_name)) > 0: orbit_number = int(file_name[-6:-3]) orbit_cycle = int(file_name[-16:-13]) self.my_attributes.orbit_list.append( [orbit_cycle, orbit_number, file_name]) # When passplan option is selected: self.orbit_files corresponds to the passplan if self.my_attributes.multi_orbit_option == 'passplan': try: plan = my_plan.orbitPassplan( self.my_attributes.passplan_path) TMP_new_orbit_list = [None] * len( plan.cycle_orbit_pairs) for orbit_file in self.my_attributes.orbit_list: for ind in plan.plan_orbit[orbit_file[1]]: TMP_new_orbit_list[ind] = [ plan.cycle_orbit_pairs[ind][0], orbit_file[1], orbit_file[2] ] self.my_attributes.orbit_list = TMP_new_orbit_list except FileNotFoundError: my_api.exitWithError("Passplan file not found: %s" % self.my_attributes.passplan_path) except IndexError: my_api.printError("[sisimp_processing] Orbit file not found") my_api.exitWithError( "Check orbit files present in the orbit folder") else: # Build the orbit_path to get the orbit_file try: for path, subdirs, files in ( os.walk(run_directory_for_orbits)): for file in files: file_name = os.path.join(path, file) if ("pass_%04d" % self.my_attributes.orbit_number) in file_name: self.my_attributes.orbit_list.append([ self.my_attributes.cycle_number, self.my_attributes.orbit_number, file_name ]) except IndexError: my_api.printError( "[sisimp_processing] Orbit file not found = %s" % path_to_orbit_file) my_api.exitWithError( "Please check that orbit number %d has been generated" % self.my_attributes.orbit_number) my_api.printInfo("") my_api.printInfo( "[sisimp_processing] List of orbit files to process =") for elem in self.my_attributes.orbit_list: my_api.printInfo( "[sisimp_processing] Cycle=%03d - Pass=%03d - Orbit file=%s" % (elem[0], elem[1], os.path.basename(elem[2]))) # Create shapefile try: self.my_attributes.create_shapefile = parameters.getValue( "Create shapefile").lower() self.my_attributes.create_shapefile = self.my_attributes.create_shapefile in [ 'oui', 'yes', 'yep' ] except Exception: self.my_attributes.create_shapefile = False my_api.printInfo( "[sisimp_processing] No Create shapefile parameter set, no shapefile will be created" ) # Create dummy L2_HR_PIXCVecRiver product, associated to pixel cloud try: self.my_attributes.create_pixc_vec_river = parameters.getValue( "Create dummy pixc vec river file").lower() self.my_attributes.create_pixc_vec_river = self.my_attributes.create_pixc_vec_river in [ 'oui', 'yes', 'yep' ] except Exception: self.my_attributes.create_pixc_vec_river = False my_api.printInfo( "[sisimp_processing] No Create dummy pixc vec river file parameter set, no L2_HR_PIXCVecRiver file will be created" ) # self.my_attributes.compute_pixc_vec_river to True only if self.my_attributes.create_pixc_vec_river is True and RIV_FLAG field is here self.my_attributes.compute_pixc_vec_river = False if self.my_attributes.create_pixc_vec_river and ( wb_layer.FindFieldIndex(str("RIV_FLAG"), True) != -1): self.my_attributes.compute_pixc_vec_river = True
# Verbose level verbose_level = my_api.setVerbose(args.verbose) print("> Verbose level = {}".format(verbose_level)) # Log file if args.logfile: logFile = os.path.join(os.path.dirname(args.parameter_file), "sisimp_" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S") + ".log") my_api.initLogger(logFile, verbose_level) print("> Log file = {}".format(logFile)) else: print("> No log file ; print info on screen") print() # 1 - Initialisation mySimu = sisimp_ps.Processing() my_api.printInfo(timer.info(0)) # 2 - Run preprocessing mySimu.run_preprocessing(args.parameter_file) my_api.printInfo(timer.info(0)) # 3 - Run processing mySimu.run_processing() my_api.printInfo(timer.info(0)) # 4 - Run post-processing mySimu.run_postprocessing() my_api.printInfo(timer.info(0)) my_api.printInfo("") my_api.printInfo(timer.stop())
def write_file(self, IN_output_file, compress=False): """ Write the pixel cloud vector attribute for river product (L2_HR_PIXCVecRiver product) NB: if there is no river pixels, write an empty file (with points = 0) :param IN_output_file: output full path :type IN_output_file: string :param compress: parameter the define to compress or not the file :type compress: boolean """ my_api.printInfo( "[l2_hr_pixc_vec_river] [write_file] == write_file : %s ==" % IN_output_file) # 1 - Open NetCDF file in writing mode data = my_nc.myNcWriter(IN_output_file) # 2 - Get river pixels indices self.pixc_river_idx = np.where(self.river_tag != "")[ 0] # Indices of river pixels in the L2_HR_PIXC product self.nb_pix_river = len(self.pixc_river_idx) # Number of river pixels # 3 - Write global attributes even if empty data.add_global_attribute('Conventions', 'CF-1.7') data.add_global_attribute( 'title', 'Level 2 KaRIn high rate pixel cloud vector attribute river product' ) data.add_global_attribute('institution', 'CNES - Large scale simulator') data.add_global_attribute('source', 'Ka-band radar interferometer') data.add_global_attribute( 'history', "%sZ: Creation" % datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")) data.add_global_attribute('mission_name', "SWOT") data.add_global_attribute('references', 'Large scale simulator') data.add_global_attribute('reference_document', 'JPL D-56415') data.add_global_attribute('contact', 'None') data.add_global_attribute('cycle_number', self.cycle_num) data.add_global_attribute('pass_number', np.int(self.pass_num)) data.add_global_attribute('tile_number', int(self.tile_ref[0:-1])) data.add_global_attribute('swath_side', self.tile_ref[-1]) data.add_global_attribute( 'tile_name', "%03d_%03d%s" % (np.int( self.pass_num), int(self.tile_ref[0:-1]), self.tile_ref[-1])) data.add_global_attribute('interferogram_size_range', self.nb_pix_range) data.add_global_attribute('interferogram_size_azimuth', self.nb_pix_azimuth) # 4 - Write file depending on the number of river pixels if self.nb_pix_river == 0: my_api.printInfo( "[l2_hr_pixc_vec_river] [write_file] NO river pixels => empty PIXCVecRiver file generated" ) data.add_dimension('points', 0) else: data.add_dimension('points', self.nb_pix_river) data.add_variable('pixc_index', np.int32, 'points', my_var.FV_NETCDF["int32"], compress) fill_vector_param(self.pixc_river_idx, 'pixc_index', self.nb_pix_river, data) data.add_variable('azimuth_index', np.int32, 'points', my_var.FV_NETCDF["int32"], compress) fill_vector_param(self.azimuth_index[self.pixc_river_idx], 'azimuth_index', self.nb_pix_river, data) data.add_variable('range_index', np.int32, 'points', my_var.FV_NETCDF["int32"], compress) fill_vector_param(self.range_index[self.pixc_river_idx], 'range_index', self.nb_pix_river, data) data.add_variable('latitude_vectorproc', np.float64, 'points', my_var.FV_NETCDF["float64"], compress) data.add_variable_attribute('latitude_vectorproc', 'units', 'degrees_north') fill_vector_param(self.latitude_vectorproc[self.pixc_river_idx], 'latitude_vectorproc', self.nb_pix_river, data) data.add_variable('longitude_vectorproc', np.float64, 'points', my_var.FV_NETCDF["float64"], compress) data.add_variable_attribute('longitude_vectorproc', 'units', 'degrees_east') fill_vector_param(self.longitude_vectorproc[self.pixc_river_idx], 'longitude_vectorproc', self.nb_pix_river, data) data.add_variable('wse_vectorproc', np.float32, 'points', np.float(my_var.FV_NETCDF["float32"]), compress) data.add_variable_attribute('wse_vectorproc', 'units', 'm') fill_vector_param(self.height_vectorproc[self.pixc_river_idx], 'wse_vectorproc', self.nb_pix_river, data) data.add_variable('node_id', str, 'points', "", compress) fill_vector_param(self.river_tag[self.pixc_river_idx], 'node_id', self.nb_pix_river, data) data.add_variable('lake_flag', np.int8, 'points', my_var.FV_NETCDF["int8"], compress) fill_vector_param(np.zeros(self.nb_pix_river), 'lake_flag', self.nb_pix_river, data) data.add_variable('climato_ice_flag', np.int8, 'points', my_var.FV_NETCDF["int8"], compress) fill_vector_param(np.zeros(self.nb_pix_river), 'climato_ice_flag', self.nb_pix_river, data) data.add_variable('dynamic_ice_flag', np.int8, 'points', my_var.FV_NETCDF["int8"], compress) fill_vector_param(np.zeros(self.nb_pix_river), 'dynamic_ice_flag', self.nb_pix_river, data) # 4 - Close output file data.close()
def make_pixel_cloud(IN_side_name, IN_cycle_number, IN_orbit_number, IN_attributes): """ Write a pixel cloud file for the given swath (left or right) :param IN_side_name: the name of the swath :type IN_side_name: string ("Left" or "Right") :param IN_cycle_number: numéro du cycle à traiter :type IN_cycle_number: int :param IN_orbit_number: numéro de l'orbite à traiter :type IN_orbit_number: int :param IN_attributes :type IN_attributes """ my_api.printInfo( "[sisimp_function] [make_pixel_cloud] == make_pixel_cloud ==") my_api.printInfo("[sisimp_function] [make_pixel_cloud] > Working on the " + IN_side_name + " swath") swath = IN_side_name # 1 - Reproject shapefile in radar coordinates fshp = IN_attributes.shapefile_path + ".shp" driver = ogr.GetDriverByName(str("ESRI Shapefile")) fshp_reproj, IN_attributes = write_poly.reproject_shapefile( fshp, swath, driver, IN_attributes, IN_cycle_number) if fshp_reproj is None: # No water body crossing the swath => stop process my_api.printInfo( "[sisimp_function] [make_pixel_cloud] No output data file to write" ) return IN_attributes # 2 - Compute the intersection between the radar grid and the water bodies water_pixels, IN_attributes.height_model_a_tab, IN_attributes.code, IN_attributes.ind_lac, IN_attributes = write_poly.compute_pixels_in_water( fshp_reproj, False, IN_attributes) if IN_attributes.create_pixc_vec_river: water_pixels_river, height_model_a_river_only, code_a_river_only, ind_lac_a_river_only, IN_attributes = write_poly.compute_pixels_in_water( fshp_reproj, True, IN_attributes) water_pixels = water_pixels + water_pixels_river # Land=0 ; Lake and other=1 ; River=2 my_api.printInfo( "[sisimp_function] [make_pixel_cloud] -> water_pixels : nb_lignes=%d nb_col=%d" % (water_pixels.shape[0], water_pixels.shape[1])) # 3 - Delete temporary file driver.DeleteDataSource(fshp_reproj) # 4 - Convert water pixels in lon-lat and output them nb_water_pixels = np.count_nonzero(water_pixels) if nb_water_pixels == 0: my_api.printInfo( "[sisimp_function] [make_pixel_cloud] Nb water pixels = 0 -> No output data file to write" ) else: write_poly.write_water_pixels_realPixC(water_pixels, swath, IN_cycle_number, IN_orbit_number, IN_attributes) return IN_attributes