Esempio n. 1
0
def test_equivalent_sources_cartesian_float32(
    region, points, masses, coordinates, data
):
    """
    Check that predictions are reasonable when interpolating from one grid to
    a denser grid, using float32 as dtype.
    """
    # The interpolation should be perfect on the data points
    eqs = EquivalentSources(dtype="float32")
    eqs.fit(coordinates, data)
    npt.assert_allclose(data, eqs.predict(coordinates), atol=1e-3 * vd.maxabs(data))

    # Gridding onto a denser grid should be reasonably accurate when compared
    # to synthetic values
    upward = 0
    shape = (60, 60)
    grid = vd.grid_coordinates(region=region, shape=shape, extra_coords=upward)
    true = point_gravity(grid, points, masses, field="g_z")
    npt.assert_allclose(true, eqs.predict(grid), atol=1e-3 * vd.maxabs(true))

    # Test grid method
    grid = eqs.grid(upward, shape=shape, region=region)
    npt.assert_allclose(true, grid.scalars, atol=1e-3 * vd.maxabs(true))

    # Test profile method
    point1 = (region[0], region[2])
    point2 = (region[0], region[3])
    profile = eqs.profile(point1, point2, upward, shape[0])
    true = point_gravity(
        (profile.easting, profile.northing, profile.upward), points, masses, field="g_z"
    )
    npt.assert_allclose(true, profile.scalars, atol=1e-3 * vd.maxabs(true))
Esempio n. 2
0
def test_gradient_boosted_eqs_predictions(region, points, masses, coordinates,
                                          data):
    """
    Test GB eq-sources predictions
    """
    # The interpolation should be sufficiently accurate on the data points
    eqs = EquivalentSourcesGB(window_size=1e3,
                              depth=1e3,
                              damping=None,
                              random_state=42)
    eqs.fit(coordinates, data)
    # Error tolerance is 2% of the maximum data.
    npt.assert_allclose(data,
                        eqs.predict(coordinates),
                        rtol=0,
                        atol=0.02 * vd.maxabs(data))

    # Gridding onto a denser grid should be reasonably accurate when compared
    # to synthetic values
    grid = vd.grid_coordinates(region, shape=(60, 60), extra_coords=0)
    true = point_gravity(grid, points, masses, field="g_z")
    # Error tolerance is 2% of the maximum data.
    npt.assert_allclose(true,
                        eqs.predict(grid),
                        rtol=0,
                        atol=0.02 * vd.maxabs(true))
def test_eql_boost_large_region():
    """
    Check if EQLHarmonicBoost works on a large region

    The iterative process ignores the effect of sources on far observation
    points. If the region is very large, this error should be diminished.
    """
    # Define a squared region
    region = (-1000e3, 1000e3, -1000e3, 1000e3)
    # Build synthetic point masses
    points = vd.grid_coordinates(region=region,
                                 shape=(6, 6),
                                 extra_coords=-1e3)
    masses = vd.datasets.CheckerBoard(amplitude=1e13,
                                      region=region).predict(points)
    # Define a set of observation points
    coordinates = vd.grid_coordinates(region=region,
                                      shape=(40, 40),
                                      extra_coords=0)
    # Get synthetic data
    data = hm.point_mass_gravity(coordinates, points, masses, field="g_z")

    # The interpolation should be sufficiently accurate on the data points
    eql = EQLHarmonicBoost(window_size=100e3)
    eql.fit(coordinates, data)
    assert mean_squared_error(
        data, eql.predict(coordinates)) < 1e-5 * vd.maxabs(data)

    # Gridding onto a denser grid should be reasonably accurate when compared
    # to synthetic values
    grid = vd.grid_coordinates(region=region, shape=(60, 60), extra_coords=0)
    true = hm.point_mass_gravity(grid, points, masses, field="g_z")
    assert mean_squared_error(true, eql.predict(grid)) < 1e-3 * vd.maxabs(data)
