Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #87

Merged
merged 12 commits into from
Aug 10, 2024
Merged

Dev #87

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
286 changes: 144 additions & 142 deletions docs/user_guide/estimating_regional_field.ipynb

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ dependencies = [
"harmonica>=0.6.0",
"polartoolkit",
"numba",
"scipy",
"scipy<1.14", # issue with UQpy import
"numba_progress",
"tqdm",
"pygmt",
Expand All @@ -56,7 +56,7 @@ dependencies = [
###
"optuna>=3.1.0", # need JournalStorage
"optuna-integration",
"botorch>=0.4.0",
"botorch>=0.8.1", # need logie_candidates_func
"joblib",
"psutil",
###
Expand Down
7 changes: 4 additions & 3 deletions src/invert4geom/cross_validation.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations # pylint: disable=too-many-lines

import copy
import itertools
import logging
import pathlib
Expand Down Expand Up @@ -639,11 +640,11 @@ def zref_density_optimal_parameter(
)
# pylint: enable=duplicate-code
# calculate regional field
reg_kwargs = regional_grav_kwargs.copy() # type: ignore[union-attr]
reg_kwargs = copy.deepcopy(regional_grav_kwargs)

grav_df = regional.regional_separation(
grav_df=grav_df,
**reg_kwargs,
**reg_kwargs, # type: ignore[arg-type]
)

# update starting model in kwargs
Expand Down Expand Up @@ -1162,7 +1163,7 @@ def regional_separation_score(
"""

# pull out kwargs
kwargs = kwargs.copy()
kwargs = copy.deepcopy(kwargs)
method = kwargs.pop("method")
grav_df = kwargs.pop("grav_df")
true_regional = kwargs.pop("true_regional", None)
Expand Down
13 changes: 9 additions & 4 deletions src/invert4geom/inversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ def grav_column_der(
prism_density: NDArray,
) -> NDArray:
"""
Function to calculate the vertical derivate of the gravitational acceleration at
an observation point caused by a right, rectangular prism. Approximated with
Hammer's annulus approximation :footcite:p:`mccubbineairborne2016`.
Function to calculate the vertical derivate of the gravitational acceleration at
an observation point caused by a right, rectangular prism. Approximated with
Hammer's annulus approximation :footcite:p:`mccubbineairborne2016`.

Parameters
----------
Expand Down Expand Up @@ -842,6 +842,11 @@ def run_inversion(

utils._check_gravity_inside_topography_region(grav_df, prism_layer) # pylint: disable=protected-access

# check no nans in gravity df
if grav_df.res.isnull().values.any():
msg = "gravity dataframe contains NaN values in the 'res' column"
raise ValueError(msg)

log.info("starting inversion")

time_start = time.perf_counter()
Expand Down Expand Up @@ -1180,7 +1185,7 @@ def run_inversion_workflow( # equivalent to monte_carlo_full_workflow
time in seconds for the inversion to run
"""

kwargs = kwargs.copy()
kwargs = copy.deepcopy(kwargs)
grav_df = grav_df.copy()

# get kwargs
Expand Down
98 changes: 76 additions & 22 deletions src/invert4geom/optimization.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations # pylint: disable=too-many-lines

import copy
import itertools
import logging
import math
Expand All @@ -19,6 +20,7 @@
import optuna
import pandas as pd
import psutil
import verde as vd
import xarray as xr
from numpy.typing import NDArray
from optuna.storages import JournalFileStorage, JournalStorage
Expand Down Expand Up @@ -845,7 +847,7 @@ def __init__(
self.fname = fname
self.grav_df = grav_df
self.constraints_df = constraints_df
self.regional_grav_kwargs = regional_grav_kwargs
self.regional_grav_kwargs = copy.deepcopy(regional_grav_kwargs)
self.zref_limits = zref_limits
self.density_contrast_limits = density_contrast_limits
self.zref = zref
Expand Down Expand Up @@ -880,7 +882,7 @@ def __call__(self, trial: optuna.trial) -> float:
msg = f"`grav_df` needs all the following columns: {cols}"
raise ValueError(msg)

kwargs = self.kwargs.copy()
kwargs = copy.deepcopy(self.kwargs)

if kwargs.get("apply_weighting_grid", None) is True:
msg = (
Expand Down Expand Up @@ -977,7 +979,7 @@ def __call__(self, trial: optuna.trial) -> float:
)
# pylint: enable=duplicate-code
# calculate regional field
reg_kwargs = self.regional_grav_kwargs.copy()
reg_kwargs = copy.deepcopy(self.regional_grav_kwargs)

constraints_warning = (
"Using constraint point minimization technique for regional field "
Expand Down Expand Up @@ -1268,9 +1270,8 @@ def optimize_inversion_zref_density_contrast(
), "test column contains True value, not needed except for during damping CV"

optuna.logging.set_verbosity(optuna.logging.WARN)

if regional_grav_kwargs is not None:
regional_grav_kwargs = regional_grav_kwargs.copy()
regional_grav_kwargs = copy.deepcopy(regional_grav_kwargs)

# if sampler not provided, use BoTorch as default unless grid_search is True
if sampler is None:
Expand Down Expand Up @@ -1641,7 +1642,6 @@ def optimize_inversion_zref_density_contrast(
"Density contrast (kg/m$^3$)",
),
)

return study, final_inversion_results


Expand Down Expand Up @@ -1700,7 +1700,7 @@ def optimize_inversion_zref_density_contrast_kfolds(
df = constraints_df.copy()
df = df[df.columns.drop(list(df.filter(regex="fold_")))]

kwargs = kwargs.copy()
kwargs = copy.deepcopy(kwargs)

# split into test and training sets
testing_training_df = cross_validation.split_test_train(
Expand Down Expand Up @@ -1763,9 +1763,17 @@ def __call__(self, trial: optuna.trial) -> float:
float
the score of the eq_sources fit
"""
kwargs = self.kwargs.copy()
kwargs = copy.deepcopy(self.kwargs)
# get parameters provided not as limits
depth = kwargs.pop("depth", "default")
# calculate 4.5 times the mean distance between points
if depth == "default":
depth = np.mean(
vd.median_distance(
(kwargs.get("coordinates")[0], kwargs.get("coordinates")[1]), # type: ignore[unused-ignore, index]
k_nearest=1,
)
)
block_size = kwargs.pop("block_size", None)
damping = kwargs.pop("damping", None)

Expand Down Expand Up @@ -1861,7 +1869,7 @@ def optimize_eq_source_params(
"""
optuna.logging.set_verbosity(optuna.logging.WARN)

kwargs = kwargs.copy()
kwargs = copy.deepcopy(kwargs)
# if sampler not provided, used TPE as default
if sampler is None:
sampler = optuna.samplers.TPESampler(
Expand Down Expand Up @@ -1964,10 +1972,14 @@ def optimize_eq_source_params(
except KeyError:
msg = (
"No depth parameter value found in best params or kwargs, setting to "
"'default'"
"'default' (4.5 times mean distance between points)"
)
log.warning(msg)
best_depth = "default"
if best_depth == "default":
best_depth = np.mean(
vd.median_distance((coordinates[0], coordinates[1]), k_nearest=1)
)
if best_block_size is None:
try:
best_block_size = kwargs["block_size"]
Expand Down Expand Up @@ -2301,7 +2313,7 @@ def __call__(self, trial: optuna.trial) -> float:
the scores
"""

new_kwargs = self.kwargs.copy()
new_kwargs = copy.deepcopy(self.kwargs)

if self.grid_method == "pygmt":
new_kwargs["tension_factor"] = trial.suggest_float(
Expand All @@ -2321,15 +2333,6 @@ def __call__(self, trial: optuna.trial) -> float:
)

elif self.grid_method == "eq_sources":
if self.depth_limits is not None:
new_kwargs["depth"] = trial.suggest_float(
"depth",
self.depth_limits[0],
self.depth_limits[1],
)
else:
new_kwargs["depth"] = self.kwargs.get("depth", "default")

if self.block_size_limits is not None:
new_kwargs["block_size"] = trial.suggest_float(
"block_size",
Expand Down Expand Up @@ -2363,6 +2366,24 @@ def __call__(self, trial: optuna.trial) -> float:
raise ValueError(msg)

if isinstance(self.training_df, pd.DataFrame):
if self.depth_limits is not None:
new_kwargs["depth"] = trial.suggest_float(
"depth",
self.depth_limits[0],
self.depth_limits[1],
)
else:
eq_depth = self.kwargs.get("depth", "default")
if eq_depth == "default":
# calculate 4.5 times the mean distance between points
eq_depth = np.mean(
vd.median_distance(
(self.training_df.easting, self.training_df.northing),
k_nearest=1,
)
)
new_kwargs["depth"] = eq_depth

with utils._log_level(logging.WARN): # pylint: disable=protected-access
(
residual_constraint_score,
Expand Down Expand Up @@ -2398,6 +2419,27 @@ def __call__(self, trial: optuna.trial) -> float:
# for each fold, run CV
results = []
for i, _ in enumerate(pbar):
if self.depth_limits is not None:
new_kwargs["depth"] = trial.suggest_float(
"depth",
self.depth_limits[0],
self.depth_limits[1],
)
else:
eq_depth = self.kwargs.get("depth", "default")
if eq_depth == "default":
# calculate 4.5 times the mean distance between points
eq_depth = np.mean(
vd.median_distance(
(
self.training_df[i].easting,
self.training_df[i].northing,
),
k_nearest=1,
)
)
new_kwargs["depth"] = eq_depth

fold_results = cross_validation.regional_separation_score(
constraints_df=self.training_df[i],
testing_df=self.testing_df[i],
Expand Down Expand Up @@ -2841,7 +2883,7 @@ def optimize_regional_eq_sources(

optuna.logging.set_verbosity(optuna.logging.WARN)

kwargs = kwargs.copy()
kwargs = copy.deepcopy(kwargs)

# if sampler not provided, use TPE as default
if sampler is None:
Expand Down Expand Up @@ -2897,6 +2939,11 @@ def optimize_regional_eq_sources(

# get optimal hyperparameter values
depth = best_trial.params.get("depth", kwargs.pop("depth", "default"))
if depth == "default":
# calculate 4.5 times the mean distance between points
depth = np.mean(
vd.median_distance((grav_df.easting, grav_df.northing), k_nearest=1)
)
damping = best_trial.params.get("damping", kwargs.pop("damping", None))
block_size = best_trial.params.get("block_size", kwargs.pop("block_size", None))
grav_obs_height = best_trial.params.get(
Expand Down Expand Up @@ -3067,7 +3114,7 @@ def optimize_regional_constraint_point_minimization(

optuna.logging.set_verbosity(optuna.logging.WARN)

kwargs = kwargs.copy()
kwargs = copy.deepcopy(kwargs)

# if sampler not provided, use TPE as default
if sampler is None:
Expand Down Expand Up @@ -3198,6 +3245,13 @@ def optimize_regional_constraint_point_minimization(
tension_factor = best_trial.params.get("tension_factor", None)
spline_dampings = best_trial.params.get("spline_dampings", None)
depth = best_trial.params.get("depth", kwargs.pop("depth", "default"))
if depth == "default":
# calculate 4.5 times the mean distance between points
depth = np.mean(
vd.median_distance(
(constraints_df.easting, constraints_df.northing), k_nearest=1
)
)
damping = best_trial.params.get("damping", kwargs.pop("damping", None))
block_size = best_trial.params.get("block_size", kwargs.pop("block_size", None))
grav_obs_height = best_trial.params.get(
Expand Down
10 changes: 9 additions & 1 deletion src/invert4geom/plotting.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations # pylint: disable=too-many-lines

import copy
import typing

import matplotlib as mpl
Expand Down Expand Up @@ -613,6 +614,7 @@ def plot_inversion_grav_results(
iterations: list[int],
constraints_df: pd.DataFrame | None = None,
fig_height: float = 12,
constraint_style: str = "x.3c",
) -> None:
"""
plot the initial and final misfit grids from the inversion and their difference
Expand All @@ -629,6 +631,8 @@ def plot_inversion_grav_results(
constraint points to include in the plots
fig_height : float, optional
height of the figure, by default 12
constraint_style : str, optional
pygmt style string for for constraint points, by default 'x.3c'
"""

grid = grav_results.set_index(["northing", "easting"]).to_xarray()
Expand Down Expand Up @@ -663,6 +667,7 @@ def plot_inversion_grav_results(
cbar_label="mGal",
title=f"Initial misfit: RMSE:{round(initial_rmse, 2)} mGal",
points=points,
points_style=constraint_style,
)
fig = maps.plot_grd(
dif,
Expand All @@ -676,6 +681,7 @@ def plot_inversion_grav_results(
cbar_label="mGal",
title=f"difference: RMSE:{round(utils.rmse(dif), 2)} mGal",
points=points,
points_style=constraint_style,
)
fig = maps.plot_grd(
final,
Expand All @@ -690,6 +696,7 @@ def plot_inversion_grav_results(
cbar_label="mGal",
title=f"Final misfit: RMSE:{round(final_rmse, 2)} mGal",
points=points,
points_style=constraint_style,
)
fig.show()

Expand Down Expand Up @@ -737,7 +744,7 @@ def plot_inversion_iteration_results(

misfit_grids, topo_grids, corrections_grids = grids

params = parameters.copy()
params = copy.deepcopy(parameters)

# set figure parameters
sub_width = 5
Expand Down Expand Up @@ -1037,6 +1044,7 @@ def plot_inversion_results(
iterations,
constraints_df=constraints_df,
fig_height=kwargs.get("fig_height", 12),
constraint_style=kwargs.get("constraint_style", "x.3c"),
)


Expand Down
Loading
Loading