From 624fb409f9dbbaefabf2fc76cb0a28c8df9e2194 Mon Sep 17 00:00:00 2001 From: jacobdparker Date: Mon, 18 Mar 2024 15:25:18 -0400 Subject: [PATCH 01/15] Adding broadcasting of weights against values using axis_input --- regridding/_regrid/_regrid_from_weights.py | 62 ++++++++++++++++------ 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/regridding/_regrid/_regrid_from_weights.py b/regridding/_regrid/_regrid_from_weights.py index e88528b..63a3a25 100644 --- a/regridding/_regrid/_regrid_from_weights.py +++ b/regridding/_regrid/_regrid_from_weights.py @@ -9,13 +9,13 @@ def regrid_from_weights( - weights: np.ndarray, - shape_input: tuple[int, ...], - shape_output: tuple[int, ...], - values_input: np.ndarray, - values_output: None | np.ndarray = None, - axis_input: None | int | Sequence[int] = None, - axis_output: None | int | Sequence[int] = None, + weights: np.ndarray, + shape_input: tuple[int, ...], + shape_output: tuple[int, ...], + values_input: np.ndarray, + values_output: None | np.ndarray = None, + axis_input: None | int | Sequence[int] = None, + axis_output: None | int | Sequence[int] = None, ) -> np.ndarray: """ Regrid an array of values using weights computed by @@ -52,27 +52,49 @@ def regrid_from_weights( :func:`regridding.regrid_from_weights` """ - shape_input = np.broadcast_shapes(shape_input, values_input.shape) + # pad coordinate shapes for broadcasting against values shape according to axis input + padded_shape_input = [] + padded_shape_output = [] + for i in range(values_input.ndim): + if i in axis_input: + j = np.where(np.array(axis_input) == i)[0][0] + padded_shape_input.append(shape_input[j]) + padded_shape_output.append(shape_output[j]) + else: + padded_shape_input.append(1) + padded_shape_output.append(1) + + print(f'{padded_shape_input=}') + print(f'{padded_shape_output=}') + + shape_input = np.broadcast_shapes(padded_shape_input, values_input.shape) + print(f'{shape_input=}') values_input = np.broadcast_to(values_input, shape=shape_input, subok=True) ndim_input = len(shape_input) axis_input = _util._normalize_axis(axis_input, ndim=ndim_input) + print(f'{axis_input=}') if values_output is None: shape_output = np.broadcast_shapes( - shape_output, + padded_shape_output, tuple( shape_input[ax] if ax not in axis_input else 1 for ax in _util._normalize_axis(None, ndim_input) ), ) values_output = np.zeros_like(values_input, shape=shape_output) + else: if values_output.shape != shape_output: raise ValueError(f"") values_output.fill(0) + print(f'{values_input.shape=}') + print(f'{values_output.shape=}') + ndim_output = len(shape_output) axis_output = _util._normalize_axis(axis_output, ndim=ndim_output) + print(f'{axis_output=}') axis_input_numba = ~np.arange(len(axis_input))[::-1] axis_output_numba = ~np.arange(len(axis_output))[::-1] @@ -85,13 +107,20 @@ def regrid_from_weights( shape_output_tmp = values_output.shape - weights = numba.typed.List(weights.reshape(-1)) values_input = values_input.reshape(-1, *shape_input_numba) values_output = values_output.reshape(-1, *shape_output_numba) + weights = numba.typed.List(np.broadcast_to(weights, values_input.shape[0]).reshape(-1)) + + print(f'{len(weights)=}') + print(f'{weights=}') + values_input = np.ascontiguousarray(values_input) values_output = np.ascontiguousarray(values_output) + print(f'{values_input.shape=}') + print(f'{values_output.shape=}') + _regrid_from_weights( weights=weights, values_input=values_input, @@ -105,17 +134,20 @@ def regrid_from_weights( return values_output -@numba.njit() +@numba.njit(parallel=True) def _regrid_from_weights( - weights: numba.typed.List, - values_input: np.ndarray, - values_output: np.ndarray, + weights: numba.typed.List, + values_input: np.ndarray, + values_output: np.ndarray, ) -> None: + # print(f'{weights=}') + # print(f'{values_input.shape=}') + # print(f'{values_output.shape=}') + for d in numba.prange(len(weights)): weights_d = weights[d] values_input_d = values_input[d].reshape(-1) values_output_d = values_output[d].reshape(-1) - for w in range(len(weights_d)): i_input, i_output, weight = weights_d[w] values_output_d[int(i_output)] += weight * values_input_d[int(i_input)] From e1b3f664e57d66357ac770f517240ff5c9d12705 Mon Sep 17 00:00:00 2001 From: jacobdparker Date: Mon, 18 Mar 2024 15:26:35 -0400 Subject: [PATCH 02/15] committing steps toward debugging conservative interpolation --- regridding/_conservative_ramshaw.py | 14 +++++++------- regridding/_regrid/_tests/test_regrid.py | 1 + regridding/_weights/_weights_conservative.py | 11 ++++++++++- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/regridding/_conservative_ramshaw.py b/regridding/_conservative_ramshaw.py index f1d9966..64b955f 100644 --- a/regridding/_conservative_ramshaw.py +++ b/regridding/_conservative_ramshaw.py @@ -7,13 +7,13 @@ __all__ = [] -@numba.njit( - error_model="numpy", - # parallel=True, - # inline="always", - # boundscheck=True, - # cache=True, -) +# @numba.njit( +# error_model="numpy", +# # parallel=True, +# # inline="always", +# # boundscheck=True, +# # cache=True, +# ) def _conservative_ramshaw( # values_input: np.ndarray, # values_output: np.ndarray, diff --git a/regridding/_regrid/_tests/test_regrid.py b/regridding/_regrid/_tests/test_regrid.py index 8d3870d..e412c71 100644 --- a/regridding/_regrid/_tests/test_regrid.py +++ b/regridding/_regrid/_tests/test_regrid.py @@ -4,6 +4,7 @@ @pytest.mark.parametrize( + # add two cases (coords broadcast against values, and vice versa) argnames="coordinates_input,coordinates_output,values_input,values_output,axis_input,axis_output,result_expected", argvalues=[ ( diff --git a/regridding/_weights/_weights_conservative.py b/regridding/_weights/_weights_conservative.py index a70c009..a345a67 100644 --- a/regridding/_weights/_weights_conservative.py +++ b/regridding/_weights/_weights_conservative.py @@ -55,7 +55,16 @@ def _weights_conservative( elif len(axis_input) == 2: coordinates_input_x, coordinates_input_y = coordinates_input coordinates_output_x, coordinates_output_y = coordinates_output - + print(f'{index_vertices_input=}') + print(f'{index_vertices_output=}') + print(f'{coordinates_input_x[index_vertices_input]=}') + print(f'{coordinates_input_y[index_vertices_input]=}') + print(f'{coordinates_output_x[index_vertices_output]=}') + print(f'{coordinates_output_y[index_vertices_output]=}') + print(f'{coordinates_input_x[index_vertices_input].shape=}') + print(f'{coordinates_input_y[index_vertices_input].shape=}') + print(f'{coordinates_output_x[index_vertices_output].shape=}') + print(f'{coordinates_output_y[index_vertices_output].shape=}') weights[index] = _conservative_ramshaw( grid_input=( coordinates_input_x[index_vertices_input], From d07011caf7c10109abbeb26e685e3150cbb06b83 Mon Sep 17 00:00:00 2001 From: jacobdparker Date: Tue, 9 Apr 2024 17:40:21 -0500 Subject: [PATCH 03/15] Breaking loop into two pieces to fix error with zip command --- regridding/_conservative_ramshaw.py | 67 +++++++++++++++++------------ 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/regridding/_conservative_ramshaw.py b/regridding/_conservative_ramshaw.py index 64b955f..c19a2a8 100644 --- a/regridding/_conservative_ramshaw.py +++ b/regridding/_conservative_ramshaw.py @@ -7,13 +7,13 @@ __all__ = [] -# @numba.njit( -# error_model="numpy", -# # parallel=True, -# # inline="always", -# # boundscheck=True, -# # cache=True, -# ) +@numba.njit( + error_model="numpy", + # parallel=True, + # inline="always", + # boundscheck=True, + # cache=True, +) def _conservative_ramshaw( # values_input: np.ndarray, # values_output: np.ndarray, @@ -32,9 +32,6 @@ def _conservative_ramshaw( shape_input = input_x.shape # shape_output = np.broadcast_shapes(output_x.shape, output_y.shape) - grids_sweep = grid_input, grid_output - grids_static = grid_output, grid_input - grids_input = "sweep", "static" axes = 0, 1 # k = slice(None, -1) @@ -55,23 +52,39 @@ def _conservative_ramshaw( # values_input = values_input / area_input - for grid_sweep, grid_static, grid_input in zip(grids_sweep, grids_static, grids_input): - grid_static_x, grid_static_y = grid_static - grid_sweep_x, grid_sweep_y = grid_sweep - for axis in axes: - _sweep_axis( - # values_input=values_input, - # values_output=values_output, - area_input=area_input, - grid_sweep_x=grid_sweep_x, - grid_sweep_y=grid_sweep_y, - grid_static_x=grid_static_x, - grid_static_y=grid_static_y, - axis=axis, - grid_input=grid_input, - epsilon=epsilon, - weights=weights, - ) + grid_static_x, grid_static_y = grid_output + grid_sweep_x, grid_sweep_y = grid_input + for axis in axes: + _sweep_axis( + # values_input=values_input, + # values_output=values_output, + area_input=area_input, + grid_sweep_x=grid_sweep_x, + grid_sweep_y=grid_sweep_y, + grid_static_x=grid_static_x, + grid_static_y=grid_static_y, + axis=axis, + grid_input="sweep", + epsilon=epsilon, + weights=weights, + ) + + grid_static_x, grid_static_y = grid_input + grid_sweep_x, grid_sweep_y = grid_output + for axis in axes: + _sweep_axis( + # values_input=values_input, + # values_output=values_output, + area_input=area_input, + grid_sweep_x=grid_sweep_x, + grid_sweep_y=grid_sweep_y, + grid_static_x=grid_static_x, + grid_static_y=grid_static_y, + axis=axis, + grid_input="static", + epsilon=epsilon, + weights=weights, + ) # return values_output return weights From 5427956c1670c739dbbbf6cbf28f4efc6e80cdac Mon Sep 17 00:00:00 2001 From: jacobdparker Date: Tue, 9 Apr 2024 17:41:19 -0500 Subject: [PATCH 04/15] Fixing bug related to improper use of insert method --- regridding/_weights/_weights_conservative.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/regridding/_weights/_weights_conservative.py b/regridding/_weights/_weights_conservative.py index a345a67..d6febe8 100644 --- a/regridding/_weights/_weights_conservative.py +++ b/regridding/_weights/_weights_conservative.py @@ -39,15 +39,16 @@ def _weights_conservative( weights = np.empty(shape_orthogonal, dtype=numba.typed.List) for index in np.ndindex(*shape_orthogonal): - index_vertices_input = list(index) + index_vertices_input = list(reversed(index)) + for ax in axis_input: - index_vertices_input.insert(ax, slice(None)) - index_vertices_input = tuple(index_vertices_input) + index_vertices_input.insert(~ax, slice(None)) + index_vertices_input = tuple(reversed(index_vertices_input)) - index_vertices_output = list(index) + index_vertices_output = list(reversed(index)) for ax in axis_output: - index_vertices_output.insert(ax, slice(None)) - index_vertices_output = tuple(index_vertices_output) + index_vertices_output.insert(~ax, slice(None)) + index_vertices_output = tuple(reversed(index_vertices_output)) if len(axis_input) == 1: raise NotImplementedError("1D regridding not supported") From 47e42c0c726988512dbd18928d561e2a7a82eb0c Mon Sep 17 00:00:00 2001 From: jacobdparker Date: Tue, 9 Apr 2024 17:41:43 -0500 Subject: [PATCH 05/15] Cleaning up print statements. --- regridding/_weights/_weights_conservative.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/regridding/_weights/_weights_conservative.py b/regridding/_weights/_weights_conservative.py index d6febe8..a6677e9 100644 --- a/regridding/_weights/_weights_conservative.py +++ b/regridding/_weights/_weights_conservative.py @@ -56,16 +56,6 @@ def _weights_conservative( elif len(axis_input) == 2: coordinates_input_x, coordinates_input_y = coordinates_input coordinates_output_x, coordinates_output_y = coordinates_output - print(f'{index_vertices_input=}') - print(f'{index_vertices_output=}') - print(f'{coordinates_input_x[index_vertices_input]=}') - print(f'{coordinates_input_y[index_vertices_input]=}') - print(f'{coordinates_output_x[index_vertices_output]=}') - print(f'{coordinates_output_y[index_vertices_output]=}') - print(f'{coordinates_input_x[index_vertices_input].shape=}') - print(f'{coordinates_input_y[index_vertices_input].shape=}') - print(f'{coordinates_output_x[index_vertices_output].shape=}') - print(f'{coordinates_output_y[index_vertices_output].shape=}') weights[index] = _conservative_ramshaw( grid_input=( coordinates_input_x[index_vertices_input], From 6b7641e77f724fac0a15397dbea0434a094054ef Mon Sep 17 00:00:00 2001 From: jacobdparker Date: Wed, 10 Apr 2024 10:30:12 -0500 Subject: [PATCH 06/15] Removing broadcasting of weights against values. It is possible this would work under specific circumstances, but is not robust as currently implemented. --- regridding/_regrid/_regrid_from_weights.py | 49 +++++++++------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/regridding/_regrid/_regrid_from_weights.py b/regridding/_regrid/_regrid_from_weights.py index 63a3a25..927fe7c 100644 --- a/regridding/_regrid/_regrid_from_weights.py +++ b/regridding/_regrid/_regrid_from_weights.py @@ -53,30 +53,30 @@ def regrid_from_weights( """ # pad coordinate shapes for broadcasting against values shape according to axis input - padded_shape_input = [] - padded_shape_output = [] - for i in range(values_input.ndim): - if i in axis_input: - j = np.where(np.array(axis_input) == i)[0][0] - padded_shape_input.append(shape_input[j]) - padded_shape_output.append(shape_output[j]) - else: - padded_shape_input.append(1) - padded_shape_output.append(1) - - print(f'{padded_shape_input=}') - print(f'{padded_shape_output=}') - - shape_input = np.broadcast_shapes(padded_shape_input, values_input.shape) - print(f'{shape_input=}') - values_input = np.broadcast_to(values_input, shape=shape_input, subok=True) + # print(f'{values_input.shape=}') + # padded_shape_input = [] + # padded_shape_output = [] + # for i in range(values_input.ndim): + # if i in axis_input: + # j = np.where(np.array(axis_input) == i)[0][0] + # padded_shape_input.append(shape_input[j]) + # padded_shape_output.append(shape_output[j]) + # else: + # padded_shape_input.append(1) + # padded_shape_output.append(1) + # + # print(f'{padded_shape_input=}') + # print(f'{padded_shape_output=}') + # + # shape_input = np.broadcast_shapes(padded_shape_input, values_input.shape) + # print(f'{shape_input=}') + # values_input = np.broadcast_to(values_input, shape=shape_input, subok=True) ndim_input = len(shape_input) axis_input = _util._normalize_axis(axis_input, ndim=ndim_input) - print(f'{axis_input=}') if values_output is None: shape_output = np.broadcast_shapes( - padded_shape_output, + shape_output, tuple( shape_input[ax] if ax not in axis_input else 1 for ax in _util._normalize_axis(None, ndim_input) @@ -89,9 +89,6 @@ def regrid_from_weights( raise ValueError(f"") values_output.fill(0) - print(f'{values_input.shape=}') - print(f'{values_output.shape=}') - ndim_output = len(shape_output) axis_output = _util._normalize_axis(axis_output, ndim=ndim_output) print(f'{axis_output=}') @@ -110,10 +107,7 @@ def regrid_from_weights( values_input = values_input.reshape(-1, *shape_input_numba) values_output = values_output.reshape(-1, *shape_output_numba) - weights = numba.typed.List(np.broadcast_to(weights, values_input.shape[0]).reshape(-1)) - - print(f'{len(weights)=}') - print(f'{weights=}') + weights = numba.typed.List(weights.reshape(-1)) values_input = np.ascontiguousarray(values_input) values_output = np.ascontiguousarray(values_output) @@ -140,9 +134,6 @@ def _regrid_from_weights( values_input: np.ndarray, values_output: np.ndarray, ) -> None: - # print(f'{weights=}') - # print(f'{values_input.shape=}') - # print(f'{values_output.shape=}') for d in numba.prange(len(weights)): weights_d = weights[d] From 8fc2587822649b5a1e28f1b4082235e46ce3bd37 Mon Sep 17 00:00:00 2001 From: jacobdparker Date: Mon, 15 Apr 2024 09:17:02 -0400 Subject: [PATCH 07/15] Cleaning up commented code and print statements. Running black formatter. --- regridding/_conservative_ramshaw.py | 483 ++++++++++++--------- regridding/_regrid/_regrid_from_weights.py | 43 +- 2 files changed, 292 insertions(+), 234 deletions(-) diff --git a/regridding/_conservative_ramshaw.py b/regridding/_conservative_ramshaw.py index c19a2a8..6ea7f8c 100644 --- a/regridding/_conservative_ramshaw.py +++ b/regridding/_conservative_ramshaw.py @@ -2,6 +2,7 @@ import math import numpy as np import numba + # import matplotlib.pyplot as plt __all__ = [] @@ -15,22 +16,18 @@ # cache=True, ) def _conservative_ramshaw( - # values_input: np.ndarray, - # values_output: np.ndarray, - grid_input: tuple[np.ndarray, np.ndarray], - grid_output: tuple[np.ndarray, np.ndarray], - epsilon: float = 1e-10, + grid_input: tuple[np.ndarray, np.ndarray], + grid_output: tuple[np.ndarray, np.ndarray], + epsilon: float = 1e-10, ) -> tuple[np.ndarray, np.ndarray, np.ndarray]: weights = numba.typed.List() for x in range(0): - weights.append((0., 0., 0.)) + weights.append((0.0, 0.0, 0.0)) input_x, input_y = grid_input - # output_x, output_y = grid_output shape_input = input_x.shape - # shape_output = np.broadcast_shapes(output_x.shape, output_y.shape) axes = 0, 1 @@ -73,8 +70,6 @@ def _conservative_ramshaw( grid_sweep_x, grid_sweep_y = grid_output for axis in axes: _sweep_axis( - # values_input=values_input, - # values_output=values_output, area_input=area_input, grid_sweep_x=grid_sweep_x, grid_sweep_y=grid_sweep_y, @@ -92,17 +87,15 @@ def _conservative_ramshaw( @numba.njit(error_model="numpy", parallel=True) def _sweep_axis( - # values_input: np.ndarray, - # values_output: np.ndarray, - area_input: np.ndarray, - grid_static_x: np.ndarray, - grid_static_y: np.ndarray, - grid_sweep_x: np.ndarray, - grid_sweep_y: np.ndarray, - axis: int, - grid_input: str, - epsilon: float, - weights: numba.typed.List, + area_input: np.ndarray, + grid_static_x: np.ndarray, + grid_static_y: np.ndarray, + grid_sweep_x: np.ndarray, + grid_sweep_y: np.ndarray, + axis: int, + grid_input: str, + epsilon: float, + weights: numba.typed.List, ) -> None: if grid_input == "static": @@ -110,7 +103,9 @@ def _sweep_axis( elif grid_input == "sweep": input_is_sweep = True else: - print(f"The `grid_input` argument must have the value 'static' or 'sweep', got '{grid_input}'") + print( + f"The `grid_input` argument must have the value 'static' or 'sweep', got '{grid_input}'" + ) # print(input_is_sweep) @@ -134,18 +129,22 @@ def _sweep_axis( edges_top = slice(None, 0, -1), ~0 edges_left = 0, slice(None, 0, -1) - edges_border_static_x = np.concatenate(( - grid_static_x[edges_bottom], - grid_static_x[edges_right], - grid_static_x[edges_top], - grid_static_x[edges_left], - )) - edges_border_static_y = np.concatenate(( - grid_static_y[edges_bottom], - grid_static_y[edges_right], - grid_static_y[edges_top], - grid_static_y[edges_left], - )) + edges_border_static_x = np.concatenate( + ( + grid_static_x[edges_bottom], + grid_static_x[edges_right], + grid_static_x[edges_top], + grid_static_x[edges_left], + ) + ) + edges_border_static_y = np.concatenate( + ( + grid_static_y[edges_bottom], + grid_static_y[edges_right], + grid_static_y[edges_top], + grid_static_y[edges_left], + ) + ) cells_bottom = slice(None), 0 cells_right = ~0, slice(None) @@ -155,41 +154,49 @@ def _sweep_axis( grid_static_m = np.arange(shape_static_x)[:, np.newaxis] grid_static_n = np.arange(shape_static_y)[np.newaxis, :] grid_static_m, grid_static_n = np.broadcast_arrays(grid_static_m, grid_static_n) - edges_border_static_m = np.concatenate(( - grid_static_m[edges_bottom], - grid_static_m[edges_right], - grid_static_m[edges_top], - grid_static_m[edges_left], - )) - edges_border_static_n = np.concatenate(( - grid_static_n[edges_bottom], - grid_static_n[edges_right], - grid_static_n[edges_top], - grid_static_n[edges_left], - )) + edges_border_static_m = np.concatenate( + ( + grid_static_m[edges_bottom], + grid_static_m[edges_right], + grid_static_m[edges_top], + grid_static_m[edges_left], + ) + ) + edges_border_static_n = np.concatenate( + ( + grid_static_n[edges_bottom], + grid_static_n[edges_right], + grid_static_n[edges_top], + grid_static_n[edges_left], + ) + ) cells_static_m = np.arange(shape_static_x - 1)[:, np.newaxis] cells_static_n = np.arange(shape_static_y - 1)[np.newaxis, :] cells_static_m, cells_static_n = np.broadcast_arrays(cells_static_m, cells_static_n) - cells_border_static_m = np.concatenate(( - cells_static_m[cells_bottom], - cells_static_m[cells_right], - cells_static_m[cells_top], - cells_static_m[cells_left], - )) - cells_border_static_n = np.concatenate(( - cells_static_n[cells_bottom], - cells_static_n[cells_right], - cells_static_n[cells_top], - cells_static_n[cells_left], - )) + cells_border_static_m = np.concatenate( + ( + cells_static_m[cells_bottom], + cells_static_m[cells_right], + cells_static_m[cells_top], + cells_static_m[cells_left], + ) + ) + cells_border_static_n = np.concatenate( + ( + cells_static_n[cells_bottom], + cells_static_n[cells_right], + cells_static_n[cells_top], + cells_static_n[cells_left], + ) + ) weight = numba.typed.List() for i in range(shape_sweep_x): w = numba.typed.List() for _ in range(0): - w.append((0., 0., 0.)) + w.append((0.0, 0.0, 0.0)) weight.append(w) for i in numba.prange(shape_sweep_x): @@ -203,11 +210,11 @@ def _sweep_axis( point_sweep_2y = grid_sweep_y[i, j + 1] if _point_is_inside_polygon( - vertices_x=edges_border_static_x, - vertices_y=edges_border_static_y, - point_x=point_sweep_1x, - point_y=point_sweep_1y, - epsilon=epsilon, + vertices_x=edges_border_static_x, + vertices_y=edges_border_static_y, + point_x=point_sweep_1x, + point_y=point_sweep_1y, + epsilon=epsilon, ): # print("initial point inside...") m, n = _indices_of_line_brute( @@ -247,7 +254,14 @@ def _sweep_axis( # plt.plot([point_sweep_1x, point_sweep_2x], [point_sweep_1y, point_sweep_2y], zorder=10) if not sweep_is_inside_static: - point_sweep_2x, point_sweep_2y, j_new, m_new, n_new, sweep_is_inside_static = _step_outside_static( + ( + point_sweep_2x, + point_sweep_2y, + j_new, + m_new, + n_new, + sweep_is_inside_static, + ) = _step_outside_static( # area_output=area_output, grid_static_x=grid_static_x, grid_static_y=grid_static_y, @@ -270,29 +284,31 @@ def _sweep_axis( ) else: - point_sweep_2x, point_sweep_2y, j_new, m_new, n_new = _step_inside_static( - # values_input=values_input, - # values_output=values_output, - # area_output=area_output, - area_input=area_input, - grid_static_x=grid_static_x, - grid_static_y=grid_static_y, - shape_sweep_x=shape_sweep_x, - shape_sweep_y=shape_sweep_y, - point_sweep_1x=point_sweep_1x, - point_sweep_1y=point_sweep_1y, - point_sweep_2x=point_sweep_2x, - point_sweep_2y=point_sweep_2y, - axis=axis, - input_is_sweep=input_is_sweep, - epsilon=epsilon, - m_old=m_old, - n_old=n_old, - i=i, - j=j, - m=m, - n=n, - weight=weight[i], + point_sweep_2x, point_sweep_2y, j_new, m_new, n_new = ( + _step_inside_static( + # values_input=values_input, + # values_output=values_output, + # area_output=area_output, + area_input=area_input, + grid_static_x=grid_static_x, + grid_static_y=grid_static_y, + shape_sweep_x=shape_sweep_x, + shape_sweep_y=shape_sweep_y, + point_sweep_1x=point_sweep_1x, + point_sweep_1y=point_sweep_1y, + point_sweep_2x=point_sweep_2x, + point_sweep_2y=point_sweep_2y, + axis=axis, + input_is_sweep=input_is_sweep, + epsilon=epsilon, + m_old=m_old, + n_old=n_old, + i=i, + j=j, + m=m, + n=n, + weight=weight[i], + ) ) # print("j_new", j_new) @@ -337,26 +353,25 @@ def _sweep_axis( @numba.njit(inline="always") def _step_outside_static( - # area_output: np.ndarray, - grid_static_x: np.ndarray, - grid_static_y: np.ndarray, - edges_border_static_m: np.ndarray, - edges_border_static_n: np.ndarray, - cells_border_static_m: np.ndarray, - cells_border_static_n: np.ndarray, - # shape_sweep_x: int, - # shape_sweep_y: int, - point_sweep_1x: float, - point_sweep_1y: float, - point_sweep_2x: float, - point_sweep_2y: float, - # input_is_sweep: bool, - epsilon: float, - # i: int, - j: int, - m: int, - n: int, - + # area_output: np.ndarray, + grid_static_x: np.ndarray, + grid_static_y: np.ndarray, + edges_border_static_m: np.ndarray, + edges_border_static_n: np.ndarray, + cells_border_static_m: np.ndarray, + cells_border_static_n: np.ndarray, + # shape_sweep_x: int, + # shape_sweep_y: int, + point_sweep_1x: float, + point_sweep_1y: float, + point_sweep_2x: float, + point_sweep_2y: float, + # input_is_sweep: bool, + epsilon: float, + # i: int, + j: int, + m: int, + n: int, ) -> tuple[float, float, int, int, int, bool]: # print("step outside") @@ -401,10 +416,14 @@ def _step_outside_static( # ) t, u = _two_line_segment_intersection_parameters( - x1=vertex_static_1x, y1=vertex_static_1y, - x2=vertex_static_2x, y2=vertex_static_2y, - x3=point_sweep_1x, y3=point_sweep_1y, - x4=point_sweep_2x, y4=point_sweep_2y, + x1=vertex_static_1x, + y1=vertex_static_1y, + x2=vertex_static_2x, + y2=vertex_static_2y, + x3=point_sweep_1x, + y3=point_sweep_1y, + x4=point_sweep_2x, + y4=point_sweep_2y, ) if u > u_min: @@ -419,12 +438,20 @@ def _step_outside_static( n_new = cells_border_static_n[index_vertex_1] if -epsilon < t < epsilon: - if direction_sweep_x * direction_static_x + direction_sweep_y * direction_static_y < 0: + if ( + direction_sweep_x * direction_static_x + + direction_sweep_y * direction_static_y + < 0 + ): m_new = m_new - direction_m n_new = n_new - direction_n elif (1 - epsilon) < t < (1 + epsilon): - if direction_sweep_x * direction_static_x + direction_sweep_y * direction_static_y > 0: + if ( + direction_sweep_x * direction_static_x + + direction_sweep_y * direction_static_y + > 0 + ): m_new = m_new + direction_m n_new = n_new + direction_n @@ -442,11 +469,19 @@ def _step_outside_static( elif math.isnan(u) or math.isnan(t): if point_sweep_1x != point_sweep_2x: - u1 = (vertex_static_1x - point_sweep_1x) / (point_sweep_2x - point_sweep_1x) - u2 = (vertex_static_2x - point_sweep_1x) / (point_sweep_2x - point_sweep_1x) + u1 = (vertex_static_1x - point_sweep_1x) / ( + point_sweep_2x - point_sweep_1x + ) + u2 = (vertex_static_2x - point_sweep_1x) / ( + point_sweep_2x - point_sweep_1x + ) else: - u1 = (vertex_static_1y - point_sweep_1y) / (point_sweep_2y - point_sweep_1y) - u2 = (vertex_static_2y - point_sweep_1y) / (point_sweep_2y - point_sweep_1y) + u1 = (vertex_static_1y - point_sweep_1y) / ( + point_sweep_2y - point_sweep_1y + ) + u2 = (vertex_static_2y - point_sweep_1y) / ( + point_sweep_2y - point_sweep_1y + ) if u1 > u_min: continue @@ -498,27 +533,27 @@ def _step_outside_static( @numba.njit(inline="always") def _step_inside_static( - # values_input: np.ndarray, - # values_output: np.ndarray, - area_input: np.ndarray, - grid_static_x: np.ndarray, - grid_static_y: np.ndarray, - shape_sweep_x: int, - shape_sweep_y: int, - point_sweep_1x: float, - point_sweep_1y: float, - point_sweep_2x: float, - point_sweep_2y: float, - axis: int, - input_is_sweep: bool, - epsilon: float, - m_old: int, - n_old: int, - i: int, - j: int, - m: int, - n: int, - weight: numba.typed.List, + # values_input: np.ndarray, + # values_output: np.ndarray, + area_input: np.ndarray, + grid_static_x: np.ndarray, + grid_static_y: np.ndarray, + shape_sweep_x: int, + shape_sweep_y: int, + point_sweep_1x: float, + point_sweep_1y: float, + point_sweep_2x: float, + point_sweep_2y: float, + axis: int, + input_is_sweep: bool, + epsilon: float, + m_old: int, + n_old: int, + i: int, + j: int, + m: int, + n: int, + weight: numba.typed.List, ) -> tuple[float, float, int, int, int]: # print("step inside") @@ -590,10 +625,14 @@ def _step_inside_static( # ) t, u = _two_line_segment_intersection_parameters( - x1=vertex_static_1x, y1=vertex_static_1y, - x2=vertex_static_2x, y2=vertex_static_2y, - x3=point_sweep_1x, y3=point_sweep_1y, - x4=point_sweep_2x, y4=point_sweep_2y, + x1=vertex_static_1x, + y1=vertex_static_1y, + x2=vertex_static_2x, + y2=vertex_static_2y, + x3=point_sweep_1x, + y3=point_sweep_1y, + x4=point_sweep_2x, + y4=point_sweep_2y, ) # print(t, u) @@ -654,11 +693,19 @@ def _step_inside_static( # print("parallel lines found") if point_sweep_1x != point_sweep_2x: - u1 = (vertex_static_1x - point_sweep_1x) / (point_sweep_2x - point_sweep_1x) - u2 = (vertex_static_2x - point_sweep_1x) / (point_sweep_2x - point_sweep_1x) + u1 = (vertex_static_1x - point_sweep_1x) / ( + point_sweep_2x - point_sweep_1x + ) + u2 = (vertex_static_2x - point_sweep_1x) / ( + point_sweep_2x - point_sweep_1x + ) else: - u1 = (vertex_static_1y - point_sweep_1y) / (point_sweep_2y - point_sweep_1y) - u2 = (vertex_static_2y - point_sweep_1y) / (point_sweep_2y - point_sweep_1y) + u1 = (vertex_static_1y - point_sweep_1y) / ( + point_sweep_2y - point_sweep_1y + ) + u2 = (vertex_static_2y - point_sweep_1y) / ( + point_sweep_2y - point_sweep_1y + ) # print("u1", u1) # print("u2", u2) @@ -687,7 +734,7 @@ def _step_inside_static( u_min = u2 min_is_coincident = True - # plt.scatter(point_sweep_2x, point_sweep_2y, zorder=10) + # plt.scatter(point_sweep_2x, point_sweep_2y, zorder=10) m_left = m m_right = m + normal_m @@ -706,7 +753,10 @@ def _step_inside_static( # color="orange" # ) - if normal_sweep_x * normal_static_x + normal_sweep_y * normal_static_y < 0: + if ( + normal_sweep_x * normal_static_x + normal_sweep_y * normal_static_y + < 0 + ): # print("switch") m_left, m_right = m_right, m_left n_left, n_right = n_right, n_left @@ -790,21 +840,33 @@ def _step_inside_static( area_sweep = (point_sweep_1x * point_sweep_2y - point_sweep_2x * point_sweep_1y) / 2 - if 0 <= i_input_left < (shape_input_x - 1) and 0 <= j_input_left < (shape_input_y - 1): - if 0 <= i_output_left < (shape_output_x - 1) and 0 <= j_output_left < (shape_output_y - 1): - weight.append(( - (shape_input_y - 1) * i_input_left + j_input_left, - (shape_output_y - 1) * i_output_left + j_output_left, - area_sweep / area_input[i_input_left, j_input_left], - )) - - if 0 <= i_input_right < (shape_input_x - 1) and 0 <= j_input_right < (shape_input_y - 1): - if 0 <= i_output_right < (shape_output_x - 1) and 0 <= j_output_right < (shape_output_y - 1): - weight.append(( - (shape_input_y - 1) * i_input_right + j_input_right, - (shape_output_y - 1) * i_output_right + j_output_right, - -area_sweep / area_input[i_input_right, j_input_right], - )) + if 0 <= i_input_left < (shape_input_x - 1) and 0 <= j_input_left < ( + shape_input_y - 1 + ): + if 0 <= i_output_left < (shape_output_x - 1) and 0 <= j_output_left < ( + shape_output_y - 1 + ): + weight.append( + ( + (shape_input_y - 1) * i_input_left + j_input_left, + (shape_output_y - 1) * i_output_left + j_output_left, + area_sweep / area_input[i_input_left, j_input_left], + ) + ) + + if 0 <= i_input_right < (shape_input_x - 1) and 0 <= j_input_right < ( + shape_input_y - 1 + ): + if 0 <= i_output_right < (shape_output_x - 1) and 0 <= j_output_right < ( + shape_output_y - 1 + ): + weight.append( + ( + (shape_input_y - 1) * i_input_right + j_input_right, + (shape_output_y - 1) * i_output_right + j_output_right, + -area_sweep / area_input[i_input_right, j_input_right], + ) + ) # if 0 <= i_input_left < (shape_input_x - 1) and 0 <= j_input_left < (shape_input_y - 1): # value_input_left = values_input[i_input_left, j_input_left] @@ -836,10 +898,10 @@ def _step_inside_static( @numba.njit(inline="always") def _grid_area_sweep( - out: np.ndarray, - grid_x: np.ndarray, - grid_y: np.ndarray, - axis: int, + out: np.ndarray, + grid_x: np.ndarray, + grid_y: np.ndarray, + axis: int, ): if axis == 0: @@ -881,13 +943,13 @@ def _grid_area_sweep( @numba.njit(inline="always", error_model="numpy") def _indices_of_line_brute( - grid_x: np.ndarray, - grid_y: np.ndarray, - point_1x: float, - point_1y: float, - point_2x: float, - point_2y: float, - epsilon: float, + grid_x: np.ndarray, + grid_y: np.ndarray, + point_1x: float, + point_1y: float, + point_2x: float, + point_2y: float, + epsilon: float, ) -> tuple[int, int]: shape_x, shape_y = grid_x.shape @@ -934,10 +996,14 @@ def _indices_of_line_brute( vertex_2y = vertices_y[index_vertex_2] t, u = _two_line_segment_intersection_parameters( - x1=vertex_1x, y1=vertex_1y, - x2=vertex_2x, y2=vertex_2y, - x3=point_1x, y3=point_1y, - x4=point_2x, y4=point_2y, + x1=vertex_1x, + y1=vertex_1y, + x2=vertex_2x, + y2=vertex_2y, + x3=point_1x, + y3=point_1y, + x4=point_2x, + y4=point_2y, ) # print(t, u) @@ -962,9 +1028,13 @@ def _indices_of_line_brute( projection_1y = normal_y * (vertex_2y - vertex_1y) projection_0 = projection_0x + projection_0y projection_1 = projection_1x + projection_1y - if (-epsilon < projection_0 < epsilon) or (-epsilon < projection_1 < epsilon): + if (-epsilon < projection_0 < epsilon) or ( + -epsilon < projection_1 < epsilon + ): pass - elif math.copysign(1, projection_0) == math.copysign(1, projection_1): + elif math.copysign(1, projection_0) == math.copysign( + 1, projection_1 + ): # print("projection_0 and projection_1 have the same sign") num_intersections -= 1 @@ -978,11 +1048,11 @@ def _indices_of_line_brute( @numba.njit(inline="always", error_model="numpy") def _point_is_inside_polygon( - vertices_x: np.ndarray, - vertices_y: np.ndarray, - point_x: float, - point_y: float, - epsilon: float + vertices_x: np.ndarray, + vertices_y: np.ndarray, + point_x: float, + point_y: float, + epsilon: float, ) -> bool: x3 = point_x @@ -1026,7 +1096,7 @@ def _point_is_inside_polygon( result = not result if y1_is_zero: y0 = vertices_y[v - 2] - point_y - if (-epsilon < y0 < epsilon) or (-epsilon < y2 = point_y) != (y0 >= point_y) # condition_2 = point_x < ((point_y - y1) / slope + x1) @@ -1072,10 +1145,14 @@ def _point_is_inside_polygon( @numba.njit(inline="always", error_model="numpy") def _two_line_segment_intersection( - x1: float, y1: float, - x2: float, y2: float, - x3: float, y3: float, - x4: float, y4: float, + x1: float, + y1: float, + x2: float, + y2: float, + x3: float, + y3: float, + x4: float, + y4: float, ) -> tuple[float, float]: t_numerator = (x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4) @@ -1098,10 +1175,14 @@ def _two_line_segment_intersection( @numba.njit(inline="always", error_model="numpy") def _two_line_segment_intersection_parameters( - x1: float, y1: float, - x2: float, y2: float, - x3: float, y3: float, - x4: float, y4: float, + x1: float, + y1: float, + x2: float, + y2: float, + x3: float, + y3: float, + x4: float, + y4: float, ) -> tuple[float, float]: t_numerator = (x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4) diff --git a/regridding/_regrid/_regrid_from_weights.py b/regridding/_regrid/_regrid_from_weights.py index 927fe7c..75501f8 100644 --- a/regridding/_regrid/_regrid_from_weights.py +++ b/regridding/_regrid/_regrid_from_weights.py @@ -9,13 +9,13 @@ def regrid_from_weights( - weights: np.ndarray, - shape_input: tuple[int, ...], - shape_output: tuple[int, ...], - values_input: np.ndarray, - values_output: None | np.ndarray = None, - axis_input: None | int | Sequence[int] = None, - axis_output: None | int | Sequence[int] = None, + weights: np.ndarray, + shape_input: tuple[int, ...], + shape_output: tuple[int, ...], + values_input: np.ndarray, + values_output: None | np.ndarray = None, + axis_input: None | int | Sequence[int] = None, + axis_output: None | int | Sequence[int] = None, ) -> np.ndarray: """ Regrid an array of values using weights computed by @@ -52,25 +52,6 @@ def regrid_from_weights( :func:`regridding.regrid_from_weights` """ - # pad coordinate shapes for broadcasting against values shape according to axis input - # print(f'{values_input.shape=}') - # padded_shape_input = [] - # padded_shape_output = [] - # for i in range(values_input.ndim): - # if i in axis_input: - # j = np.where(np.array(axis_input) == i)[0][0] - # padded_shape_input.append(shape_input[j]) - # padded_shape_output.append(shape_output[j]) - # else: - # padded_shape_input.append(1) - # padded_shape_output.append(1) - # - # print(f'{padded_shape_input=}') - # print(f'{padded_shape_output=}') - # - # shape_input = np.broadcast_shapes(padded_shape_input, values_input.shape) - # print(f'{shape_input=}') - # values_input = np.broadcast_to(values_input, shape=shape_input, subok=True) ndim_input = len(shape_input) axis_input = _util._normalize_axis(axis_input, ndim=ndim_input) @@ -91,7 +72,6 @@ def regrid_from_weights( ndim_output = len(shape_output) axis_output = _util._normalize_axis(axis_output, ndim=ndim_output) - print(f'{axis_output=}') axis_input_numba = ~np.arange(len(axis_input))[::-1] axis_output_numba = ~np.arange(len(axis_output))[::-1] @@ -112,9 +92,6 @@ def regrid_from_weights( values_input = np.ascontiguousarray(values_input) values_output = np.ascontiguousarray(values_output) - print(f'{values_input.shape=}') - print(f'{values_output.shape=}') - _regrid_from_weights( weights=weights, values_input=values_input, @@ -130,9 +107,9 @@ def regrid_from_weights( @numba.njit(parallel=True) def _regrid_from_weights( - weights: numba.typed.List, - values_input: np.ndarray, - values_output: np.ndarray, + weights: numba.typed.List, + values_input: np.ndarray, + values_output: np.ndarray, ) -> None: for d in numba.prange(len(weights)): From 4064e5cc21d94a874d2290af6bc0c1ca876a1759 Mon Sep 17 00:00:00 2001 From: jacobdparker Date: Mon, 15 Apr 2024 12:59:00 -0400 Subject: [PATCH 08/15] Revert "Cleaning up commented code and print statements. Running black formatter." This reverts commit 8fc2587822649b5a1e28f1b4082235e46ce3bd37. --- regridding/_conservative_ramshaw.py | 483 +++++++++------------ regridding/_regrid/_regrid_from_weights.py | 43 +- 2 files changed, 234 insertions(+), 292 deletions(-) diff --git a/regridding/_conservative_ramshaw.py b/regridding/_conservative_ramshaw.py index 6ea7f8c..c19a2a8 100644 --- a/regridding/_conservative_ramshaw.py +++ b/regridding/_conservative_ramshaw.py @@ -2,7 +2,6 @@ import math import numpy as np import numba - # import matplotlib.pyplot as plt __all__ = [] @@ -16,18 +15,22 @@ # cache=True, ) def _conservative_ramshaw( - grid_input: tuple[np.ndarray, np.ndarray], - grid_output: tuple[np.ndarray, np.ndarray], - epsilon: float = 1e-10, + # values_input: np.ndarray, + # values_output: np.ndarray, + grid_input: tuple[np.ndarray, np.ndarray], + grid_output: tuple[np.ndarray, np.ndarray], + epsilon: float = 1e-10, ) -> tuple[np.ndarray, np.ndarray, np.ndarray]: weights = numba.typed.List() for x in range(0): - weights.append((0.0, 0.0, 0.0)) + weights.append((0., 0., 0.)) input_x, input_y = grid_input + # output_x, output_y = grid_output shape_input = input_x.shape + # shape_output = np.broadcast_shapes(output_x.shape, output_y.shape) axes = 0, 1 @@ -70,6 +73,8 @@ def _conservative_ramshaw( grid_sweep_x, grid_sweep_y = grid_output for axis in axes: _sweep_axis( + # values_input=values_input, + # values_output=values_output, area_input=area_input, grid_sweep_x=grid_sweep_x, grid_sweep_y=grid_sweep_y, @@ -87,15 +92,17 @@ def _conservative_ramshaw( @numba.njit(error_model="numpy", parallel=True) def _sweep_axis( - area_input: np.ndarray, - grid_static_x: np.ndarray, - grid_static_y: np.ndarray, - grid_sweep_x: np.ndarray, - grid_sweep_y: np.ndarray, - axis: int, - grid_input: str, - epsilon: float, - weights: numba.typed.List, + # values_input: np.ndarray, + # values_output: np.ndarray, + area_input: np.ndarray, + grid_static_x: np.ndarray, + grid_static_y: np.ndarray, + grid_sweep_x: np.ndarray, + grid_sweep_y: np.ndarray, + axis: int, + grid_input: str, + epsilon: float, + weights: numba.typed.List, ) -> None: if grid_input == "static": @@ -103,9 +110,7 @@ def _sweep_axis( elif grid_input == "sweep": input_is_sweep = True else: - print( - f"The `grid_input` argument must have the value 'static' or 'sweep', got '{grid_input}'" - ) + print(f"The `grid_input` argument must have the value 'static' or 'sweep', got '{grid_input}'") # print(input_is_sweep) @@ -129,22 +134,18 @@ def _sweep_axis( edges_top = slice(None, 0, -1), ~0 edges_left = 0, slice(None, 0, -1) - edges_border_static_x = np.concatenate( - ( - grid_static_x[edges_bottom], - grid_static_x[edges_right], - grid_static_x[edges_top], - grid_static_x[edges_left], - ) - ) - edges_border_static_y = np.concatenate( - ( - grid_static_y[edges_bottom], - grid_static_y[edges_right], - grid_static_y[edges_top], - grid_static_y[edges_left], - ) - ) + edges_border_static_x = np.concatenate(( + grid_static_x[edges_bottom], + grid_static_x[edges_right], + grid_static_x[edges_top], + grid_static_x[edges_left], + )) + edges_border_static_y = np.concatenate(( + grid_static_y[edges_bottom], + grid_static_y[edges_right], + grid_static_y[edges_top], + grid_static_y[edges_left], + )) cells_bottom = slice(None), 0 cells_right = ~0, slice(None) @@ -154,49 +155,41 @@ def _sweep_axis( grid_static_m = np.arange(shape_static_x)[:, np.newaxis] grid_static_n = np.arange(shape_static_y)[np.newaxis, :] grid_static_m, grid_static_n = np.broadcast_arrays(grid_static_m, grid_static_n) - edges_border_static_m = np.concatenate( - ( - grid_static_m[edges_bottom], - grid_static_m[edges_right], - grid_static_m[edges_top], - grid_static_m[edges_left], - ) - ) - edges_border_static_n = np.concatenate( - ( - grid_static_n[edges_bottom], - grid_static_n[edges_right], - grid_static_n[edges_top], - grid_static_n[edges_left], - ) - ) + edges_border_static_m = np.concatenate(( + grid_static_m[edges_bottom], + grid_static_m[edges_right], + grid_static_m[edges_top], + grid_static_m[edges_left], + )) + edges_border_static_n = np.concatenate(( + grid_static_n[edges_bottom], + grid_static_n[edges_right], + grid_static_n[edges_top], + grid_static_n[edges_left], + )) cells_static_m = np.arange(shape_static_x - 1)[:, np.newaxis] cells_static_n = np.arange(shape_static_y - 1)[np.newaxis, :] cells_static_m, cells_static_n = np.broadcast_arrays(cells_static_m, cells_static_n) - cells_border_static_m = np.concatenate( - ( - cells_static_m[cells_bottom], - cells_static_m[cells_right], - cells_static_m[cells_top], - cells_static_m[cells_left], - ) - ) - cells_border_static_n = np.concatenate( - ( - cells_static_n[cells_bottom], - cells_static_n[cells_right], - cells_static_n[cells_top], - cells_static_n[cells_left], - ) - ) + cells_border_static_m = np.concatenate(( + cells_static_m[cells_bottom], + cells_static_m[cells_right], + cells_static_m[cells_top], + cells_static_m[cells_left], + )) + cells_border_static_n = np.concatenate(( + cells_static_n[cells_bottom], + cells_static_n[cells_right], + cells_static_n[cells_top], + cells_static_n[cells_left], + )) weight = numba.typed.List() for i in range(shape_sweep_x): w = numba.typed.List() for _ in range(0): - w.append((0.0, 0.0, 0.0)) + w.append((0., 0., 0.)) weight.append(w) for i in numba.prange(shape_sweep_x): @@ -210,11 +203,11 @@ def _sweep_axis( point_sweep_2y = grid_sweep_y[i, j + 1] if _point_is_inside_polygon( - vertices_x=edges_border_static_x, - vertices_y=edges_border_static_y, - point_x=point_sweep_1x, - point_y=point_sweep_1y, - epsilon=epsilon, + vertices_x=edges_border_static_x, + vertices_y=edges_border_static_y, + point_x=point_sweep_1x, + point_y=point_sweep_1y, + epsilon=epsilon, ): # print("initial point inside...") m, n = _indices_of_line_brute( @@ -254,14 +247,7 @@ def _sweep_axis( # plt.plot([point_sweep_1x, point_sweep_2x], [point_sweep_1y, point_sweep_2y], zorder=10) if not sweep_is_inside_static: - ( - point_sweep_2x, - point_sweep_2y, - j_new, - m_new, - n_new, - sweep_is_inside_static, - ) = _step_outside_static( + point_sweep_2x, point_sweep_2y, j_new, m_new, n_new, sweep_is_inside_static = _step_outside_static( # area_output=area_output, grid_static_x=grid_static_x, grid_static_y=grid_static_y, @@ -284,31 +270,29 @@ def _sweep_axis( ) else: - point_sweep_2x, point_sweep_2y, j_new, m_new, n_new = ( - _step_inside_static( - # values_input=values_input, - # values_output=values_output, - # area_output=area_output, - area_input=area_input, - grid_static_x=grid_static_x, - grid_static_y=grid_static_y, - shape_sweep_x=shape_sweep_x, - shape_sweep_y=shape_sweep_y, - point_sweep_1x=point_sweep_1x, - point_sweep_1y=point_sweep_1y, - point_sweep_2x=point_sweep_2x, - point_sweep_2y=point_sweep_2y, - axis=axis, - input_is_sweep=input_is_sweep, - epsilon=epsilon, - m_old=m_old, - n_old=n_old, - i=i, - j=j, - m=m, - n=n, - weight=weight[i], - ) + point_sweep_2x, point_sweep_2y, j_new, m_new, n_new = _step_inside_static( + # values_input=values_input, + # values_output=values_output, + # area_output=area_output, + area_input=area_input, + grid_static_x=grid_static_x, + grid_static_y=grid_static_y, + shape_sweep_x=shape_sweep_x, + shape_sweep_y=shape_sweep_y, + point_sweep_1x=point_sweep_1x, + point_sweep_1y=point_sweep_1y, + point_sweep_2x=point_sweep_2x, + point_sweep_2y=point_sweep_2y, + axis=axis, + input_is_sweep=input_is_sweep, + epsilon=epsilon, + m_old=m_old, + n_old=n_old, + i=i, + j=j, + m=m, + n=n, + weight=weight[i], ) # print("j_new", j_new) @@ -353,25 +337,26 @@ def _sweep_axis( @numba.njit(inline="always") def _step_outside_static( - # area_output: np.ndarray, - grid_static_x: np.ndarray, - grid_static_y: np.ndarray, - edges_border_static_m: np.ndarray, - edges_border_static_n: np.ndarray, - cells_border_static_m: np.ndarray, - cells_border_static_n: np.ndarray, - # shape_sweep_x: int, - # shape_sweep_y: int, - point_sweep_1x: float, - point_sweep_1y: float, - point_sweep_2x: float, - point_sweep_2y: float, - # input_is_sweep: bool, - epsilon: float, - # i: int, - j: int, - m: int, - n: int, + # area_output: np.ndarray, + grid_static_x: np.ndarray, + grid_static_y: np.ndarray, + edges_border_static_m: np.ndarray, + edges_border_static_n: np.ndarray, + cells_border_static_m: np.ndarray, + cells_border_static_n: np.ndarray, + # shape_sweep_x: int, + # shape_sweep_y: int, + point_sweep_1x: float, + point_sweep_1y: float, + point_sweep_2x: float, + point_sweep_2y: float, + # input_is_sweep: bool, + epsilon: float, + # i: int, + j: int, + m: int, + n: int, + ) -> tuple[float, float, int, int, int, bool]: # print("step outside") @@ -416,14 +401,10 @@ def _step_outside_static( # ) t, u = _two_line_segment_intersection_parameters( - x1=vertex_static_1x, - y1=vertex_static_1y, - x2=vertex_static_2x, - y2=vertex_static_2y, - x3=point_sweep_1x, - y3=point_sweep_1y, - x4=point_sweep_2x, - y4=point_sweep_2y, + x1=vertex_static_1x, y1=vertex_static_1y, + x2=vertex_static_2x, y2=vertex_static_2y, + x3=point_sweep_1x, y3=point_sweep_1y, + x4=point_sweep_2x, y4=point_sweep_2y, ) if u > u_min: @@ -438,20 +419,12 @@ def _step_outside_static( n_new = cells_border_static_n[index_vertex_1] if -epsilon < t < epsilon: - if ( - direction_sweep_x * direction_static_x - + direction_sweep_y * direction_static_y - < 0 - ): + if direction_sweep_x * direction_static_x + direction_sweep_y * direction_static_y < 0: m_new = m_new - direction_m n_new = n_new - direction_n elif (1 - epsilon) < t < (1 + epsilon): - if ( - direction_sweep_x * direction_static_x - + direction_sweep_y * direction_static_y - > 0 - ): + if direction_sweep_x * direction_static_x + direction_sweep_y * direction_static_y > 0: m_new = m_new + direction_m n_new = n_new + direction_n @@ -469,19 +442,11 @@ def _step_outside_static( elif math.isnan(u) or math.isnan(t): if point_sweep_1x != point_sweep_2x: - u1 = (vertex_static_1x - point_sweep_1x) / ( - point_sweep_2x - point_sweep_1x - ) - u2 = (vertex_static_2x - point_sweep_1x) / ( - point_sweep_2x - point_sweep_1x - ) + u1 = (vertex_static_1x - point_sweep_1x) / (point_sweep_2x - point_sweep_1x) + u2 = (vertex_static_2x - point_sweep_1x) / (point_sweep_2x - point_sweep_1x) else: - u1 = (vertex_static_1y - point_sweep_1y) / ( - point_sweep_2y - point_sweep_1y - ) - u2 = (vertex_static_2y - point_sweep_1y) / ( - point_sweep_2y - point_sweep_1y - ) + u1 = (vertex_static_1y - point_sweep_1y) / (point_sweep_2y - point_sweep_1y) + u2 = (vertex_static_2y - point_sweep_1y) / (point_sweep_2y - point_sweep_1y) if u1 > u_min: continue @@ -533,27 +498,27 @@ def _step_outside_static( @numba.njit(inline="always") def _step_inside_static( - # values_input: np.ndarray, - # values_output: np.ndarray, - area_input: np.ndarray, - grid_static_x: np.ndarray, - grid_static_y: np.ndarray, - shape_sweep_x: int, - shape_sweep_y: int, - point_sweep_1x: float, - point_sweep_1y: float, - point_sweep_2x: float, - point_sweep_2y: float, - axis: int, - input_is_sweep: bool, - epsilon: float, - m_old: int, - n_old: int, - i: int, - j: int, - m: int, - n: int, - weight: numba.typed.List, + # values_input: np.ndarray, + # values_output: np.ndarray, + area_input: np.ndarray, + grid_static_x: np.ndarray, + grid_static_y: np.ndarray, + shape_sweep_x: int, + shape_sweep_y: int, + point_sweep_1x: float, + point_sweep_1y: float, + point_sweep_2x: float, + point_sweep_2y: float, + axis: int, + input_is_sweep: bool, + epsilon: float, + m_old: int, + n_old: int, + i: int, + j: int, + m: int, + n: int, + weight: numba.typed.List, ) -> tuple[float, float, int, int, int]: # print("step inside") @@ -625,14 +590,10 @@ def _step_inside_static( # ) t, u = _two_line_segment_intersection_parameters( - x1=vertex_static_1x, - y1=vertex_static_1y, - x2=vertex_static_2x, - y2=vertex_static_2y, - x3=point_sweep_1x, - y3=point_sweep_1y, - x4=point_sweep_2x, - y4=point_sweep_2y, + x1=vertex_static_1x, y1=vertex_static_1y, + x2=vertex_static_2x, y2=vertex_static_2y, + x3=point_sweep_1x, y3=point_sweep_1y, + x4=point_sweep_2x, y4=point_sweep_2y, ) # print(t, u) @@ -693,19 +654,11 @@ def _step_inside_static( # print("parallel lines found") if point_sweep_1x != point_sweep_2x: - u1 = (vertex_static_1x - point_sweep_1x) / ( - point_sweep_2x - point_sweep_1x - ) - u2 = (vertex_static_2x - point_sweep_1x) / ( - point_sweep_2x - point_sweep_1x - ) + u1 = (vertex_static_1x - point_sweep_1x) / (point_sweep_2x - point_sweep_1x) + u2 = (vertex_static_2x - point_sweep_1x) / (point_sweep_2x - point_sweep_1x) else: - u1 = (vertex_static_1y - point_sweep_1y) / ( - point_sweep_2y - point_sweep_1y - ) - u2 = (vertex_static_2y - point_sweep_1y) / ( - point_sweep_2y - point_sweep_1y - ) + u1 = (vertex_static_1y - point_sweep_1y) / (point_sweep_2y - point_sweep_1y) + u2 = (vertex_static_2y - point_sweep_1y) / (point_sweep_2y - point_sweep_1y) # print("u1", u1) # print("u2", u2) @@ -734,7 +687,7 @@ def _step_inside_static( u_min = u2 min_is_coincident = True - # plt.scatter(point_sweep_2x, point_sweep_2y, zorder=10) + # plt.scatter(point_sweep_2x, point_sweep_2y, zorder=10) m_left = m m_right = m + normal_m @@ -753,10 +706,7 @@ def _step_inside_static( # color="orange" # ) - if ( - normal_sweep_x * normal_static_x + normal_sweep_y * normal_static_y - < 0 - ): + if normal_sweep_x * normal_static_x + normal_sweep_y * normal_static_y < 0: # print("switch") m_left, m_right = m_right, m_left n_left, n_right = n_right, n_left @@ -840,33 +790,21 @@ def _step_inside_static( area_sweep = (point_sweep_1x * point_sweep_2y - point_sweep_2x * point_sweep_1y) / 2 - if 0 <= i_input_left < (shape_input_x - 1) and 0 <= j_input_left < ( - shape_input_y - 1 - ): - if 0 <= i_output_left < (shape_output_x - 1) and 0 <= j_output_left < ( - shape_output_y - 1 - ): - weight.append( - ( - (shape_input_y - 1) * i_input_left + j_input_left, - (shape_output_y - 1) * i_output_left + j_output_left, - area_sweep / area_input[i_input_left, j_input_left], - ) - ) - - if 0 <= i_input_right < (shape_input_x - 1) and 0 <= j_input_right < ( - shape_input_y - 1 - ): - if 0 <= i_output_right < (shape_output_x - 1) and 0 <= j_output_right < ( - shape_output_y - 1 - ): - weight.append( - ( - (shape_input_y - 1) * i_input_right + j_input_right, - (shape_output_y - 1) * i_output_right + j_output_right, - -area_sweep / area_input[i_input_right, j_input_right], - ) - ) + if 0 <= i_input_left < (shape_input_x - 1) and 0 <= j_input_left < (shape_input_y - 1): + if 0 <= i_output_left < (shape_output_x - 1) and 0 <= j_output_left < (shape_output_y - 1): + weight.append(( + (shape_input_y - 1) * i_input_left + j_input_left, + (shape_output_y - 1) * i_output_left + j_output_left, + area_sweep / area_input[i_input_left, j_input_left], + )) + + if 0 <= i_input_right < (shape_input_x - 1) and 0 <= j_input_right < (shape_input_y - 1): + if 0 <= i_output_right < (shape_output_x - 1) and 0 <= j_output_right < (shape_output_y - 1): + weight.append(( + (shape_input_y - 1) * i_input_right + j_input_right, + (shape_output_y - 1) * i_output_right + j_output_right, + -area_sweep / area_input[i_input_right, j_input_right], + )) # if 0 <= i_input_left < (shape_input_x - 1) and 0 <= j_input_left < (shape_input_y - 1): # value_input_left = values_input[i_input_left, j_input_left] @@ -898,10 +836,10 @@ def _step_inside_static( @numba.njit(inline="always") def _grid_area_sweep( - out: np.ndarray, - grid_x: np.ndarray, - grid_y: np.ndarray, - axis: int, + out: np.ndarray, + grid_x: np.ndarray, + grid_y: np.ndarray, + axis: int, ): if axis == 0: @@ -943,13 +881,13 @@ def _grid_area_sweep( @numba.njit(inline="always", error_model="numpy") def _indices_of_line_brute( - grid_x: np.ndarray, - grid_y: np.ndarray, - point_1x: float, - point_1y: float, - point_2x: float, - point_2y: float, - epsilon: float, + grid_x: np.ndarray, + grid_y: np.ndarray, + point_1x: float, + point_1y: float, + point_2x: float, + point_2y: float, + epsilon: float, ) -> tuple[int, int]: shape_x, shape_y = grid_x.shape @@ -996,14 +934,10 @@ def _indices_of_line_brute( vertex_2y = vertices_y[index_vertex_2] t, u = _two_line_segment_intersection_parameters( - x1=vertex_1x, - y1=vertex_1y, - x2=vertex_2x, - y2=vertex_2y, - x3=point_1x, - y3=point_1y, - x4=point_2x, - y4=point_2y, + x1=vertex_1x, y1=vertex_1y, + x2=vertex_2x, y2=vertex_2y, + x3=point_1x, y3=point_1y, + x4=point_2x, y4=point_2y, ) # print(t, u) @@ -1028,13 +962,9 @@ def _indices_of_line_brute( projection_1y = normal_y * (vertex_2y - vertex_1y) projection_0 = projection_0x + projection_0y projection_1 = projection_1x + projection_1y - if (-epsilon < projection_0 < epsilon) or ( - -epsilon < projection_1 < epsilon - ): + if (-epsilon < projection_0 < epsilon) or (-epsilon < projection_1 < epsilon): pass - elif math.copysign(1, projection_0) == math.copysign( - 1, projection_1 - ): + elif math.copysign(1, projection_0) == math.copysign(1, projection_1): # print("projection_0 and projection_1 have the same sign") num_intersections -= 1 @@ -1048,11 +978,11 @@ def _indices_of_line_brute( @numba.njit(inline="always", error_model="numpy") def _point_is_inside_polygon( - vertices_x: np.ndarray, - vertices_y: np.ndarray, - point_x: float, - point_y: float, - epsilon: float, + vertices_x: np.ndarray, + vertices_y: np.ndarray, + point_x: float, + point_y: float, + epsilon: float ) -> bool: x3 = point_x @@ -1096,7 +1026,7 @@ def _point_is_inside_polygon( result = not result if y1_is_zero: y0 = vertices_y[v - 2] - point_y - if (-epsilon < y0 < epsilon) or (-epsilon < y2 < epsilon): + if (-epsilon < y0 < epsilon) or (-epsilon < y2 = point_y) != (y0 >= point_y) # condition_2 = point_x < ((point_y - y1) / slope + x1) @@ -1145,14 +1072,10 @@ def _point_is_inside_polygon( @numba.njit(inline="always", error_model="numpy") def _two_line_segment_intersection( - x1: float, - y1: float, - x2: float, - y2: float, - x3: float, - y3: float, - x4: float, - y4: float, + x1: float, y1: float, + x2: float, y2: float, + x3: float, y3: float, + x4: float, y4: float, ) -> tuple[float, float]: t_numerator = (x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4) @@ -1175,14 +1098,10 @@ def _two_line_segment_intersection( @numba.njit(inline="always", error_model="numpy") def _two_line_segment_intersection_parameters( - x1: float, - y1: float, - x2: float, - y2: float, - x3: float, - y3: float, - x4: float, - y4: float, + x1: float, y1: float, + x2: float, y2: float, + x3: float, y3: float, + x4: float, y4: float, ) -> tuple[float, float]: t_numerator = (x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4) diff --git a/regridding/_regrid/_regrid_from_weights.py b/regridding/_regrid/_regrid_from_weights.py index 75501f8..927fe7c 100644 --- a/regridding/_regrid/_regrid_from_weights.py +++ b/regridding/_regrid/_regrid_from_weights.py @@ -9,13 +9,13 @@ def regrid_from_weights( - weights: np.ndarray, - shape_input: tuple[int, ...], - shape_output: tuple[int, ...], - values_input: np.ndarray, - values_output: None | np.ndarray = None, - axis_input: None | int | Sequence[int] = None, - axis_output: None | int | Sequence[int] = None, + weights: np.ndarray, + shape_input: tuple[int, ...], + shape_output: tuple[int, ...], + values_input: np.ndarray, + values_output: None | np.ndarray = None, + axis_input: None | int | Sequence[int] = None, + axis_output: None | int | Sequence[int] = None, ) -> np.ndarray: """ Regrid an array of values using weights computed by @@ -52,6 +52,25 @@ def regrid_from_weights( :func:`regridding.regrid_from_weights` """ + # pad coordinate shapes for broadcasting against values shape according to axis input + # print(f'{values_input.shape=}') + # padded_shape_input = [] + # padded_shape_output = [] + # for i in range(values_input.ndim): + # if i in axis_input: + # j = np.where(np.array(axis_input) == i)[0][0] + # padded_shape_input.append(shape_input[j]) + # padded_shape_output.append(shape_output[j]) + # else: + # padded_shape_input.append(1) + # padded_shape_output.append(1) + # + # print(f'{padded_shape_input=}') + # print(f'{padded_shape_output=}') + # + # shape_input = np.broadcast_shapes(padded_shape_input, values_input.shape) + # print(f'{shape_input=}') + # values_input = np.broadcast_to(values_input, shape=shape_input, subok=True) ndim_input = len(shape_input) axis_input = _util._normalize_axis(axis_input, ndim=ndim_input) @@ -72,6 +91,7 @@ def regrid_from_weights( ndim_output = len(shape_output) axis_output = _util._normalize_axis(axis_output, ndim=ndim_output) + print(f'{axis_output=}') axis_input_numba = ~np.arange(len(axis_input))[::-1] axis_output_numba = ~np.arange(len(axis_output))[::-1] @@ -92,6 +112,9 @@ def regrid_from_weights( values_input = np.ascontiguousarray(values_input) values_output = np.ascontiguousarray(values_output) + print(f'{values_input.shape=}') + print(f'{values_output.shape=}') + _regrid_from_weights( weights=weights, values_input=values_input, @@ -107,9 +130,9 @@ def regrid_from_weights( @numba.njit(parallel=True) def _regrid_from_weights( - weights: numba.typed.List, - values_input: np.ndarray, - values_output: np.ndarray, + weights: numba.typed.List, + values_input: np.ndarray, + values_output: np.ndarray, ) -> None: for d in numba.prange(len(weights)): From 399a23b81bcde4bbec3463f671dff73b24890c4c Mon Sep 17 00:00:00 2001 From: jacobdparker Date: Mon, 15 Apr 2024 14:20:46 -0400 Subject: [PATCH 09/15] Undoing strange black reformatting --- regridding/_conservative_ramshaw.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/regridding/_conservative_ramshaw.py b/regridding/_conservative_ramshaw.py index c19a2a8..62c7cdb 100644 --- a/regridding/_conservative_ramshaw.py +++ b/regridding/_conservative_ramshaw.py @@ -15,8 +15,6 @@ # cache=True, ) def _conservative_ramshaw( - # values_input: np.ndarray, - # values_output: np.ndarray, grid_input: tuple[np.ndarray, np.ndarray], grid_output: tuple[np.ndarray, np.ndarray], epsilon: float = 1e-10, @@ -27,10 +25,8 @@ def _conservative_ramshaw( weights.append((0., 0., 0.)) input_x, input_y = grid_input - # output_x, output_y = grid_output shape_input = input_x.shape - # shape_output = np.broadcast_shapes(output_x.shape, output_y.shape) axes = 0, 1 From 8934c2ced2a9874c43a711967d891dff353b30eb Mon Sep 17 00:00:00 2001 From: jacobdparker Date: Mon, 15 Apr 2024 14:55:11 -0400 Subject: [PATCH 10/15] formatting update --- regridding/_regrid/_regrid_from_weights.py | 24 +++++++++------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/regridding/_regrid/_regrid_from_weights.py b/regridding/_regrid/_regrid_from_weights.py index 927fe7c..558830c 100644 --- a/regridding/_regrid/_regrid_from_weights.py +++ b/regridding/_regrid/_regrid_from_weights.py @@ -9,13 +9,13 @@ def regrid_from_weights( - weights: np.ndarray, - shape_input: tuple[int, ...], - shape_output: tuple[int, ...], - values_input: np.ndarray, - values_output: None | np.ndarray = None, - axis_input: None | int | Sequence[int] = None, - axis_output: None | int | Sequence[int] = None, + weights: np.ndarray, + shape_input: tuple[int, ...], + shape_output: tuple[int, ...], + values_input: np.ndarray, + values_output: None | np.ndarray = None, + axis_input: None | int | Sequence[int] = None, + axis_output: None | int | Sequence[int] = None, ) -> np.ndarray: """ Regrid an array of values using weights computed by @@ -91,7 +91,6 @@ def regrid_from_weights( ndim_output = len(shape_output) axis_output = _util._normalize_axis(axis_output, ndim=ndim_output) - print(f'{axis_output=}') axis_input_numba = ~np.arange(len(axis_input))[::-1] axis_output_numba = ~np.arange(len(axis_output))[::-1] @@ -112,9 +111,6 @@ def regrid_from_weights( values_input = np.ascontiguousarray(values_input) values_output = np.ascontiguousarray(values_output) - print(f'{values_input.shape=}') - print(f'{values_output.shape=}') - _regrid_from_weights( weights=weights, values_input=values_input, @@ -130,9 +126,9 @@ def regrid_from_weights( @numba.njit(parallel=True) def _regrid_from_weights( - weights: numba.typed.List, - values_input: np.ndarray, - values_output: np.ndarray, + weights: numba.typed.List, + values_input: np.ndarray, + values_output: np.ndarray, ) -> None: for d in numba.prange(len(weights)): From 330633f0f2c6612f9abaffdf6d0ebda5784f8ac9 Mon Sep 17 00:00:00 2001 From: jacobdparker Date: Thu, 23 May 2024 12:28:26 -0400 Subject: [PATCH 11/15] Adding additional tests that test broadcasting within regrid. Bug fixes to broadcasting in regrid_from_weights. --- regridding/_regrid/_regrid_from_weights.py | 25 ++---- regridding/_regrid/_tests/test_regrid.py | 91 +++++++++++++++++----- 2 files changed, 77 insertions(+), 39 deletions(-) diff --git a/regridding/_regrid/_regrid_from_weights.py b/regridding/_regrid/_regrid_from_weights.py index 558830c..4165d5a 100644 --- a/regridding/_regrid/_regrid_from_weights.py +++ b/regridding/_regrid/_regrid_from_weights.py @@ -52,28 +52,15 @@ def regrid_from_weights( :func:`regridding.regrid_from_weights` """ - # pad coordinate shapes for broadcasting against values shape according to axis input - # print(f'{values_input.shape=}') - # padded_shape_input = [] - # padded_shape_output = [] - # for i in range(values_input.ndim): - # if i in axis_input: - # j = np.where(np.array(axis_input) == i)[0][0] - # padded_shape_input.append(shape_input[j]) - # padded_shape_output.append(shape_output[j]) - # else: - # padded_shape_input.append(1) - # padded_shape_output.append(1) - # - # print(f'{padded_shape_input=}') - # print(f'{padded_shape_output=}') - # - # shape_input = np.broadcast_shapes(padded_shape_input, values_input.shape) - # print(f'{shape_input=}') - # values_input = np.broadcast_to(values_input, shape=shape_input, subok=True) + shape_input = np.broadcast_shapes(values_input.shape, shape_input) + ndim_input = len(shape_input) axis_input = _util._normalize_axis(axis_input, ndim=ndim_input) + shape_orthogonal = (1 if i in axis_input else shape_input[i] for i in range(-len(shape_input), 0)) + weights = np.broadcast_to(np.array(weights), shape_orthogonal) + values_input = np.broadcast_to(values_input, shape_input) + if values_output is None: shape_output = np.broadcast_shapes( shape_output, diff --git a/regridding/_regrid/_tests/test_regrid.py b/regridding/_regrid/_tests/test_regrid.py index e412c71..5ee542c 100644 --- a/regridding/_regrid/_tests/test_regrid.py +++ b/regridding/_regrid/_tests/test_regrid.py @@ -2,6 +2,29 @@ import numpy as np import regridding +x = np.linspace(-1, 1, num=10) +y = np.linspace(-1, 1, num=11) +x_broadcasted, y_broadcasted = np.meshgrid( + x, + y, + indexing="ij", +) + +new_y = np.linspace(-1, 1, num=5) +new_x = np.linspace(-1, 1, num=6) + +new_x_broadcasted, new_y_broadcasted = np.meshgrid( + x, + new_y, + indexing="ij", +) + +new_x_broadcasted_2, new_y_broadcasted_2 = np.meshgrid( + new_x, + y, + indexing="ij", +) + @pytest.mark.parametrize( # add two cases (coords broadcast against values, and vice versa) @@ -25,6 +48,33 @@ None, np.square(np.linspace(-1, 1, num=11)), ), + ( + (y,), + (new_y,), + x_broadcasted + y_broadcasted, + None, + (~0,), + (~0,), + new_x_broadcasted + new_y_broadcasted, + ), + ( + (x[..., np.newaxis],), + (new_x[..., np.newaxis],), + x_broadcasted + y_broadcasted, + None, + (0,), + (0,), + new_x_broadcasted_2 + new_y_broadcasted_2, + ), + ( + (x[..., np.newaxis],), + (0.1 * new_x[..., np.newaxis] + 0.001 * new_y,), + x[..., np.newaxis], + None, + (0,), + (0,), + 0.1 * new_x[..., np.newaxis] + 0.001 * new_y, + ), ], ) def test_regrid_multilinear_1d( @@ -47,35 +97,28 @@ def test_regrid_multilinear_1d( ) assert isinstance(result, np.ndarray) assert np.issubdtype(result.dtype, float) - assert np.all(result == result_expected) + assert np.allclose(result, result_expected) @pytest.mark.parametrize( - argnames="coordinates_input, values_input, axis_input", + argnames="coordinates_input, values_input, axis_input, coordinates_output, values_output, axis_output", argvalues=[ ( - np.meshgrid( - np.linspace(-1, 1, num=10), - np.linspace(-1, 1, num=11), - indexing="ij", - ), + (x_broadcasted,y_broadcasted), np.random.normal(size=(10 - 1, 11 - 1)), None, + (1.1* x_broadcasted + 0.01, 1.2 * y_broadcasted + 0.01), + None, + None, ), - ], -) -@pytest.mark.parametrize( - argnames="coordinates_output, values_output, axis_output", - argvalues=[ ( - np.meshgrid( - 1.1 * np.linspace(-1, 1, num=10) + 0.001, - 1.2 * np.linspace(-1, 1, num=11) + 0.001, - indexing="ij", - ), - None, + (x_broadcasted[...,np.newaxis] + np.array([0,.001]),y_broadcasted[...,np.newaxis] + np.array([0,.001])), + np.random.normal(size=(x.shape[0] - 1, y.shape[0] - 1, 2)), + (0, 1), + (1.1*(x_broadcasted[...,np.newaxis] + np.array([0,.001]))+.01,1.2*(y_broadcasted[...,np.newaxis] + np.array([0,.01]))+.001), None, - ) + (0, 1), + ), ], ) def test_regrid_conservative_2d( @@ -96,6 +139,14 @@ def test_regrid_conservative_2d( method="conservative", ) + result_shape = np.array(np.broadcast(*coordinates_output).shape) + + if axis_input is None: + result_shape = result_shape - 1 + else: + for ax in axis_input: + result_shape[ax] = result_shape[ax]-1 + assert np.issubdtype(result.dtype, float) - assert result.shape == tuple(np.array(np.broadcast(*coordinates_output).shape) - 1) + assert result.shape == tuple(result_shape) assert np.isclose(result.sum(), values_input.sum()) From a6c2bc628b488222bc2a2b78562ddb32cf26912c Mon Sep 17 00:00:00 2001 From: jacobdparker Date: Thu, 23 May 2024 17:04:34 -0400 Subject: [PATCH 12/15] Addressing comments in pull request --- regridding/_conservative_ramshaw.py | 4 ---- regridding/_regrid/_regrid_from_weights.py | 1 - 2 files changed, 5 deletions(-) diff --git a/regridding/_conservative_ramshaw.py b/regridding/_conservative_ramshaw.py index 62c7cdb..767c6f2 100644 --- a/regridding/_conservative_ramshaw.py +++ b/regridding/_conservative_ramshaw.py @@ -52,8 +52,6 @@ def _conservative_ramshaw( grid_sweep_x, grid_sweep_y = grid_input for axis in axes: _sweep_axis( - # values_input=values_input, - # values_output=values_output, area_input=area_input, grid_sweep_x=grid_sweep_x, grid_sweep_y=grid_sweep_y, @@ -69,8 +67,6 @@ def _conservative_ramshaw( grid_sweep_x, grid_sweep_y = grid_output for axis in axes: _sweep_axis( - # values_input=values_input, - # values_output=values_output, area_input=area_input, grid_sweep_x=grid_sweep_x, grid_sweep_y=grid_sweep_y, diff --git a/regridding/_regrid/_regrid_from_weights.py b/regridding/_regrid/_regrid_from_weights.py index 4165d5a..cc01aa2 100644 --- a/regridding/_regrid/_regrid_from_weights.py +++ b/regridding/_regrid/_regrid_from_weights.py @@ -70,7 +70,6 @@ def regrid_from_weights( ), ) values_output = np.zeros_like(values_input, shape=shape_output) - else: if values_output.shape != shape_output: raise ValueError(f"") From f4614d6282cd499e09a470cf41f0408c361ef3ae Mon Sep 17 00:00:00 2001 From: jacobdparker Date: Thu, 23 May 2024 17:22:15 -0400 Subject: [PATCH 13/15] Reformating with black --- regridding/_regrid/_regrid_from_weights.py | 4 +++- regridding/_regrid/_tests/test_regrid.py | 17 +++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/regridding/_regrid/_regrid_from_weights.py b/regridding/_regrid/_regrid_from_weights.py index cc01aa2..73236f3 100644 --- a/regridding/_regrid/_regrid_from_weights.py +++ b/regridding/_regrid/_regrid_from_weights.py @@ -57,7 +57,9 @@ def regrid_from_weights( ndim_input = len(shape_input) axis_input = _util._normalize_axis(axis_input, ndim=ndim_input) - shape_orthogonal = (1 if i in axis_input else shape_input[i] for i in range(-len(shape_input), 0)) + shape_orthogonal = ( + 1 if i in axis_input else shape_input[i] for i in range(-len(shape_input), 0) + ) weights = np.broadcast_to(np.array(weights), shape_orthogonal) values_input = np.broadcast_to(values_input, shape_input) diff --git a/regridding/_regrid/_tests/test_regrid.py b/regridding/_regrid/_tests/test_regrid.py index 5ee542c..2bc846d 100644 --- a/regridding/_regrid/_tests/test_regrid.py +++ b/regridding/_regrid/_tests/test_regrid.py @@ -27,7 +27,6 @@ @pytest.mark.parametrize( - # add two cases (coords broadcast against values, and vice versa) argnames="coordinates_input,coordinates_output,values_input,values_output,axis_input,axis_output,result_expected", argvalues=[ ( @@ -104,18 +103,24 @@ def test_regrid_multilinear_1d( argnames="coordinates_input, values_input, axis_input, coordinates_output, values_output, axis_output", argvalues=[ ( - (x_broadcasted,y_broadcasted), + (x_broadcasted, y_broadcasted), np.random.normal(size=(10 - 1, 11 - 1)), None, - (1.1* x_broadcasted + 0.01, 1.2 * y_broadcasted + 0.01), + (1.1 * x_broadcasted + 0.01, 1.2 * y_broadcasted + 0.01), None, None, ), ( - (x_broadcasted[...,np.newaxis] + np.array([0,.001]),y_broadcasted[...,np.newaxis] + np.array([0,.001])), + ( + x_broadcasted[..., np.newaxis] + np.array([0, 0.001]), + y_broadcasted[..., np.newaxis] + np.array([0, 0.001]), + ), np.random.normal(size=(x.shape[0] - 1, y.shape[0] - 1, 2)), (0, 1), - (1.1*(x_broadcasted[...,np.newaxis] + np.array([0,.001]))+.01,1.2*(y_broadcasted[...,np.newaxis] + np.array([0,.01]))+.001), + ( + 1.1 * (x_broadcasted[..., np.newaxis] + np.array([0, 0.001])) + 0.01, + 1.2 * (y_broadcasted[..., np.newaxis] + np.array([0, 0.01])) + 0.001, + ), None, (0, 1), ), @@ -145,7 +150,7 @@ def test_regrid_conservative_2d( result_shape = result_shape - 1 else: for ax in axis_input: - result_shape[ax] = result_shape[ax]-1 + result_shape[ax] = result_shape[ax] - 1 assert np.issubdtype(result.dtype, float) assert result.shape == tuple(result_shape) From b454d2731490c3edd9c56516a62cd04dee3a1561 Mon Sep 17 00:00:00 2001 From: jacobdparker Date: Fri, 24 May 2024 08:58:33 -0400 Subject: [PATCH 14/15] adding subok=True to broadcast shapes --- regridding/_regrid/_regrid_from_weights.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/regridding/_regrid/_regrid_from_weights.py b/regridding/_regrid/_regrid_from_weights.py index 73236f3..54935dc 100644 --- a/regridding/_regrid/_regrid_from_weights.py +++ b/regridding/_regrid/_regrid_from_weights.py @@ -52,7 +52,7 @@ def regrid_from_weights( :func:`regridding.regrid_from_weights` """ - shape_input = np.broadcast_shapes(values_input.shape, shape_input) + shape_input = np.broadcast_shapes(values_input.shape, shape_input, subok=True) ndim_input = len(shape_input) axis_input = _util._normalize_axis(axis_input, ndim=ndim_input) From dc3b6f0f9d4896b9535206ad6fdf59eac83b7bd7 Mon Sep 17 00:00:00 2001 From: jacobdparker Date: Fri, 24 May 2024 09:14:24 -0400 Subject: [PATCH 15/15] correcting mistake of adding subok keyword to broadcast shapes instead of broadcast_to --- regridding/_regrid/_regrid_from_weights.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/regridding/_regrid/_regrid_from_weights.py b/regridding/_regrid/_regrid_from_weights.py index 54935dc..86f788a 100644 --- a/regridding/_regrid/_regrid_from_weights.py +++ b/regridding/_regrid/_regrid_from_weights.py @@ -52,7 +52,7 @@ def regrid_from_weights( :func:`regridding.regrid_from_weights` """ - shape_input = np.broadcast_shapes(values_input.shape, shape_input, subok=True) + shape_input = np.broadcast_shapes(values_input.shape, shape_input) ndim_input = len(shape_input) axis_input = _util._normalize_axis(axis_input, ndim=ndim_input) @@ -60,8 +60,8 @@ def regrid_from_weights( shape_orthogonal = ( 1 if i in axis_input else shape_input[i] for i in range(-len(shape_input), 0) ) - weights = np.broadcast_to(np.array(weights), shape_orthogonal) - values_input = np.broadcast_to(values_input, shape_input) + weights = np.broadcast_to(np.array(weights), shape_orthogonal, subok=True) + values_input = np.broadcast_to(values_input, shape_input, subok=True) if values_output is None: shape_output = np.broadcast_shapes(