Skip to content

Commit df05f70

Browse files
authored
Merge pull request #131 from OSIPI/wrapper_dev_testing
Wrapper dev testing
2 parents f72458f + c4fafb7 commit df05f70

11 files changed

+84
-101
lines changed

src/standardized/IAR_LU_biexp.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,10 @@ def ivim_fit_full_volume(self, signals, bvalues, **kwargs):
114114
Returns:
115115
_type_: _description_
116116
"""
117-
117+
# Make sure bounds and initial guess conform to the algorithm requirements
118+
bounds = [[self.bounds["S0"][0], self.bounds["f"][0], self.bounds["Dp"][0], self.bounds["D"][0]],
119+
[self.bounds["S0"][1], self.bounds["f"][1], self.bounds["Dp"][1], self.bounds["D"][1]]]
120+
initial_guess = [self.initial_guess["S0"], self.initial_guess["f"], self.initial_guess["Dp"], self.initial_guess["D"]]
118121
if self.IAR_algorithm is None:
119122
if bvalues is None:
120123
bvalues = self.bvalues
@@ -125,7 +128,7 @@ def ivim_fit_full_volume(self, signals, bvalues, **kwargs):
125128
bvec[:,2] = 1
126129
gtab = gradient_table(bvalues, bvecs=bvec, b0_threshold=0)
127130

128-
self.IAR_algorithm = IvimModelBiExp(gtab, bounds=self.bounds, initial_guess=self.initial_guess)
131+
self.IAR_algorithm = IvimModelBiExp(gtab, bounds=bounds, initial_guess=initial_guess)
129132
b0_index = np.where(bvalues == 0)[0][0]
130133
mask = signals[...,b0_index]>0
131134
fit_results = self.IAR_algorithm.fit(signals, mask=mask)

src/standardized/IVIM_NEToptim.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,17 @@ def initialize(self, bounds, initial_guess, fitS0, traindata, SNR, n):
6666
SNR = (5, 100)
6767
self.training_data(self.bvalues,n=n,SNR=SNR)
6868
self.arg=Arg()
69+
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%')
6970
if bounds is not None:
7071
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
7172
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
72-
self.use_bounds = True
73+
self.bounds = bounds
74+
else:
75+
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')
76+
self.bounds = {"S0" : [0, 2], "f" : [0, 0.8], "Dp" : [0.005, 0.2], "D" : [0, 0.005]} # These are defined as [lower, upper]
77+
78+
self.use_bounds = {"f": True, "Dp": True, "D": True}
79+
self.use_initial_guess = {"f": False, "Dp": False, "D": False}
7380
if traindata is None:
7481
self.net = deep.learn_IVIM(self.train_data['data'], self.bvalues, self.arg)
7582
else:

src/standardized/TCML_TechnionIIT_SLS.py

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from src.wrappers.OsipiBase import OsipiBase
22
from super_ivim_dc.source.Classsic_ivim_fit import IVIM_fit_sls
33
import numpy as np
4-
4+
import warnings
55
class TCML_TechnionIIT_SLS(OsipiBase):
66
"""
77
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
4646
self.initialize(bounds, fitS0,thresholds)
4747

4848
def initialize(self, bounds, fitS0,thresholds):
49-
if bounds is None:
50-
print('warning, only D* is bounded between 0.001 and 0.5)')
51-
self.bounds = ([0.0003, 0.001, 0.009, 0],[0.008, 0.5,0.04, 3])
52-
else:
53-
print('warning, although bounds are given, only D* is bounded)')
54-
#bounds=bounds
55-
#self.bounds = bounds
56-
self.bounds = ([self.bounds["D"][0], self.bounds["f"][0], self.bounds["Dp"][0], self.bounds["S0"][0]],
57-
[self.bounds["D"][1], self.bounds["f"][1], self.bounds["Dp"][1], self.bounds["S0"][1]])
49+
self.use_bounds = {"f": False, "Dp": False, "D": False}
50+
warnings.warn('bounds are only used for initialization fit')
51+
52+
self.use_initial_guess = {"f": False, "Dp": False, "D": False}
53+
5854
self.fitS0=fitS0
59-
self.use_bounds = True
6055
if thresholds is None:
6156
self.thresholds = 150
6257
print('warning, no thresholds were defined, so default bounds are used of 150')
6358
else:
6459
self.thresholds = thresholds
65-
self.use_initial_guess = False
6660

