From ac3125f15c9dfe695708bd0b7b8c82a7015001c2 Mon Sep 17 00:00:00 2001 From: IvanARashid Date: Tue, 29 Aug 2023 10:36:22 +0200 Subject: [PATCH] Tried some testing with the standardized version of an algorithm --- .gitignore | 1 + .../__pycache__/LinearFitting.cpython-39.pyc | Bin 3097 -> 3121 bytes src/standardized/ETP_SRI_LinearFitting.py | 16 ++++++++++------ src/wrappers/OsipiBase.py | 16 ++++++++++++---- .../__pycache__/OsipiBase.cpython-39.pyc | Bin 5697 -> 5987 bytes tests/IVIMmodels/data/test_GenerateData.py | 2 +- .../unit_tests/test_ivim_fit_linear.py | 13 +++++++++++-- 7 files changed, 35 insertions(+), 13 deletions(-) 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 f356058523cabb5462f63a9f91c2f7805550e013..6f5bef64e54ae46041f9e80863117f6c57daf1e9 100644 GIT binary patch delta 339 zcmbO!u~C9Ik(ZZ?0SHM7*ZIU8JieuSc-B=n6p@5>T8%%m{OQ)m{VAKS!0-LS!;nZllL%7Db%o}F$FWA zD+MZK?`5fFEn(QahuM!wktwg>7JFiGVo_0I)t%&OE|ECu;FmABYIWLjp)WNkKC z#;D1jY$jX+AXoEqF>*0(Ze~kkmgfg@i$H=!f*^tkM6d#hTg*B6=|z&0Ik*CKqBwI( z;*(2D^3&3yIMZRwA{mfc2_O;0S)7@kmzWdpQV=z{l}nRRfAV^+sce!UdDY2Y+=nAs(vqBV>Q8EcqQm};0)*n3%OSxcBVUtsoQQe-L4 ztV+GbQjnihd5axHre&7gV#+JH#hzH4SX7i)IoX~~mhsl)ST++j9*|@BH_v8EW0n^J zGK+*k1V4yi0uii0;udpGetMDAWCgB3om-qaCGp9nCHZM-w>Z;b%pzHkT1k*v&f?7U zyu_S%mx5c9=W=N>>P|k+HI+>YB(F7@kw<)TCAYY!co8#DK$GJZYhGz?L1huh=3A4O Na%(aQOg_(@1OSybQ9b|w 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 22331cb0b03afae04bf717781f3ad0a093ea4721..2dc522f45c3869baf6526cce0218acd7dd650de0 100644 GIT binary patch delta 1275 zcmZ`&&1(};5P!3~Nw#S=ZIht*8tcbJtrbhLNW25ryx*I7GxOWo>e%;W*ffkF z!>8r>Ppi=VK70;r3%4#~V<_4zOBd7$>1KhwfwxCw@N<$@RL5d|b@l?6Co(8;W z?@`duaHViL9SB)$`A%~M1&~c>E^H|)T8eS<;vs~D;wi~-Pc?Z~?rUJ+i5Hy6*-j~4 z%r8&2_!I1bTcV@!+prWwbL_PYm$eNZl|=N124P|6a;OX9 zBjg}QOSW;e|GE)}jCf=0#$}sw2#@r{%e-#!(TD}^7Rv?8DTq(uA91M&4K4p~&=3WQ z^SS}6;#bp?zPcoJi^So_5jMn&=Bp$1gSsX43)S>9%cXlozPY2fyaX5%ZzGp3k|RzH z4e`9nR~@wJ<$8X{&KAtvHh4a?@@7q3nXd)U1uh;DqtPuteO}xzs?pvHJW8QjK4TU< z%~|0kPhB;+Y%vk74WgR5K3AJV8gEYD3-3e_J*}cqR(+NzLwsnB!(*}AnuXJ1CU#~f zOmr7PoM4zBK|t;E69h?ulLV&-rU>dnNXrn_SeqIMhJ_a!1fTdD>mEJqf?=LMkuO^1 PTxJq*=g^0%LrDDx2-5?F delta 1007 zcmZvb%WD%+6o==`BhQ({G)+QVlA4-Qqf!cWQ>f{pMSNkQEeHjvm&`N{=H;DftkQ+J z6IXI~Zq#L5DftToSAw{3934blc_le9_Na9UY<@`}EOUh%Yy+_}ei zBOvP`Y1b)}w+xNqiS_Zm;W(~H?8`e@rNj`zdA|??zL|&l}^ugoq#OHVsa)ZC| z3CLkgdZ1)VY>$J1yx<@i%T*R_>DGe_CZ=owb-#%Csvz&5Y{`bZtaOW^;;90lTR5= z6Sowk;T?9RrApihq{Ugg;Yo{e&hE>Y-}75IBhqYntgSk6mxt2msa>o>H9H(WWBd9R z&7OpPX>9~*5+!ViT23S>t+V(kTYSk?;Guwg15OJ+zkJKV*C!Cuh#ABz0_($1Au5P@ z!~$XsK`uw2iW+JIa|zH>3`{){NkqlJd>KqpD$JZ2nUkUt$5vY%_n_(3@CT!xD+adl E9~yDSRsaA1 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)