Esempio n. 4
0
def plot_data(coordinates, velocity, weights, title_data, title_weights):
    "Make two maps of our data, one with the data and one with the weights/uncertainty"
    fig, axes = plt.subplots(1,
                             2,
                             figsize=(9.5, 7),
                             subplot_kw=dict(projection=ccrs.Mercator()))
    crs = ccrs.PlateCarree()
    ax = axes[0]
    ax.set_title(title_data)
    maxabs = vd.maxabs(velocity)
    pc = ax.scatter(
        *coordinates,
        c=velocity,
        s=30,
        cmap="seismic",
        vmin=-maxabs,
        vmax=maxabs,
        transform=crs,
    )
    plt.colorbar(pc, ax=ax, orientation="horizontal",
                 pad=0.05).set_label("m/yr")
    vd.datasets.setup_california_gps_map(ax)
    ax = axes[1]
    ax.set_title(title_weights)
    pc = ax.scatter(*coordinates,
                    c=weights,
                    s=30,
                    cmap="magma",
                    transform=crs,
                    norm=LogNorm())
    plt.colorbar(pc, ax=ax, orientation="horizontal", pad=0.05)
    vd.datasets.setup_california_gps_map(ax)
    plt.show()
Esempio n. 5
0
def test_gradient_boosted_eqs_float32(coordinates, data):
    """
    Check that predictions are reasonable when interpolating from one grid to
    a denser grid, using float32 as dtype.
    """
    eqs = EquivalentSourcesGB(depth=500,
                              damping=None,
                              window_size=1e3,
                              random_state=42,
                              dtype="float32")
    eqs.fit(coordinates, data)
    # Error tolerance is 5% of the maximum data.
    npt.assert_allclose(data,
                        eqs.predict(coordinates),
                        rtol=0,
                        atol=0.05 * vd.maxabs(data))
Esempio n. 6
0
def test_gb_eqs_small_data(coordinates_small, data_small, weights):
    """
    Check predictions against synthetic data using few data points for speed
    """
    # The interpolation should be good enought on the data points
    # Gradient-boosted equivalent sources don't perform well on small data, so
    # we will check if the error is no larger than 1mGal
    # (sample data ranges from approximately -7mGal to 7mGal)
    eqs = EquivalentSourcesGB(depth=1e3,
                              damping=None,
                              window_size=1e3,
                              random_state=42)
    eqs.fit(coordinates_small, data_small, weights=weights)
    # Error tolerance is 5% of the maximum data.
    npt.assert_allclose(
        data_small,
        eqs.predict(coordinates_small),
        rtol=0,
        atol=0.05 * vd.maxabs(data_small),
    )
Esempio n. 7
0
def plot_data(column, i, title):
    "Plot the column from the DataFrame in the ith subplot"
    crs = ccrs.PlateCarree()
    ax = plt.subplot(2, 2, i, projection=ccrs.Mercator())
    ax.set_title(title)
    # Set vmin and vmax to the extremes of the original data
    maxabs = vd.maxabs(data.air_temperature_c)
    mappable = ax.scatter(
        data.longitude,
        data.latitude,
        c=data[column],
        s=50,
        cmap="seismic",
        vmin=-maxabs,
        vmax=maxabs,
        transform=crs,
    )
    # Set the proper ticks for a Cartopy map
    vd.datasets.setup_texas_wind_map(ax)
    return mappable
def test_eql_boost_custom_points():
    """
    Check EQLHarmonicBoost with custom points

    Check if the iterative gridder works well with a custom set of sources.
    By default, the gridder puts one source beneath each data point, therefore
    the indices of data and sources windows are identical. When passing
    a custom set of sources, these indices may differ.
    """
    region = (-3e3, -1e3, 5e3, 7e3)
    # Build synthetic point masses
    points = vd.grid_coordinates(region=region,
                                 shape=(6, 6),
                                 extra_coords=-1e3)
    masses = vd.datasets.CheckerBoard(amplitude=1e13,
                                      region=region).predict(points)
    # Define a set of observation points
    coordinates = vd.grid_coordinates(region=region,
                                      shape=(20, 20),
                                      extra_coords=0)
    # Get synthetic data
    data = hm.point_mass_gravity(coordinates, points, masses, field="g_z")

    # Define a set of block-averaged equivalent sources
    sources = block_averaged_sources(coordinates,
                                     100,
                                     depth_type="relative_depth",
                                     depth=500)

    # Fit EQLHarmonicBoost with the block-averaged sources
    eql = EQLHarmonicBoost(window_size=500, points=sources)
    eql.fit(coordinates, data)

    # Check if sources are located on the same points
    for i in range(3):
        npt.assert_allclose(sources[i], eql.points_[i])

    # The interpolation should be sufficiently accurate on the data points
    assert mean_squared_error(
        data, eql.predict(coordinates)) < 1e-3 * vd.maxabs(data)