6761
def ivim_fit(self, signals, bvalues, **kwargs):
6862
"""Perform the IVIM fit
@@ -76,8 +70,8 @@ def ivim_fit(self, signals, bvalues, **kwargs):
7670
"""
7771

7872
bvalues=np.array(bvalues)
79-
bounds=np.array(self.bounds)
80-
bounds=[bounds[0][[0, 2, 1, 3]], bounds[1][[0, 2, 1, 3]]]
73+
bounds = ([self.bounds["D"][0], self.bounds["Dp"][0], self.bounds["f"][0], self.bounds["S0"][0]],
74+
[self.bounds["D"][1], self.bounds["Dp"][1], self.bounds["f"][1], self.bounds["S0"][1]])
8175
signals[signals<0]=0
8276

8377
fit_results = self.fit_least_squares(np.array(signals)[:,np.newaxis],bvalues, bounds, min_bval_high=self.thresholds)

src/standardized/TCML_TechnionIIT_lsqBOBYQA.py

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -48,23 +48,15 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non
4848

4949
def initialize(self, bounds, initial_guess, fitS0):
5050
if bounds is None:
51-
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]')
52-
self.bounds = ([0, 0, 0.005, 0.7],[0.005, 1.0, 0.2, 1.3])
51+
self.use_bounds = {"f": False, "Dp": False, "D": False}
5352
else:
54-
#bounds=bounds
55-
#self.bounds = bounds
56-
self.bounds = ([self.bounds["D"][0], self.bounds["f"][0], self.bounds["Dp"][0], self.bounds["S0"][0]],
57-
[self.bounds["D"][1], self.bounds["f"][1], self.bounds["Dp"][1], self.bounds["S0"][1]])
53+
self.use_bounds = {"f": True, "Dp": True, "D": True}
54+
5855
if initial_guess is None:
59-
print('warning, no initial guesses were defined, so default bounds are used of [0.001, 0.001, 0.01, 1]')
60-
self.initial_guess = [0.001, 0.1, 0.02, 1] # D, Dp, f, S0
56+
self.use_initial_guess = {"f": False, "Dp": False, "D": False}
6157
else:
62-
#self.initial_guess = initial_guess
63-
self.initial_guess = [self.initial_guess["D"], self.initial_guess["f"], self.initial_guess["Dp"], self.initial_guess["S0"]]
64-
self.use_initial_guess = True
58+
self.use_initial_guess = {"f": True, "Dp": True, "D": True}
6559
self.fitS0=fitS0
66-
self.use_initial_guess = True
67-
self.use_bounds = True
6860

6961
def ivim_fit(self, signals, bvalues, **kwargs):
7062
"""Perform the IVIM fit
@@ -78,10 +70,9 @@ def ivim_fit(self, signals, bvalues, **kwargs):
7870
"""
7971

8072
bvalues=np.array(bvalues)
81-
bounds=np.array(self.bounds)
82-
bounds=[bounds[0][[0, 2, 1, 3]], bounds[1][[0, 2, 1, 3]]]
83-
initial_guess = np.array(self.initial_guess)
84-
initial_guess = initial_guess[[0, 2, 1, 3]]
73+
bounds = ([self.bounds["D"][0], self.bounds["Dp"][0], self.bounds["f"][0], self.bounds["S0"][0]],
74+
[self.bounds["D"][1], self.bounds["Dp"][1], self.bounds["f"][1], self.bounds["S0"][1]])
75+
initial_guess = [self.initial_guess["D"], self.initial_guess["Dp"], self.initial_guess["f"], self.initial_guess["S0"]]
8576

8677
fit_results = self.fit_least_squares(bvalues, np.array(signals)[:,np.newaxis], bounds, initial_guess.copy())
8778

