Skip to content

Commit f00050e

Browse files
committed
Merge branch 'main' into mainfunction
2 parents 0e86148 + f03ac68 commit f00050e

File tree

4 files changed

+68
-21
lines changed

4 files changed

+68
-21
lines changed

diffpy/snmf/io.py

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from diffpy.utils.parsers.loaddata import loadData
55

66

7-
def initialize_variables(data_input, component_amount, data_type, sparsity=1, smoothness=1e18):
7+
def initialize_variables(data_input, number_of_components, data_type, sparsity=1, smoothness=1e18):
88
"""Determines the variables and initial values used in the SNMF algorithm.
99
1010
Parameters
@@ -13,7 +13,7 @@ def initialize_variables(data_input, component_amount, data_type, sparsity=1, sm
1313
The observed or simulated PDF or XRD data provided by the user. Has dimensions R x N where R is the signal length
1414
and N is the number of PDF/XRD signals.
1515
16-
component_amount: int
16+
number_of_components: int
1717
The number of component signals the user would like to decompose 'data_input' into.
1818
1919
data_type: str
@@ -40,27 +40,19 @@ def initialize_variables(data_input, component_amount, data_type, sparsity=1, sm
4040
4141
"""
4242
signal_length = data_input.shape[0]
43-
moment_amount = data_input.shape[1]
43+
number_of_signals = data_input.shape[1]
4444

45-
component_matrix_guess = np.random.rand(signal_length, component_amount)
46-
weight_matrix_guess = np.random.rand(component_amount, moment_amount)
47-
stretching_matrix_guess = np.ones(component_amount, moment_amount) + np.random.randn(component_amount,
48-
moment_amount) * 1e-3
45+
diagonals = [np.ones(number_of_signals - 2), -2 * np.ones(number_of_signals - 2), np.ones(number_of_signals - 2)]
46+
smoothness_term = .25 * scipy.sparse.diags(diagonals, [0, 1, 2], shape=(number_of_signals - 2, number_of_signals))
4947

50-
diagonals = [np.ones(moment_amount - 2), -2 * np.ones(moment_amount - 2), np.ones(moment_amount - 2)]
51-
smoothness_term = .25 * scipy.sparse.diags(diagonals, [0, 1, 2], shape=(moment_amount - 2, moment_amount))
52-
53-
hessian_helper_matrix = scipy.sparse.block_diag([smoothness_term.T @ smoothness_term] * component_amount)
54-
sequence = np.arange(moment_amount * component_amount).reshape(component_amount, moment_amount).T.flatten()
48+
hessian_helper_matrix = scipy.sparse.block_diag([smoothness_term.T @ smoothness_term] * number_of_components)
49+
sequence = np.arange(number_of_signals * number_of_components).reshape(number_of_components, number_of_signals).T.flatten()
5550
hessian_helper_matrix = hessian_helper_matrix[sequence, :][:, sequence]
5651

