From 36fce4d2a0bc9432fc6c5f726d058b1018c4d7f0 Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Wed, 21 Jun 2023 08:09:30 -0500 Subject: [PATCH 01/16] Initial commit creating main --- diffpy/snmf/main.py | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 diffpy/snmf/main.py diff --git a/diffpy/snmf/main.py b/diffpy/snmf/main.py new file mode 100644 index 0000000..12e0aad --- /dev/null +++ b/diffpy/snmf/main.py @@ -0,0 +1,6 @@ +def main(): + pass + + +if __name__ == "__main__": + main() \ No newline at end of file From 42dac412ece8a30a908a3098c140923b814ecaa3 Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Mon, 17 Jul 2023 12:00:10 -0500 Subject: [PATCH 02/16] reformatted --- diffpy/snmf/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diffpy/snmf/main.py b/diffpy/snmf/main.py index 12e0aad..cd9ac48 100644 --- a/diffpy/snmf/main.py +++ b/diffpy/snmf/main.py @@ -3,4 +3,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() From dfa4910dbc719ffa40881520256088afd6aa429a Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Tue, 18 Jul 2023 08:36:38 -0500 Subject: [PATCH 03/16] setup library behavior --- diffpy/snmf/{main.py => stretchednmfapp.py} | 2 +- setup.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename diffpy/snmf/{main.py => stretchednmfapp.py} (66%) diff --git a/diffpy/snmf/main.py b/diffpy/snmf/stretchednmfapp.py similarity index 66% rename from diffpy/snmf/main.py rename to diffpy/snmf/stretchednmfapp.py index cd9ac48..9ef98b1 100644 --- a/diffpy/snmf/main.py +++ b/diffpy/snmf/stretchednmfapp.py @@ -1,5 +1,5 @@ def main(): - pass + print("Hello World!") if __name__ == "__main__": diff --git a/setup.py b/setup.py index 32cc5f4..4b108be 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Installation script for diffpy.pdfmorph +# Installation script for diffpy.snmf """diffpy.snmf - a package implementing the stretched NMF algorithm. @@ -28,7 +28,7 @@ entry_points={ # define console_scripts here, see setuptools docs for details. 'console_scripts': [ - 'pdfmorph = diffpy.pdfmorph.pdfmorphapp:main', + 'stretched_nmf = diffpy.snmf.stretchednmfapp:main', ], }, test_suite='tests', From b982382dcc7565243764a3ef217bc0a6c7ebcefd Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Tue, 18 Jul 2023 11:30:10 -0500 Subject: [PATCH 04/16] updated main, fixed io --- diffpy/snmf/io.py | 6 ++++-- diffpy/snmf/stretchednmfapp.py | 23 ++++++++++++++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/diffpy/snmf/io.py b/diffpy/snmf/io.py index f666949..939e31d 100644 --- a/diffpy/snmf/io.py +++ b/diffpy/snmf/io.py @@ -44,7 +44,7 @@ def initialize_variables(data_input, component_amount, data_type, sparsity=1, sm component_matrix_guess = np.random.rand(signal_length, component_amount) weight_matrix_guess = np.random.rand(component_amount, moment_amount) - stretching_matrix_guess = np.ones(component_amount, moment_amount) + np.random.randn(component_amount, + stretching_matrix_guess = np.ones((component_amount, moment_amount)) + np.random.randn(component_amount, moment_amount) * 1e-3 diagonals = [np.ones(moment_amount - 2), -2 * np.ones(moment_amount - 2), np.ones(moment_amount - 2)] @@ -52,6 +52,8 @@ def initialize_variables(data_input, component_amount, data_type, sparsity=1, sm hessian_helper_matrix = scipy.sparse.block_diag([smoothness_term.T @ smoothness_term] * component_amount) sequence = np.arange(moment_amount * component_amount).reshape(component_amount, moment_amount).T.flatten() + + hessian_helper_matrix = hessian_helper_matrix.tocsr() hessian_helper_matrix = hessian_helper_matrix[sequence, :][:, sequence] return { @@ -102,7 +104,7 @@ def load_input_signals(file_path=None): for item in directory_path.iterdir(): if item.is_file(): data = loadData(item.resolve()) - if current_grid and current_grid != data[:, 0]: + if len(current_grid) != 0 and (current_grid != data[:, 0]).any(): print(f"{item.name} was ignored as it is not on a compatible grid.") continue else: diff --git a/diffpy/snmf/stretchednmfapp.py b/diffpy/snmf/stretchednmfapp.py index 9ef98b1..b09109a 100644 --- a/diffpy/snmf/stretchednmfapp.py +++ b/diffpy/snmf/stretchednmfapp.py @@ -1,5 +1,26 @@ +import numpy as np + +from diffpy.snmf.io import load_input_signals, initialize_variables + + def main(): - print("Hello World!") + directory_path = input("Specify Path (Optional. Press enter to skip):") + if not directory_path: + directory_path = None + + data_type = input("Specify the data type ('xrd' or 'pdf'): ") + if data_type != 'xrd' and data_type != 'pdf': + raise ValueError("The data type must be 'xrd' or 'pdf'") + + component_amount = input("\nEnter the amount of components to obtain:") + try: + component_amount = int(component_amount) + except TypeError: + raise TypeError("Please enter an integer greater than 0") + + grid, data_input = load_input_signals(directory_path) + variables = initialize_variables(data_input, component_amount, data_type) + lifted_data = data_input - np.ndarray.min(data_input[:]) if __name__ == "__main__": From 6d8be9030d29c42aca75f3f89a417fd3fee6615b Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Wed, 19 Jul 2023 11:20:03 -0500 Subject: [PATCH 05/16] added create_parser function to handle application input --- diffpy/snmf/stretchednmfapp.py | 39 ++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/diffpy/snmf/stretchednmfapp.py b/diffpy/snmf/stretchednmfapp.py index b09109a..e833c7f 100644 --- a/diffpy/snmf/stretchednmfapp.py +++ b/diffpy/snmf/stretchednmfapp.py @@ -1,26 +1,33 @@ import numpy as np +import argparse from diffpy.snmf.io import load_input_signals, initialize_variables +def create_parser(): + parser = argparse.ArgumentParser( + prog="stretched_nmf", + description="Stretched Nonnegative Matrix Factorization" + ) + parser.add_argument('-v', '--version', action='version', help='Print the software version number') + parser.add_argument('-d', '--directory', type=str, + help="Directory containing experimental data. Ensure it is in quotations or apostrophes.") + + parser.add_argument('component_number', type=int, + help="The number of component signals to obtain from experimental " + "data. Must be an integer greater than 0.") + parser.add_argument('data_type', type=str, choices=['xrd', 'pdf'], help="The type of the experimental data.") + args = parser.parse_args() + return args + + def main(): - directory_path = input("Specify Path (Optional. Press enter to skip):") - if not directory_path: - directory_path = None - - data_type = input("Specify the data type ('xrd' or 'pdf'): ") - if data_type != 'xrd' and data_type != 'pdf': - raise ValueError("The data type must be 'xrd' or 'pdf'") - - component_amount = input("\nEnter the amount of components to obtain:") - try: - component_amount = int(component_amount) - except TypeError: - raise TypeError("Please enter an integer greater than 0") - - grid, data_input = load_input_signals(directory_path) - variables = initialize_variables(data_input, component_amount, data_type) + args = create_parser() + + grid, data_input = load_input_signals(args.directory) + variables = initialize_variables(data_input, args.component_number, args.data_type) lifted_data = data_input - np.ndarray.min(data_input[:]) + return lifted_data if __name__ == "__main__": From 6fb2879413f66355a9d028e0eaf5b230dccf74ce Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Wed, 19 Jul 2023 15:49:06 -0500 Subject: [PATCH 06/16] added the maximum iterations variable and the condition for when the raw data is lifted --- diffpy/snmf/stretchednmfapp.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/diffpy/snmf/stretchednmfapp.py b/diffpy/snmf/stretchednmfapp.py index e833c7f..061ce6d 100644 --- a/diffpy/snmf/stretchednmfapp.py +++ b/diffpy/snmf/stretchednmfapp.py @@ -26,7 +26,9 @@ def main(): grid, data_input = load_input_signals(args.directory) variables = initialize_variables(data_input, args.component_number, args.data_type) - lifted_data = data_input - np.ndarray.min(data_input[:]) + if variables["data_type"] == 'pdf': + lifted_data = data_input - np.ndarray.min(data_input[:]) + maxiter = 300 return lifted_data From 07cd3ecc5427bc16fc9e9b3ab3c9ab911c0c6224 Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Thu, 20 Jul 2023 13:58:33 -0500 Subject: [PATCH 07/16] renamed parameters and added output directory parameter. Added functionality for getting data type from file extension --- diffpy/snmf/io.py | 10 +++++++++- diffpy/snmf/stretchednmfapp.py | 20 +++++++++++++------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/diffpy/snmf/io.py b/diffpy/snmf/io.py index 939e31d..df96a41 100644 --- a/diffpy/snmf/io.py +++ b/diffpy/snmf/io.py @@ -101,8 +101,10 @@ def load_input_signals(file_path=None): values_list = [] grid_list = [] current_grid = [] + file_extension = "" for item in directory_path.iterdir(): if item.is_file(): + file_extension = Path(item).suffix data = loadData(item.resolve()) if len(current_grid) != 0 and (current_grid != data[:, 0]).any(): print(f"{item.name} was ignored as it is not on a compatible grid.") @@ -115,4 +117,10 @@ def load_input_signals(file_path=None): grid_array = np.column_stack(grid_list) grid_vector = np.unique(grid_array, axis=1) values_array = np.column_stack(values_list) - return grid_vector, values_array + if file_extension in {'.gr','.chi'}: + data_type = 'pdf' + elif file_extension in {'iq','.xy','.xye','.xrd'}: + data_type = 'xrd' + else: + data_type = None + return grid_vector, values_array,data_type diff --git a/diffpy/snmf/stretchednmfapp.py b/diffpy/snmf/stretchednmfapp.py index 061ce6d..2b2ab11 100644 --- a/diffpy/snmf/stretchednmfapp.py +++ b/diffpy/snmf/stretchednmfapp.py @@ -10,13 +10,15 @@ def create_parser(): description="Stretched Nonnegative Matrix Factorization" ) parser.add_argument('-v', '--version', action='version', help='Print the software version number') - parser.add_argument('-d', '--directory', type=str, - help="Directory containing experimental data. Ensure it is in quotations or apostrophes.") - - parser.add_argument('component_number', type=int, + parser.add_argument('-i', '--input-directory', type=str, + help="Directory containing experimental data. Has a default value of None which sets the input as your current working directory.") + parser.add_argument('-o', '--output-directory', type=str, + help="The directory where the results will be dumped. Default behavior will create a new directory named 'smnf_results' inside the input directory.") + parser.add_argument('-t', '--data-type', type=str, choices=['xrd', 'pdf'], + help="The type of the experimental data.") + parser.add_argument('components', type=int, help="The number of component signals to obtain from experimental " "data. Must be an integer greater than 0.") - parser.add_argument('data_type', type=str, choices=['xrd', 'pdf'], help="The type of the experimental data.") args = parser.parse_args() return args @@ -24,8 +26,12 @@ def create_parser(): def main(): args = create_parser() - grid, data_input = load_input_signals(args.directory) - variables = initialize_variables(data_input, args.component_number, args.data_type) + grid, data_input, data_type = load_input_signals(args.input_directory) + if args.data_type is not None: + variables = initialize_variables(data_input, args.components, args.data_type) + else: + variables = initialize_variables(data_input, args.components, data_type) + if variables["data_type"] == 'pdf': lifted_data = data_input - np.ndarray.min(data_input[:]) maxiter = 300 From 32bf269ccf80fdde905332c20da9457e6258dbae Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Thu, 20 Jul 2023 15:22:59 -0500 Subject: [PATCH 08/16] added import statement, synced main with branch --- diffpy/snmf/stretchednmfapp.py | 1 + 1 file changed, 1 insertion(+) diff --git a/diffpy/snmf/stretchednmfapp.py b/diffpy/snmf/stretchednmfapp.py index 2b2ab11..33cea44 100644 --- a/diffpy/snmf/stretchednmfapp.py +++ b/diffpy/snmf/stretchednmfapp.py @@ -2,6 +2,7 @@ import argparse from diffpy.snmf.io import load_input_signals, initialize_variables +from diffpy.snmf.subroutines import * def create_parser(): From e527a19e6c9bd0dade296c45e60f188ce1ab7b7f Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Fri, 21 Jul 2023 16:03:30 -0500 Subject: [PATCH 09/16] added functionality to test cli app --- diffpy/snmf/stretchednmfapp.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/diffpy/snmf/stretchednmfapp.py b/diffpy/snmf/stretchednmfapp.py index 33cea44..e15f787 100644 --- a/diffpy/snmf/stretchednmfapp.py +++ b/diffpy/snmf/stretchednmfapp.py @@ -35,8 +35,22 @@ def main(): if variables["data_type"] == 'pdf': lifted_data = data_input - np.ndarray.min(data_input[:]) + + weights_matrix = variables["weight_matrix_guess"] + component_matrix = variables["component_matrix_guess"] + stretching_factor_matrix = variables["stretching_matrix_guess"] maxiter = 300 - return lifted_data + + for out_iter in range(maxiter): + weight_matrix = update_weights_matrix(variables["component_amount"], variables["signal_length"], + stretching_factor_matrix, component_matrix, lifted_data, + variables["moment_amount"], weights_matrix, None) + residual_matrix = get_residual_matrix(component_matrix, weights_matrix, stretching_factor_matrix, lifted_data, + variables["moment_amount"], variables["component_amount"], + variables["signal_length"]) + fun = objective_function(residual_matrix, stretching_factor_matrix, variables["smoothness"], + variables["smoothness_term"], component_matrix, variables["sparsity"]) + print(fun) if __name__ == "__main__": From 865251e11384f5e556cd66d8009e7a8b226b074b Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Fri, 21 Jul 2023 16:08:41 -0500 Subject: [PATCH 10/16] added explicit default value for --input-directory and modified help string --- diffpy/snmf/stretchednmfapp.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/diffpy/snmf/stretchednmfapp.py b/diffpy/snmf/stretchednmfapp.py index e15f787..b8153e7 100644 --- a/diffpy/snmf/stretchednmfapp.py +++ b/diffpy/snmf/stretchednmfapp.py @@ -11,8 +11,8 @@ def create_parser(): description="Stretched Nonnegative Matrix Factorization" ) parser.add_argument('-v', '--version', action='version', help='Print the software version number') - parser.add_argument('-i', '--input-directory', type=str, - help="Directory containing experimental data. Has a default value of None which sets the input as your current working directory.") + parser.add_argument('-i', '--input-directory', type=str, default=None, + help="Directory containing experimental data. Default before will cause the program to use the current working directory as the input directory.") parser.add_argument('-o', '--output-directory', type=str, help="The directory where the results will be dumped. Default behavior will create a new directory named 'smnf_results' inside the input directory.") parser.add_argument('-t', '--data-type', type=str, choices=['xrd', 'pdf'], From 8f6b94e7c314a4bb45b162fbef543e9ae5628d46 Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Fri, 21 Jul 2023 16:09:11 -0500 Subject: [PATCH 11/16] changed import statement to explicitly import functions --- diffpy/snmf/stretchednmfapp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diffpy/snmf/stretchednmfapp.py b/diffpy/snmf/stretchednmfapp.py index b8153e7..9b0ec1c 100644 --- a/diffpy/snmf/stretchednmfapp.py +++ b/diffpy/snmf/stretchednmfapp.py @@ -2,7 +2,7 @@ import argparse from diffpy.snmf.io import load_input_signals, initialize_variables -from diffpy.snmf.subroutines import * +from diffpy.snmf.subroutines import update_weights_matrix, get_residual_matrix, objective_function def create_parser(): From a174475065076795efe94c5a112fe92c9bf540be Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Sat, 22 Jul 2023 11:16:50 -0500 Subject: [PATCH 12/16] reformatted io.py, moved version argument to bottom of create_parser, changed help string of output-directory default behavior for input_directory handled in main, --- diffpy/snmf/io.py | 13 +++++-------- diffpy/snmf/stretchednmfapp.py | 13 ++++++++----- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/diffpy/snmf/io.py b/diffpy/snmf/io.py index df96a41..603bc9c 100644 --- a/diffpy/snmf/io.py +++ b/diffpy/snmf/io.py @@ -45,7 +45,7 @@ def initialize_variables(data_input, component_amount, data_type, sparsity=1, sm component_matrix_guess = np.random.rand(signal_length, component_amount) weight_matrix_guess = np.random.rand(component_amount, moment_amount) stretching_matrix_guess = np.ones((component_amount, moment_amount)) + np.random.randn(component_amount, - moment_amount) * 1e-3 + moment_amount) * 1e-3 diagonals = [np.ones(moment_amount - 2), -2 * np.ones(moment_amount - 2), np.ones(moment_amount - 2)] smoothness_term = .25 * scipy.sparse.diags(diagonals, [0, 1, 2], shape=(moment_amount - 2, moment_amount)) @@ -93,10 +93,7 @@ def load_input_signals(file_path=None): """ - if file_path is None: - directory_path = Path.cwd() - else: - directory_path = Path(file_path) + directory_path = Path(file_path) values_list = [] grid_list = [] @@ -117,10 +114,10 @@ def load_input_signals(file_path=None): grid_array = np.column_stack(grid_list) grid_vector = np.unique(grid_array, axis=1) values_array = np.column_stack(values_list) - if file_extension in {'.gr','.chi'}: + if file_extension in {'.gr', '.chi'}: data_type = 'pdf' - elif file_extension in {'iq','.xy','.xye','.xrd'}: + elif file_extension in {'iq', '.xy', '.xye', '.xrd'}: data_type = 'xrd' else: data_type = None - return grid_vector, values_array,data_type + return grid_vector, values_array, data_type diff --git a/diffpy/snmf/stretchednmfapp.py b/diffpy/snmf/stretchednmfapp.py index 9b0ec1c..f1e3c3d 100644 --- a/diffpy/snmf/stretchednmfapp.py +++ b/diffpy/snmf/stretchednmfapp.py @@ -1,5 +1,6 @@ import numpy as np import argparse +from pathlib import Path from diffpy.snmf.io import load_input_signals, initialize_variables from diffpy.snmf.subroutines import update_weights_matrix, get_residual_matrix, objective_function @@ -10,22 +11,24 @@ def create_parser(): prog="stretched_nmf", description="Stretched Nonnegative Matrix Factorization" ) - parser.add_argument('-v', '--version', action='version', help='Print the software version number') + parser.add_argument('-i', '--input-directory', type=str, default=None, - help="Directory containing experimental data. Default before will cause the program to use the current working directory as the input directory.") + help="Directory containing experimental data. Defaults to current working directory.") parser.add_argument('-o', '--output-directory', type=str, - help="The directory where the results will be dumped. Default behavior will create a new directory named 'smnf_results' inside the input directory.") + help="The directory where the results will be written. Defaults to '/snmf_results'.") parser.add_argument('-t', '--data-type', type=str, choices=['xrd', 'pdf'], help="The type of the experimental data.") parser.add_argument('components', type=int, - help="The number of component signals to obtain from experimental " - "data. Must be an integer greater than 0.") + help="The number of component signals for the NMF decomposition. Must be an integer greater than 0.") + parser.add_argument('-v', '--version', action='version', help='Print the software version number') args = parser.parse_args() return args def main(): args = create_parser() + if args.input_directory is None: + args.input_directory = Path.cwd() grid, data_input, data_type = load_input_signals(args.input_directory) if args.data_type is not None: From 8b26f4fd62197565100e4977e15570666c751c64 Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Sat, 22 Jul 2023 11:29:46 -0500 Subject: [PATCH 13/16] changed "component_amount" to "number_of_components" in io.py. changed "moment_amount" to "number_of_moments" in io.py --- diffpy/snmf/io.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/diffpy/snmf/io.py b/diffpy/snmf/io.py index 603bc9c..aff291d 100644 --- a/diffpy/snmf/io.py +++ b/diffpy/snmf/io.py @@ -4,7 +4,7 @@ from diffpy.utils.parsers.loaddata import loadData -def initialize_variables(data_input, component_amount, data_type, sparsity=1, smoothness=1e18): +def initialize_variables(data_input, number_of_components, data_type, sparsity=1, smoothness=1e18): """Determines the variables and initial values used in the SNMF algorithm. Parameters @@ -13,7 +13,7 @@ def initialize_variables(data_input, component_amount, data_type, sparsity=1, sm The observed or simulated PDF or XRD data provided by the user. Has dimensions R x N where R is the signal length and N is the number of PDF/XRD signals. - component_amount: int + number_of_components: int The number of component signals the user would like to decompose 'data_input' into. data_type: str @@ -40,29 +40,30 @@ def initialize_variables(data_input, component_amount, data_type, sparsity=1, sm """ signal_length = data_input.shape[0] - moment_amount = data_input.shape[1] + number_of_moments = data_input.shape[1] - component_matrix_guess = np.random.rand(signal_length, component_amount) - weight_matrix_guess = np.random.rand(component_amount, moment_amount) - stretching_matrix_guess = np.ones((component_amount, moment_amount)) + np.random.randn(component_amount, - moment_amount) * 1e-3 + 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 - diagonals = [np.ones(moment_amount - 2), -2 * np.ones(moment_amount - 2), np.ones(moment_amount - 2)] - smoothness_term = .25 * scipy.sparse.diags(diagonals, [0, 1, 2], shape=(moment_amount - 2, moment_amount)) + diagonals = [np.ones(number_of_moments - 2), -2 * np.ones(number_of_moments - 2), np.ones(number_of_moments - 2)] + smoothness_term = .25 * scipy.sparse.diags(diagonals, [0, 1, 2], shape=(number_of_moments - 2, number_of_moments)) - hessian_helper_matrix = scipy.sparse.block_diag([smoothness_term.T @ smoothness_term] * component_amount) - sequence = np.arange(moment_amount * component_amount).reshape(component_amount, moment_amount).T.flatten() + hessian_helper_matrix = scipy.sparse.block_diag([smoothness_term.T @ smoothness_term] * number_of_components) + sequence = np.arange(number_of_moments * number_of_components).reshape(number_of_components, + number_of_moments).T.flatten() hessian_helper_matrix = hessian_helper_matrix.tocsr() hessian_helper_matrix = hessian_helper_matrix[sequence, :][:, sequence] return { "signal_length": signal_length, - "moment_amount": moment_amount, + "number_of_moments": number_of_moments, "component_matrix_guess": component_matrix_guess, "weight_matrix_guess": weight_matrix_guess, "stretching_matrix_guess": stretching_matrix_guess, - "component_amount": component_amount, + "number_of_components": number_of_components, "data_type": data_type, "smoothness": smoothness, "sparsity": sparsity, From a024bb5b40ff550963db59aa29e28d4bc8ec1ae5 Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Sat, 22 Jul 2023 11:36:56 -0500 Subject: [PATCH 14/16] fixed typo out-directory help string --- diffpy/snmf/stretchednmfapp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diffpy/snmf/stretchednmfapp.py b/diffpy/snmf/stretchednmfapp.py index f1e3c3d..a37c498 100644 --- a/diffpy/snmf/stretchednmfapp.py +++ b/diffpy/snmf/stretchednmfapp.py @@ -15,7 +15,7 @@ def create_parser(): parser.add_argument('-i', '--input-directory', type=str, default=None, help="Directory containing experimental data. Defaults to current working directory.") parser.add_argument('-o', '--output-directory', type=str, - help="The directory where the results will be written. Defaults to '/snmf_results'.") + help="The directory where the results will be written. Defaults to '/snmf_results'.") parser.add_argument('-t', '--data-type', type=str, choices=['xrd', 'pdf'], help="The type of the experimental data.") parser.add_argument('components', type=int, From 1331805353fe8cce8e6a04f632562f0642dabeca Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Mon, 24 Jul 2023 15:13:20 -0500 Subject: [PATCH 15/16] changed 'xrd' to 'power_diffraction' choices for data_type, renamed variables in initialize_variables result, --- diffpy/snmf/io.py | 6 +++--- diffpy/snmf/stretchednmfapp.py | 36 ++++++++++++++++++---------------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/diffpy/snmf/io.py b/diffpy/snmf/io.py index aff291d..7be406f 100644 --- a/diffpy/snmf/io.py +++ b/diffpy/snmf/io.py @@ -60,9 +60,9 @@ def initialize_variables(data_input, number_of_components, data_type, sparsity=1 return { "signal_length": signal_length, "number_of_moments": number_of_moments, - "component_matrix_guess": component_matrix_guess, - "weight_matrix_guess": weight_matrix_guess, - "stretching_matrix_guess": stretching_matrix_guess, + "component_matrix": component_matrix_guess, + "weights_matrix": weight_matrix_guess, + "stretching_factor_matrix": stretching_matrix_guess, "number_of_components": number_of_components, "data_type": data_type, "smoothness": smoothness, diff --git a/diffpy/snmf/stretchednmfapp.py b/diffpy/snmf/stretchednmfapp.py index a37c498..0acb278 100644 --- a/diffpy/snmf/stretchednmfapp.py +++ b/diffpy/snmf/stretchednmfapp.py @@ -16,7 +16,7 @@ def create_parser(): help="Directory containing experimental data. Defaults to current working directory.") parser.add_argument('-o', '--output-directory', type=str, help="The directory where the results will be written. Defaults to '/snmf_results'.") - parser.add_argument('-t', '--data-type', type=str, choices=['xrd', 'pdf'], + parser.add_argument('-t', '--data-type', type=str, choices=['powder_diffraction', 'pdf'], help="The type of the experimental data.") parser.add_argument('components', type=int, help="The number of component signals for the NMF decomposition. Must be an integer greater than 0.") @@ -31,29 +31,31 @@ def main(): args.input_directory = Path.cwd() grid, data_input, data_type = load_input_signals(args.input_directory) - if args.data_type is not None: - variables = initialize_variables(data_input, args.components, args.data_type) - else: - variables = initialize_variables(data_input, args.components, data_type) + if args.data_type: + data_type = args.data_type + variables = initialize_variables(data_input, args.components, data_type) if variables["data_type"] == 'pdf': - lifted_data = data_input - np.ndarray.min(data_input[:]) + lifted_data = data_input - np.ndarray.min(data_input[:]) # Will later use to function in subroutines - weights_matrix = variables["weight_matrix_guess"] - component_matrix = variables["component_matrix_guess"] - stretching_factor_matrix = variables["stretching_matrix_guess"] maxiter = 300 for out_iter in range(maxiter): - weight_matrix = update_weights_matrix(variables["component_amount"], variables["signal_length"], - stretching_factor_matrix, component_matrix, lifted_data, - variables["moment_amount"], weights_matrix, None) - residual_matrix = get_residual_matrix(component_matrix, weights_matrix, stretching_factor_matrix, lifted_data, - variables["moment_amount"], variables["component_amount"], + variables["weights_matrix"] = update_weights_matrix(variables["number_of_components"], + variables["signal_length"], + variables["stretching_factor_matrix"], + variables["component_matrix"], lifted_data, + variables["number_of_moments"], variables["weights_matrix"], + None) + + residual_matrix = get_residual_matrix(variables["component_matrix"], variables["weights_matrix"], + variables["stretching_factor_matrix"], lifted_data, + variables["number_of_moments"], variables["number_of_components"], variables["signal_length"]) - fun = objective_function(residual_matrix, stretching_factor_matrix, variables["smoothness"], - variables["smoothness_term"], component_matrix, variables["sparsity"]) - print(fun) + fun = objective_function(residual_matrix, variables["stretching_factor_matrix"], variables["smoothness"], + variables["smoothness_term"], variables["component_matrix"], variables["sparsity"]) + + return 1 if __name__ == "__main__": From 7d4c97fedb321698b75bcfb2dd630999c3e45de6 Mon Sep 17 00:00:00 2001 From: Adeolu Ajayi Date: Wed, 26 Jul 2023 14:38:45 -0500 Subject: [PATCH 16/16] added a lifting factor optional argument --- diffpy/snmf/stretchednmfapp.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/diffpy/snmf/stretchednmfapp.py b/diffpy/snmf/stretchednmfapp.py index 0acb278..d14d223 100644 --- a/diffpy/snmf/stretchednmfapp.py +++ b/diffpy/snmf/stretchednmfapp.py @@ -18,6 +18,8 @@ def create_parser(): help="The directory where the results will be written. Defaults to '/snmf_results'.") parser.add_argument('-t', '--data-type', type=str, choices=['powder_diffraction', 'pdf'], help="The type of the experimental data.") + parser.add_argument('-l', '--lift', type=float, default=1, + help="The factor that determines how much the data is lifted. By default, the data will be vertically translated to make the minimum value 0.") parser.add_argument('components', type=int, help="The number of component signals for the NMF decomposition. Must be an integer greater than 0.") parser.add_argument('-v', '--version', action='version', help='Print the software version number') @@ -36,17 +38,17 @@ def main(): variables = initialize_variables(data_input, args.components, data_type) if variables["data_type"] == 'pdf': - lifted_data = data_input - np.ndarray.min(data_input[:]) # Will later use to function in subroutines + lifted_data = data_input - np.ndarray.min(data_input[:]) # Will later use the lift_data function in subroutines maxiter = 300 for out_iter in range(maxiter): variables["weights_matrix"] = update_weights_matrix(variables["number_of_components"], - variables["signal_length"], - variables["stretching_factor_matrix"], - variables["component_matrix"], lifted_data, - variables["number_of_moments"], variables["weights_matrix"], - None) + variables["signal_length"], + variables["stretching_factor_matrix"], + variables["component_matrix"], lifted_data, + variables["number_of_moments"], variables["weights_matrix"], + None) residual_matrix = get_residual_matrix(variables["component_matrix"], variables["weights_matrix"], variables["stretching_factor_matrix"], lifted_data,