src/standardized/TCML_TechnionIIT_lsq_sls_BOBYQA.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,21 @@ def ivim_fit(self, signals, bvalues, **kwargs):
6666
Returns:
6767
_type_: _description_
6868
"""
69-
bounds = ([self.bounds["D"][0], self.bounds["f"][0], self.bounds["Dp"][0], self.bounds["S0"][0]],
70-
[self.bounds["D"][1], self.bounds["f"][1], self.bounds["Dp"][1], self.bounds["S0"][1]])
71-
7269
signals[signals<0]=0
7370
bvalues=np.array(bvalues)
74-
bounds=np.array(bounds)
75-
bounds=[bounds[0][[0, 2, 1, 3]], bounds[1][[0, 2, 1, 3]]]
71+
bounds = ([self.bounds["D"][0], self.bounds["Dp"][0], self.bounds["f"][0], self.bounds["S0"][0]],
72+
[self.bounds["D"][1], self.bounds["Dp"][1], self.bounds["f"][1], self.bounds["S0"][1]])
73+
7674
fit_results = self.fit_least_squares(np.array(signals)[:,np.newaxis],bvalues, bounds,min_bval_high=self.thresholds)
7775

7876
results = {}
79-
results["D"] = fit_results[0]
80-
results["f"] = fit_results[2]
81-
results["Dp"] = fit_results[1]
77+
if fit_results[0].size > 0:
78+
results["D"] = fit_results[0]
79+
results["f"] = fit_results[2]
80+
results["Dp"] = fit_results[1]
81+
else:
82+
results["D"] = 0
83+
results["f"] = 0
84+
results["Dp"] = 0
8285

8386
return results

src/standardized/TCML_TechnionIIT_lsq_sls_lm.py

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from src.wrappers.OsipiBase import OsipiBase
22
from super_ivim_dc.source.Classsic_ivim_fit import IVIM_fit_sls_lm
33
import numpy as np
4+
import warnings
45

56
class TCML_TechnionIIT_lsq_sls_lm(OsipiBase):
67
"""
@@ -47,23 +48,16 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non
4748
self.initialize(bounds, fitS0,thresholds)
4849

4950
def initialize(self, bounds, fitS0,thresholds):
50-
if bounds is None:
51-
print(
52-
'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])')
53-
self.bounds = ([0.0003, 0.001, 0.009, 0], [0.008, 0.5, 0.04, 3])
54-
else:
55-
#bounds = bounds
56-
#self.bounds = bounds
57-
self.bounds = ([self.bounds["D"][0], self.bounds["f"][0], self.bounds["Dp"][0], self.bounds["S0"][0]],
58-
[self.bounds["D"][1], self.bounds["f"][1], self.bounds["Dp"][1], self.bounds["S0"][1]])
51+
self.use_bounds = {"f": False, "Dp": False, "D": False}
52+
warnings.warn('bounds are only used for initialization fit')
53+
5954
if thresholds is None:
6055
self.thresholds = 150
6156
print('warning, no thresholds were defined, so default bounds are used of 150')
6257
else:
6358
self.thresholds = thresholds
6459
self.fitS0=fitS0
65-
self.use_bounds = True
66-
self.use_initial_guess = False
60+
self.use_initial_guess = {"f": False, "Dp": False, "D": False}
6761

6862
def ivim_fit(self, signals, bvalues, **kwargs):
6963
"""Perform the IVIM fit
@@ -77,7 +71,9 @@ def ivim_fit(self, signals, bvalues, **kwargs):
7771
"""
7872
signals[signals<0]=0
7973
bvalues=np.array(bvalues)
80-
fit_results = self.fit_least_squares(np.array(signals)[:,np.newaxis],bvalues, self.bounds, min_bval_high=self.thresholds)
74+
bounds = ([self.bounds["D"][0], self.bounds["Dp"][0], self.bounds["f"][0], self.bounds["S0"][0]],
75+
[self.bounds["D"][1], self.bounds["Dp"][1], self.bounds["f"][1], self.bounds["S0"][1]])
76+
fit_results = self.fit_least_squares(np.array(signals)[:,np.newaxis],bvalues, bounds, min_bval_high=self.thresholds)
8177

