Skip to content

Commit 0515c18

Browse files
redo bayesian wrapper for single input testing
1 parent 929337f commit 0515c18

File tree

5 files changed

+37
-20
lines changed

5 files changed

+37
-20
lines changed

.gitignore

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
.idea*
22
.github*
33
__pycache__/
4-
5-
4+
*.nii.gz
5+
bvals.txt
6+
*json
67
# Unit test / coverage reports
78
.tox/
89
.coverage

phantoms/MR_XCAT_qMRI/sim_ivim_sig.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
# code adapted from MAtlab code by Eric Schrauben: https://github.com/schrau24/XCAT-ERIC
99
# This code generates a 4D IVIM phantom as nifti file
1010

11-
def phantom(bvalue, noise, TR=3000, TE=40, motion=False, rician=False, interleaved=False):
11+
def phantom(bvalue, noise, TR=8000, TE=80, motion=False, rician=False, interleaved=False):
1212
np.random.seed(42)
1313
if motion:
1414
states = range(1,21)
@@ -367,7 +367,8 @@ def XCAT_to_MR_DCE(XCAT, TR, TE, bvalue, D, f, Ds, b0=3, ivim_cont = True):
367367
bvalue = np.array([0., 1, 2, 5, 10, 20, 30, 50, 75, 100, 150, 250, 350, 400, 550, 700, 850, 1000])
368368
noise = 0.0005
369369
motion = False
370-
sig, XCAT, Dim, fim, Dpim, legend = phantom(bvalue, noise, motion=motion, interleaved=False)
370+
interleaved = False
371+
sig, XCAT, Dim, fim, Dpim, legend = phantom(bvalue, noise, motion=motion, interleaved=interleaved)
371372
# sig = np.flip(sig,axis=0)
372373
# sig = np.flip(sig,axis=1)
373374
res=np.eye(4)
@@ -402,12 +403,16 @@ def XCAT_to_MR_DCE(XCAT, TR, TE, bvalue, D, f, Ds, b0=3, ivim_cont = True):
402403
nifti_img = nib.Nifti1Image(sig, affine=res) # Replace affine if necessary
403404
# Save the NIfTI image to a file
404405
nifti_img.header.set_data_dtype(np.float64)
405-
if motion:
406+
if not motion:
407+
output_file = 'output.nii.gz' # Replace with your desired output file name
408+
elif interleaved:
406409
output_file = 'output_resp_int.nii.gz' # Replace with your desired output file name
407410
else:
408-
output_file = 'output.nii.gz' # Replace with your desired output file name
411+
output_file = 'output_resp.nii.gz' # Replace with your desired output file name
412+
409413
nib.save(nifti_img, output_file)
410414

415+
411416
nifti_img = nib.Nifti1Image(XCAT, affine=res) # Replace affine if necessary
412417
# Save the NIfTI image to a file
413418
output_file = 'output_xcat.nii.gz' # Replace with your desired output file name

