Beispiel #1
0
    def discretize_in_n(n):
        """ Discretize the geometry at a given lengthscale, 
        here specifiec by the number of cells along each direction of the
        horizontal plane.
    
        """
        nx = n
        ny = n
        # Regrid.
        x, step_x = np.linspace(x_min, x_max, nx, endpoint=True, retstep=True)
        y, step_y = np.linspace(y_min, y_max, ny, endpoint=True, retstep=True)
        print("Step x {}".format(step_x))
        print("Step y {}".format(step_y))

        # Set the same resolution for z.
        z_step = float(np.mean([step_x, step_y]))
        print("Step z {}".format(z_step))

        # Find z by getting closest cell in fine grid.
        tree_x = KDTree(dsm_x)
        tree_y = KDTree(dsm_y)
        _, inds_x = tree_x.query(x[:, None])
        _, inds_y = tree_y.query(y[:, None])

        # Remesh the z-s.
        a, b = np.meshgrid(inds_x, inds_y)
        z = dsm_z[a, b]
        print("Minimal altitude {}".format(np.min(z)))

        my_grid = Grid.build_grid(x, y, z, z_low=-1600, z_step=z_step)
        print("Grid with {} cells.".format(my_grid.shape[0]))
        print(my_grid.res_x)
        print(my_grid.res_y)
        print(my_grid.res_z)

        # Return mean resolution and total number of cells.
        return my_grid.shape[0], np.mean(np.array([step_x, step_y, z_step]))
