diff --git a/.gitignore b/.gitignore index cc53dcf..3549f1b 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ __pycache__/ .cache nosetests.xml coverage.xml +*.pyc diff --git a/src/original/ETP_SRI/__pycache__/LinearFitting.cpython-39.pyc b/src/original/ETP_SRI/__pycache__/LinearFitting.cpython-39.pyc index f356058..6f5bef6 100644 Binary files a/src/original/ETP_SRI/__pycache__/LinearFitting.cpython-39.pyc and b/src/original/ETP_SRI/__pycache__/LinearFitting.cpython-39.pyc differ diff --git a/src/standardized/ETP_SRI_LinearFitting.py b/src/standardized/ETP_SRI_LinearFitting.py index 40deb8d..712d4b8 100644 --- a/src/standardized/ETP_SRI_LinearFitting.py +++ b/src/standardized/ETP_SRI_LinearFitting.py @@ -20,7 +20,7 @@ class ETP_SRI_LinearFitting(OsipiBase): # Algorithm requirements required_bvalues = 3 - required_thresholds = [1,1] # Interval from 1 to 1, in case submissions allow a custom number of thresholds + required_thresholds = [0,1] # Interval from 1 to 1, in case submissions allow a custom number of thresholds required_bounds = False required_bounds_optional = True # Bounds may not be required but are optional required_initial_guess = False @@ -45,7 +45,7 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non # Check the inputs - def ivim_fit(self, signals, bvalues): + def ivim_fit(self, signals, bvalues=None): """ We may want this function to be as simple as data and b-values in -> parameter estimates out. @@ -55,8 +55,13 @@ def ivim_fit(self, signals, bvalues): This makes the execution of submissions easy and predictable. All execution stepts requires should be performed here. """ + if bvalues is None: + bvalues = self.bvalues - ETP_object = LinearFit(self.thresholds[0]) + if self.thresholds is None: + ETP_object = LinearFit() + else: + ETP_object = LinearFit(self.thresholds[0]) f, D, Dstar = ETP_object.ivim_fit(bvalues, signals) @@ -73,7 +78,6 @@ def ivim_model(b, S0=1, f=0.1, Dstar=0.03, D=0.001): signals = ivim_model(bvalues) -model = ETP_SRI_LinearFitting(thresholds=[200]) +model = ETP_SRI_LinearFitting() results = model.ivim_fit(signals, bvalues) -test = model.osipi_simple_bias_and_RMSE_test(SNR=20, bvalues=bvalues, f=0.1, Dstar=0.03, D=0.001, noise_realizations=10) -#model.print_requirements_osipi() \ No newline at end of file +test = model.osipi_simple_bias_and_RMSE_test(SNR=20, bvalues=bvalues, f=0.1, Dstar=0.03, D=0.001, noise_realizations=10) \ No newline at end of file diff --git a/src/wrappers/OsipiBase.py b/src/wrappers/OsipiBase.py index 8624aa2..ea15680 100644 --- a/src/wrappers/OsipiBase.py +++ b/src/wrappers/OsipiBase.py @@ -6,15 +6,23 @@ class OsipiBase: """The base class for OSIPI IVIM fitting""" def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=None): - self.bvalues = np.asarray(bvalues) - self.thresholds = np.asarray(thresholds) - self.bounds = np.asarray(bounds) - self.initial_guess = np.asarray(initial_guess) + # Define the attributes as numpy arrays only if they are not None + self.bvalues = np.asarray(bvalues) if bvalues is not None else None + self.thresholds = np.asarray(thresholds) if thresholds is not None else None + self.bounds = np.asarray(bounds) if bounds is not None else None + self.initial_guess = np.asarray(initial_guess) if initial_guess is not None else None def osipi_fit(self, data=None, bvalues=None, initial_guess=None, bounds=None, thresholds=None, **kwargs): """Fits the data with the bvalues Returns [S0, f, D*, D] """ + if bvalues is None: + bvalues = self.bvalues + + args = [data, bvalues, initial_guess, bounds, thresholds] + args = [arg for arg in args if arg is not None] + f, Dstar, D = self.ivim_fit(*args) + #self.parameter_estimates = self.ivim_fit(data, bvalues) pass diff --git a/src/wrappers/__pycache__/OsipiBase.cpython-39.pyc b/src/wrappers/__pycache__/OsipiBase.cpython-39.pyc index 22331cb..2dc522f 100644 Binary files a/src/wrappers/__pycache__/OsipiBase.cpython-39.pyc and b/src/wrappers/__pycache__/OsipiBase.cpython-39.pyc differ diff --git a/tests/IVIMmodels/data/test_GenerateData.py b/tests/IVIMmodels/data/test_GenerateData.py index a8370cf..bd3e655 100644 --- a/tests/IVIMmodels/data/test_GenerateData.py +++ b/tests/IVIMmodels/data/test_GenerateData.py @@ -1,7 +1,7 @@ import numpy as np import numpy.testing as npt import pytest -import torch +#import torch from utilities.data_simulation.GenerateData import GenerateData diff --git a/tests/IVIMmodels/unit_tests/test_ivim_fit_linear.py b/tests/IVIMmodels/unit_tests/test_ivim_fit_linear.py index 5436c2c..d54f86e 100644 --- a/tests/IVIMmodels/unit_tests/test_ivim_fit_linear.py +++ b/tests/IVIMmodels/unit_tests/test_ivim_fit_linear.py @@ -7,6 +7,8 @@ from utilities.data_simulation.GenerateData import GenerateData from src.original.ETP_SRI.LinearFitting import LinearFit +# Import the standardized version of the algorithm +from src.standardized.ETP_SRI_LinearFitting import ETP_SRI_LinearFitting #run using python -m pytest from the root folder @@ -39,10 +41,17 @@ def test_linear_fit(D, bvals): ] @pytest.mark.parametrize("f, D, Dp, bvals", test_ivim_data) def test_ivim_fit(f, D, Dp, bvals): + # We should make a wrapper that runs this for a range of different settings, such as b thresholds, bounds, etc. + # An additional inputs to these functions could perhaps be a "settings" class with attributes that are the settings to the + # algorithms. I.e. bvalues, thresholds, bounds, initial guesses. + # That way, we can write something that defines a range of settings, and then just run them through here. gd = GenerateData() gd_signal = gd.ivim_signal(D, Dp, f, 1, bvals) - fit = LinearFit() - [f_fit, D_fit, Dp_fit] = fit.ivim_fit(bvals, gd_signal) + #fit = LinearFit() # This is the old code by ETP + + fit = ETP_SRI_LinearFitting() # This is the standardized format by IAR, which every algorithm will be implemented with + + [f_fit, Dp_fit, D_fit] = fit.ivim_fit(gd_signal, bvals) # Note that I have transposed Dp and D. We should decide on a standard order for these. I usually go with f, Dp, and D ordered after size. npt.assert_allclose([f, D], [f_fit, D_fit], atol=1e-5) if not np.allclose(f, 0): npt.assert_allclose(Dp, Dp_fit, rtol=1e-2, atol=1e-3)