From aaf5f998c149ed93dad8e07951c9e58c3abc8f0b Mon Sep 17 00:00:00 2001 From: DominikaDlugosz Date: Wed, 5 Jun 2024 11:44:39 +0200 Subject: [PATCH 01/15] Prepare (rescale, select, and reshape) weights for ilp unwrapping --- kamui/core.py | 6 ++++++ kamui/utils.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/kamui/core.py b/kamui/core.py index f697ae6..f34b1a2 100644 --- a/kamui/core.py +++ b/kamui/core.py @@ -4,6 +4,9 @@ import numpy as np from typing import Optional, Iterable +from .utils import prepare_weights + + try: import maxflow except ImportError: @@ -101,6 +104,7 @@ def calculate_k( else: c = np.ones((M * 2,), dtype=np.int64) else: + weights = prepare_weights(weights, edges=edges) c = np.tile(weights, 2) res = linprog(c, A_eq=A_eq, b_eq=b_eq, integrality=1) @@ -144,6 +148,8 @@ def calculate_m( ) if weights is None: weights = np.ones((M,), dtype=np.int64) + else: + weights = prepare_weights(weights, edges=edges) c = np.concatenate((np.zeros(N, dtype=np.int64), weights, weights)) diff --git a/kamui/utils.py b/kamui/utils.py index b590b14..84e7e36 100644 --- a/kamui/utils.py +++ b/kamui/utils.py @@ -1,4 +1,5 @@ import numpy as np +import numpy.typing as npt from typing import Tuple, Optional, Iterable, Union __all__ = ["get_2d_edges_and_simplices", "get_3d_edges_and_simplices"] @@ -194,3 +195,44 @@ def get_3d_edges_and_simplices( ).tolist() return edges, simplices + + +def prepare_weights(weights: npt.NDArray, edges: npt.NDArray[np.int_], smoothing: float = 0.1 + ) -> npt.NDArray[np.float_]: + """Prepare weights for `calculate_m` and `calculate_k` functions. + + Assume the weights are the same shape as the phases to be unwrapped. + + Scale the weights from 0 to 1. Pick the weights corresponding to the phase pairs connected by the edges. + Compute the mean of each of those pair to give a weight for each edge. + + Args: + weights : Array of weights of shapr corresponding to the original phases array shape. + edges : Edges connecting the phases. Shape: (N, 2), where N is the number of edges. + smoothing : A positive value between 0 (inclusive) and 1 (not inclusive). This is the minimal value + of the rescaled weights where they are defined. If smoothing > 0, the value of 0 is reserved + for places where the weights are originally NaN. If smoothing == 0, 0 will be used for both + NaN weights and smallest non-NaN ones. + + Returns: + Array of weights for the edges, shape: (N,). Rescaled to (0, 1). + """ + + if not 0 <= smoothing < 1: + raise ValueError( + "`smoothing` should be a value between 0 (inclusive) and 1 (non inclusive); got " + str(smoothing)) + + # scale the weights from 0 to 1 + weights = weights - np.nanmin(weights) + weights /= np.nanmax(weights) + weights *= (1 - smoothing) + weights += smoothing + + # pick the weights corresponding to the phases connected by the edges + # and compute means to get one weight for each edge + weights_for_edges = np.mean(weights.ravel()[edges], axis=1) + + # make sure there are no NaNs in the weights; replace any with 0s + weights_for_edges[np.isnan(weights_for_edges)] = 0 + + return weights_for_edges From 13af36c0a3a27ffbf30160321363d09ad542fdd9 Mon Sep 17 00:00:00 2001 From: DominikaDlugosz Date: Wed, 5 Jun 2024 12:13:48 +0200 Subject: [PATCH 02/15] Methods for merging phase weights into edge weights: mean/max/min --- kamui/core.py | 8 ++++++-- kamui/utils.py | 27 ++++++++++++++++----------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/kamui/core.py b/kamui/core.py index f34b1a2..7308dd8 100644 --- a/kamui/core.py +++ b/kamui/core.py @@ -43,6 +43,7 @@ def calculate_k( differences: np.ndarray, weights: Optional[np.ndarray] = None, adaptive_weighting: bool = True, + merging_method: str = 'mean' ) -> Optional[np.ndarray]: """ Args: @@ -51,6 +52,7 @@ def calculate_k( differences: (M,) array of differences, could be float or int weights: (M,) array of weights adaptive_weighting: whether to use adaptive weighting + merging_method: how to combine phase weights to yield edge weight """ M, N = edges.shape[0], len(simplices) @@ -104,7 +106,7 @@ def calculate_k( else: c = np.ones((M * 2,), dtype=np.int64) else: - weights = prepare_weights(weights, edges=edges) + weights = prepare_weights(weights, edges=edges, merging_method=merging_method) c = np.tile(weights, 2) res = linprog(c, A_eq=A_eq, b_eq=b_eq, integrality=1) @@ -119,12 +121,14 @@ def calculate_m( edges: np.ndarray, differences: np.ndarray, weights: Optional[np.ndarray] = None, + merging_method: str = 'mean' ) -> Optional[np.ndarray]: """ Args: edges: (M, 2) array of edges differences: (M,) quantised array of differences, must be int weights: (M,) array of weights + merging_method: how to combine phase weights to yield edge weight """ assert differences.dtype == np.int64, "differences must be int" M = edges.shape[0] @@ -149,7 +153,7 @@ def calculate_m( if weights is None: weights = np.ones((M,), dtype=np.int64) else: - weights = prepare_weights(weights, edges=edges) + weights = prepare_weights(weights, edges=edges, merging_method=merging_method) c = np.concatenate((np.zeros(N, dtype=np.int64), weights, weights)) diff --git a/kamui/utils.py b/kamui/utils.py index 84e7e36..752c58c 100644 --- a/kamui/utils.py +++ b/kamui/utils.py @@ -197,22 +197,23 @@ def get_3d_edges_and_simplices( return edges, simplices -def prepare_weights(weights: npt.NDArray, edges: npt.NDArray[np.int_], smoothing: float = 0.1 - ) -> npt.NDArray[np.float_]: +def prepare_weights(weights: npt.NDArray, edges: npt.NDArray[np.int_], smoothing: float = 0.1, + merging_method: str = 'mean') -> npt.NDArray[np.float_]: """Prepare weights for `calculate_m` and `calculate_k` functions. Assume the weights are the same shape as the phases to be unwrapped. Scale the weights from 0 to 1. Pick the weights corresponding to the phase pairs connected by the edges. - Compute the mean of each of those pair to give a weight for each edge. + Compute the mean/max/min (depending on the `merging_method`) of each of those pairs to give a weight for each edge. Args: - weights : Array of weights of shapr corresponding to the original phases array shape. - edges : Edges connecting the phases. Shape: (N, 2), where N is the number of edges. - smoothing : A positive value between 0 (inclusive) and 1 (not inclusive). This is the minimal value - of the rescaled weights where they are defined. If smoothing > 0, the value of 0 is reserved - for places where the weights are originally NaN. If smoothing == 0, 0 will be used for both - NaN weights and smallest non-NaN ones. + weights : Array of weights of shapr corresponding to the original phases array shape. + edges : Edges connecting the phases. Shape: (N, 2), where N is the number of edges. + smoothing : A positive value between 0 (inclusive) and 1 (not inclusive). This is the minimal value + of the rescaled weights where they are defined. If smoothing > 0, the value of 0 is reserved + for places where the weights are originally NaN. If smoothing == 0, 0 will be used for both + NaN weights and smallest non-NaN ones. + merging_method : Way of combining two phase weights into a single edge weight. Returns: Array of weights for the edges, shape: (N,). Rescaled to (0, 1). @@ -229,8 +230,12 @@ def prepare_weights(weights: npt.NDArray, edges: npt.NDArray[np.int_], smoothing weights += smoothing # pick the weights corresponding to the phases connected by the edges - # and compute means to get one weight for each edge - weights_for_edges = np.mean(weights.ravel()[edges], axis=1) + # and use `merging_method` to get one weight for each edge + allowed_merging_methods = ['min', 'max', 'mean'] + if merging_method not in allowed_merging_methods: + raise ValueError( + "`merging_method` should be one of: " + ', '.join(merging_method) + '; got ' + str(merging_method)) + weights_for_edges = getattr(np, merging_method)(weights.ravel()[edges], axis=1) # make sure there are no NaNs in the weights; replace any with 0s weights_for_edges[np.isnan(weights_for_edges)] = 0 From 57f1e41e4e3d6382d2088ea17557bbc300c204d6 Mon Sep 17 00:00:00 2001 From: DominikaDlugosz Date: Fri, 7 Jun 2024 09:12:51 +0200 Subject: [PATCH 03/15] Fix for uniform weights --- kamui/utils.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/kamui/utils.py b/kamui/utils.py index 752c58c..b243c27 100644 --- a/kamui/utils.py +++ b/kamui/utils.py @@ -225,9 +225,14 @@ def prepare_weights(weights: npt.NDArray, edges: npt.NDArray[np.int_], smoothing # scale the weights from 0 to 1 weights = weights - np.nanmin(weights) - weights /= np.nanmax(weights) - weights *= (1 - smoothing) - weights += smoothing + current_max = np.nanmax(weights) + if not current_max: + # current maximum is 0, which means all weights originally had the same value, now 0; replace everything with 1 + weights += 1 + else: + weights /= current_max + weights *= (1 - smoothing) + weights += smoothing # pick the weights corresponding to the phases connected by the edges # and use `merging_method` to get one weight for each edge From 8087644fb473c2f9c62e5e1f4ab93af15f660e4d Mon Sep 17 00:00:00 2001 From: DominikaDlugosz Date: Fri, 7 Jun 2024 14:46:03 +0200 Subject: [PATCH 04/15] prepare_weights called in unwrap_dimensional --- kamui/__init__.py | 12 +++++++++--- kamui/core.py | 9 --------- kamui/utils.py | 4 ++-- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/kamui/__init__.py b/kamui/__init__.py index e832eff..a36a9d2 100644 --- a/kamui/__init__.py +++ b/kamui/__init__.py @@ -1,5 +1,5 @@ import numpy as np -from typing import Tuple, Optional, Iterable, Union +from typing import Tuple, Optional, Iterable, Union, Any from .core import * from .utils import * @@ -27,8 +27,9 @@ def unwrap_dimensional( start_pixel: Optional[Union[Tuple[int, int], Tuple[int, int, int]]] = None, use_edgelist: bool = False, cyclical_axis: Union[int, Tuple[int, int]] = (), - **kwargs, -) -> np.ndarray: + merging_method: str = 'mean', + **kwargs: Any, +) -> Optional[np.ndarray]: """ Unwrap the phase of a 2-D or 3-D array. @@ -45,6 +46,7 @@ def unwrap_dimensional( cyclical_axis : int or (int, int) The axis that is cyclical. Default to (). + merging_method : Way of combining two phase weights into a single edge weight. kwargs : dict Other arguments passed to `kamui.unwrap_arbitrary`. @@ -74,6 +76,10 @@ def unwrap_dimensional( raise ValueError("x must be 2D or 3D") psi = x.ravel() + weights = kwargs.pop('weights', None) + if weights is not None: + kwargs['weights'] = prepare_weights(weights, edges=edges, merging_method=merging_method) + result = unwrap_arbitrary( psi, edges, None if use_edgelist else simplices, start_i=start_i, **kwargs ) diff --git a/kamui/core.py b/kamui/core.py index 7308dd8..0b1109e 100644 --- a/kamui/core.py +++ b/kamui/core.py @@ -4,8 +4,6 @@ import numpy as np from typing import Optional, Iterable -from .utils import prepare_weights - try: import maxflow @@ -43,7 +41,6 @@ def calculate_k( differences: np.ndarray, weights: Optional[np.ndarray] = None, adaptive_weighting: bool = True, - merging_method: str = 'mean' ) -> Optional[np.ndarray]: """ Args: @@ -52,7 +49,6 @@ def calculate_k( differences: (M,) array of differences, could be float or int weights: (M,) array of weights adaptive_weighting: whether to use adaptive weighting - merging_method: how to combine phase weights to yield edge weight """ M, N = edges.shape[0], len(simplices) @@ -106,7 +102,6 @@ def calculate_k( else: c = np.ones((M * 2,), dtype=np.int64) else: - weights = prepare_weights(weights, edges=edges, merging_method=merging_method) c = np.tile(weights, 2) res = linprog(c, A_eq=A_eq, b_eq=b_eq, integrality=1) @@ -121,14 +116,12 @@ def calculate_m( edges: np.ndarray, differences: np.ndarray, weights: Optional[np.ndarray] = None, - merging_method: str = 'mean' ) -> Optional[np.ndarray]: """ Args: edges: (M, 2) array of edges differences: (M,) quantised array of differences, must be int weights: (M,) array of weights - merging_method: how to combine phase weights to yield edge weight """ assert differences.dtype == np.int64, "differences must be int" M = edges.shape[0] @@ -152,8 +145,6 @@ def calculate_m( ) if weights is None: weights = np.ones((M,), dtype=np.int64) - else: - weights = prepare_weights(weights, edges=edges, merging_method=merging_method) c = np.concatenate((np.zeros(N, dtype=np.int64), weights, weights)) diff --git a/kamui/utils.py b/kamui/utils.py index b243c27..aeb2e1c 100644 --- a/kamui/utils.py +++ b/kamui/utils.py @@ -1,8 +1,8 @@ import numpy as np import numpy.typing as npt -from typing import Tuple, Optional, Iterable, Union +from typing import Tuple, Iterable, Union -__all__ = ["get_2d_edges_and_simplices", "get_3d_edges_and_simplices"] +__all__ = ["get_2d_edges_and_simplices", "get_3d_edges_and_simplices", "prepare_weights"] def get_2d_edges_and_simplices( From 0dfa51b68f6654f2fe4a87cb37a70e4070bcf289 Mon Sep 17 00:00:00 2001 From: DominikaDlugosz Date: Fri, 7 Jun 2024 14:48:03 +0200 Subject: [PATCH 05/15] Docs fixes --- kamui/utils.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/kamui/utils.py b/kamui/utils.py index aeb2e1c..06314c9 100644 --- a/kamui/utils.py +++ b/kamui/utils.py @@ -208,15 +208,15 @@ def prepare_weights(weights: npt.NDArray, edges: npt.NDArray[np.int_], smoothing Args: weights : Array of weights of shapr corresponding to the original phases array shape. - edges : Edges connecting the phases. Shape: (N, 2), where N is the number of edges. - smoothing : A positive value between 0 (inclusive) and 1 (not inclusive). This is the minimal value - of the rescaled weights where they are defined. If smoothing > 0, the value of 0 is reserved - for places where the weights are originally NaN. If smoothing == 0, 0 will be used for both - NaN weights and smallest non-NaN ones. + edges : Edges connecting the phases. Shape: (M, 2), where M is the number of edges. + smoothing : A positive value in range [0, 1). This is the minimal value of the rescaled weights + where they are defined. If smoothing > 0, the value of 0 is reserved for places where + the weights are originally NaN. If smoothing == 0, 0 will be used for both NaN weights + and smallest non-NaN ones. merging_method : Way of combining two phase weights into a single edge weight. Returns: - Array of weights for the edges, shape: (N,). Rescaled to (0, 1). + Array of weights for the edges, shape: (M,). Rescaled to [0, 1]. """ if not 0 <= smoothing < 1: From 35230233d25008b1925bef2b26d17fe87a6a0a6f Mon Sep 17 00:00:00 2001 From: DominikaDlugosz Date: Mon, 15 Jul 2024 13:42:26 +0200 Subject: [PATCH 06/15] Made 'weights' and explicit argument --- kamui/__init__.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/kamui/__init__.py b/kamui/__init__.py index a36a9d2..6fcb1fb 100644 --- a/kamui/__init__.py +++ b/kamui/__init__.py @@ -28,6 +28,7 @@ def unwrap_dimensional( use_edgelist: bool = False, cyclical_axis: Union[int, Tuple[int, int]] = (), merging_method: str = 'mean', + weights: Optional[np.ndarray] = None, **kwargs: Any, ) -> Optional[np.ndarray]: """ @@ -46,6 +47,7 @@ def unwrap_dimensional( cyclical_axis : int or (int, int) The axis that is cyclical. Default to (). + weights : Weights defining the 'goodness' of value at each vertex. Shape must match the shape of x. merging_method : Way of combining two phase weights into a single edge weight. kwargs : dict Other arguments passed to `kamui.unwrap_arbitrary`. @@ -76,12 +78,12 @@ def unwrap_dimensional( raise ValueError("x must be 2D or 3D") psi = x.ravel() - weights = kwargs.pop('weights', None) if weights is not None: - kwargs['weights'] = prepare_weights(weights, edges=edges, merging_method=merging_method) + # convert per-vertex weights to per-edge weights + weights = prepare_weights(weights, edges=edges, merging_method=merging_method) result = unwrap_arbitrary( - psi, edges, None if use_edgelist else simplices, start_i=start_i, **kwargs + psi, edges, None if use_edgelist else simplices, start_i=start_i, weights=weights, **kwargs ) if result is None: return None @@ -96,6 +98,7 @@ def unwrap_arbitrary( method: str = "ilp", period: float = 2 * np.pi, start_i: int = 0, + weights: Optional[np.ndarray] = None, **kwargs, ) -> Optional[np.ndarray]: """ @@ -121,6 +124,7 @@ def unwrap_arbitrary( start_i : int The index of the reference vertex to start unwrapping. Default to 0. + weights : Array of weights for each of the edges. kwargs : dict Other arguments passed to the solver. @@ -130,6 +134,8 @@ def unwrap_arbitrary( The unwrapped phase of the same shape as psi. """ if method == "gc": + if weights is not None: + raise ValueError("PUMA method does not take in weights") m = puma(psi / period, edges, **kwargs) m -= m[start_i] result = m * period + psi @@ -140,7 +146,8 @@ def unwrap_arbitrary( np.round((psi[edges[:, 1]] - psi[edges[:, 0]]) / period).astype( np.int64 ), - **kwargs, + weights=weights, + **kwargs ) if m is None: return None @@ -148,7 +155,7 @@ def unwrap_arbitrary( result = m * period + psi else: diff = wrap_difference(psi[edges[:, 1]] - psi[edges[:, 0]], period) - k = calculate_k(edges, simplices, diff / period, **kwargs) + k = calculate_k(edges, simplices, diff / period, weights=weights, **kwargs) correct_diff = diff + k * period result = ( From aed257a73c0d69f3192c870a429e228bdec98667 Mon Sep 17 00:00:00 2001 From: DominikaDlugosz Date: Mon, 15 Jul 2024 13:53:10 +0200 Subject: [PATCH 07/15] Code formatting with black (using the online playground ver) --- kamui/__init__.py | 15 +++++++++------ kamui/core.py | 8 -------- kamui/utils.py | 38 ++++++++++++++++++++++++++------------ 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/kamui/__init__.py b/kamui/__init__.py index 6fcb1fb..0515048 100644 --- a/kamui/__init__.py +++ b/kamui/__init__.py @@ -27,7 +27,7 @@ def unwrap_dimensional( start_pixel: Optional[Union[Tuple[int, int], Tuple[int, int, int]]] = None, use_edgelist: bool = False, cyclical_axis: Union[int, Tuple[int, int]] = (), - merging_method: str = 'mean', + merging_method: str = "mean", weights: Optional[np.ndarray] = None, **kwargs: Any, ) -> Optional[np.ndarray]: @@ -65,7 +65,6 @@ def unwrap_dimensional( for i, s in enumerate(start_pixel): start_i *= x.shape[i] start_i += s - if x.ndim == 2: edges, simplices = get_2d_edges_and_simplices( x.shape, cyclical_axis=cyclical_axis @@ -80,14 +79,18 @@ def unwrap_dimensional( if weights is not None: # convert per-vertex weights to per-edge weights - weights = prepare_weights(weights, edges=edges, merging_method=merging_method) + weights = prepare_weights(weights, edges=edges, merging_method=merging_method) result = unwrap_arbitrary( - psi, edges, None if use_edgelist else simplices, start_i=start_i, weights=weights, **kwargs + psi, + edges, + None if use_edgelist else simplices, + start_i=start_i, + weights=weights, + **kwargs, ) if result is None: return None - return result.reshape(x.shape) @@ -147,7 +150,7 @@ def unwrap_arbitrary( np.int64 ), weights=weights, - **kwargs + **kwargs, ) if m is None: return None diff --git a/kamui/core.py b/kamui/core.py index 0b1109e..49d6b8d 100644 --- a/kamui/core.py +++ b/kamui/core.py @@ -9,7 +9,6 @@ import maxflow except ImportError: print("PyMaxflow not found, some functions will not be available.") - __all__ = ["integrate", "calculate_k", "calculate_m", "puma"] @@ -31,7 +30,6 @@ def integrate(edges: np.ndarray, weights: np.ndarray, start_i: int = 0): pairs = np.stack([nodes[:-1], nodes[1:]], axis=1) for u, v in pairs: result[v] = result[u] + G[u, v] - return result @@ -74,7 +72,6 @@ def calculate_k( raise ValueError("simplices contain invalid edges") vals.append(-1) u = v - rows = np.array(rows) cols = np.array(cols) vals = np.array(vals) @@ -103,7 +100,6 @@ def calculate_k( c = np.ones((M * 2,), dtype=np.int64) else: c = np.tile(weights, 2) - res = linprog(c, A_eq=A_eq, b_eq=b_eq, integrality=1) if res.x is None: return None @@ -145,7 +141,6 @@ def calculate_m( ) if weights is None: weights = np.ones((M,), dtype=np.int64) - c = np.concatenate((np.zeros(N, dtype=np.int64), weights, weights)) b_eq = differences @@ -171,7 +166,6 @@ def puma(psi: np.ndarray, edges: np.ndarray, max_jump: int = 1, p: float = 1): jump_steps = list(range(1, max_jump + 1)) * 2 else: jump_steps = [max_jump] - total_nodes = psi.size def V(x): @@ -212,7 +206,6 @@ def cal_Ek(K, psi, i, j): for i in range(total_nodes): G.add_tedge(i, tmp_st_weight[0, i], tmp_st_weight[1, i]) - G.maxflow() partition = G.get_grid_segments(np.arange(total_nodes)) @@ -225,5 +218,4 @@ def cal_Ek(K, psi, i, j): else: K[~partition] -= step break - return K diff --git a/kamui/utils.py b/kamui/utils.py index 06314c9..4b9d24d 100644 --- a/kamui/utils.py +++ b/kamui/utils.py @@ -2,7 +2,11 @@ import numpy.typing as npt from typing import Tuple, Iterable, Union -__all__ = ["get_2d_edges_and_simplices", "get_3d_edges_and_simplices", "prepare_weights"] +__all__ = [ + "get_2d_edges_and_simplices", + "get_3d_edges_and_simplices", + "prepare_weights", +] def get_2d_edges_and_simplices( @@ -26,8 +30,8 @@ def get_2d_edges_and_simplices( nodes = np.arange(np.prod(shape)).reshape(shape) if type(cyclical_axis) is int: cyclical_axis = (cyclical_axis,) - # if the axis length <= 2, then the axis is already cyclical + cyclical_axis = tuple(filter(lambda ax: shape[ax] > 2, cyclical_axis)) edges = np.concatenate( @@ -79,7 +83,6 @@ def get_2d_edges_and_simplices( ), axis=0, ).tolist() - return edges, simplices @@ -193,12 +196,15 @@ def get_3d_edges_and_simplices( ), axis=0, ).tolist() - return edges, simplices -def prepare_weights(weights: npt.NDArray, edges: npt.NDArray[np.int_], smoothing: float = 0.1, - merging_method: str = 'mean') -> npt.NDArray[np.float_]: +def prepare_weights( + weights: npt.NDArray, + edges: npt.NDArray[np.int_], + smoothing: float = 0.1, + merging_method: str = "mean", +) -> npt.NDArray[np.float_]: """Prepare weights for `calculate_m` and `calculate_k` functions. Assume the weights are the same shape as the phases to be unwrapped. @@ -221,28 +227,36 @@ def prepare_weights(weights: npt.NDArray, edges: npt.NDArray[np.int_], smoothing if not 0 <= smoothing < 1: raise ValueError( - "`smoothing` should be a value between 0 (inclusive) and 1 (non inclusive); got " + str(smoothing)) - + "`smoothing` should be a value between 0 (inclusive) and 1 (non inclusive); got " + + str(smoothing) + ) # scale the weights from 0 to 1 + weights = weights - np.nanmin(weights) current_max = np.nanmax(weights) if not current_max: # current maximum is 0, which means all weights originally had the same value, now 0; replace everything with 1 + weights += 1 else: weights /= current_max - weights *= (1 - smoothing) + weights *= 1 - smoothing weights += smoothing - # pick the weights corresponding to the phases connected by the edges # and use `merging_method` to get one weight for each edge - allowed_merging_methods = ['min', 'max', 'mean'] + + allowed_merging_methods = ["min", "max", "mean"] if merging_method not in allowed_merging_methods: raise ValueError( - "`merging_method` should be one of: " + ', '.join(merging_method) + '; got ' + str(merging_method)) + "`merging_method` should be one of: " + + ", ".join(merging_method) + + "; got " + + str(merging_method) + ) weights_for_edges = getattr(np, merging_method)(weights.ravel()[edges], axis=1) # make sure there are no NaNs in the weights; replace any with 0s + weights_for_edges[np.isnan(weights_for_edges)] = 0 return weights_for_edges From ee07e3c91db20be86ca212e432555e7cf148245b Mon Sep 17 00:00:00 2001 From: Chin-Yun Yu Date: Tue, 16 Jul 2024 14:10:10 +0100 Subject: [PATCH 08/15] Update kamui/__init__.py --- kamui/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/kamui/__init__.py b/kamui/__init__.py index 0515048..6b66b5f 100644 --- a/kamui/__init__.py +++ b/kamui/__init__.py @@ -101,7 +101,6 @@ def unwrap_arbitrary( method: str = "ilp", period: float = 2 * np.pi, start_i: int = 0, - weights: Optional[np.ndarray] = None, **kwargs, ) -> Optional[np.ndarray]: """ From e8759e2b3e4db4166d8c1918ee2366af41cac4a9 Mon Sep 17 00:00:00 2001 From: Chin-Yun Yu Date: Tue, 16 Jul 2024 14:10:20 +0100 Subject: [PATCH 09/15] Update kamui/__init__.py --- kamui/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/kamui/__init__.py b/kamui/__init__.py index 6b66b5f..61df408 100644 --- a/kamui/__init__.py +++ b/kamui/__init__.py @@ -126,7 +126,6 @@ def unwrap_arbitrary( start_i : int The index of the reference vertex to start unwrapping. Default to 0. - weights : Array of weights for each of the edges. kwargs : dict Other arguments passed to the solver. From 2fbe88cf2abc2d49cddb251f33aadf31a61897e4 Mon Sep 17 00:00:00 2001 From: Chin-Yun Yu Date: Tue, 16 Jul 2024 14:10:30 +0100 Subject: [PATCH 10/15] Update kamui/__init__.py --- kamui/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/kamui/__init__.py b/kamui/__init__.py index 61df408..0649494 100644 --- a/kamui/__init__.py +++ b/kamui/__init__.py @@ -135,8 +135,6 @@ def unwrap_arbitrary( The unwrapped phase of the same shape as psi. """ if method == "gc": - if weights is not None: - raise ValueError("PUMA method does not take in weights") m = puma(psi / period, edges, **kwargs) m -= m[start_i] result = m * period + psi From 5e8df9abe02afe20cf582c15820663200dbc05ce Mon Sep 17 00:00:00 2001 From: Chin-Yun Yu Date: Tue, 16 Jul 2024 14:10:39 +0100 Subject: [PATCH 11/15] Update kamui/__init__.py --- kamui/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/kamui/__init__.py b/kamui/__init__.py index 0649494..992093f 100644 --- a/kamui/__init__.py +++ b/kamui/__init__.py @@ -145,7 +145,6 @@ def unwrap_arbitrary( np.round((psi[edges[:, 1]] - psi[edges[:, 0]]) / period).astype( np.int64 ), - weights=weights, **kwargs, ) if m is None: From 8e4a2cf871c50fdb8fc41cff3bce17c1730aa79f Mon Sep 17 00:00:00 2001 From: Chin-Yun Yu Date: Tue, 16 Jul 2024 14:10:48 +0100 Subject: [PATCH 12/15] Update kamui/__init__.py --- kamui/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kamui/__init__.py b/kamui/__init__.py index 992093f..ac16c93 100644 --- a/kamui/__init__.py +++ b/kamui/__init__.py @@ -153,7 +153,7 @@ def unwrap_arbitrary( result = m * period + psi else: diff = wrap_difference(psi[edges[:, 1]] - psi[edges[:, 0]], period) - k = calculate_k(edges, simplices, diff / period, weights=weights, **kwargs) + k = calculate_k(edges, simplices, diff / period, **kwargs) correct_diff = diff + k * period result = ( From dafa0640efb42e7f155197112166105477f5015a Mon Sep 17 00:00:00 2001 From: Chin-Yun Yu Date: Tue, 16 Jul 2024 14:10:57 +0100 Subject: [PATCH 13/15] Update kamui/__init__.py --- kamui/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kamui/__init__.py b/kamui/__init__.py index ac16c93..5b7b256 100644 --- a/kamui/__init__.py +++ b/kamui/__init__.py @@ -47,7 +47,7 @@ def unwrap_dimensional( cyclical_axis : int or (int, int) The axis that is cyclical. Default to (). - weights : Weights defining the 'goodness' of value at each vertex. Shape must match the shape of x. + weights : Weights defining the 'goodness' of value at each vertex. Shape must match the shape of x. merging_method : Way of combining two phase weights into a single edge weight. kwargs : dict Other arguments passed to `kamui.unwrap_arbitrary`. From 977aefeb3ff8d696736a4e3fc464f5a4c996426e Mon Sep 17 00:00:00 2001 From: Chin-Yun Yu Date: Tue, 16 Jul 2024 14:11:06 +0100 Subject: [PATCH 14/15] Update kamui/__init__.py --- kamui/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kamui/__init__.py b/kamui/__init__.py index 5b7b256..6e187c3 100644 --- a/kamui/__init__.py +++ b/kamui/__init__.py @@ -48,7 +48,7 @@ def unwrap_dimensional( The axis that is cyclical. Default to (). weights : Weights defining the 'goodness' of value at each vertex. Shape must match the shape of x. - merging_method : Way of combining two phase weights into a single edge weight. + merging_method : Way of combining two phase weights into a single edge weight. kwargs : dict Other arguments passed to `kamui.unwrap_arbitrary`. From cd4ffa01602622fdc043cf08ef0fbd3e1e0b8f76 Mon Sep 17 00:00:00 2001 From: Chin-Yun Yu Date: Tue, 16 Jul 2024 14:11:16 +0100 Subject: [PATCH 15/15] Update kamui/utils.py --- kamui/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kamui/utils.py b/kamui/utils.py index 4b9d24d..675f6cd 100644 --- a/kamui/utils.py +++ b/kamui/utils.py @@ -213,7 +213,7 @@ def prepare_weights( Compute the mean/max/min (depending on the `merging_method`) of each of those pairs to give a weight for each edge. Args: - weights : Array of weights of shapr corresponding to the original phases array shape. + weights : Array of weights of shape corresponding to the original phases array shape. edges : Edges connecting the phases. Shape: (M, 2), where M is the number of edges. smoothing : A positive value in range [0, 1). This is the minimal value of the rescaled weights where they are defined. If smoothing > 0, the value of 0 is reserved for places where