Esempio n. 9
0
    reference=0,
    properties={"density": density},
)

# Compute gravity field on a regular grid located at 4000m above the ellipsoid
coordinates = vd.grid_coordinates(region=(12, 33, -35, -18),
                                  spacing=0.2,
                                  extra_coords=4000)
easting, northing = projection(*coordinates[:2])
coordinates_projected = (easting, northing, coordinates[-1])
prisms_gravity = prisms.prism_layer.gravity(coordinates_projected, field="g_z")

# Make a plot of the computed gravity
plt.figure(figsize=(8, 8))
ax = plt.axes(projection=ccrs.Mercator())
maxabs = vd.maxabs(prisms_gravity)
tmp = ax.pcolormesh(*coordinates[:2],
                    prisms_gravity,
                    vmin=-maxabs,
                    vmax=maxabs,
                    cmap="RdBu_r",
                    transform=ccrs.PlateCarree())
ax.set_extent(vd.get_region(coordinates), crs=ccrs.PlateCarree())
plt.title("Gravitational acceleration of the topography")
plt.colorbar(tmp,
             label="mGal",
             orientation="horizontal",
             shrink=0.93,
             pad=0.01,
             aspect=50)
plt.show()
Esempio n. 10
0
ax = axes[0]
ax.set_title("Trend")
tmp = ax.scatter(
    data.longitude,
    data.latitude,
    c=trend_values,
    s=60,
    cmap="plasma",
    transform=ccrs.PlateCarree(),
)
plt.colorbar(tmp, ax=ax, orientation="horizontal", pad=0.06)
vd.datasets.setup_texas_wind_map(ax)

ax = axes[1]
ax.set_title("Residuals")
maxabs = vd.maxabs(residuals)
tmp = ax.scatter(
    data.longitude,
    data.latitude,
    c=residuals,
    s=60,
    cmap="bwr",
    vmin=-maxabs,
    vmax=maxabs,
    transform=ccrs.PlateCarree(),
)
plt.colorbar(tmp, ax=ax, orientation="horizontal", pad=0.08)
vd.datasets.setup_texas_wind_map(ax)
plt.show()

########################################################################################
Esempio n. 11
0
print("\nGridded 2-component trend:")
print(grid)

# Now we can map both trends along with the original data for comparison
fig, axes = plt.subplots(1,
                         2,
                         figsize=(9, 7),
                         subplot_kw=dict(projection=ccrs.Mercator()))
