diff --git a/src/standardized/IAR_LU_biexp.py b/src/standardized/IAR_LU_biexp.py index 801d4d0..1ec3c16 100644 --- a/src/standardized/IAR_LU_biexp.py +++ b/src/standardized/IAR_LU_biexp.py @@ -114,7 +114,10 @@ def ivim_fit_full_volume(self, signals, bvalues, **kwargs): Returns: _type_: _description_ """ - + # Make sure bounds and initial guess conform to the algorithm requirements + bounds = [[self.bounds["S0"][0], self.bounds["f"][0], self.bounds["Dp"][0], self.bounds["D"][0]], + [self.bounds["S0"][1], self.bounds["f"][1], self.bounds["Dp"][1], self.bounds["D"][1]]] + initial_guess = [self.initial_guess["S0"], self.initial_guess["f"], self.initial_guess["Dp"], self.initial_guess["D"]] if self.IAR_algorithm is None: if bvalues is None: bvalues = self.bvalues @@ -125,7 +128,7 @@ def ivim_fit_full_volume(self, signals, bvalues, **kwargs): bvec[:,2] = 1 gtab = gradient_table(bvalues, bvecs=bvec, b0_threshold=0) - self.IAR_algorithm = IvimModelBiExp(gtab, bounds=self.bounds, initial_guess=self.initial_guess) + self.IAR_algorithm = IvimModelBiExp(gtab, bounds=bounds, initial_guess=initial_guess) b0_index = np.where(bvalues == 0)[0][0] mask = signals[...,b0_index]>0 fit_results = self.IAR_algorithm.fit(signals, mask=mask) diff --git a/src/standardized/IVIM_NEToptim.py b/src/standardized/IVIM_NEToptim.py index 13cf643..d9bf5c4 100644 --- a/src/standardized/IVIM_NEToptim.py +++ b/src/standardized/IVIM_NEToptim.py @@ -66,10 +66,17 @@ def initialize(self, bounds, initial_guess, fitS0, traindata, SNR, n): SNR = (5, 100) self.training_data(self.bvalues,n=n,SNR=SNR) self.arg=Arg() + print('note that the bounds in the network are soft bounds and implemented by a sigmoid transform. In order for the network to be sensitive over the range, we extend the bounds ny 30%') if bounds is not None: self.arg.net_pars.cons_min = np.array([self.bounds["D"][0], self.bounds["f"][0], self.bounds["Dp"][0], self.bounds["S0"][0]])#bounds[0] # Dt, Fp, Ds, S0 self.arg.net_pars.cons_max = np.array([self.bounds["D"][1], self.bounds["f"][1], self.bounds["Dp"][1], self.bounds["S0"][1]])#bounds[1] # Dt, Fp, Ds, S0 - self.use_bounds = True + self.bounds = bounds + else: + warnings.warn('No bounds indicated. default bounds are used of self.cons_min = [0, 0, 0.005, 0] and self.cons_max = [0.005, 0.8, 0.2, 2.0] # Dt, Fp, Ds, S0') + self.bounds = {"S0" : [0, 2], "f" : [0, 0.8], "Dp" : [0.005, 0.2], "D" : [0, 0.005]} # These are defined as [lower, upper] + + self.use_bounds = {"f": True, "Dp": True, "D": True} + self.use_initial_guess = {"f": False, "Dp": False, "D": False} if traindata is None: self.net = deep.learn_IVIM(self.train_data['data'], self.bvalues, self.arg) else: diff --git a/src/standardized/TCML_TechnionIIT_SLS.py b/src/standardized/TCML_TechnionIIT_SLS.py index c99e1f4..cb11cd3 100644 --- a/src/standardized/TCML_TechnionIIT_SLS.py +++ b/src/standardized/TCML_TechnionIIT_SLS.py @@ -1,7 +1,7 @@ from src.wrappers.OsipiBase import OsipiBase from super_ivim_dc.source.Classsic_ivim_fit import IVIM_fit_sls import numpy as np - +import warnings class TCML_TechnionIIT_SLS(OsipiBase): """ TCML_TechnionIIT_lsqlm fitting algorithm by Angeleene Ang, Moti Freiman and Noam Korngut, TechnionIIT @@ -46,23 +46,17 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non self.initialize(bounds, fitS0,thresholds) def initialize(self, bounds, fitS0,thresholds): - if bounds is None: - print('warning, only D* is bounded between 0.001 and 0.5)') - self.bounds = ([0.0003, 0.001, 0.009, 0],[0.008, 0.5,0.04, 3]) - else: - print('warning, although bounds are given, only D* is bounded)') - #bounds=bounds - #self.bounds = bounds - self.bounds = ([self.bounds["D"][0], self.bounds["f"][0], self.bounds["Dp"][0], self.bounds["S0"][0]], - [self.bounds["D"][1], self.bounds["f"][1], self.bounds["Dp"][1], self.bounds["S0"][1]]) + self.use_bounds = {"f": False, "Dp": False, "D": False} + warnings.warn('bounds are only used for initialization fit') + + self.use_initial_guess = {"f": False, "Dp": False, "D": False} + self.fitS0=fitS0 - self.use_bounds = True if thresholds is None: self.thresholds = 150 print('warning, no thresholds were defined, so default bounds are used of 150') else: self.thresholds = thresholds - self.use_initial_guess = False def ivim_fit(self, signals, bvalues, **kwargs): """Perform the IVIM fit @@ -76,8 +70,8 @@ def ivim_fit(self, signals, bvalues, **kwargs): """ bvalues=np.array(bvalues) - bounds=np.array(self.bounds) - bounds=[bounds[0][[0, 2, 1, 3]], bounds[1][[0, 2, 1, 3]]] + bounds = ([self.bounds["D"][0], self.bounds["Dp"][0], self.bounds["f"][0], self.bounds["S0"][0]], + [self.bounds["D"][1], self.bounds["Dp"][1], self.bounds["f"][1], self.bounds["S0"][1]]) signals[signals<0]=0 fit_results = self.fit_least_squares(np.array(signals)[:,np.newaxis],bvalues, bounds, min_bval_high=self.thresholds) diff --git a/src/standardized/TCML_TechnionIIT_lsqBOBYQA.py b/src/standardized/TCML_TechnionIIT_lsqBOBYQA.py index 724fe71..ed9aa9e 100644 --- a/src/standardized/TCML_TechnionIIT_lsqBOBYQA.py +++ b/src/standardized/TCML_TechnionIIT_lsqBOBYQA.py @@ -48,23 +48,15 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non def initialize(self, bounds, initial_guess, fitS0): if bounds is None: - print('warning, no bounds were defined, so default bounds are used of [0, 0, 0.005, 0.7],[0.005, 1.0, 0.2, 1.3]') - self.bounds = ([0, 0, 0.005, 0.7],[0.005, 1.0, 0.2, 1.3]) + self.use_bounds = {"f": False, "Dp": False, "D": False} else: - #bounds=bounds - #self.bounds = bounds - self.bounds = ([self.bounds["D"][0], self.bounds["f"][0], self.bounds["Dp"][0], self.bounds["S0"][0]], - [self.bounds["D"][1], self.bounds["f"][1], self.bounds["Dp"][1], self.bounds["S0"][1]]) + self.use_bounds = {"f": True, "Dp": True, "D": True} + if initial_guess is None: - print('warning, no initial guesses were defined, so default bounds are used of [0.001, 0.001, 0.01, 1]') - self.initial_guess = [0.001, 0.1, 0.02, 1] # D, Dp, f, S0 + self.use_initial_guess = {"f": False, "Dp": False, "D": False} else: - #self.initial_guess = initial_guess - self.initial_guess = [self.initial_guess["D"], self.initial_guess["f"], self.initial_guess["Dp"], self.initial_guess["S0"]] - self.use_initial_guess = True + self.use_initial_guess = {"f": True, "Dp": True, "D": True} self.fitS0=fitS0 - self.use_initial_guess = True - self.use_bounds = True def ivim_fit(self, signals, bvalues, **kwargs): """Perform the IVIM fit @@ -78,10 +70,9 @@ def ivim_fit(self, signals, bvalues, **kwargs): """ bvalues=np.array(bvalues) - bounds=np.array(self.bounds) - bounds=[bounds[0][[0, 2, 1, 3]], bounds[1][[0, 2, 1, 3]]] - initial_guess = np.array(self.initial_guess) - initial_guess = initial_guess[[0, 2, 1, 3]] + bounds = ([self.bounds["D"][0], self.bounds["Dp"][0], self.bounds["f"][0], self.bounds["S0"][0]], + [self.bounds["D"][1], self.bounds["Dp"][1], self.bounds["f"][1], self.bounds["S0"][1]]) + initial_guess = [self.initial_guess["D"], self.initial_guess["Dp"], self.initial_guess["f"], self.initial_guess["S0"]] fit_results = self.fit_least_squares(bvalues, np.array(signals)[:,np.newaxis], bounds, initial_guess.copy()) diff --git a/src/standardized/TCML_TechnionIIT_lsq_sls_BOBYQA.py b/src/standardized/TCML_TechnionIIT_lsq_sls_BOBYQA.py index 8483b2a..3a37c10 100644 --- a/src/standardized/TCML_TechnionIIT_lsq_sls_BOBYQA.py +++ b/src/standardized/TCML_TechnionIIT_lsq_sls_BOBYQA.py @@ -66,18 +66,21 @@ def ivim_fit(self, signals, bvalues, **kwargs): Returns: _type_: _description_ """ - bounds = ([self.bounds["D"][0], self.bounds["f"][0], self.bounds["Dp"][0], self.bounds["S0"][0]], - [self.bounds["D"][1], self.bounds["f"][1], self.bounds["Dp"][1], self.bounds["S0"][1]]) - signals[signals<0]=0 bvalues=np.array(bvalues) - bounds=np.array(bounds) - bounds=[bounds[0][[0, 2, 1, 3]], bounds[1][[0, 2, 1, 3]]] + bounds = ([self.bounds["D"][0], self.bounds["Dp"][0], self.bounds["f"][0], self.bounds["S0"][0]], + [self.bounds["D"][1], self.bounds["Dp"][1], self.bounds["f"][1], self.bounds["S0"][1]]) + fit_results = self.fit_least_squares(np.array(signals)[:,np.newaxis],bvalues, bounds,min_bval_high=self.thresholds) results = {} - results["D"] = fit_results[0] - results["f"] = fit_results[2] - results["Dp"] = fit_results[1] + if fit_results[0].size > 0: + results["D"] = fit_results[0] + results["f"] = fit_results[2] + results["Dp"] = fit_results[1] + else: + results["D"] = 0 + results["f"] = 0 + results["Dp"] = 0 return results \ No newline at end of file diff --git a/src/standardized/TCML_TechnionIIT_lsq_sls_lm.py b/src/standardized/TCML_TechnionIIT_lsq_sls_lm.py index b48e0da..ce064d3 100644 --- a/src/standardized/TCML_TechnionIIT_lsq_sls_lm.py +++ b/src/standardized/TCML_TechnionIIT_lsq_sls_lm.py @@ -1,6 +1,7 @@ from src.wrappers.OsipiBase import OsipiBase from super_ivim_dc.source.Classsic_ivim_fit import IVIM_fit_sls_lm import numpy as np +import warnings class TCML_TechnionIIT_lsq_sls_lm(OsipiBase): """ @@ -47,23 +48,16 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non self.initialize(bounds, fitS0,thresholds) def initialize(self, bounds, fitS0,thresholds): - if bounds is None: - print( - 'warning, no bounds were defined, so default bounds are used of ([0.0003, 0.001, 0.009, 0],[0.008, 0.5,0.04, 3])') - self.bounds = ([0.0003, 0.001, 0.009, 0], [0.008, 0.5, 0.04, 3]) - else: - #bounds = bounds - #self.bounds = bounds - self.bounds = ([self.bounds["D"][0], self.bounds["f"][0], self.bounds["Dp"][0], self.bounds["S0"][0]], - [self.bounds["D"][1], self.bounds["f"][1], self.bounds["Dp"][1], self.bounds["S0"][1]]) + self.use_bounds = {"f": False, "Dp": False, "D": False} + warnings.warn('bounds are only used for initialization fit') + if thresholds is None: self.thresholds = 150 print('warning, no thresholds were defined, so default bounds are used of 150') else: self.thresholds = thresholds self.fitS0=fitS0 - self.use_bounds = True - self.use_initial_guess = False + self.use_initial_guess = {"f": False, "Dp": False, "D": False} def ivim_fit(self, signals, bvalues, **kwargs): """Perform the IVIM fit @@ -77,7 +71,9 @@ def ivim_fit(self, signals, bvalues, **kwargs): """ signals[signals<0]=0 bvalues=np.array(bvalues) - fit_results = self.fit_least_squares(np.array(signals)[:,np.newaxis],bvalues, self.bounds, min_bval_high=self.thresholds) + bounds = ([self.bounds["D"][0], self.bounds["Dp"][0], self.bounds["f"][0], self.bounds["S0"][0]], + [self.bounds["D"][1], self.bounds["Dp"][1], self.bounds["f"][1], self.bounds["S0"][1]]) + fit_results = self.fit_least_squares(np.array(signals)[:,np.newaxis],bvalues, bounds, min_bval_high=self.thresholds) results = {} if fit_results[0].size > 0: diff --git a/src/standardized/TCML_TechnionIIT_lsq_sls_trf.py b/src/standardized/TCML_TechnionIIT_lsq_sls_trf.py index cb44e77..43e9665 100644 --- a/src/standardized/TCML_TechnionIIT_lsq_sls_trf.py +++ b/src/standardized/TCML_TechnionIIT_lsq_sls_trf.py @@ -48,21 +48,17 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non def initialize(self, bounds, fitS0, thresholds): if bounds is None: - print('warning, no bounds were defined, so default bounds are used of ([0.0003, 0.001, 0.009, 0],[0.008, 1.0,0.04, 3])') - self.bounds = ([0.0003, 0.001, 0.009, 0],[0.008, 1.0,0.04, 3]) + self.use_bounds = {"f": False, "Dp": False, "D": False} else: - #bounds=bounds - #self.bounds = bounds - self.bounds = ([self.bounds["D"][0], self.bounds["f"][0], self.bounds["Dp"][0], self.bounds["S0"][0]], - [self.bounds["D"][1], self.bounds["f"][1], self.bounds["Dp"][1], self.bounds["S0"][1]]) + self.use_bounds = {"f": True, "Dp": True, "D": True} + self.use_initial_guess = {"f": False, "Dp": False, "D": False} + if thresholds is None: self.thresholds = 200 print('warning, no thresholds were defined, so default bounds are used of 200') else: self.thresholds = thresholds self.fitS0=fitS0 - self.use_bounds = True - self.use_initial_guess = False def ivim_fit(self, signals, bvalues, **kwargs): """Perform the IVIM fit @@ -76,8 +72,8 @@ def ivim_fit(self, signals, bvalues, **kwargs): """ signals[signals<0]=0 bvalues=np.array(bvalues) - bounds=np.array(self.bounds) - bounds=[bounds[0][[0, 2, 1, 3]], bounds[1][[0, 2, 1, 3]]] + bounds = ([self.bounds["D"][0], self.bounds["Dp"][0], self.bounds["f"][0], self.bounds["S0"][0]], + [self.bounds["D"][1], self.bounds["Dp"][1], self.bounds["f"][1], self.bounds["S0"][1]]) fit_results = self.fit_least_squares(np.array(signals)[:,np.newaxis],bvalues, bounds,min_bval_high=self.thresholds) results = {} diff --git a/src/standardized/TCML_TechnionIIT_lsqlm.py b/src/standardized/TCML_TechnionIIT_lsqlm.py index fbcabae..3da1ef0 100644 --- a/src/standardized/TCML_TechnionIIT_lsqlm.py +++ b/src/standardized/TCML_TechnionIIT_lsqlm.py @@ -47,16 +47,13 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non self.initialize(bounds, initial_guess, fitS0) def initialize(self, bounds, initial_guess, fitS0): + self.use_bounds = {"f": False, "Dp": False, "D": False} + if initial_guess is None: - print('warning, no initial guesses were defined, so default bounds are used of [0.001, 0.1, 0.01, 1]') - self.initial_guess = [0.001, 0.1, 0.01, 1] + self.use_initial_guess = {"f": False, "Dp": False, "D": False} else: - #self.initial_guess = initial_guess - self.initial_guess = [self.initial_guess["D"], self.initial_guess["f"], self.initial_guess["Dp"], self.initial_guess["S0"]] - self.use_initial_guess = True + self.use_initial_guess = {"f": True, "Dp": True, "D": True} self.fitS0=fitS0 - self.use_initial_guess = True - self.use_bounds = False def ivim_fit(self, signals, bvalues, **kwargs): """Perform the IVIM fit @@ -70,8 +67,7 @@ def ivim_fit(self, signals, bvalues, **kwargs): """ bvalues=np.array(bvalues) - initial_guess = np.array(self.initial_guess) - initial_guess = initial_guess[[0, 2, 1, 3]] + initial_guess = [self.initial_guess["D"], self.initial_guess["Dp"], self.initial_guess["f"], self.initial_guess["S0"]] fit_results = self.fit_least_squares(bvalues, np.array(signals)[:,np.newaxis], initial_guess) results = {} diff --git a/src/standardized/TCML_TechnionIIT_lsqtrf.py b/src/standardized/TCML_TechnionIIT_lsqtrf.py index ae1c43c..40aaf56 100644 --- a/src/standardized/TCML_TechnionIIT_lsqtrf.py +++ b/src/standardized/TCML_TechnionIIT_lsqtrf.py @@ -48,23 +48,16 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non def initialize(self, bounds, initial_guess, fitS0): if bounds is None: - print('warning, no bounds were defined, so default bounds are used of ([0.0003, 0.001, 0.009, 0],[0.008, 0.5,0.04, 3])') - self.bounds = ([0.0003, 0.001, 0.009, 0],[0.008, 0.5,0.04, 3]) + self.use_bounds = {"f": False, "Dp": False, "D": False} else: - #bounds=bounds - #self.bounds = bounds - self.bounds = ([self.bounds["D"][0], self.bounds["f"][0], self.bounds["Dp"][0], self.bounds["S0"][0]], - [self.bounds["D"][1], self.bounds["f"][1], self.bounds["Dp"][1], self.bounds["S0"][1]]) + self.use_bounds = {"f": True, "Dp": True, "D": True} + if initial_guess is None: - print('warning, no initial guesses were defined, so default bounds are used of [0.001, 0.1, 0.01, 1]') - self.initial_guess = [0.001, 0.1, 0.01, 1] # D, Dp, f, S0 + self.use_initial_guess = {"f": False, "Dp": False, "D": False} else: - #self.initial_guess = initial_guess - self.initial_guess = [self.initial_guess["D"], self.initial_guess["f"], self.initial_guess["Dp"], self.initial_guess["S0"]] - self.use_initial_guess = True + self.use_initial_guess = {"f": True, "Dp": True, "D": True} + self.fitS0=fitS0 - self.use_initial_guess = True - self.use_bounds = True def ivim_fit(self, signals, bvalues, **kwargs): """Perform the IVIM fit @@ -76,12 +69,11 @@ def ivim_fit(self, signals, bvalues, **kwargs): Returns: _type_: _description_ """ + bounds = ([self.bounds["D"][0], self.bounds["Dp"][0], self.bounds["f"][0], self.bounds["S0"][0]], + [self.bounds["D"][1], self.bounds["Dp"][1], self.bounds["f"][1], self.bounds["S0"][1]]) + initial_guess = [self.initial_guess["D"], self.initial_guess["Dp"], self.initial_guess["f"], self.initial_guess["S0"]] bvalues=np.array(bvalues) - bounds=np.array(self.bounds) - bounds=[bounds[0][[0, 2, 1, 3]], bounds[1][[0, 2, 1, 3]]] - initial_guess = np.array(self.initial_guess) - initial_guess = initial_guess[[0, 2, 1, 3]] fit_results = self.fit_least_squares(bvalues, np.array(signals)[:,np.newaxis], bounds,initial_guess) results = {} diff --git a/src/wrappers/OsipiBase.py b/src/wrappers/OsipiBase.py index d6c34ca..292de11 100644 --- a/src/wrappers/OsipiBase.py +++ b/src/wrappers/OsipiBase.py @@ -121,7 +121,7 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non self.forced_default_bounds = True if self.initial_guess is None: - print('warning, no initial guesses were defined, so default bounds are used of [0.001, 0.001, 0.01, 1]') + print('warning, no initial guesses were defined, so default initial guesses are used of [0.001, 0.001, 0.01, 1]') self.initial_guess = {"S0" : 1, "f" : 0.1, "Dp" : 0.01, "D" : 0.001} self.forced_default_initial_guess = True @@ -528,7 +528,7 @@ def osipi_simple_bias_and_RMSE_test(self, SNR, bvalues, f, Dstar, D, noise_reali def D_and_Ds_swap(self,results): - if results['D']>results['Dp']: + if results['D']>results['Dp'] and results['Dp'] < 0.05: D=results['Dp'] results['Dp']=results['D'] results['D']=D diff --git a/tests/IVIMmodels/unit_tests/test_ivim_fit.py b/tests/IVIMmodels/unit_tests/test_ivim_fit.py index c0ea9c0..4167ff2 100644 --- a/tests/IVIMmodels/unit_tests/test_ivim_fit.py +++ b/tests/IVIMmodels/unit_tests/test_ivim_fit.py @@ -47,7 +47,10 @@ def test_ivim_fit_saved(data_ivim_fit_saved, eng, request, record_property): request.node.add_marker(mark) signal = signal_helper(data["data"]) tolerances = tolerances_helper(tolerances, data) - test_bounds = {"S0" : [0.7, 1.3], "f" : [0, 1.0], "Dp" : [0.005, 0.2], "D" : [0, 0.005]} + if data['f'] == 0: + test_bounds = {"S0" : [0.7, 1.3], "f" : [0, 1.0], "Dp" : [0.01, 0.2], "D" : [0, 0.005]} + else: + test_bounds = {"S0" : [0.7, 1.3], "f" : [0, 1.0], "Dp" : [0.005, 0.2], "D" : [0, 0.005]} fit = OsipiBase(algorithm=algorithm, bounds=test_bounds, **kwargs) start_time = time.time() # Record the start time fit_result = fit.osipi_fit(signal, bvals) @@ -67,7 +70,7 @@ def to_list_if_needed(value): "atol": tolerances["atol"] } record_property('test_data', test_result) - if (data['f'] > 0.99 or data['f'] < 0.01) and not fit.use_bounds: #in these cases there are multiple solutions (D can become D*, f will be 0 and D* can be anything. This will be a good description of the data, so technically not a fail + if (data['f'] > 0.99 or data['f'] < 0.01) and not (fit.use_bounds["f"] or fit.use_bounds["D"] or fit.use_bounds["Dp"]): #in these cases there are multiple solutions (D can become D*, f will be 0 and D* can be anything. This will be a good description of the data, so technically not a fail return npt.assert_allclose(fit_result['f'],data['f'], rtol=tolerances["rtol"]["f"], atol=tolerances["atol"]["f"]) if data['f']<0.80: # we need some signal for D to be detected @@ -92,7 +95,7 @@ def test_default_bounds_and_initial_guesses(algorithmlist,eng): fit = OsipiBase(algorithm=algorithm,**kwargs) #assert fit.bounds is not None, f"For {algorithm}, there is no default fit boundary" #assert fit.initial_guess is not None, f"For {algorithm}, there is no default fit initial guess" - if fit.use_bounds: + if (fit.use_bounds["f"] or fit.use_bounds["D"] or fit.use_bounds["Dp"]): assert 0 <= fit.osipi_bounds["D"][0] <= 0.003, f"For {algorithm}, the default lower bound of D {fit.osipi_bounds['D'][0]} is unrealistic" assert 0 <= fit.osipi_bounds["D"][1] <= 0.01, f"For {algorithm}, the default upper bound of D {fit.osipi_bounds['D'][1]} is unrealistic" assert 0 <= fit.osipi_bounds["f"][0] <= 1, f"For {algorithm}, the default lower bound of f {fit.osipi_bounds['f'][0]} is unrealistic" @@ -102,7 +105,7 @@ def test_default_bounds_and_initial_guesses(algorithmlist,eng): assert 0 <= fit.osipi_bounds["S0"][0] <= 1, f"For {algorithm}, the default lower bound of S0 {fit.osipi_bounds['S0'][0]} is unrealistic; note data is normaized" assert 1 <= fit.osipi_bounds["S0"][1] <= 1000, f"For {algorithm}, the default upper bound of S0 {fit.osipi_bounds['S0'][1]} is unrealistic; note data is normaized" assert fit.osipi_bounds["D"][1] <= fit.osipi_bounds["Dp"][0], f"For {algorithm}, the default upper bound of D {fit.osipi_bounds['D'][1]} is higher than lower bound of Dp {fit.osipi_bounds['Dp'][0]}" - if fit.use_initial_guess: + if (fit.use_initial_guess["f"] or fit.use_initial_guess["D"] or fit.use_initial_guess["Dp"]): assert 0.0008 <= fit.osipi_initial_guess["D"] <= 0.002, f"For {algorithm}, the default initial guess for D {fit.osipi_initial_guess['D']} is unrealistic" assert 0 <= fit.osipi_initial_guess["f"] <= 0.5, f"For {algorithm}, the default initial guess for f {fit.osipi_initial_guess['f']} is unrealistic" assert 0.003 <= fit.osipi_initial_guess["Dp"] <= 0.1, f"For {algorithm}, the default initial guess for Dp {fit.osipi_initial_guess['Dp']} is unrealistic" @@ -120,13 +123,15 @@ def test_bounds(bound_input, eng): bounds = {"S0" : [1.1, 1.3], "f" : [0.2, 0.3], "Dp" : [0.01, 0.02], "D" : [0.0008, 0.0012]} # deliberately have silly bounds to see whether they are used fit = OsipiBase(algorithm=algorithm, bounds=bounds, initial_guess={"S0" : 1.2, "f" : 0.25, "Dp" : 0.015, "D" : 0.001}, **kwargs) - if fit.use_bounds: + if fit.use_bounds["f"] or fit.use_bounds["D"] or fit.use_bounds["Dp"]: signal = signal_helper(data["data"]) fit_result = fit.osipi_fit(signal, bvals) - - assert bounds["D"][0] <= fit_result['D'] <= bounds["D"][1], f"Result {fit_result['D']} out of bounds for data: {name}" - assert bounds["f"][0] <= fit_result['f'] <= bounds["f"][1], f"Result {fit_result['f']} out of bounds for data: {name}" - assert bounds["Dp"][0] <= fit_result['Dp'] <= bounds["Dp"][1], f"Result {fit_result['Dp']} out of bounds for data: {name}" + if fit.use_bounds["D"]: + assert bounds["D"][0] <= fit_result['D'] <= bounds["D"][1], f"Result {fit_result['D']} out of bounds for data: {name}" + if fit.use_bounds["f"]: + assert bounds["f"][0] <= fit_result['f'] <= bounds["f"][1], f"Result {fit_result['f']} out of bounds for data: {name}" + if fit.use_bounds["Dp"]: + assert bounds["Dp"][0] <= fit_result['Dp'] <= bounds["Dp"][1], f"Result {fit_result['Dp']} out of bounds for data: {name}" # S0 is not returned as argument... #assert bounds[0][3] <= fit_result['S0'] <= bounds[1][3], f"Result {fit_result['S0']} out of bounds for data: {name}" '''if fit.use_initial_guess: