Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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))
Ejemplo n.º 3
0
    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()
Ejemplo n.º 6
0
    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)
Ejemplo n.º 7
0
    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
Ejemplo n.º 9
0
    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
Ejemplo n.º 10
0
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
Ejemplo n.º 11
0
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
Ejemplo n.º 12
0
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
Ejemplo n.º 14
0
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
Ejemplo n.º 15
0
    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()
Ejemplo n.º 16
0
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")
Ejemplo n.º 17
0
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()
Ejemplo n.º 20
0
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
Ejemplo n.º 22
0
    # 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())
Ejemplo n.º 23
0
    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