Skip to content

Commit d471105

Browse files
fixed bugs
- fixed initial guesses and bounds such that it passes tests - changed matlab huild for github, hopefully overcoming errors.
1 parent 9d407fd commit d471105

File tree

6 files changed

+46
-25
lines changed

6 files changed

+46
-25
lines changed

.github/workflows/unit_test.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,11 @@ jobs:
3434
uses: actions/checkout@v4
3535
- name: Set up MATLAB
3636
uses: matlab-actions/setup-matlab@v2
37-
- name: Run build
38-
uses: matlab-actions/run-build@v2
37+
with:
38+
release: R2025a
39+
- name: Install MATLAB Engine for Python
40+
run: |
41+
python -m pip install matlabengine==25.1.2
3942
- name: Test with pytest
4043
run: |
4144
pip install pytest pytest-cov

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ md5sums.txt
1919
*.asv
2020
src/original/ASD_MemorialSloanKettering/MRI-QAMPER_IVIM/test_data
2121
src/original/ASD_MemorialSloanKettering/MRI-QAMPER_IVIM/output_files
22-
22+
tests/IVIMmodels/unit_tests/*.log
2323

2424

2525
# Unit test / coverage reports

src/standardized/ASD_MemorialSloanKettering_QAMPER_IVIM.py

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class ASD_MemorialSloanKettering_QAMPER_IVIM(OsipiBase):
3333
supported_initial_guess = True
3434
supported_thresholds = False
3535

36-
def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=None):
36+
def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=None,eng=None):
3737
"""
3838
Everything this algorithm requires should be implemented here.
3939
Number of segmentation thresholds, bounds, etc.
@@ -44,7 +44,14 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non
4444
#super(OGC_AmsterdamUMC_biexp, self).__init__(bvalues, bounds, initial_guess, fitS0)
4545
super(ASD_MemorialSloanKettering_QAMPER_IVIM, self).__init__(bvalues=bvalues, bounds=bounds, initial_guess=initial_guess)
4646
self.initialize(bounds, initial_guess)
47-
self.eng=matlab.engine.start_matlab()
47+
if eng is None:
48+
print('initiating matlab; this may take some time. For repeated testing one could use the optional input eng as an already initiated matlab engine')
49+
self.eng=matlab.engine.start_matlab()
50+
self.keep_alive=False
51+
else:
52+
self.eng = eng
53+
self.keep_alive=True
54+
4855

4956

5057
def algorithm(self,dwi_arr, bval_arr, LB0, UB0, x0in):
@@ -61,12 +68,12 @@ def algorithm(self,dwi_arr, bval_arr, LB0, UB0, x0in):
6168
def initialize(self, bounds, initial_guess):
6269
if bounds is None:
6370
print('warning, no bounds were defined, so algorithm-specific default bounds are used')
64-
self.bounds=([1e-6, 0, 1e-6, 0],[0.003, 1.0, 5e-2, 5])
71+
self.bounds=([1e-6, 0, 0.004, 0],[0.003, 1.0, 0.2, 5])
6572
else:
6673
self.bounds=bounds
6774
if initial_guess is None:
6875
print('warning, no initial guesses were defined, so algorithm-specific default initial guess is used')
69-
self.initial_guess = [0.001, 0.001, 0.2, 1]
76+
self.initial_guess = [0.001, 0.2, 0.01, 1]
7077
else:
7178
self.initial_guess = initial_guess
7279
self.use_initial_guess = True
@@ -85,10 +92,10 @@ def ivim_fit(self, signals, bvalues, **kwargs):
8592
"""
8693

8794
bvalues=np.array(bvalues)
88-
LB = np.array(self.bounds[0])
89-
UB = np.array(self.bounds[1])
95+
LB = np.array(self.bounds[0])[[1,0,2,3]]
96+
UB = np.array(self.bounds[1])[[1,0,2,3]]
9097

91-
fit_results = self.algorithm(np.array(signals)[:,np.newaxis], bvalues, LB, UB, np.array(self.initial_guess))
98+
fit_results = self.algorithm(np.array(signals)[:,np.newaxis], bvalues, LB, UB, np.array(self.initial_guess)[[1,0,2,3]])
9299

93100
results = {}
94101
results["D"] = fit_results[0]
@@ -99,20 +106,22 @@ def ivim_fit(self, signals, bvalues, **kwargs):
99106

100107

101108
def __del__(self):
102-
if hasattr(self, "eng") and self.eng:
103-
try:
104-
self.eng.quit()
105-
except Exception as e:
106-
print(f"Warning: Failed to quit MATLAB engine cleanly: {e}")
109+
if not self.keep_alive:
110+
if hasattr(self, "eng") and self.eng:
111+
try:
112+
self.eng.quit()
113+
except Exception as e:
114+
print(f"Warning: Failed to quit MATLAB engine cleanly: {e}")
107115

108116

109117
def __enter__(self):
110118
return self
111119

112120

113121
def __exit__(self, exc_type, exc_val, exc_tb):
114-
if hasattr(self, "eng") and self.eng:
115-
try:
116-
self.eng.quit()
117-
except Exception as e:
118-
print(f"Warning: Failed to quit MATLAB engine cleanly: {e}")
122+
if not self.keep_alive:
123+
if hasattr(self, "eng") and self.eng:
124+
try:
125+
self.eng.quit()
126+
except Exception as e:
127+
print(f"Warning: Failed to quit MATLAB engine cleanly: {e}")

src/standardized/OGC_AmsterdamUMC_biexp.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def initialize(self, bounds, initial_guess, fitS0):
5555
self.bounds=bounds
5656
if initial_guess is None:
5757
print('warning, no initial guesses were defined, so default bounds are used of [0.001, 0.001, 0.01, 1]')
58-
self.initial_guess = [0.001, 0.001, 0.01, 1]
58+
self.initial_guess = [0.001, 0.1, 0.01, 1]
5959
else:
6060
self.initial_guess = initial_guess
6161
self.use_initial_guess = True

tests/IVIMmodels/unit_tests/algorithms.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
"PvH_KB_NKI_IVIMfit",
1616
"OJ_GU_seg"
1717
],
18+
"ASD_MemorialSloanKettering_QAMPER_IVIM": {
19+
"requieres_matlab": true,
20+
"fail_first_time": true
21+
},
1822
"IAR_LU_biexp": {
1923
"fail_first_time": true
2024
},

tests/IVIMmodels/unit_tests/test_ivim_fit.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
import time
77
from src.wrappers.OsipiBase import OsipiBase
88
#run using python -m pytest from the root folder
9+
import matlab.engine
10+
11+
eng=matlab.engine.start_matlab()
912

1013
def signal_helper(signal):
1114
signal = np.asarray(signal)
@@ -44,9 +47,9 @@ def data_ivim_fit_saved():
4447
algorithms = algorithm_information["algorithms"]
4548
bvals = all_data.pop('config')
4649
bvals = bvals['bvalues']
47-
first=True
48-
for name, data in all_data.items():
49-
for algorithm in algorithms:
50+
for algorithm in algorithms:
51+
first = True
52+
for name, data in all_data.items():
5053
algorithm_dict = algorithm_information.get(algorithm, {})
5154
xfail = {"xfail": name in algorithm_dict.get("xfail_names", {}),
5255
"strict": algorithm_dict.get("xfail_names", {}).get(name, True)}
@@ -56,7 +59,9 @@ def data_ivim_fit_saved():
5659
if first == True:
5760
if algorithm_dict.get("fail_first_time", {}) == True:
5861
skiptime = True
59-
first = False
62+
first = False # this will only work for 1 algorithm... If two algorithms use fail_first_time, the second will not see it is the first time.
63+
if algorithm_dict.get("requieres_matlab", {}) == True:
64+
kwargs={**kwargs,'eng': eng}
6065
yield name, bvals, data, algorithm, xfail, kwargs, tolerances, skiptime
6166

6267
@pytest.mark.parametrize("name, bvals, data, algorithm, xfail, kwargs, tolerances, skiptime", data_ivim_fit_saved())

0 commit comments

Comments
 (0)