From bb173da49c5c0603cbc1ae99f8d668324f5e1d90 Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Sat, 22 Jul 2023 11:46:09 -0500 Subject: [PATCH 01/10] initial commit --- diffpy/snmf/subroutines.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/diffpy/snmf/subroutines.py b/diffpy/snmf/subroutines.py index d565a15b..1f762015 100644 --- a/diffpy/snmf/subroutines.py +++ b/diffpy/snmf/subroutines.py @@ -3,6 +3,33 @@ from diffpy.snmf.factorizers import lsqnonneg import numdifftools +def lift_data(data_input, lift): + """ + + Parameters + ---------- + data_input + lift + + Returns + ------- + + """ + pass + +def initialize_arrays(number_of_components, number_of_arrays): + """ + + Parameters + ---------- + number_of_components + number_of_arrays + + Returns + ------- + + """ + pass def objective_function(residual_matrix, stretching_factor_matrix, smoothness, smoothness_term, component_matrix, sparsity): From 2aa44dafbb9382b7be1da6ad15c0173fdd0990f5 Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Sat, 22 Jul 2023 11:56:20 -0500 Subject: [PATCH 02/10] added docstring and code for lift_data --- diffpy/snmf/subroutines.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/diffpy/snmf/subroutines.py b/diffpy/snmf/subroutines.py index 1f762015..1fa66669 100644 --- a/diffpy/snmf/subroutines.py +++ b/diffpy/snmf/subroutines.py @@ -3,19 +3,30 @@ from diffpy.snmf.factorizers import lsqnonneg import numdifftools -def lift_data(data_input, lift): - """ + +def lift_data(data_input, lift=1): + """Lifts values of data_input + + Adds 'lift' * the minimum value in data_input to data_input element-wise. Parameters ---------- - data_input - lift + data_input: 2d array like + The matrix containing a series of signals to be decomposed. Has dimensions N x M where N is the length of each + signal and M is the number of signals. + + lift: float + The factor representing how much to lift 'data_input'. Returns ------- + 2d array like + The matrix that contains data_input - (min(data_input) * lift). """ - pass + data_input = np.asarray(data_input) + return data_input - (np.min(data_input[:]) * lift) + def initialize_arrays(number_of_components, number_of_arrays): """ @@ -31,6 +42,7 @@ def initialize_arrays(number_of_components, number_of_arrays): """ pass + def objective_function(residual_matrix, stretching_factor_matrix, smoothness, smoothness_term, component_matrix, sparsity): """Defines the objective function of the algorithm and returns its value. @@ -107,6 +119,7 @@ def get_stretched_component(stretching_factor, component, signal_length): def stretched_component_func(stretching_factor): return np.interp(normalized_grid / stretching_factor, normalized_grid, component, left=0, right=0) + derivative_func = numdifftools.Derivative(stretched_component_func) second_derivative_func = numdifftools.Derivative(derivative_func) From 212ad4480aa0630204fd9cecf99c3244d5c0e5a2 Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Sat, 22 Jul 2023 12:05:44 -0500 Subject: [PATCH 03/10] added docstring for initialize_arrays --- diffpy/snmf/subroutines.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/diffpy/snmf/subroutines.py b/diffpy/snmf/subroutines.py index 1fa66669..4023c84c 100644 --- a/diffpy/snmf/subroutines.py +++ b/diffpy/snmf/subroutines.py @@ -28,16 +28,29 @@ def lift_data(data_input, lift=1): return data_input - (np.min(data_input[:]) * lift) -def initialize_arrays(number_of_components, number_of_arrays): +def initialize_arrays(number_of_components, number_of_moments, signal_length): """ + Calculates the initial guesses for the component matrix, stretching factor matrix, and weight matrix. The initial + guess for the component matrix is a random (signal_length) x (number_of_components) matrix where each element is + between 0 and 1. The initial stretching factor matrix is a random (number_of_components) ẋ (number_of_moments) + matrix where each element is number slightly perturbed from 1. The initial weight matrix guess is a random + (number_of_components) ẋ (number_of_moments) matrix where each element is between 0 and 1. + Parameters ---------- - number_of_components - number_of_arrays + number_of_components: int + The number of component signals to obtain from the stretched nmf decomposition. + number_of_moments: int + The number of signals in the user provided dataset where each signal is at a different moment. + signal_length: int + The length of each signal in the user provided dataset. Returns ------- + tuple of 2d arrays of floats + The tuple containing three elements: the initial component matrix guess, the initial stretching factor matrix + guess, and the initial weight factor matrix guess in that order. """ pass From ce0890b2fdd5d944b218ad50b26706df8120853d Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Sat, 22 Jul 2023 12:06:44 -0500 Subject: [PATCH 04/10] added blank lines between the parameters in initialize_arrays --- diffpy/snmf/subroutines.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/diffpy/snmf/subroutines.py b/diffpy/snmf/subroutines.py index 4023c84c..fe3a2cdf 100644 --- a/diffpy/snmf/subroutines.py +++ b/diffpy/snmf/subroutines.py @@ -41,8 +41,10 @@ def initialize_arrays(number_of_components, number_of_moments, signal_length): ---------- number_of_components: int The number of component signals to obtain from the stretched nmf decomposition. + number_of_moments: int The number of signals in the user provided dataset where each signal is at a different moment. + signal_length: int The length of each signal in the user provided dataset. From 302a3c31fcc6e7c3d16cd2b1eacf4ab91d661f4e Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Mon, 24 Jul 2023 13:28:54 -0500 Subject: [PATCH 05/10] added code and return statement for initialize_arrays --- diffpy/snmf/subroutines.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/diffpy/snmf/subroutines.py b/diffpy/snmf/subroutines.py index fe3a2cdf..3457a868 100644 --- a/diffpy/snmf/subroutines.py +++ b/diffpy/snmf/subroutines.py @@ -55,7 +55,11 @@ def initialize_arrays(number_of_components, number_of_moments, signal_length): guess, and the initial weight factor matrix guess in that order. """ - pass + component_matrix_guess = np.random.rand(signal_length, number_of_components) + weight_matrix_guess = np.random.rand(number_of_components, number_of_moments) + stretching_matrix_guess = np.ones(number_of_components, number_of_moments) + np.random.randn(number_of_components, + number_of_moments) * 1e-3 + return component_matrix_guess, weight_matrix_guess, stretching_matrix_guess def objective_function(residual_matrix, stretching_factor_matrix, smoothness, smoothness_term, component_matrix, From 5b6172f8a45800a41a67e5500f6a405f8573292a Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Mon, 24 Jul 2023 13:47:14 -0500 Subject: [PATCH 06/10] added tests for lift_data --- diffpy/snmf/tests/test_subroutines.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/diffpy/snmf/tests/test_subroutines.py b/diffpy/snmf/tests/test_subroutines.py index 33eab888..82f431bf 100644 --- a/diffpy/snmf/tests/test_subroutines.py +++ b/diffpy/snmf/tests/test_subroutines.py @@ -1,7 +1,7 @@ import pytest import numpy as np from diffpy.snmf.subroutines import objective_function, get_stretched_component, reconstruct_data, get_residual_matrix, \ - update_weights_matrix + update_weights_matrix, initialize_arrays, lift_data to = [ ([[[1, 2], [3, 4]], [[5, 6], [7, 8]], 1e11, [[1, 2], [3, 4]], [[1, 2], [3, 4]], 1], 2.574e14), @@ -134,3 +134,20 @@ def test_reconstruct_data(trd): actual = reconstruct_data(trd[0][0], trd[0][1], trd[0][2], trd[0][3], trd[0][4], trd[0][5]) expected = trd[1] np.testing.assert_allclose(actual, expected, rtol=1e-03) + + +tld = [([[[1, -1, 1], [0, 0, 0], [2, 10, -3]], 1], [[4, 2, 4], [3, 3, 3], [5, 13, 0]]), + ([[[1, -1, 1], [0, 0, 0], [2, 10, -3]], 0], [[1, -1, 1], [0, 0, 0], [2, 10, -3]]), + ([[[1, -1, 1], [0, 0, 0], [2, 10, -3]], .5], [[2.5, .5, 2.5], [1.5, 1.5, 1.5], [3.5, 11.5, -1.5]]), + ([[[1, -1, 1], [0, 0, 0], [2, 10, -3]], -1], [[-2, -4, -2], [-3, -3, -3], [-1, 7, -6]]), + ([[[0, 0, 0], [0, 0, 0], [0, 0, 0]], 100], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]), + ([[[1.5, 2], [10.5, 1], [0.5, 2]], 1], [[1, 1.5], [10, .5], [0, 1.5]]), + ([[[-10, -10.5], [-12.2, -12.2], [0, 0]], 1], [[2.2, 1.7], [0, 0], [12.2, 12.2]]), + ] + + +@pytest.mark.parametrize('tld', tld) +def test_lift_data(tld): + actual = lift_data(tld[0][0], tld[0][1]) + expected = tld[1] + np.testing.assert_allclose(actual, expected) From cbae64b1774d722445b3e116086dfe85236ecb72 Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Mon, 24 Jul 2023 13:51:33 -0500 Subject: [PATCH 07/10] added single-line description to initialize_arrays --- diffpy/snmf/subroutines.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diffpy/snmf/subroutines.py b/diffpy/snmf/subroutines.py index 3457a868..fbd71120 100644 --- a/diffpy/snmf/subroutines.py +++ b/diffpy/snmf/subroutines.py @@ -29,7 +29,7 @@ def lift_data(data_input, lift=1): def initialize_arrays(number_of_components, number_of_moments, signal_length): - """ + """Generates the initial guesses for the weight, stretching, and component matrices Calculates the initial guesses for the component matrix, stretching factor matrix, and weight matrix. The initial guess for the component matrix is a random (signal_length) x (number_of_components) matrix where each element is From 95b7a4a322b096b5f950b47786fc57c9c274b425 Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Mon, 24 Jul 2023 13:53:28 -0500 Subject: [PATCH 08/10] corrected typos in intialize_arrays extended description --- diffpy/snmf/subroutines.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/diffpy/snmf/subroutines.py b/diffpy/snmf/subroutines.py index fbd71120..7e5b1138 100644 --- a/diffpy/snmf/subroutines.py +++ b/diffpy/snmf/subroutines.py @@ -33,9 +33,9 @@ def initialize_arrays(number_of_components, number_of_moments, signal_length): Calculates the initial guesses for the component matrix, stretching factor matrix, and weight matrix. The initial guess for the component matrix is a random (signal_length) x (number_of_components) matrix where each element is - between 0 and 1. The initial stretching factor matrix is a random (number_of_components) ẋ (number_of_moments) + between 0 and 1. The initial stretching factor matrix is a random (number_of_components) x (number_of_moments) matrix where each element is number slightly perturbed from 1. The initial weight matrix guess is a random - (number_of_components) ẋ (number_of_moments) matrix where each element is between 0 and 1. + (number_of_components) x (number_of_moments) matrix where each element is between 0 and 1. Parameters ---------- From cd4687453db201dd115462a365e9d6036601485b Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Wed, 26 Jul 2023 14:31:02 -0500 Subject: [PATCH 09/10] reformatted test inputs and outputs and return statement in lift_data --- diffpy/snmf/subroutines.py | 2 +- diffpy/snmf/tests/test_subroutines.py | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/diffpy/snmf/subroutines.py b/diffpy/snmf/subroutines.py index 7e5b1138..6b80ecdc 100644 --- a/diffpy/snmf/subroutines.py +++ b/diffpy/snmf/subroutines.py @@ -25,7 +25,7 @@ def lift_data(data_input, lift=1): """ data_input = np.asarray(data_input) - return data_input - (np.min(data_input[:]) * lift) + return data_input - (np.min(data_input) * lift) def initialize_arrays(number_of_components, number_of_moments, signal_length): diff --git a/diffpy/snmf/tests/test_subroutines.py b/diffpy/snmf/tests/test_subroutines.py index 82f431bf..466a7a54 100644 --- a/diffpy/snmf/tests/test_subroutines.py +++ b/diffpy/snmf/tests/test_subroutines.py @@ -136,16 +136,14 @@ def test_reconstruct_data(trd): np.testing.assert_allclose(actual, expected, rtol=1e-03) -tld = [([[[1, -1, 1], [0, 0, 0], [2, 10, -3]], 1], [[4, 2, 4], [3, 3, 3], [5, 13, 0]]), - ([[[1, -1, 1], [0, 0, 0], [2, 10, -3]], 0], [[1, -1, 1], [0, 0, 0], [2, 10, -3]]), - ([[[1, -1, 1], [0, 0, 0], [2, 10, -3]], .5], [[2.5, .5, 2.5], [1.5, 1.5, 1.5], [3.5, 11.5, -1.5]]), - ([[[1, -1, 1], [0, 0, 0], [2, 10, -3]], -1], [[-2, -4, -2], [-3, -3, -3], [-1, 7, -6]]), - ([[[0, 0, 0], [0, 0, 0], [0, 0, 0]], 100], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]), - ([[[1.5, 2], [10.5, 1], [0.5, 2]], 1], [[1, 1.5], [10, .5], [0, 1.5]]), - ([[[-10, -10.5], [-12.2, -12.2], [0, 0]], 1], [[2.2, 1.7], [0, 0], [12.2, 12.2]]), +tld = [(([[[1, -1, 1], [0, 0, 0], [2, 10, -3]], 1]), ([[4, 2, 4], [3, 3, 3], [5, 13, 0]])), + (([[[1, -1, 1], [0, 0, 0], [2, 10, -3]], 0]), ([[1, -1, 1], [0, 0, 0], [2, 10, -3]])), + (([[[1, -1, 1], [0, 0, 0], [2, 10, -3]], .5]), ([[2.5, .5, 2.5], [1.5, 1.5, 1.5], [3.5, 11.5, -1.5]])), + (([[[1, -1, 1], [0, 0, 0], [2, 10, -3]], -1]), ([[-2, -4, -2], [-3, -3, -3], [-1, 7, -6]])), + (([[[0, 0, 0], [0, 0, 0], [0, 0, 0]], 100]), ([[0, 0, 0], [0, 0, 0], [0, 0, 0]])), + (([[[1.5, 2], [10.5, 1], [0.5, 2]], 1]), ([[1, 1.5], [10, .5], [0, 1.5]])), + (([[[-10, -10.5], [-12.2, -12.2], [0, 0]], 1]), ([[2.2, 1.7], [0, 0], [12.2, 12.2]])), ] - - @pytest.mark.parametrize('tld', tld) def test_lift_data(tld): actual = lift_data(tld[0][0], tld[0][1]) From d3f77741f051520ee8b156b2184f834b18f40982 Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Wed, 26 Jul 2023 15:06:59 -0500 Subject: [PATCH 10/10] changed behavior of lift_data to add abs(min(data_input) * lift). Changed expections of test cases to reflect changed bahvior --- diffpy/snmf/subroutines.py | 2 +- diffpy/snmf/tests/test_subroutines.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/diffpy/snmf/subroutines.py b/diffpy/snmf/subroutines.py index 6b80ecdc..17b32918 100644 --- a/diffpy/snmf/subroutines.py +++ b/diffpy/snmf/subroutines.py @@ -25,7 +25,7 @@ def lift_data(data_input, lift=1): """ data_input = np.asarray(data_input) - return data_input - (np.min(data_input) * lift) + return data_input + np.abs(np.min(data_input) * lift) def initialize_arrays(number_of_components, number_of_moments, signal_length): diff --git a/diffpy/snmf/tests/test_subroutines.py b/diffpy/snmf/tests/test_subroutines.py index 466a7a54..91f6f7d1 100644 --- a/diffpy/snmf/tests/test_subroutines.py +++ b/diffpy/snmf/tests/test_subroutines.py @@ -139,9 +139,9 @@ def test_reconstruct_data(trd): tld = [(([[[1, -1, 1], [0, 0, 0], [2, 10, -3]], 1]), ([[4, 2, 4], [3, 3, 3], [5, 13, 0]])), (([[[1, -1, 1], [0, 0, 0], [2, 10, -3]], 0]), ([[1, -1, 1], [0, 0, 0], [2, 10, -3]])), (([[[1, -1, 1], [0, 0, 0], [2, 10, -3]], .5]), ([[2.5, .5, 2.5], [1.5, 1.5, 1.5], [3.5, 11.5, -1.5]])), - (([[[1, -1, 1], [0, 0, 0], [2, 10, -3]], -1]), ([[-2, -4, -2], [-3, -3, -3], [-1, 7, -6]])), + (([[[1, -1, 1], [0, 0, 0], [2, 10, -3]], -1]), ([[4, 2, 4], [3, 3, 3], [5, 13, 0]])), (([[[0, 0, 0], [0, 0, 0], [0, 0, 0]], 100]), ([[0, 0, 0], [0, 0, 0], [0, 0, 0]])), - (([[[1.5, 2], [10.5, 1], [0.5, 2]], 1]), ([[1, 1.5], [10, .5], [0, 1.5]])), + (([[[1.5, 2], [10.5, 1], [0.5, 2]], 1]), ([[2, 2.5], [11, 1.5], [1, 2.5]])), (([[[-10, -10.5], [-12.2, -12.2], [0, 0]], 1]), ([[2.2, 1.7], [0, 0], [12.2, 12.2]])), ] @pytest.mark.parametrize('tld', tld)