diff --git a/.coveragerc b/.coveragerc index b14e675..72a8c92 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,5 +1,5 @@ [run] -source = +source = diffpy/snmf/ [report] omit = diff --git a/.flake8 b/.flake8 index 076b992..2d2cb16 100644 --- a/.flake8 +++ b/.flake8 @@ -8,4 +8,4 @@ exclude = max-line-length = 115 # Ignore some style 'errors' produced while formatting by 'black' # https://black.readthedocs.io/en/stable/guides/using_black_with_other_tools.html#labels-why-pycodestyle-warnings -extend-ignore = E203 \ No newline at end of file +extend-ignore = E203 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..c458806 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,43 @@ +default_language_version: + python: python3 +ci: + autofix_commit_msg: | + [pre-commit.ci] auto fixes from pre-commit hooks + autofix_prs: true + autoupdate_branch: 'pre-commit-autoupdate' + autoupdate_commit_msg: '[pre-commit.ci] pre-commit autoupdate' + autoupdate_schedule: monthly + skip: [no-commit-to-branch] + submodules: false +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + exclude: '\.(rst|txt)$' + - repo: https://github.com/psf/black + rev: 24.4.2 + hooks: + - id: black + - repo: https://github.com/pycqa/flake8 + rev: 7.0.0 + hooks: + - id: flake8 + - repo: https://github.com/pycqa/isort + rev: 5.13.2 + hooks: + - id: isort + args: ["--profile", "black"] + - repo: https://github.com/kynan/nbstripout + rev: 0.7.1 + hooks: + - id: nbstripout + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: no-commit-to-branch + name: Prevent Commit to Main Branch + args: ["--branch", "main"] + stages: [pre-commit] diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7bc0953..f01f133 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,4 +3,3 @@ =========== .. current developments - diff --git a/diffpy/snmf/containers.py b/diffpy/snmf/containers.py index 947b07a..41bf03f 100644 --- a/diffpy/snmf/containers.py +++ b/diffpy/snmf/containers.py @@ -1,5 +1,5 @@ -import numpy as np import numdifftools +import numpy as np class ComponentSignal: @@ -8,7 +8,7 @@ class ComponentSignal: ---------- grid: 1d array of floats The vector containing the grid points of the component. - iq: 1d array of floats + The intensity/g(r) values of the component. weights: 1d array of floats The vector containing the weight of the component signal for each signal. @@ -36,13 +36,18 @@ def apply_stretch(self, m): Returns ------- tuple of 1d arrays - The tuple of vectors where one vector is the stretched component, one vector is the 1st derivative of the - stretching operation, and one vector is the second derivative of the stretching operation. + The tuple of vectors where one vector is the stretched component, one vector is the 1st derivative + of the stretching operation, and one vector is the second derivative of the stretching operation. """ normalized_grid = np.arange(len(self.grid)) - func = lambda stretching_factor: np.interp( - normalized_grid / stretching_factor, normalized_grid, self.iq, left=0, right=0 - ) + # func = lambda stretching_factor: np.interp( + # normalized_grid / stretching_factor, normalized_grid, self.iq, left=0, right=0 + # ) + + # E731 do not assign a lambda expression, use a def + def func(stretching_factor): + return np.interp(normalized_grid / stretching_factor, normalized_grid, self.iq, left=0, right=0) + derivative_func = numdifftools.Derivative(func) second_derivative_func = numdifftools.Derivative(derivative_func) diff --git a/diffpy/snmf/factorizers.py b/diffpy/snmf/factorizers.py index ef6b2c0..b4620fd 100644 --- a/diffpy/snmf/factorizers.py +++ b/diffpy/snmf/factorizers.py @@ -5,27 +5,26 @@ def lsqnonneg(stretched_component_matrix, target_signal): """Finds the weights of stretched component signals under one-sided constraint. - Solves ``argmin_x || Ax - b ||_2`` for ``x>=0`` where A is the stretched_component_matrix and b is the target_signal - vector. Finds the weights of component signals given undecomposed signal data and stretched components under a - one-sided constraint on the weights. + Solves ``argmin_x || Ax - b ||_2`` for ``x>=0`` where A is the stretched_component_matrix and b is the + target_signal vector. Finds the weights of component signals given undecomposed signal data and stretched + components under a one-sided constraint on the weights. Parameters ---------- stretched_component_matrix: 2d array like The component matrix where each column contains a stretched component signal. Has dimensions R x C where R is - the length of the signal and C is the number of components. Does not need to be nonnegative. Corresponds with 'A' - from the objective function. + the length of the signal and C is the number of components. Does not need to be nonnegative. Corresponds with + 'A' from the objective function. target_signal: 1d array like - The signal that is used as reference against which weight factors will be determined. Any column from the matrix - of the entire, unfactorized input data could be used. Has length R. Does not need to be nonnegative. Corresponds - with 'b' from the objective function. + The signal that is used as reference against which weight factors will be determined. Any column from the + matrix of the entire, unfactorized input data could be used. Has length R. Does not need to be nonnegative. + Corresponds with 'b' from the objective function. Returns ------- 1d array like The vector containing component signal weights at a moment. Has length C. - """ stretched_component_matrix = np.asarray(stretched_component_matrix) target_signal = np.asarray(target_signal) diff --git a/diffpy/snmf/io.py b/diffpy/snmf/io.py index 7132d70..12eb1b2 100644 --- a/diffpy/snmf/io.py +++ b/diffpy/snmf/io.py @@ -1,6 +1,8 @@ +from pathlib import Path + import numpy as np import scipy.sparse -from pathlib import Path + from diffpy.utils.parsers.loaddata import loadData @@ -10,8 +12,8 @@ def initialize_variables(data_input, number_of_components, data_type, sparsity=1 Parameters ---------- data_input: 2d array like - 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. + The observed or simulated PDF or XRD data provided by the user. Has dimensions R x N where R is the signa + length and N is the number of PDF/XRD signals. number_of_components: int The number of component signals the user would like to decompose 'data_input' into. @@ -20,23 +22,23 @@ def initialize_variables(data_input, number_of_components, data_type, sparsity=1 The type of data the user has passed into the program. Can assume the value of 'PDF' or 'XRD.' sparsity: float, optional - The regularization parameter that behaves as the coefficient of a "sparseness" regularization term that enhances - the ability to decompose signals in the case of sparse data e.g. X-ray Diffraction data. A non-zero value - indicates sparsity in the data; greater magnitudes indicate greater amounts of sparsity. + The regularization parameter that behaves as the coefficient of a "sparseness" regularization term that + enhances the ability to decompose signals in the case of sparse data e.g. X-ray Diffraction data. + A non-zero value indicates sparsity in the data; greater magnitudes indicate greater amounts of sparsity. smoothness: float, optional - The regularization parameter that behaves as the coefficient of a "smoothness" term that ensures that component - signal weightings change smoothly with time. Assumes a default value of 1e18. + The regularization parameter that behaves as the coefficient of a "smoothness" term that ensures that + component signal weightings change smoothly with time. Assumes a default value of 1e18. Returns ------- dictionary - The collection of the names and values of the constants used in the algorithm. Contains the number of observed PDF - /XRD patterns, the length of each pattern, the type of the data, the number of components the user would like to - decompose the data into, an initial guess for the component matrix, and initial guess for the weight factor matrix - ,an initial guess for the stretching factor matrix, a parameter controlling smoothness of the solution, a - parameter controlling sparseness of the solution, the matrix representing the smoothness term, and a matrix used - to construct a hessian matrix. + The collection of the names and values of the constants used in the algorithm. Contains the number of + observed PDF/XRD patterns, the length of each pattern, the type of the data, the number of components + the user would like to decompose the data into, an initial guess for the component matrix, and initial + guess for the weight factor matrix, an initial guess for the stretching factor matrix, a parameter + controlling smoothness of the solution, a parameter controlling sparseness of the solution, the matrix + representing the smoothness term, and a matrix used to construct a hessian matrix. """ signal_length = data_input.shape[0] @@ -74,22 +76,22 @@ def initialize_variables(data_input, number_of_components, data_type, sparsity=1 def load_input_signals(file_path=None): """Processes a directory of a series of PDF/XRD patterns into a usable format. - Constructs a 2d array out of a directory of PDF/XRD patterns containing each files dependent variable column in a - new column. Constructs a 1d array containing the grid values. + Constructs a 2d array out of a directory of PDF/XRD patterns containing each files dependent variable + column in a new column. Constructs a 1d array containing the grid values. Parameters ---------- file_path: str or Path object, optional - The path to the directory containing the input XRD/PDF data. If no path is specified, defaults to the current - working directory. Accepts a string or a pathlib.Path object. Input data not on the same grid as the first file - read will be ignored. + The path to the directory containing the input XRD/PDF data. If no path is specified, defaults to the + current working directory. Accepts a string or a pathlib.Path object. Input data not on the same grid + as the first file read will be ignored. Returns ------- tuple - The tuple whose first element is an R x M 2d array made of PDF/XRD patterns as each column; R is the length of the - signal and M is the number of patterns. The tuple contains a 1d array containing the values of the grid points as - its second element; Has length R. + The tuple whose first element is an R x M 2d array made of PDF/XRD patterns as each column; R is the + length of the signal and M is the number of patterns. The tuple contains a 1d array containing the values + of the grid points as its second element; Has length R. """ diff --git a/diffpy/snmf/optimizers.py b/diffpy/snmf/optimizers.py index 8c94c58..4198907 100644 --- a/diffpy/snmf/optimizers.py +++ b/diffpy/snmf/optimizers.py @@ -1,37 +1,39 @@ -import numpy as np import cvxpy +import numpy as np def get_weights(stretched_component_gram_matrix, linear_coefficient, lower_bound, upper_bound): """Finds the weights of stretched component signals under a two-sided constraint - Solves min J(y) = (linear_coefficient)' * y + (1/2) * y' * (quadratic coefficient) * y where lower_bound <= y <= - upper_bound and stretched_component_gram_matrix is symmetric positive definite. Finds the weightings of stretched - component signals under a two-sided constraint. + Solves min J(y) = (linear_coefficient)' * y + (1/2) * y' * (quadratic coefficient) * y where + lower_bound <= y <= upper_bound and stretched_component_gram_matrix is symmetric positive definite. + Finds the weightings of stretched component signals under a two-sided constraint. Parameters ---------- stretched_component_gram_matrix: 2d array like - The Gram matrix constructed from the stretched component matrix. It is a square positive definite matrix. It has - dimensions C x C where C is the number of component signals. Must be symmetric positive definite. + The Gram matrix constructed from the stretched component matrix. It is a square positive definite matrix. + It has dimensions C x C where C is the number of component signals. Must be symmetric positive definite. linear_coefficient: 1d array like - The vector containing the product of the stretched component matrix and the transpose of the observed data matrix. - Has length C. + The vector containing the product of the stretched component matrix and the transpose of the observed + data matrix. Has length C. lower_bound: 1d array like The lower bound on the values of the output weights. Has the same dimensions of the function output. Each - element in 'lower_bound' determines the minimum value the corresponding element in the function output may take. + element in 'lower_bound' determines the minimum value the corresponding element in the function output may + take. upper_bound: 1d array like - The upper bound on the values of the output weights. Has the same dimensions of the function output. Each element - in 'upper_bound' determines the maximum value the corresponding element in the function output may take. + The upper bound on the values of the output weights. Has the same dimensions of the function output. Each + element in 'upper_bound' determines the maximum value the corresponding element in the function output may + take. Returns ------- 1d array like - The vector containing the weightings of the components needed to reconstruct a given input signal from the input - set. Has length C + The vector containing the weightings of the components needed to reconstruct a given input signal from the + input set. Has length C """ stretched_component_gram_matrix = np.asarray(stretched_component_gram_matrix) diff --git a/diffpy/snmf/polynomials.py b/diffpy/snmf/polynomials.py index 3c8d5dd..265be05 100644 --- a/diffpy/snmf/polynomials.py +++ b/diffpy/snmf/polynomials.py @@ -3,7 +3,8 @@ def rooth(linear_coefficient, constant_term): """ - Returns the largest real root of x^3+(linear_coefficient) * x + constant_term. If there are no real roots return 0. + Returns the largest real root of x^3+(linear_coefficient) * x + constant_term. If there are no real roots + return 0. Parameters ---------- @@ -15,7 +16,8 @@ def rooth(linear_coefficient, constant_term): Returns ------- ndarray of floats - The largest real root of x^3+(linear_coefficient) * x + constant_term if roots are real, else return 0 array + The largest real root of x^3+(linear_coefficient) * x + constant_term if roots are real, else + return 0 array """ diff --git a/diffpy/snmf/stretchednmfapp.py b/diffpy/snmf/stretchednmfapp.py index 7feb5ce..7080e0c 100644 --- a/diffpy/snmf/stretchednmfapp.py +++ b/diffpy/snmf/stretchednmfapp.py @@ -1,9 +1,8 @@ -import numpy as np import argparse from pathlib import Path -from diffpy.snmf.subroutines import lift_data, initialize_components -from diffpy.snmf.containers import ComponentSignal -from diffpy.snmf.io import load_input_signals, initialize_variables + +from diffpy.snmf.io import initialize_variables, load_input_signals +from diffpy.snmf.subroutines import initialize_components, lift_data ALLOWED_DATA_TYPES = ["powder_diffraction", "pd", "pair_distribution_function", "pdf"] @@ -38,7 +37,7 @@ def create_parser(): "--lift-factor", type=float, default=1, - help="The lifting factor. Data will be lifted by lifted_data = data + abs(min(data) * lift). Default is 1.", + help="The lifting factor. Data will be lifted by lifted_data = data + abs(min(data) * lift). Default 1.", ) parser.add_argument( "number-of-components", diff --git a/diffpy/snmf/subroutines.py b/diffpy/snmf/subroutines.py index e3acafb..e4f6a5f 100644 --- a/diffpy/snmf/subroutines.py +++ b/diffpy/snmf/subroutines.py @@ -1,12 +1,13 @@ +import numdifftools import numpy as np -from diffpy.snmf.optimizers import get_weights -from diffpy.snmf.factorizers import lsqnonneg + from diffpy.snmf.containers import ComponentSignal -import numdifftools +from diffpy.snmf.factorizers import lsqnonneg +from diffpy.snmf.optimizers import get_weights def initialize_components(number_of_components, number_of_signals, grid_vector): - """Initializes ComponentSignals for each of the components in the decomposition + """Initializes ComponentSignals for each of the components in the decomposition. Parameters ---------- @@ -31,15 +32,15 @@ def initialize_components(number_of_components, number_of_signals, grid_vector): def lift_data(data_input, lift=1): - """Lifts values of data_input + """Lifts values of data_input. Adds 'lift' * the minimum value in data_input to data_input element-wise. Parameters ---------- 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. + 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'. @@ -48,14 +49,13 @@ def lift_data(data_input, lift=1): ------- 2d array like The matrix that contains data_input - (min(data_input) * lift). - """ data_input = np.asarray(data_input) return data_input + np.abs(np.min(data_input) * lift) def construct_stretching_matrix(components, number_of_components, number_of_signals): - """Constructs the stretching factor matrix + """Constructs the stretching factor matrix. Parameters ---------- @@ -67,9 +67,8 @@ def construct_stretching_matrix(components, number_of_components, number_of_sign Returns ------- 2d array - The matrix containing the stretching factors for the component signals for each of the signals in the raw data. - Has dimensions `component_signal` x `number_of_signals` - + The matrix containing the stretching factors for the component signals for each of the signals in the + raw data. Has dimensions `component_signal` x `number_of_signals` """ if (len(components)) == 0: raise ValueError(f"Number of components = {number_of_components}. Number_of_components must be >= 1.") @@ -85,7 +84,7 @@ def construct_stretching_matrix(components, number_of_components, number_of_sign def construct_component_matrix(components): - """Constructs the component matrix + """Constructs the component matrix. Parameters ---------- @@ -96,7 +95,6 @@ def construct_component_matrix(components): ------- 2d array The matrix containing the component signal values. Has dimensions `signal_length` x `number_of_components`. - """ signal_length = len(components[0].iq) number_of_components = len(components) @@ -112,7 +110,7 @@ def construct_component_matrix(components): def construct_weight_matrix(components): - """Constructs the weights matrix + """Constructs the weights matrix. Constructs a ΔΆ x M matrix where K is the number of components and M is the number of signals. Each element is the stretching factor for a specific @@ -150,16 +148,16 @@ def update_weights(components, data_input, method=None): components: tuple of ComponentSignal objects The tuple containing the component signals. method: str - The string specifying which method should be used to find a new weight matrix: non-negative least squares or a - quadratic program. + The string specifying which method should be used to find a new weight matrix: non-negative least squares + or a quadratic program. data_input: 2d array The 2d array containing the user-provided signals. Returns ------- 2d array - The 2d array containing the weight factors for each component for each signal from `data_input`. Has dimensions - K x M where K is the number of components and M is the number of signals in `data_input.` + The 2d array containing the weight factors for each component for each signal from `data_input`. + Has dimensions K x M where K is the number of components and M is the number of signals in `data_input.` """ data_input = np.asarray(data_input) weight_matrix = construct_weight_matrix(components) @@ -200,7 +198,6 @@ def reconstruct_signal(components, signal_idx): ------- 1d array like The reconstruction of a signal from calculated weights, stretching factors, and iq values. - """ signal_length = len(components[0].grid) reconstruction = np.zeros(signal_length) @@ -212,13 +209,14 @@ def reconstruct_signal(components, signal_idx): def initialize_arrays(number_of_components, number_of_moments, signal_length): - """Generates the initial guesses for the weight, stretching, and component matrices + """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 - 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) x (number_of_moments) matrix where each element is between 0 and 1. + 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) 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) x (number_of_moments) matrix where + each element is between 0 and 1. Parameters ---------- @@ -236,7 +234,6 @@ def initialize_arrays(number_of_components, number_of_moments, signal_length): 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. - """ component_matrix_guess = np.random.rand(signal_length, number_of_components) weight_matrix_guess = np.random.rand(number_of_components, number_of_moments) @@ -258,25 +255,26 @@ def objective_function( Parameters ---------- residual_matrix: 2d array like - The matrix where each column is the difference between an experimental PDF/XRD pattern and a calculated PDF/XRD - pattern at each grid point. Has dimensions R x M where R is the length of each pattern and M is the amount of - patterns. + The matrix where each column is the difference between an experimental PDF/XRD pattern and a calculated + PDF/XRD pattern at each grid point. Has dimensions R x M where R is the length of each pattern and M is + the amount of patterns. stretching_factor_matrix: 2d array like - The matrix containing the stretching factors of the calculated component signal. Has dimensions K x M where K is - the amount of components and M is the number of experimental PDF/XRD patterns. + The matrix containing the stretching factors of the calculated component signal. Has dimensions K x M where + K is the amount of components and M is the number of experimental PDF/XRD patterns. smoothness: float - The coefficient of the smoothness term which determines the intensity of the smoothness term and its behavior. - It is not very sensitive and is usually adjusted by multiplying it by ten. + The coefficient of the smoothness term which determines the intensity of the smoothness term and its + behavior. It is not very sensitive and is usually adjusted by multiplying it by ten. smoothness_term: 2d array like The regularization term that ensures that smooth changes in the component stretching signals are favored. - Has dimensions (M-2) x M where M is the amount of experimentally obtained PDF/XRD patterns, the moment amount. + Has dimensions (M-2) x M where M is the amount of experimentally obtained PDF/XRD patterns, the moment + amount. component_matrix: 2d array like - The matrix containing the calculated component signals of the experimental PDF/XRD patterns. Has dimensions R x K - where R is the signal length and K is the number of component signals. + The matrix containing the calculated component signals of the experimental PDF/XRD patterns. Has dimensions + R x K where R is the signal length and K is the number of component signals. sparsity: float The parameter determining the intensity of the sparsity regularization term which enables the algorithm to @@ -286,7 +284,6 @@ def objective_function( ------- float The value of the objective function. - """ residual_matrix = np.asarray(residual_matrix) stretching_factor_matrix = np.asarray(stretching_factor_matrix) @@ -301,10 +298,10 @@ def objective_function( def get_stretched_component(stretching_factor, component, signal_length): """Applies a stretching factor to a component signal. - Computes a stretched signal and reinterpolates it onto the original grid of points. Uses a normalized grid of evenly - spaced integers counting from 0 to signal_length (exclusive) to approximate values in between grid nodes. Once this - grid is stretched, values at grid nodes past the unstretched signal's domain are set to zero. Returns the - approximate values of x(r/a) from x(r) where x is a component signal. + Computes a stretched signal and reinterpolates it onto the original grid of points. Uses a normalized grid + of evenly spaced integers counting from 0 to signal_length (exclusive) to approximate values in between grid + nodes. Once this grid is stretched, values at grid nodes past the unstretched signal's domain are set to zero. + Returns the approximate values of x(r/a) from x(r) where x is a component signal. Parameters ---------- @@ -320,7 +317,6 @@ def get_stretched_component(stretching_factor, component, signal_length): tuple of 1d array of floats The calculated component signal with stretching factors applied. Has length N, the length of the unstretched component signal. Also returns the gradient and hessian of the stretching transformation. - """ component = np.asarray(component) normalized_grid = np.arange(signal_length) @@ -363,23 +359,23 @@ def update_weights_matrix( The length of the experimental signal patterns stretching_factor_matrix: 2d array like - The matrx containing the stretching factors of the calculated component signals. Has dimensions K x M where K is - the number of component signals and M is the number of XRD/PDF patterns. + The matrx containing the stretching factors of the calculated component signals. Has dimensions K x M + where K is the number of component signals and M is the number of XRD/PDF patterns. - component_matrix: 2d array like - The matrix containing the unstretched calculated component signals. Has dimensions N x K where N is the length of - the signals and K is the number of component signals. + component_matrix: 2d array lik + The matrix containing the unstretched calculated component signals. Has dimensions N x K where N is the + length of the signals and K is the number of component signals. data_input: 2d array like - The experimental series of PDF/XRD patterns. Has dimensions N x M where N is the length of the PDF/XRD signals and - M is the number of PDF/XRD patterns. + The experimental series of PDF/XRD patterns. Has dimensions N x M where N is the length of the PDF/XRD + signals and M is the number of PDF/XRD patterns. moment_amount: int The number of PDF/XRD patterns from the experimental data. weights_matrix: 2d array like - The matrix containing the weights of the stretched component signals. Has dimensions K x M where K is the number - of component signals and M is the number of XRD/PDF patterns. + The matrix containing the weights of the stretched component signals. Has dimensions K x M where K is + the number of component signals and M is the number of XRD/PDF patterns. method: str The string specifying the method for obtaining individual weights. @@ -388,7 +384,6 @@ def update_weights_matrix( ------- 2d array like The matrix containing the new weight factors of the stretched component signals. - """ stretching_factor_matrix = np.asarray(stretching_factor_matrix) component_matrix = np.asarray(component_matrix) @@ -417,29 +412,29 @@ def update_weights_matrix( def get_residual_matrix( component_matrix, weights_matrix, stretching_matrix, data_input, moment_amount, component_amount, signal_length ): - """Obtains the residual matrix between the experimental data and calculated data + """Obtains the residual matrix between the experimental data and calculated data. - Calculates the difference between the experimental data and the reconstructed experimental data created from the - calculated components, weights, and stretching factors. For each experimental pattern, the stretched and weighted - components making up that pattern are subtracted. + Calculates the difference between the experimental data and the reconstructed experimental data created from + the calculated components, weights, and stretching factors. For each experimental pattern, the stretched and + weighted components making up that pattern are subtracted. Parameters ---------- component_matrix: 2d array like - The matrix containing the calculated component signals. Has dimensions N x K where N is the length of the signal - and K is the number of calculated component signals. + The matrix containing the calculated component signals. Has dimensions N x K where N is the length of the + signal and K is the number of calculated component signals. weights_matrix: 2d array like - The matrix containing the calculated weights of the stretched component signals. Has dimensions K x M where K is - the number of components and M is the number of moments or experimental PDF/XRD patterns. + The matrix containing the calculated weights of the stretched component signals. Has dimensions K x M where + K is the number of components and M is the number of moments or experimental PDF/XRD patterns. stretching_matrix: 2d array like - The matrix containing the calculated stretching factors of the calculated component signals. Has dimensions K x M - where K is the number of components and M is the number of moments or experimental PDF/XRD patterns. + The matrix containing the calculated stretching factors of the calculated component signals. Has dimensions + K x M where K is the number of components and M is the number of moments or experimental PDF/XRD patterns. data_input: 2d array like - The matrix containing the experimental PDF/XRD data. Has dimensions N x M where N is the length of the signals and - M is the number of signal patterns. + The matrix containing the experimental PDF/XRD data. Has dimensions N x M where N is the length of the + signals and M is the number of signal patterns. moment_amount: int The number of patterns in the experimental data. Represents the number of moments in time in the data series @@ -454,11 +449,10 @@ def get_residual_matrix( Returns ------- 2d array like - The matrix containing the residual between the experimental data and reconstructed data from calculated values. - Has dimensions N x M where N is the signal length and M is the number of moments. Each column contains the - difference between an experimental signal and a reconstruction of that signal from the calculated weights, - components, and stretching factors. - + The matrix containing the residual between the experimental data and reconstructed data from calculated + values. Has dimensions N x M where N is the signal length and M is the number of moments. Each column + contains the difference between an experimental signal and a reconstruction of that signal from the + calculated weights, components, and stretching factors. """ component_matrix = np.asarray(component_matrix) weights_matrix = np.asarray(weights_matrix) @@ -478,7 +472,7 @@ def get_residual_matrix( def reconstruct_data(components): - """Reconstructs the `input_data` matrix + """Reconstructs the `input_data` matrix. Reconstructs the `input_data` matrix from calculated component signals, weights, and stretching factors. @@ -491,7 +485,6 @@ def reconstruct_data(components): ------- 2d array The 2d array containing the reconstruction of input_data. - """ signal_length = len(components[0].iq) number_of_signals = len(components[0].weights) diff --git a/diffpy/snmf/tests/test_containers.py b/diffpy/snmf/tests/test_containers.py index 2ccb036..1c78be0 100644 --- a/diffpy/snmf/tests/test_containers.py +++ b/diffpy/snmf/tests/test_containers.py @@ -1,5 +1,6 @@ -import pytest import numpy as np +import pytest + from diffpy.snmf.containers import ComponentSignal tas = [ diff --git a/diffpy/snmf/tests/test_factorizers.py b/diffpy/snmf/tests/test_factorizers.py index a0c4546..c20d192 100644 --- a/diffpy/snmf/tests/test_factorizers.py +++ b/diffpy/snmf/tests/test_factorizers.py @@ -1,6 +1,6 @@ import numpy as np -import scipy import pytest + from diffpy.snmf.factorizers import lsqnonneg tl = [ diff --git a/diffpy/snmf/tests/test_optimizers.py b/diffpy/snmf/tests/test_optimizers.py index 25d90e7..ab7a71f 100644 --- a/diffpy/snmf/tests/test_optimizers.py +++ b/diffpy/snmf/tests/test_optimizers.py @@ -1,4 +1,5 @@ import pytest + from diffpy.snmf.optimizers import get_weights tm = [ diff --git a/diffpy/snmf/tests/test_polynomials.py b/diffpy/snmf/tests/test_polynomials.py index 6078b26..d935834 100644 --- a/diffpy/snmf/tests/test_polynomials.py +++ b/diffpy/snmf/tests/test_polynomials.py @@ -1,5 +1,6 @@ -import pytest import numpy as np +import pytest + from diffpy.snmf.polynomials import rooth tr = [ diff --git a/diffpy/snmf/tests/test_subroutines.py b/diffpy/snmf/tests/test_subroutines.py index bdb721f..66029d2 100644 --- a/diffpy/snmf/tests/test_subroutines.py +++ b/diffpy/snmf/tests/test_subroutines.py @@ -1,20 +1,20 @@ -import pytest import numpy as np +import pytest + from diffpy.snmf.containers import ComponentSignal from diffpy.snmf.subroutines import ( - objective_function, - get_stretched_component, - reconstruct_data, - get_residual_matrix, - update_weights_matrix, - initialize_arrays, - lift_data, - initialize_components, - construct_stretching_matrix, construct_component_matrix, + construct_stretching_matrix, construct_weight_matrix, - update_weights, + get_residual_matrix, + get_stretched_component, + initialize_components, + lift_data, + objective_function, + reconstruct_data, reconstruct_signal, + update_weights, + update_weights_matrix, ) to = [ @@ -336,7 +336,8 @@ def test_initialize_components(tcc): ([ComponentSignal([0, 0.5, 1, 1.5], 20, 0), ComponentSignal([0, 0.5, 1, 1.5], 20, 1)], 2, 20), ([ComponentSignal([0, 0.5, 1, 1.5], 20, 0), ComponentSignal([0, 0.5, 1, 21.5], 20, 1)], 2, 20), ([ComponentSignal([0, 1, 1.5], 20, 0), ComponentSignal([0, 0.5, 1, 21.5], 20, 1)], 2, 20), - # ([ComponentSignal([0,.5,1,1.5],20,0),ComponentSignal([0,.5,1,1.5],20,1)],1,-3), # Negative signal length. Raises an exception + # ([ComponentSignal([0,.5,1,1.5],20,0),ComponentSignal([0,.5,1,1.5],20,1)],1,-3), + # Negative signal length. Raises an exception # ([],1,20), # Empty components. Raises an Exception # ([],-1,20), # Empty components with negative number of components. Raises an exception # ([],0,20), # Empty components with zero number of components. Raises an exception @@ -379,7 +380,9 @@ def test_construct_stretching_matrix(tcso): ), ([ComponentSignal([0.25], 20, 0), ComponentSignal([0.25], 20, 1), ComponentSignal([0.25], 20, 2)]), ([ComponentSignal([0, 0.25, 0.5, 0.75, 1], 20, 0), ComponentSignal([0, 0.25, 0.5, 0.75, 1], 20, 1)]), - # ([ComponentSignal([[0, .25, .5, .75, 1],[0, .25, .5, .75, 1]], 20, 0), ComponentSignal([[0, .25, .5, .75, 1],[0, .25, .5, .75, 1]], 20, 1)]), # iq is multidimensional. Expected to fail + # ([ComponentSignal([[0, .25, .5, .75, 1],[0, .25, .5, .75, 1]], 20, 0), + # ComponentSignal([[0, .25, .5, .75, 1],[0, .25, .5, .75, 1]], 20, 1)]), + # iq is multidimensional. Expected to fail # (ComponentSignal([], 20, 0)), # Expected to fail # ([]), #Expected to fail ] diff --git a/doc/source/conf.py b/doc/source/conf.py index 4c28b45..c450885 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -6,12 +6,13 @@ # -- Path setup -------------------------------------------------------------- +import os + # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # import sys -import os sys.path.insert(0, os.path.abspath("../..")) @@ -48,7 +49,7 @@ # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] -from jinja2 import Template, Environment, FileSystemLoader +from jinja2 import Environment, FileSystemLoader, Template source_suffix = ".rst" diff --git a/doc/source/release.rst b/doc/source/release.rst index ca8fa0b..8956c78 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -1,4 +1,3 @@ .. index:: release notes .. include:: /../../CHANGELOG.rst - diff --git a/requirements/docs.txt b/requirements/docs.txt index 661d44d..8b08785 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -1,4 +1,3 @@ make sphinx_rtd_theme m2r - diff --git a/run_tests.py b/run_tests.py index 69cde5f..829a2e3 100644 --- a/run_tests.py +++ b/run_tests.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import sys + import pytest if __name__ == "__main__": diff --git a/setup.py b/setup.py index 54d138c..7a02188 100644 --- a/setup.py +++ b/setup.py @@ -8,8 +8,8 @@ """ import os -from setuptools import setup, find_packages +from setuptools import find_packages, setup MYDIR = os.path.dirname(os.path.abspath(__file__))