src/original/OGC_AmsterdamUMC/LSQ_fitting.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ def fit_segmented(bvalues, dw_data, bounds=([0, 0, 0.005],[0.005, 0.7, 0.2]), cu
139139
Dt, Fp = params[0] / 1000, 1 - params[1]
140140
# remove the diffusion part to only keep the pseudo-diffusion
141141
dw_data_remaining = dw_data - (1 - Fp) * np.exp(-bvalues * Dt)
142-
bounds2 = (bounds[0][2], bounds[1][2])
142+
bounds2 = (bounds[0][2]*10, bounds[1][2]*10)
143143
# fit for D*
144144
params, _ = curve_fit(lambda b, Dp: Fp * np.exp(-b * Dp), bvalues, dw_data_remaining, p0=(p0[2]), bounds=bounds2)
145145
Dp = params[0]
@@ -561,19 +561,19 @@ def neg_log_prior(p):
561561
Dt, Fp, Dp = p[0], p[1], p[2]
562562
# make D*<D very unlikely
563563
if (Dp < Dt):
564-
return 1e8
564+
return 1e3
565565
else:
566566
# determine and return the prior for D, f and D* (and S0)
567567
if len(p) == 4:
568568
if Dt_range[0] < Dt < Dt_range[1] and Fp_range[0] < Fp < Fp_range[1] and Dp_range[0] < Dp < Dp_range[1]: # and S0_range[0] < S0 < S0_range[1]: << not sure whether this helps. Technically it should be here
569569
return 0
570570
else:
571-
return 1e8
571+
return 1e3
572572
else:
573573
if Dt_range[0] < Dt < Dt_range[1] and Fp_range[0] < Fp < Fp_range[1] and Dp_range[0] < Dp < Dp_range[1]:
574574
return 0
575575
else:
576-
return 1e8
576+
return 1e3
577577

578578
return neg_log_prior
579579

@@ -638,7 +638,7 @@ def parfun(i):
638638
return Dt_pred, Fp_pred, Dp_pred, S0_pred
639639

640640

641-
def fit_bayesian(bvalues, dw_data, neg_log_prior, x0=[0.001, 0.2, 0.05], fitS0=True):
641+
def fit_bayesian(bvalues, dw_data, neg_log_prior, x0=[0.001, 0.2, 0.05, 1], fitS0=True):
642642
'''
643643
This is an implementation of the Bayesian IVIM fit. It returns the Maximum a posterior probability.
644644
The fit is taken from Barbieri et al. which was initially introduced in http://arxiv.org/10.1002/mrm.25765 and
@@ -655,7 +655,7 @@ def fit_bayesian(bvalues, dw_data, neg_log_prior, x0=[0.001, 0.2, 0.05], fitS0=T
655655
'''
656656
try:
657657
# define fit bounds
658-
bounds = [(0, 0.005), (0, 1), (0, 2), (0, 2.5)]
658+
bounds = [(0, 0.005), (0, 1.5), (0, 2), (0, 2.5)]
659659
# Find the Maximum a posterior probability (MAP) by minimising the negative log of the posterior
660660
if fitS0:
661661
params = minimize(neg_log_posterior, x0=x0, args=(bvalues, dw_data, neg_log_prior), bounds=bounds)

src/standardized/OGC_AmsterdamUMC_Bayesian_biexp.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from src.wrappers.OsipiBase import OsipiBase
2-
from src.original.OGC_AmsterdamUMC.LSQ_fitting import flat_neg_log_prior, fit_bayesian
2+
from src.original.OGC_AmsterdamUMC.LSQ_fitting import flat_neg_log_prior, fit_bayesian, empirical_neg_log_prior, fit_segmented
33
import numpy as np
44

55
class OGC_AmsterdamUMC_Bayesian_biexp(OsipiBase):
@@ -27,23 +27,32 @@ class OGC_AmsterdamUMC_Bayesian_biexp(OsipiBase):
2727
required_initial_guess_optional = True
2828
accepted_dimensions = 1 # Not sure how to define this for the number of accepted dimensions. Perhaps like the thresholds, at least and at most?
2929

30-
def __init__(self, bvalues=None, bounds=([0, 0, 0.005, 0.7],[0.005, 0.7, 0.2, 1.3]), initial_guess=None, fitS0=True, thresholds=None):
30+
def __init__(self, bvalues=None, bounds=([0, 0, 0.005, 0.7],[0.005, 0.7, 0.2, 1.3]), initial_guess=None, fitS0=True, thresholds=None, prior_in=None):
3131
"""
3232
Everything this algorithm requires should be implemented here.
3333
Number of segmentation thresholds, bounds, etc.
3434
3535
Our OsipiBase object could contain functions that compare the inputs with
3636
the requirements.
37+
38+
Args:
39+
datain is a 2D array with values of D, f, D* (and S0) that will form the prior.
3740
"""
38-
super(OGC_AmsterdamUMC_Bayesian_biexp, self).__init__(bvalues, bounds,initial_guess,fitS0)
41+
super(OGC_AmsterdamUMC_Bayesian_biexp, self).__init__(bvalues, bounds,initial_guess,fitS0,prior_in)
3942
if bounds is None:
40-
self.bounds=([0, 0, 0.005, 0.7],[0.005, 1.0, 0.2, 1.3])
43+
self.bounds=([0, 0, 0.005, 0.7],[0.005, 1, 0.2, 1.3])
4144
else:
4245
self.bounds=bounds
43-
self.neg_log_prior=flat_neg_log_prior([self.bounds[0][0],self.bounds[1][0]],[self.bounds[0][1],self.bounds[1][1]],[self.bounds[0][2],self.bounds[1][2]],[self.bounds[0][3],self.bounds[1][3]])
46+
if prior_in is None:
47+
self.neg_log_prior=flat_neg_log_prior([self.bounds[0][0],self.bounds[1][0]],[self.bounds[0][1],self.bounds[1][1]],[self.bounds[0][2],self.bounds[1][2]],[self.bounds[0][3],self.bounds[1][3]])
48+
else:
49+
if len(prior_in) is 4:
50+
self.neg_log_prior = empirical_neg_log_prior(prior_in[0], prior_in[1], prior_in[2],prior_in[3])
51+
else:
52+
self.neg_log_prior = empirical_neg_log_prior(prior_in[0], prior_in[1], prior_in[2])
4453
self.OGC_algorithm = fit_bayesian
4554
if initial_guess is None:
46-
self.initial_guess = [0.001, 0.001, 0.01, 1]
55+
self.initial_guess = [0.001, 0.5, 0.1, 1]
4756
else:
4857
self.initial_guess = initial_guess
4958
self.fitS0=fitS0
@@ -59,7 +68,9 @@ def ivim_fit(self, signals, bvalues=None):
5968
_type_: _description_
6069
"""
6170
bvalues=np.array(bvalues)
62-
fit_results = self.OGC_algorithm(bvalues, signals, self.neg_log_prior, x0=self.initial_guess, fitS0=self.fitS0)
71+
fit_results = fit_segmented(bvalues, signals,bounds=self.bounds,cutoff=150,p0=self.initial_guess)
72+
fit_results=fit_results+(1,)
73+
fit_results = self.OGC_algorithm(bvalues, signals, self.neg_log_prior, x0=fit_results, fitS0=self.fitS0)
6374

6475
D = fit_results[0]
6576
f = fit_results[1]

src/standardized/OGC_AmsterdamUMC_biexp_segmented.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def __init__(self, bvalues=None, thresholds=150, bounds=([0, 0, 0.005],[0.005, 0
4242
else:
4343
self.bounds=bounds
4444
if initial_guess is None:
45-
self.initial_guess = [0.001, 0.001, 0.01, 1]
45+
self.initial_guess = [0.001, 0.1, 0.03, 1]
4646
else:
4747
self.initial_guess = initial_guess
4848
self.thresholds=thresholds

0 commit comments

Comments
 (0)