5752
return {
5853
"signal_length": signal_length,
59-
"moment_amount": moment_amount,
60-
"component_matrix_guess": component_matrix_guess,
61-
"weight_matrix_guess": weight_matrix_guess,
62-
"stretching_matrix_guess": stretching_matrix_guess,
63-
"component_amount": component_amount,
54+
"number_of_signals": number_of_signals,
55+
"number_of_components": number_of_components,
6456
"data_type": data_type,
6557
"smoothness": smoothness,
6658
"sparsity": sparsity,

diffpy/snmf/subroutines.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def initialize_components(number_of_components, number_of_signals, grid_vector):
2525
raise ValueError(f"Number of components = {number_of_components}. Number_of_components must be >= 1.")
2626
components = list()
2727
for component in range(number_of_components):
28-
component = ComponentSignal(grid_vector,number_of_signals,component)
28+
component = ComponentSignal(grid_vector, number_of_signals, component)
2929
components.append(component)
3030
return tuple(components)
3131

@@ -54,6 +54,36 @@ def lift_data(data_input, lift=1):
5454
return data_input + np.abs(np.min(data_input) * lift)
5555

5656

57+
def construct_stretching_matrix(components, number_of_components, number_of_signals):
58+
"""Constructs the stretching factor matrix
59+
60+
Parameters
61+
----------
62+
components: tuple of ComponentSignal objects
63+
The tuple containing the component signals in ComponentSignal objects.
64+
number_of_signals: int
65+
The number of signals in the data provided by the user.
66+
67+
Returns
68+
-------
69+
2d array
70+
The matrix containing the stretching factors for the component signals for each of the signals in the raw data.
71+
Has dimensions `component_signal` x `number_of_signals`
72+
73+
"""
74+
if (len(components)) == 0:
75+
raise ValueError(f"Number of components = {number_of_components}. Number_of_components must be >= 1.")
76+
number_of_components = len(components)
77+
78+
if number_of_signals <= 0:
79+
raise ValueError(f"Number of signals = {number_of_signals}. Number_of_signals must be >= 1.")
80+
81+
stretching_factor_matrix = np.zeros((number_of_components, number_of_signals))
82+
for i, component in enumerate(components):
83+
stretching_factor_matrix[i] = component.stretching_factors
84+
return stretching_factor_matrix
85+
86+
5787
def initialize_arrays(number_of_components, number_of_moments, signal_length):
5888
"""Generates the initial guesses for the weight, stretching, and component matrices
5989

diffpy/snmf/tests/test_subroutines.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import pytest
22
import numpy as np
3+
from diffpy.snmf.containers import ComponentSignal
34
from diffpy.snmf.subroutines import objective_function, get_stretched_component, reconstruct_data, get_residual_matrix, \
4-
update_weights_matrix, initialize_arrays, lift_data, initialize_components
5+
update_weights_matrix, initialize_arrays, lift_data, initialize_components, construct_stretching_matrix
56

67
to = [
78
([[[1, 2], [3, 4]], [[5, 6], [7, 8]], 1e11, [[1, 2], [3, 4]], [[1, 2], [3, 4]], 1], 2.574e14),
@@ -161,3 +162,27 @@ def test_initialize_components(tcc):
161162
assert len(actual) == tcc[0]
162163
assert len(actual[0].weights) == tcc[1]
163164
assert (actual[0].grid == np.array(tcc[2])).all()
165+
166+
tcso =[([ComponentSignal([0,.5,1,1.5],20,0)],1,20),
167+
([ComponentSignal([0,.5,1,1.5],20,0)],4,20),
168+
# ([ComponentSignal([0,.5,1,1.5],20,0)],0,20), # Raises an exception
169+
# ([ComponentSignal([0,.5,1,1.5],20,0)],-2,20), # Raises an exception
170+
# ([ComponentSignal([0,.5,1,1.5],20,0)],1,0), # Raises an Exception
171+
# ([ComponentSignal([0,.5,1,1.5],20,0)],1,-3), # Raises an exception
172+
([ComponentSignal([0,.5,1,1.5],20,0),ComponentSignal([0,.5,1,1.5],20,1)],2,20),
173+
([ComponentSignal([0,.5,1,1.5],20,0),ComponentSignal([0,.5,1,21.5],20,1)],2,20),
174+
([ComponentSignal([0,1,1.5],20,0),ComponentSignal([0,.5,1,21.5],20,1)],2,20),
175+
# ([ComponentSignal([0,.5,1,1.5],20,0),ComponentSignal([0,.5,1,1.5],20,1)],1,-3), # Negative signal length. Raises an exception
176+
#([],1,20), # Empty components. Raises an Exception
177+
#([],-1,20), # Empty components with negative number of components. Raises an exception
178+
#([],0,20), # Empty components with zero number of components. Raises an exception
179+
#([],1,0), # Empty components with zero signal length. Raises an exception.
180+
#([],-1,-2), # Empty components with negative number of components and signal length Raises an exception.
181+
182+
]
183+
@pytest.mark.parametrize('tcso',tcso)
184+
def test_construct_stretching_matrix(tcso):
185+
actual = construct_stretching_matrix(tcso[0],tcso[1],tcso[2])
186+
for component in tcso[0]:
187+
np.testing.assert_allclose(actual[component.id,:], component.stretching_factors)
188+
#assert actual[component.id, :] == component.stretching_factors

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python
22

3-
# Installation script for diffpy.pdfmorph
3+
# Installation script for diffpy.snmf
44

55
"""diffpy.snmf - a package implementing the stretched NMF algorithm.
66
@@ -28,7 +28,7 @@
2828
entry_points={
2929
# define console_scripts here, see setuptools docs for details.
3030
'console_scripts': [
31-
'pdfmorph = diffpy.pdfmorph.pdfmorphapp:main',
31+
'snmf = diffpy.snmf.stretchednmfapp:main',
3232
],
3333
},
3434
test_suite='tests',

0 commit comments

Comments
 (0)