Beispiel #2
0
def prepare_stromboli(input_path, output_path, z_step):
    dsm_x = np.load(os.path.join(input_path, "dsm_stromboli_x.npy"))
    dsm_y = np.load(os.path.join(input_path, "dsm_stromboli_y.npy"))
    dsm_z = np.load(os.path.join(input_path, "dsm_stromboli_z.npy"))

    my_grid = Grid.build_grid(dsm_x, dsm_y, dsm_z, z_low=-800, z_step=z_step)
    my_grid.save(os.path.join(output_path, "grid.pickle"))
    print("Grid with {} cells.".format(my_grid.shape[0]))

    # Name the output directory with the number of cells.
    dir_name = "stromboli_{}_cells".format(my_grid.shape[0])
    output_path = os.path.join(output_path, dir_name)
    os.makedirs(output_path, exist_ok=True)

    # Determines which cells lie deep inside the volcano (i.e. away from the
    # surface).
    # This is useful when using IVR to select new datapoints, since we are mostly
    # interested at variance reduction deep below the surface.
    DEPTH_THRESHOLD = 150.0  # Only keep cells at least that far from the surface.
    surface_tree = KDTree(my_grid.surface)

    # Loop over cells and only keep the ones that are far away from the surface.
    deep_cells_inds = []
    for i, cell in enumerate(my_grid.cells):
        print("Processing cell {}/{}".format(i, my_grid.cells.shape[0]))
        d, _ = surface_tree.query(cell)
        if d > DEPTH_THRESHOLD:
            deep_cells_inds.append(i)

    print("There are {} surface cells.".format(my_grid.surface.shape[0]))
    print("Kept {}/{} cells".format(len(deep_cells_inds),
                                    my_grid.cells.shape[0]))

    np.save(os.path.join(output_path, "deep_cells_inds.npy"),
            np.array(deep_cells_inds, dtype=np.int32))

    # Put measurement stations on the whole surface, at 1 meter from the ground.
    # First only keep cells that are outside the water.
    data_coords = np.array([x for x in my_grid.surface if x[2] > 0.0])
    print(("There are {} surface cells above sea level. " +
           "Placing potential observation " +
           "sites on each of those..").format(data_coords.shape[0]))
    data_coords[:, 2] = data_coords[:, 2] + 1.0

    # Also load locations of Niklas data points.
    from volcapy.loading import load_niklas
    niklas_data = load_niklas(ORIGINAL_NIKLAS_DATA_PATH)
    niklas_data_coords = np.array(niklas_data["data_coords"])[1:]
    niklas_data_values = np.array(niklas_data["d"])

    # Find the indices of the closest data points to Niklas data.
    # This may be used to mitigate the difference between the two in case there
    # are a lot of difference in altitude because of the discretization.
    tree_surf_data = KDTree(data_coords)
    _, inds_niklas_in_surface = tree_surf_data.query(niklas_data_coords)
    niklas_data_coords_insurf = data_coords[inds_niklas_in_surface]
    np.save(os.path.join(output_path, "niklas_data_inds_insurf.npy"),
            inds_niklas_in_surface)

    # Save location of data points before computing forward.
    # Save the surface of the volcano and the datapoints. in vtk.
    from volcapy.plotting.vtkutils import irregular_array_to_point_cloud, array_to_vector_cloud
    irregular_array_to_point_cloud(my_grid.surface,
                                   np.ones(my_grid.surface.shape[0]),
                                   os.path.join(output_path, "surface.vtk"),
                                   fill_nan_val=-20000.0)

    orientation_data = np.zeros((data_coords.shape[0], 3))
    orientation_data[:, 2] = -1.0
    array_to_vector_cloud(data_coords, orientation_data,
                          os.path.join(output_path, "data_points.vtk"))

    orientation_data = np.zeros((niklas_data_coords.shape[0], 3))
    orientation_data[:, 2] = -1.0
    orientation_data_vals = np.zeros((niklas_data_coords.shape[0], 3))
    orientation_data_vals[:, 2] = niklas_data_values
    array_to_vector_cloud(niklas_data_coords, orientation_data,
                          os.path.join(output_path, "niklas_data_coords.vtk"))
    array_to_vector_cloud(
        niklas_data_coords_insurf, orientation_data,
        os.path.join(output_path, "niklas_data_coords_insurf.vtk"))
    array_to_vector_cloud(niklas_data_coords, orientation_data_vals,
                          os.path.join(output_path, "niklas_data_vals.vtk"))

    # ----------------------------------------------------------------------

    # Also compute forward for Niklas data.
    # TODO: WARNING!!! There is one too many data site. Here remove the first, but
    # maybe its the last who should be removed.
    ref_coords = np.array(niklas_data["data_coords"][0])[None, :]

    # TODO: Verify this. According to Niklas, we should subtract the response on
    # the reference station. Assuming this is the first data site, then, from every
    # line, we should subract the first line.
    F_ref_station = compute_forward(my_grid.cells,
                                    my_grid.cells_roof,
                                    my_grid.res_x,
                                    my_grid.res_y,
                                    my_grid.res_z,
                                    ref_coords,
                                    n_procs=4)

    F_niklas = compute_forward(my_grid.cells,
                               my_grid.cells_roof,
                               my_grid.res_x,
                               my_grid.res_y,
                               my_grid.res_z,
                               niklas_data_coords,
                               n_procs=4)

    # Subtract the first station.
    F_niklas_corr = F_niklas - np.repeat(
        F_ref_station, F_niklas.shape[0], axis=0)

    np.save(os.path.join(output_path, "F_niklas.npy"), F_niklas)
    np.save(os.path.join(output_path, "F_niklas_corr.npy"), F_niklas_corr[1:])
    np.save(os.path.join(output_path, "niklas_data_coords.npy"),
            niklas_data_coords[1:, :])
    np.save(os.path.join(output_path, "niklas_data_obs.npy"),
            niklas_data['d'][1:])

    # Compute forward on whole surface.
    F_full_surface = compute_forward(my_grid.cells,
                                     my_grid.cells_roof,
                                     my_grid.res_x,
                                     my_grid.res_y,
                                     my_grid.res_z,
                                     data_coords,
                                     n_procs=4)

    # Save everything, but cut first observation.
    np.save(os.path.join(output_path, "surface_data_coords.npy"), data_coords)
    np.save(os.path.join(output_path, "F_full_surface.npy"), F_full_surface)