-
Notifications
You must be signed in to change notification settings - Fork 64
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
Regular grid interpolation #244
Merged
Merged
Changes from 23 commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
b01db55
added tests for regular grid interpolation
flabowski b3d3001
added regular grid interpolation module
flabowski fe25304
added some tests
flabowski 880962b
wrapper for scipy's regular grid interpolation
flabowski ce6b8e4
removed some comments
flabowski 8df7469
minor code style improvements
flabowski 6977a9e
adjusted docsting
flabowski 24bee31
added pre-processing to map points and values onto regular grid in 2D
flabowski b5835b8
modified pre-processing to map points and values onto regular grid in nD
flabowski a9deaa0
modified the regular grid interpolation so it works with the grid poi…
flabowski 98d1425
removed useless fill_value argument
flabowski 761fcde
added a doc file for the automatic doc generation of the new module
flabowski 9326752
improved docstring of get_grid_axes
flabowski c2692fb
moved ValueError to the right place and adjusted the error message.
flabowski 3f79063
added docstring for predict method
flabowski eb7f1a3
removed 'dim' variable
flabowski 706bae7
removed calculate_flat_index(...) entirely
flabowski 4148b4f
removed TODO comment
flabowski 4a77030
other cosmetic changes
flabowski 638af8d
some simplifications, no need to operate with the transposed of the v…
flabowski e49ad18
reverted suggested change, as it changed the behaviour
flabowski 3f77b6a
improved code style
flabowski 48f0c42
updated autogenerated rst and added it to the code documentation
flabowski 1d8b690
added test to make sure exception is raised.
flabowski 2ad23ae
removed 'def' member manually
flabowski File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,3 +17,4 @@ Code Documentation | |
ae | ||
podae | ||
reducedordermodel | ||
regular_grid |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
RegularGrid | ||
===================== | ||
|
||
.. currentmodule:: ezyrb.regular_grid | ||
|
||
.. automodule:: ezyrb.regular_grid | ||
|
||
.. autosummary:: | ||
:toctree: _summaries | ||
:nosignatures: | ||
|
||
RegularGrid | ||
RegularGrid.def | ||
RegularGrid.get_grid_axes | ||
RegularGrid.fit | ||
RegularGrid.predict | ||
|
||
.. autoclass:: RegularGrid | ||
:members: | ||
:private-members: | ||
:undoc-members: | ||
:show-inheritance: | ||
:noindex: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
""" | ||
Module for higher order interpolation on regular grids | ||
""" | ||
import numpy as np | ||
from scipy.interpolate import RegularGridInterpolator as RGI | ||
from .approximation import Approximation | ||
|
||
|
||
class RegularGrid(Approximation): | ||
""" | ||
Multidimensional interpolator on regular grids. | ||
See also scipy's RegularGridInterpolator for information on kwargs. | ||
|
||
:param array_like points: the coordinates of the points on a regular grid. | ||
:param array_like values: The (vector-) data on the regular grid in | ||
n dimensions. | ||
|
||
:Example: | ||
|
||
>>> import ezyrb | ||
>>> import numpy as np | ||
>>> def f(x, y, z): | ||
... return 2 * x**3 + 3 * y**2 - z | ||
>>> x = np.linspace(1, 4, 11) | ||
>>> y = np.linspace(4, 7, 22) | ||
>>> z = np.linspace(7, 9, 33) | ||
>>> xg, yg, zg = np.meshgrid(x, y, z, indexing='ij') | ||
>>> points = np.c_[xg.ravel(), yg.ravel(), zg.ravel()] | ||
>>> data_mode_x = f(xg, yg, zg).reshape(-1, 1) | ||
# lets assume we have 2 modes, i.e. a rank 2 model | ||
>>> data = np.concatenate((data_mode_x, data_mode_x/10), axis=1) | ||
>>> rgi = ezyrb.RegularGrid() | ||
>>> rgi.fit(points, data, method="linear") | ||
>>> pts = np.array([[2.1, 6.2, 8.3], | ||
... [3.3, 5.2, 7.1], | ||
... [1., 4., 7.], | ||
... [4., 7., 9.]]) | ||
>>> rgi.predict(pts) | ||
array([[125.80469388, 12.58046939], | ||
[146.30069388, 14.63006939], | ||
[ 43. , 4.3 ], | ||
[266. , 26.6 ]]) | ||
>>> f(pts[:, 0], pts[:, 1], pts[:, 2]) | ||
array([125.542, 145.894, 43. , 266. ]) | ||
>>> f(pts[:, 0], pts[:, 1], pts[:, 2])/10 | ||
array([12.5542, 14.5894, 4.3 , 26.6 ]) | ||
""" | ||
|
||
def __init__(self): | ||
self.interpolator = None | ||
|
||
def get_grid_axes(self, pts_scrmbld, vals_scrmbld): | ||
""" | ||
Calculates the grid axes from a meshed grid and re-orders the values so | ||
they fit on a mesh generated with | ||
numpy.meshgrid(ax1, ax2, ..., axn, indexing="ij") | ||
|
||
flabowski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
:param array_like pts_scrmbld: the coordinates of the points. | ||
:param array_like vals_scrmbld: the (vector-)values in the points. | ||
:return: The grid axes given as a tuple of ndarray, with shapes | ||
(m1, ), …, (mn, ) and values mapped on the ordered grid. | ||
:rtype: (list, numpy.ndarray) | ||
|
||
""" | ||
grid_axes = [] | ||
iN = [] # index in dimension N | ||
nN = [] # size of dimension N | ||
dim = pts_scrmbld.shape[1] | ||
for i in range(dim): | ||
xn, unique_inverse_n = np.unique(pts_scrmbld[:, i], | ||
return_inverse=True) | ||
grid_axes.append(xn) | ||
nN.append(len(xn)) | ||
iN.append(unique_inverse_n) | ||
if np.prod(nN) != len(vals_scrmbld): | ||
msg = "Values don't match grid. Make sure to pass a list of "\ | ||
"points that are on a regular grid! Be aware of floating "\ | ||
"point precision." | ||
raise ValueError(msg) | ||
new_row_index = np.ravel_multi_index(iN, nN) | ||
reverse_scrambling = np.argsort(new_row_index) | ||
vals_on_regular_grid = vals_scrmbld[reverse_scrambling] | ||
return grid_axes, vals_on_regular_grid | ||
|
||
def fit(self, points, values, **kwargs): | ||
""" | ||
Construct the interpolator given `points` and `values`. | ||
Assumes that the points are on a regular grid, fails when not. | ||
see scipy.interpolate.RegularGridInterpolator | ||
|
||
:param array_like points: the coordinates of the points. | ||
:param array_like values: the values in the points. | ||
""" | ||
points = np.asarray(points) | ||
if not np.issubdtype(points.dtype, np.number): | ||
raise ValueError('Invalid format or dimension for the argument' | ||
'`points`.') | ||
if points.ndim == 1: | ||
points = points[:, None] | ||
vals = np.asarray(values) | ||
grid_axes, values_grd = self.get_grid_axes(points, vals) | ||
shape = [len(ax) for ax in grid_axes] | ||
shape.append(-1) | ||
self.interpolator = RGI(grid_axes, values_grd.reshape(shape), **kwargs) | ||
|
||
def predict(self, new_point): | ||
flabowski marked this conversation as resolved.
Show resolved
Hide resolved
|
||
""" | ||
Evaluate interpolator at given `new_point`, can be multiple points. | ||
|
||
:param array_like new_point: the coordinates of the given point(s). | ||
:return: the interpolated values. | ||
:rtype: numpy.ndarray | ||
""" | ||
new_point = np.asarray(new_point) | ||
if new_point.ndim == 1: | ||
new_point = new_point[:, None] | ||
return self.interpolator(new_point) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import numpy as np | ||
from unittest import TestCase | ||
from ezyrb import RegularGrid, Database, POD, ReducedOrderModel | ||
|
||
|
||
class TestRegularGrid(TestCase): | ||
|
||
def test_1D_1mode(self): | ||
reg = RegularGrid() | ||
reg.fit(np.array([1, 2, 3])[:, None], | ||
np.array([1, 5, 3])[:, None]) | ||
assert reg.predict([1]) == 1 | ||
assert reg.predict([2]) == 5 | ||
assert reg.predict([3]) == 3 | ||
|
||
def test_predict1d(self): | ||
reg = RegularGrid() | ||
x1 = np.array([[1], [6], [8]]) | ||
V = np.array([[1, 0], [20, 5], [8, 6]]) # n, r = 3, 2 | ||
reg.fit(x1, V) | ||
result = reg.predict([[1], [8], [6]]) | ||
assert (result[0] == [1, 0]).all() | ||
assert (result[1] == [8, 6]).all() | ||
assert (result[2] == [20, 5]).all() | ||
|
||
def test_predict1d_2(self): | ||
reg = RegularGrid() | ||
x1 = [1, 2] | ||
reg.fit(x1, [[1, 1], [2, 2]]) | ||
result = reg.predict([[1.5]]) | ||
assert (result[0] == [[1.5, 1.5]]).all() | ||
|
||
def test_predict2d(self): | ||
reg = RegularGrid() | ||
x1 = [1, 2, 3] | ||
x2 = [4, 5, 6, 7] | ||
xx1, xx2 = np.meshgrid(x1, x2, indexing="ij") | ||
points = np.c_[xx1.ravel(), xx2.ravel()] | ||
V = [[1, 21], [2, 22], [3, 23], [4, 24], [5, 25], [6, 26], | ||
[7, 27], [8, 28], [9, 29], [10, 30], [11, 31], [12, 32]] | ||
reg.fit(points, V, method="linear") | ||
result = reg.predict([[1, 4], [1, 5]]) | ||
assert (result[0] == [1, 21]).all() | ||
assert (result[1] == [2, 22]).all() | ||
|
||
def test_get_grid_axes_2D(self): | ||
x1 = [.1, .2, .3] | ||
x2 = [4, 5, 6, 7] | ||
xx1, xx2 = np.meshgrid(x1, x2, indexing="ij") | ||
V = np.arange(len(x1)*len(x2)*2).reshape(-1, 2) | ||
pts = np.c_[xx1.ravel(), xx2.ravel()] | ||
|
||
random_order = np.arange(len(pts)) | ||
np.random.shuffle(random_order) | ||
pts_scrmbld = pts[random_order, :] | ||
V_scrmbld = V[random_order, :] | ||
|
||
reg = RegularGrid() | ||
grid_axes, V_unscrambled = reg.get_grid_axes(pts_scrmbld, V_scrmbld) | ||
|
||
assert np.allclose(V_unscrambled, V) | ||
assert np.allclose(grid_axes[0], x1) | ||
assert np.allclose(grid_axes[1], x2) | ||
|
||
def test_get_grid_axes_3D(self): | ||
x1 = [.1, .2, .3] | ||
x2 = [4, 5, 6, 7] | ||
x3 = [.12, .34, .56, .78, .90] | ||
xx1, xx2, xx3 = np.meshgrid(x1, x2, x3, indexing="ij") | ||
V = np.arange(len(x1)*len(x2)*len(x3)*2).reshape(-1, 2) | ||
pts = np.c_[xx1.ravel(), xx2.ravel(), xx3.ravel()] | ||
|
||
random_order = np.arange(len(pts)) | ||
np.random.shuffle(random_order) | ||
pts_scrmbld = pts[random_order, :] | ||
V_scrmbld = V[random_order, :] | ||
|
||
reg = RegularGrid() | ||
grid_axes, V_unscrambled = reg.get_grid_axes(pts_scrmbld, V_scrmbld) | ||
|
||
assert np.allclose(V_unscrambled, V) | ||
assert np.allclose(grid_axes[0], x1) | ||
assert np.allclose(grid_axes[1], x2) | ||
assert np.allclose(grid_axes[2], x3) | ||
|
||
def test_with_db_predict(self): | ||
reg = RegularGrid() | ||
pod = POD() | ||
db = Database(np.array([1, 2, 3])[:, None], | ||
np.array([1, 5, 3])[:, None]) | ||
rom = ReducedOrderModel(db, pod, reg) | ||
rom.fit() | ||
assert rom.predict([1]) == 1 | ||
assert rom.predict([2]) == 5 | ||
assert rom.predict([3]) == 3 | ||
flabowski marked this conversation as resolved.
Show resolved
Hide resolved
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not needed. Or at least we don't use it in the other files. I am not sure about the generated outcome...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure either. The file was generated automatically when ran
make_rst.sh
. Some other things seem to be fishy.edit: everything seems fine after reverting what
make_rst.sh
did. @ndem0 maybe some commands need to be updated?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are not using that script anymore! Sorry, it's not written, I gonna remove it in the next release of EZyRB (#232).
The file now looks correct, thanks!