8278
results = {}
8379
if fit_results[0].size > 0:

src/standardized/TCML_TechnionIIT_lsq_sls_trf.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,21 +48,17 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non
4848

4949
def initialize(self, bounds, fitS0, thresholds):
5050
if bounds is None:
51-
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])')
52-
self.bounds = ([0.0003, 0.001, 0.009, 0],[0.008, 1.0,0.04, 3])
51+
self.use_bounds = {"f": False, "Dp": False, "D": False}
5352
else:
54-
#bounds=bounds
55-
#self.bounds = bounds
56-
self.bounds = ([self.bounds["D"][0], self.bounds["f"][0], self.bounds["Dp"][0], self.bounds["S0"][0]],
57-
[self.bounds["D"][1], self.bounds["f"][1], self.bounds["Dp"][1], self.bounds["S0"][1]])
53+
self.use_bounds = {"f": True, "Dp": True, "D": True}
54+
self.use_initial_guess = {"f": False, "Dp": False, "D": False}
55+
5856
if thresholds is None:
5957
self.thresholds = 200
6058
print('warning, no thresholds were defined, so default bounds are used of 200')
6159
else:
6260
self.thresholds = thresholds
6361
self.fitS0=fitS0
64-
self.use_bounds = True
65-
self.use_initial_guess = False
6662

6763
def ivim_fit(self, signals, bvalues, **kwargs):
6864
"""Perform the IVIM fit
@@ -76,8 +72,8 @@ def ivim_fit(self, signals, bvalues, **kwargs):
7672
"""
7773
signals[signals<0]=0
7874
bvalues=np.array(bvalues)
79-
bounds=np.array(self.bounds)
80-
bounds=[bounds[0][[0, 2, 1, 3]], bounds[1][[0, 2, 1, 3]]]
75+
bounds = ([self.bounds["D"][0], self.bounds["Dp"][0], self.bounds["f"][0], self.bounds["S0"][0]],
76+
[self.bounds["D"][1], self.bounds["Dp"][1], self.bounds["f"][1], self.bounds["S0"][1]])
8177
fit_results = self.fit_least_squares(np.array(signals)[:,np.newaxis],bvalues, bounds,min_bval_high=self.thresholds)
8278

8379
results = {}

src/standardized/TCML_TechnionIIT_lsqlm.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,13 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non
4747
self.initialize(bounds, initial_guess, fitS0)
4848

4949
def initialize(self, bounds, initial_guess, fitS0):
50+
self.use_bounds = {"f": False, "Dp": False, "D": False}
51+
5052
if initial_guess is None:
51-
print('warning, no initial guesses were defined, so default bounds are used of [0.001, 0.1, 0.01, 1]')
52-
self.initial_guess = [0.001, 0.1, 0.01, 1]
53+
self.use_initial_guess = {"f": False, "Dp": False, "D": False}
5354
else:
54-
#self.initial_guess = initial_guess
55-
self.initial_guess = [self.initial_guess["D"], self.initial_guess["f"], self.initial_guess["Dp"], self.initial_guess["S0"]]
56-
self.use_initial_guess = True
55+
self.use_initial_guess = {"f": True, "Dp": True, "D": True}
5756
self.fitS0=fitS0
58-
self.use_initial_guess = True
59-
self.use_bounds = False
6057

6158
def ivim_fit(self, signals, bvalues, **kwargs):
6259
"""Perform the IVIM fit
@@ -70,8 +67,7 @@ def ivim_fit(self, signals, bvalues, **kwargs):
7067
"""
7168

7269
bvalues=np.array(bvalues)
73-
initial_guess = np.array(self.initial_guess)
74-
initial_guess = initial_guess[[0, 2, 1, 3]]
70+
initial_guess = [self.initial_guess["D"], self.initial_guess["Dp"], self.initial_guess["f"], self.initial_guess["S0"]]
7571
fit_results = self.fit_least_squares(bvalues, np.array(signals)[:,np.newaxis], initial_guess)
7672