crs = ccrs.PlateCarree()
# Plot the two trend components
titles = ["East component trend", "North component trend"]
components = [grid.east_component, grid.north_component]
for ax, component, title in zip(axes, components, titles):
    ax.set_title(title)
    # Plot the trend in pseudo color
    maxabs = vd.maxabs(component)
    tmp = ax.pcolormesh(
        component.longitude,
        component.latitude,
        component.values,
        vmin=-maxabs,
        vmax=maxabs,
        cmap="seismic",
        transform=crs,
    )
    cb = plt.colorbar(tmp, ax=ax, orientation="horizontal", pad=0.05)
    cb.set_label("meters/year")
    # Plot the original data
    ax.quiver(
        data.longitude.values,
        data.latitude.values,
Esempio n. 12
0
grid = eqs.grid(
    upward=coordinates[-1].max(),
    spacing=0.2,
    data_names=["gravity_disturbance"],
)

# The grid is a xarray.Dataset with values, coordinates, and metadata
print("\nGenerated grid:\n", grid)

# Mask grid points too far from data points
grid = vd.distance_mask(data_coordinates=coordinates, maxdist=0.5, grid=grid)

# Get the maximum absolute value between the original and gridded data so we
# can use the same color scale for both plots and have 0 centered at the white
# color.
maxabs = vd.maxabs(gravity_disturbance, grid.gravity_disturbance.values)

# Get the region boundaries
region = vd.get_region(coordinates)

# Plot observed and gridded gravity disturbance
fig, (ax1, ax2) = plt.subplots(
    nrows=1,
    ncols=2,
    figsize=(10, 5),
    sharey=True,
)

tmp = ax1.scatter(
    longitude,
    latitude,
Esempio n. 13
0
print("R² score:", eql.score(coordinates, data.total_field_anomaly_nt))

# Interpolate data on a regular grid with 400 m spacing. The interpolation requires an
# extra coordinate (upward height). By passing in 500 m, we're effectively
# upward-continuing the data (mean flight height is 200 m).
grid = eql.grid(spacing=400, data_names=["magnetic_anomaly"], extra_coords=500)

# The grid is a xarray.Dataset with values, coordinates, and metadata
print("\nGenerated grid:\n", grid)

# Plot original magnetic anomaly and the gridded and upward-continued version
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(12, 6), sharey=True)

# Get the maximum absolute value between the original and gridded data so we can use the
# same color scale for both plots and have 0 centered at the white color.
maxabs = vd.maxabs(data.total_field_anomaly_nt, grid.magnetic_anomaly.values)

ax1.set_title("Observed magnetic anomaly data")
tmp = ax1.scatter(
    easting,
    northing,
    c=data.total_field_anomaly_nt,
    s=20,
    vmin=-maxabs,
    vmax=maxabs,
    cmap="seismic",
)
plt.colorbar(tmp,
             ax=ax1,
             label="nT",
             pad=0.05,
Esempio n. 14
0
ax.set_aspect("equal")
ax.set_yticks([])
ax.set_xticks([])
clb = plt.colorbar(tmp, ax=ax, **cbar_kwargs)
clb.set_label(**cbar_label_kwargs)
plt.tight_layout()
plt.savefig("airborne_survey.svg")
plt.show()

# +
ground_difference = target - ground_prediction
airborne_difference = target - airborne_prediction

vmin = min(ground_prediction.min(), airborne_prediction.min())
vmax = max(ground_prediction.max(), airborne_prediction.max())
difference_maxabs = vd.maxabs(ground_difference, airborne_difference)

# +
fig, ax = plt.subplots(figsize=figsize)
tmp = plt.pcolormesh(
    ground_prediction.easting,
    ground_prediction.northing,
    ground_prediction.values,
    vmin=vmin,
    vmax=vmax,
    rasterized=True,
)
ax.set_aspect("equal")
ax.set_yticks([])
ax.set_xticks([])
clb = plt.colorbar(tmp, ax=ax, **cbar_kwargs)
Esempio n. 15
0
import numpy as np
import verde as vd

# The data are in a pandas.DataFrame
data = vd.datasets.fetch_rio_magnetic()
print(data.head())

# Make a Mercator map of the data using Cartopy
crs = ccrs.PlateCarree()
plt.figure(figsize=(7, 5))
ax = plt.axes(projection=ccrs.Mercator())
ax.set_title("Total-field Magnetic Anomaly of Rio de Janeiro")
# Since the data is diverging (going from negative to positive) we need to center our
# colorbar on 0. To do this, we calculate the maximum absolute value of the data to set
# vmin and vmax.
maxabs = vd.maxabs(data.total_field_anomaly_nt)
# Cartopy requires setting the projection of the original data through the transform
# argument. Use PlateCarree for geographic data.
plt.scatter(
    data.longitude,
    data.latitude,
    c=data.total_field_anomaly_nt,
    s=1,
    cmap="seismic",
    vmin=-maxabs,
    vmax=maxabs,
    transform=crs,
)
plt.colorbar(pad=0.01).set_label("nT")
# Set the proper ticks for a Cartopy map
vd.datasets.setup_rio_magnetic_map(ax)
Esempio n. 16
0
# the smaller values
pc = ax.scatter(
    *coordinates,
    c=data.std_up * 1000,
    s=20,
    cmap="magma",
    transform=crs,
    norm=PowerNorm(gamma=1 / 2)
)
cb = plt.colorbar(pc, ax=ax, orientation="horizontal", pad=0.05)
cb.set_label("uncertainty [mm/yr]")
vd.datasets.setup_california_gps_map(ax, region=region)
# Plot the gridded velocities
ax = axes[1]
ax.set_title("Weighted spline interpolated velocity")
maxabs = vd.maxabs(data.velocity_up) * 1000
pc = (grid.velocity * 1000).plot.pcolormesh(
    ax=ax,
    cmap="seismic",
    vmin=-maxabs,
    vmax=maxabs,
    transform=crs,
    add_colorbar=False,
    add_labels=False,
)
cb = plt.colorbar(pc, ax=ax, orientation="horizontal", pad=0.05)
cb.set_label("vertical velocity [mm/yr]")
ax.scatter(*coordinates, c="black", s=0.5, alpha=0.1, transform=crs)
vd.datasets.setup_california_gps_map(ax, region=region)
ax.coastlines()
plt.tight_layout()
Esempio n. 17
0
# 1000 m, we're effectively upward-continuing the data.
grid = eqs_gb.grid(
    upward=1000,
    spacing=2e3,
    data_names="gravity_disturbance",
)
print(grid)

# Plot the original gravity disturbance and the gridded and upward-continued
# version
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(12, 9), sharey=True)

# Get the maximum absolute value between the original and gridded data so we
# can use the same color scale for both plots and have 0 centered at the white
# color.
maxabs = vd.maxabs(data.gravity_disturbance, grid.gravity_disturbance)

ax1.set_title("Observed gravity disturbance data")
tmp = ax1.scatter(
    easting,
    northing,
    c=data.gravity_disturbance,
    s=5,
    vmin=-maxabs,
    vmax=maxabs,
    cmap="seismic",
)
plt.colorbar(tmp,
             ax=ax1,
             label="mGal",
             pad=0.07,
Esempio n. 18
0
# Define computation points on a grid at 500m above the ground
coordinates = vd.grid_coordinates(
    region=[0, 20e3, 0, 20e3], shape=(100, 100), extra_coords=500
)

# Compute the downward component of the gravitational acceleration
gravity = hm.point_mass_gravity(
    coordinates, points, masses, field="g_z", coordinate_system="cartesian"
)
print(gravity)

# Plot the results on a map
fig, ax = plt.subplots(figsize=(8, 6))
ax.set_aspect("equal")
# Get the maximum absolute value so we can center the colorbar on zero
maxabs = vd.maxabs(gravity)
img = ax.contourf(
    *coordinates[:2], gravity, 60, vmin=-maxabs, vmax=maxabs, cmap="seismic"
)
plt.colorbar(img, ax=ax, pad=0.04, shrink=0.73, label="mGal")
# Plot the point mass locations
ax.plot(easting, northing, "oy")
ax.set_title("Gravitational acceleration (downward)")
# Convert axes units to km
ax.set_xticklabels(ax.get_xticks() * 1e-3)
ax.set_yticklabels(ax.get_yticks() * 1e-3)
ax.set_xlabel("km")
ax.set_ylabel("km")
plt.tight_layout()
plt.show()
Esempio n. 19
0
grid = chain.grid(
    region=region,
    spacing=spacing,
    projection=projection,
    dims=["latitude", "longitude"],
    data_names=["total_field_anomaly"],
)
print("\nChained geographic grid:")
print(grid)

# We'll plot only the chained grid on a Mercator map
plt.figure(figsize=(7, 5))
crs = ccrs.PlateCarree()
ax = plt.axes(projection=ccrs.Mercator())
ax.set_title("De-trend, decimate, and spline")
maxabs = vd.maxabs(grid.total_field_anomaly)
pc = ax.pcolormesh(
    grid.longitude,
    grid.latitude,
    grid.total_field_anomaly,
    transform=crs,
    cmap="seismic",
    vmin=-maxabs,
    vmax=maxabs,
)
plt.colorbar(pc, pad=0.01).set_label("total field anomaly [nT]")
# Set the proper ticks for a Cartopy map
vd.datasets.setup_rio_magnetic_map(ax)
plt.tight_layout()
plt.show()