Source code for deepfield.field.models.property_transfer

"""Property transfer models."""
import numpy as np

from sklearn.base import BaseEstimator
from sklearn.neighbors import NearestNeighbors

[docs]class PropertiesTransfer(BaseEstimator): """Model to transfer rock properties using Nearest Neighbors algorithm.""" def __init__(self): self._nn = None self._neigh_dist = None self._neigh_ind = None self._new_shape = None
[docs] def fit(self, original_grid, new_grid, n_neighbors=5, normalize_vector=(1, 1, 1)): """Fit Nearest Neighbors model. Parameters ---------- original_grid : geology.Grid Original grid. new_grid : geology.Grid New grid. n_neighbors : int, optional number of neighbors to use, by default 5. normalize_vector : list, optional vector to normalize distance, by default [1, 1, 1]. """ self._nn = NearestNeighbors(n_neighbors=n_neighbors) self._nn.fit(original_grid.cell_centroids.reshape(-1, 3) / np.asarray(normalize_vector)) self._neigh_dist, self._neigh_ind = self._nn.kneighbors( new_grid.cell_centroids.reshape(-1, 3) / np.asarray(normalize_vector)) self._new_shape = new_grid.dimens return self
[docs] def dump(self, path): """Dump to a file (*.npz). Parameters ---------- path : str or pathlib.Path Path to file, ``.npz`` extension will be appended to the file name if it is not already there. """ np.savez(path, **{att: getattr(self, att) for att in ('_neigh_dist', '_neigh_ind', '_new_shape')}, ) return self
[docs] def load(self, path): """Load from file. Parameters ---------- path : str or pathlib.Path File path. """ npzfile = np.load(path, allow_pickle=True) for att in npzfile.files: value = npzfile[att] setattr(self, att, value if (value.ndim > 0) or (value[()] is not None) else None) return self
[docs] def predict(self, original_properties, aggr=lambda values, dist: np.average(values, axis=1, weights=1/dist)): """Transfer property values to the new grid. Parameters ---------- original_properties : numpy.ndarray Properties on original grid. aggr : Callable, optional Function to aggregate nearest neighbors values, by default weighted average. Returns ------- array : ndarray New values. """ reshaped_properties = original_properties.reshape([-1] + list(original_properties.shape[-3:])) new_values = np.stack([ aggr(prop.ravel()[self._neigh_ind], self._neigh_dist) for prop in reshaped_properties ]) return new_values.reshape(list(original_properties.shape[:-3]) + list(self._new_shape))