7773
results = {}

src/standardized/TCML_TechnionIIT_lsqtrf.py

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -48,23 +48,16 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non
4848

4949
def initialize(self, bounds, initial_guess, fitS0):
5050
if bounds is None:
51-
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])')
52-
self.bounds = ([0.0003, 0.001, 0.009, 0],[0.008, 0.5,0.04, 3])
51+
self.use_bounds = {"f": False, "Dp": False, "D": False}
5352
else:
54-
#bounds=bounds
55-
#self.bounds = bounds
56-
self.bounds = ([self.bounds["D"][0], self.bounds["f"][0], self.bounds["Dp"][0], self.bounds["S0"][0]],
57-
[self.bounds["D"][1], self.bounds["f"][1], self.bounds["Dp"][1], self.bounds["S0"][1]])
53+
self.use_bounds = {"f": True, "Dp": True, "D": True}
54+
5855
if initial_guess is None:
59-
print('warning, no initial guesses were defined, so default bounds are used of [0.001, 0.1, 0.01, 1]')
60-
self.initial_guess = [0.001, 0.1, 0.01, 1] # D, Dp, f, S0
56+
self.use_initial_guess = {"f": False, "Dp": False, "D": False}
6157
else:
62-
#self.initial_guess = initial_guess
63-
self.initial_guess = [self.initial_guess["D"], self.initial_guess["f"], self.initial_guess["Dp"], self.initial_guess["S0"]]
64-
self.use_initial_guess = True
58+
self.use_initial_guess = {"f": True, "Dp": True, "D": True}
59+
6560
self.fitS0=fitS0
66-
self.use_initial_guess = True
67-
self.use_bounds = True
6861

6962
def ivim_fit(self, signals, bvalues, **kwargs):
7063
"""Perform the IVIM fit
@@ -76,12 +69,11 @@ def ivim_fit(self, signals, bvalues, **kwargs):
7669
Returns:
7770
_type_: _description_
7871
"""
72+
bounds = ([self.bounds["D"][0], self.bounds["Dp"][0], self.bounds["f"][0], self.bounds["S0"][0]],
73+
[self.bounds["D"][1], self.bounds["Dp"][1], self.bounds["f"][1], self.bounds["S0"][1]])
74+
initial_guess = [self.initial_guess["D"], self.initial_guess["Dp"], self.initial_guess["f"], self.initial_guess["S0"]]
7975

8076
bvalues=np.array(bvalues)
81-
bounds=np.array(self.bounds)
82-
bounds=[bounds[0][[0, 2, 1, 3]], bounds[1][[0, 2, 1, 3]]]
83-
initial_guess = np.array(self.initial_guess)
84-
initial_guess = initial_guess[[0, 2, 1, 3]]
8577
fit_results = self.fit_least_squares(bvalues, np.array(signals)[:,np.newaxis], bounds,initial_guess)
8678

8779
results = {}

src/wrappers/OsipiBase.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non
121121
self.forced_default_bounds = True
122122

123123
if self.initial_guess is None:
124-
print('warning, no initial guesses were defined, so default bounds are used of [0.001, 0.001, 0.01, 1]')
124+
print('warning, no initial guesses were defined, so default initial guesses are used of [0.001, 0.001, 0.01, 1]')
125125
self.initial_guess = {"S0" : 1, "f" : 0.1, "Dp" : 0.01, "D" : 0.001}
126126
self.forced_default_initial_guess = True
127127

@@ -528,7 +528,7 @@ def osipi_simple_bias_and_RMSE_test(self, SNR, bvalues, f, Dstar, D, noise_reali
528528

529529

530530
def D_and_Ds_swap(self,results):
531-
if results['D']>results['Dp']:
531+
if results['D']>results['Dp'] and results['Dp'] < 0.05:
532532
D=results['Dp']
533533
results['Dp']=results['D']
534534
results['D']=D

0 commit comments

Comments
 (0)