From becea1a33e364655127656fa7672359f483546be Mon Sep 17 00:00:00 2001 From: IvanARashid Date: Fri, 3 Jan 2025 16:28:26 +0100 Subject: [PATCH 1/4] Fixed bug --- src/original/IAR_LundUniversity/ivim_fit_method_biexp.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/original/IAR_LundUniversity/ivim_fit_method_biexp.py b/src/original/IAR_LundUniversity/ivim_fit_method_biexp.py index 735ab0b8..e855bba6 100644 --- a/src/original/IAR_LundUniversity/ivim_fit_method_biexp.py +++ b/src/original/IAR_LundUniversity/ivim_fit_method_biexp.py @@ -61,13 +61,13 @@ def ivim_model(self, b, S0, f, D_star, D): def set_bounds(self, bounds): # Use this function for fits that uses curve_fit - if bounds == None: + if bounds is None: self.bounds = np.array([(0, 0, 0.005, 0), (np.inf, 1, 0.1, 0.004)]) else: - self.bounds = np.array([(0, *bounds[0]), (np.inf, *bounds[1])]) + self.bounds = np.array([bounds[0], bounds[1]]) def set_initial_guess(self, initial_guess): - if initial_guess == None: + if initial_guess is None: self.initial_guess = (1, 0.2, 0.03, 0.001) else: self.initial_guess = initial_guess From 9dfe0af2d0fae133d7ef7f8dd8ed4d7b811f1bc4 Mon Sep 17 00:00:00 2001 From: IvanARashid Date: Wed, 8 Jan 2025 09:44:21 +0100 Subject: [PATCH 2/4] Bugfixes for bounds and initial guesses --- src/original/IAR_LundUniversity/ivim_fit_method_linear.py | 6 +++--- .../IAR_LundUniversity/ivim_fit_method_modified_mix.py | 2 +- .../IAR_LundUniversity/ivim_fit_method_modified_topopro.py | 2 +- .../IAR_LundUniversity/ivim_fit_method_segmented_2step.py | 6 +++--- .../IAR_LundUniversity/ivim_fit_method_segmented_3step.py | 6 +++--- src/original/IAR_LundUniversity/ivim_fit_method_sivim.py | 6 +++--- .../IAR_LundUniversity/ivim_fit_method_subtracted.py | 6 +++--- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/original/IAR_LundUniversity/ivim_fit_method_linear.py b/src/original/IAR_LundUniversity/ivim_fit_method_linear.py index 25b98fd1..69fd168e 100644 --- a/src/original/IAR_LundUniversity/ivim_fit_method_linear.py +++ b/src/original/IAR_LundUniversity/ivim_fit_method_linear.py @@ -83,13 +83,13 @@ def sivim_model(self, b, S0, f, D): def set_bounds(self, bounds): # Use this function for fits that uses curve_fit - if bounds == None: + if bounds is None: self.bounds = np.array([(0, 0, 0), (np.inf, 1, 0.004)]) else: - self.bounds = np.array([(0, *bounds[0]), (np.inf, *bounds[1])]) + self.bounds = np.array([bounds[0], bounds[1]]) def set_initial_guess(self, initial_guess): - if initial_guess == None: + if initial_guess is None: self.initial_guess = (1, 0.2, 0.001) else: self.initial_guess = initial_guess diff --git a/src/original/IAR_LundUniversity/ivim_fit_method_modified_mix.py b/src/original/IAR_LundUniversity/ivim_fit_method_modified_mix.py index 8b6bb7e3..1dde9a08 100644 --- a/src/original/IAR_LundUniversity/ivim_fit_method_modified_mix.py +++ b/src/original/IAR_LundUniversity/ivim_fit_method_modified_mix.py @@ -78,7 +78,7 @@ def __init__(self, gtab, bounds=None, maxiter=10, xtol=1e-8, rescale_units=False if gtab.bvals[-1] >= 10: self.bvals = gtab.bvals/1000 - if bounds == None: + if bounds is None: # Bounds expressed as (lower bound, upper bound) for [f, D*, D]. self.bounds = np.array([(0, 1), (5, 100), (0, 4)]) elif (bounds[0][1] <= 1) or rescale_units: # Realistically, if mm2/s units are used, D* bound is <= 1 diff --git a/src/original/IAR_LundUniversity/ivim_fit_method_modified_topopro.py b/src/original/IAR_LundUniversity/ivim_fit_method_modified_topopro.py index 587d00f8..7e0816d1 100644 --- a/src/original/IAR_LundUniversity/ivim_fit_method_modified_topopro.py +++ b/src/original/IAR_LundUniversity/ivim_fit_method_modified_topopro.py @@ -76,7 +76,7 @@ def __init__(self, gtab, bounds=[[0, 0.005, 1e-5], [1, 0.1, 0.004]], \ # and are thus not changed. if gtab.bvals[-1] >= 10: self.bvals = gtab.bvals/1000 - if bounds == None: + if bounds is None: # Bounds expressed as (lower bound, upper bound) for [f, D*, D]. self.bounds = np.array([(0, 1), (5, 100), (0, 4)]) elif (bounds[0][1] <= 1) or rescale_units: # Realistically, if mm2/s units are used, D* bound is <= 1 diff --git a/src/original/IAR_LundUniversity/ivim_fit_method_segmented_2step.py b/src/original/IAR_LundUniversity/ivim_fit_method_segmented_2step.py index 382f06ea..eebe1265 100644 --- a/src/original/IAR_LundUniversity/ivim_fit_method_segmented_2step.py +++ b/src/original/IAR_LundUniversity/ivim_fit_method_segmented_2step.py @@ -86,13 +86,13 @@ def ivim_signal(self, b, S0, f, D_star, D): def set_bounds(self, bounds): # Use this function for fits that uses curve_fit - if bounds == None: + if bounds is None: self.bounds = np.array([(0, 0, 0.005, 0), (np.inf, 1, 0.1, 0.004)]) else: - self.bounds = np.array([(0, *bounds[0]), (np.inf, *bounds[1])]) + self.bounds = np.array([bounds[0], bounds[1]]) def set_initial_guess(self, initial_guess): - if initial_guess == None: + if initial_guess is None: self.initial_guess = (1, 0.2, 0.03, 0.001) else: self.initial_guess = initial_guess diff --git a/src/original/IAR_LundUniversity/ivim_fit_method_segmented_3step.py b/src/original/IAR_LundUniversity/ivim_fit_method_segmented_3step.py index de60269c..3a2f675e 100644 --- a/src/original/IAR_LundUniversity/ivim_fit_method_segmented_3step.py +++ b/src/original/IAR_LundUniversity/ivim_fit_method_segmented_3step.py @@ -105,13 +105,13 @@ def ivim_signal(self, b, S0, f, D_star, D): def set_bounds(self, bounds): # Use this function for fits that uses curve_fit - if bounds == None: + if bounds is None: self.bounds = np.array([(0, 0, 0.005, 0), (np.inf, 1, 0.1, 0.004)]) else: - self.bounds = np.array([(0, *bounds[0]), (np.inf, *bounds[1])]) + self.bounds = np.array([bounds[0], bounds[1]]) def set_initial_guess(self, initial_guess): - if initial_guess == None: + if initial_guess is None: self.initial_guess = (1, 0.2, 0.03, 0.001) else: self.initial_guess = initial_guess diff --git a/src/original/IAR_LundUniversity/ivim_fit_method_sivim.py b/src/original/IAR_LundUniversity/ivim_fit_method_sivim.py index 8fe1800b..3b0ec9ab 100644 --- a/src/original/IAR_LundUniversity/ivim_fit_method_sivim.py +++ b/src/original/IAR_LundUniversity/ivim_fit_method_sivim.py @@ -77,13 +77,13 @@ def sivim_model(self, b, S0, f, D): def set_bounds(self, bounds): # Use this function for fits that uses curve_fit - if bounds == None: + if bounds is None: self.bounds = np.array([(0, 0, 0), (np.inf, 1, 0.004)]) else: - self.bounds = np.array([(0, *bounds[0]), (np.inf, *bounds[1])]) + self.bounds = np.array([bounds[0], bounds[1]]) def set_initial_guess(self, initial_guess): - if initial_guess == None: + if initial_guess is None: self.initial_guess = (1, 0.2, 0.001) else: self.initial_guess = initial_guess diff --git a/src/original/IAR_LundUniversity/ivim_fit_method_subtracted.py b/src/original/IAR_LundUniversity/ivim_fit_method_subtracted.py index be514805..0780a97a 100644 --- a/src/original/IAR_LundUniversity/ivim_fit_method_subtracted.py +++ b/src/original/IAR_LundUniversity/ivim_fit_method_subtracted.py @@ -93,13 +93,13 @@ def perfusion_signal(self, b, S0, D_star): def set_bounds(self, bounds): # Use this function for fits that uses curve_fit - if bounds == None: + if bounds is None: self.bounds = np.array([(0, 0, 0.005, 0), (np.inf, 1, 0.1, 0.004)]) else: - self.bounds = np.array([(0, *bounds[0]), (np.inf, *bounds[1])]) + self.bounds = np.array([bounds[0], bounds[1]]) def set_initial_guess(self, initial_guess): - if initial_guess == None: + if initial_guess is None: self.initial_guess = (1, 0.2, 0.03, 0.001) else: self.initial_guess = initial_guess From c7c4376d0a06bb2d170b33c71ade3c0423ee7418 Mon Sep 17 00:00:00 2001 From: IvanARashid Date: Fri, 7 Feb 2025 13:46:10 +0100 Subject: [PATCH 3/4] Added support for initial guesses, bounds, and thresholds where applicable --- src/standardized/ETP_SRI_LinearFitting.py | 9 +++++++-- src/standardized/IAR_LU_biexp.py | 11 ++++++++--- src/standardized/IAR_LU_modified_mix.py | 9 +++++++-- src/standardized/IAR_LU_modified_topopro.py | 9 +++++++-- src/standardized/IAR_LU_segmented_2step.py | 14 +++++++++++--- src/standardized/IAR_LU_segmented_3step.py | 9 +++++++-- src/standardized/IAR_LU_subtracted.py | 9 +++++++-- .../OGC_AmsterdamUMC_Bayesian_biexp.py | 9 +++++++-- src/standardized/OGC_AmsterdamUMC_biexp.py | 5 +++++ .../OGC_AmsterdamUMC_biexp_segmented.py | 5 +++++ src/standardized/OJ_GU_seg.py | 5 +++++ src/standardized/PV_MUMC_biexp.py | 16 +++++++++++++--- src/standardized/PvH_KB_NKI_IVIMfit.py | 7 ++++++- 13 files changed, 95 insertions(+), 22 deletions(-) diff --git a/src/standardized/ETP_SRI_LinearFitting.py b/src/standardized/ETP_SRI_LinearFitting.py index a5d45c55..41aa1665 100644 --- a/src/standardized/ETP_SRI_LinearFitting.py +++ b/src/standardized/ETP_SRI_LinearFitting.py @@ -27,6 +27,11 @@ class ETP_SRI_LinearFitting(OsipiBase): required_initial_guess_optional = False accepted_dimensions = 1 # Not sure how to define this for the number of accepted dimensions. Perhaps like the thresholds, at least and at most? + + # Supported inputs in the standardized class + supported_bounds = False + supported_initial_guess = False + supported_thresholds = True def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=None, weighting=None, stats=False): """ @@ -36,7 +41,7 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non Our OsipiBase object could contain functions that compare the inputs with the requirements. """ - super(ETP_SRI_LinearFitting, self).__init__(bvalues, thresholds, bounds, initial_guess) + super(ETP_SRI_LinearFitting, self).__init__(bvalues=bvalues, thresholds=thresholds, bounds=bounds, initial_guess=initial_guess) # Could be a good idea to have all the submission-specfic variable be # defined with initials? @@ -67,7 +72,7 @@ def ivim_fit(self, signals, bvalues=None, linear_fit_option=False, **kwargs): results = {} if linear_fit_option: - f, Dstar = ETP_object.linear_fit(bvalues, signals) + f, Dstar = ETP_object.linear_fit(bvalues, signals, self.ETP_weighting, self.ETP_stats) results["f"] = f results["D*"] = Dstar diff --git a/src/standardized/IAR_LU_biexp.py b/src/standardized/IAR_LU_biexp.py index 4f4f7231..3192b6ca 100644 --- a/src/standardized/IAR_LU_biexp.py +++ b/src/standardized/IAR_LU_biexp.py @@ -27,6 +27,11 @@ class IAR_LU_biexp(OsipiBase): required_initial_guess = False required_initial_guess_optional = True accepted_dimensions = 1 # Not sure how to define this for the number of accepted dimensions. Perhaps like the thresholds, at least and at most? + + # Supported inputs in the standardized class + supported_bounds = True + supported_initial_guess = True + supported_thresholds = False def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=None, weighting=None, stats=False): """ @@ -46,7 +51,7 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non bvec[:,2] = 1 gtab = gradient_table(self.bvalues, bvec, b0_threshold=0) - self.IAR_algorithm = IvimModelBiExp(gtab) + self.IAR_algorithm = IvimModelBiExp(gtab, bounds=self.bounds, initial_guess=self.initial_guess) else: self.IAR_algorithm = None @@ -72,7 +77,7 @@ def ivim_fit(self, signals, bvalues, **kwargs): bvec[:,2] = 1 gtab = gradient_table(bvalues, bvec, b0_threshold=0) - self.IAR_algorithm = IvimModelBiExp(gtab) + self.IAR_algorithm = IvimModelBiExp(gtab, bounds=self.bounds, initial_guess=self.initial_guess) fit_results = self.IAR_algorithm.fit(signals) @@ -104,7 +109,7 @@ def ivim_fit_full_volume(self, signals, bvalues, **kwargs): bvec[:,2] = 1 gtab = gradient_table(bvalues, bvec, b0_threshold=0) - self.IAR_algorithm = IvimModelBiExp(gtab) + self.IAR_algorithm = IvimModelBiExp(gtab, bounds=self.bounds, initial_guess=self.initial_guess) fit_results = self.IAR_algorithm.fit(signals) diff --git a/src/standardized/IAR_LU_modified_mix.py b/src/standardized/IAR_LU_modified_mix.py index 9571a569..eb667971 100644 --- a/src/standardized/IAR_LU_modified_mix.py +++ b/src/standardized/IAR_LU_modified_mix.py @@ -28,6 +28,11 @@ class IAR_LU_modified_mix(OsipiBase): required_initial_guess_optional = True accepted_dimensions = 1 # Not sure how to define this for the number of accepted dimensions. Perhaps like the thresholds, at least and at most? + # Supported inputs in the standardized class + supported_bounds = True + supported_initial_guess = False + supported_thresholds = False + def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=None, weighting=None, stats=False): """ Everything this algorithm requires should be implemented here. @@ -46,7 +51,7 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non bvec[:,2] = 1 gtab = gradient_table(self.bvalues, bvec, b0_threshold=0) - self.IAR_algorithm = IvimModelVP(gtab) + self.IAR_algorithm = IvimModelVP(gtab, bounds=self.bounds, rescale_results_to_mm2_s=True) else: self.IAR_algorithm = None @@ -72,7 +77,7 @@ def ivim_fit(self, signals, bvalues, **kwargs): bvec[:,2] = 1 gtab = gradient_table(bvalues, bvec, b0_threshold=0) - self.IAR_algorithm = IvimModelVP(gtab, rescale_results_to_mm2_s=True) + self.IAR_algorithm = IvimModelVP(gtab, bounds=self.bounds, rescale_results_to_mm2_s=True) fit_results = self.IAR_algorithm.fit(signals) diff --git a/src/standardized/IAR_LU_modified_topopro.py b/src/standardized/IAR_LU_modified_topopro.py index 9e39fc20..5b7cb7a8 100644 --- a/src/standardized/IAR_LU_modified_topopro.py +++ b/src/standardized/IAR_LU_modified_topopro.py @@ -28,6 +28,11 @@ class IAR_LU_modified_topopro(OsipiBase): required_initial_guess_optional = True accepted_dimensions = 1 # Not sure how to define this for the number of accepted dimensions. Perhaps like the thresholds, at least and at most? + # Supported inputs in the standardized class + supported_bounds = True + supported_initial_guess = False + supported_thresholds = False + def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=None, weighting=None, stats=False): """ Everything this algorithm requires should be implemented here. @@ -46,7 +51,7 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non bvec[:,2] = 1 gtab = gradient_table(self.bvalues, bvec, b0_threshold=0) - self.IAR_algorithm = IvimModelTopoPro(gtab) + self.IAR_algorithm = IvimModelTopoPro(gtab, bounds=self.bounds, rescale_results_to_mm2_s=True) else: self.IAR_algorithm = None @@ -72,7 +77,7 @@ def ivim_fit(self, signals, bvalues, **kwargs): bvec[:,2] = 1 gtab = gradient_table(bvalues, bvec, b0_threshold=0) - self.IAR_algorithm = IvimModelTopoPro(gtab, rescale_results_to_mm2_s=True) + self.IAR_algorithm = IvimModelTopoPro(gtab, bounds=self.bounds, rescale_results_to_mm2_s=True) fit_results = self.IAR_algorithm.fit(signals) diff --git a/src/standardized/IAR_LU_segmented_2step.py b/src/standardized/IAR_LU_segmented_2step.py index 3fb5cdd8..c0849ede 100644 --- a/src/standardized/IAR_LU_segmented_2step.py +++ b/src/standardized/IAR_LU_segmented_2step.py @@ -28,6 +28,11 @@ class IAR_LU_segmented_2step(OsipiBase): required_initial_guess_optional = True accepted_dimensions = 1 # Not sure how to define this for the number of accepted dimensions. Perhaps like the thresholds, at least and at most? + # Supported inputs in the standardized class + supported_bounds = True + supported_initial_guess = True + supported_thresholds = True + def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=None): """ Everything this algorithm requires should be implemented here. @@ -46,7 +51,7 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non bvec[:,2] = 1 gtab = gradient_table(self.bvalues, bvec, b0_threshold=0) - self.IAR_algorithm = IvimModelSegmented2Step(gtab) + self.IAR_algorithm = IvimModelSegmented2Step(gtab, bounds=self.bounds, initial_guess=self.initial_guess, b_threshold=self.thresholds) else: self.IAR_algorithm = None @@ -72,8 +77,11 @@ def ivim_fit(self, signals, bvalues, thresholds=None, **kwargs): bvec = np.zeros((bvalues.size, 3)) bvec[:,2] = 1 gtab = gradient_table(bvalues, bvec, b0_threshold=0) - - self.IAR_algorithm = IvimModelSegmented2Step(gtab) + + if self.thresholds is None: + self.thresholds = 200 + + self.IAR_algorithm = IvimModelSegmented2Step(gtab, bounds=self.bounds, initial_guess=self.initial_guess, b_threshold=self.thresholds) fit_results = self.IAR_algorithm.fit(signals) diff --git a/src/standardized/IAR_LU_segmented_3step.py b/src/standardized/IAR_LU_segmented_3step.py index 170b8ee0..390d86a5 100644 --- a/src/standardized/IAR_LU_segmented_3step.py +++ b/src/standardized/IAR_LU_segmented_3step.py @@ -28,6 +28,11 @@ class IAR_LU_segmented_3step(OsipiBase): required_initial_guess_optional = True accepted_dimensions = 1 # Not sure how to define this for the number of accepted dimensions. Perhaps like the thresholds, at least and at most? + # Supported inputs in the standardized class + supported_bounds = True + supported_initial_guess = True + supported_thresholds = False + def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=None, weighting=None, stats=False): """ Everything this algorithm requires should be implemented here. @@ -46,7 +51,7 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non bvec[:,2] = 1 gtab = gradient_table(self.bvalues, bvec, b0_threshold=0) - self.IAR_algorithm = IvimModelSegmented3Step(gtab) + self.IAR_algorithm = IvimModelSegmented3Step(gtab, bounds=self.bounds, initial_guess=self.initial_guess) else: self.IAR_algorithm = None @@ -72,7 +77,7 @@ def ivim_fit(self, signals, bvalues, **kwargs): bvec[:,2] = 1 gtab = gradient_table(bvalues, bvec, b0_threshold=0) - self.IAR_algorithm = IvimModelSegmented3Step(gtab) + self.IAR_algorithm = IvimModelSegmented3Step(gtab, bounds=self.bounds, initial_guess=self.initial_guess) fit_results = self.IAR_algorithm.fit(signals) diff --git a/src/standardized/IAR_LU_subtracted.py b/src/standardized/IAR_LU_subtracted.py index d5508f22..19dd3ec4 100644 --- a/src/standardized/IAR_LU_subtracted.py +++ b/src/standardized/IAR_LU_subtracted.py @@ -28,6 +28,11 @@ class IAR_LU_subtracted(OsipiBase): required_initial_guess_optional = True accepted_dimensions = 1 # Not sure how to define this for the number of accepted dimensions. Perhaps like the thresholds, at least and at most? + # Supported inputs in the standardized class + supported_bounds = True + supported_initial_guess = True + supported_thresholds = False + def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=None): """ Everything this algorithm requires should be implemented here. @@ -46,7 +51,7 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non bvec[:,2] = 1 gtab = gradient_table(self.bvalues, bvec, b0_threshold=0) - self.IAR_algorithm = IvimModelSubtracted(gtab) + self.IAR_algorithm = IvimModelSubtracted(gtab, bounds=self.bounds, initial_guess=self.initial_guess) else: self.IAR_algorithm = None @@ -72,7 +77,7 @@ def ivim_fit(self, signals, bvalues, **kwargs): bvec[:,2] = 1 gtab = gradient_table(bvalues, bvec, b0_threshold=0) - self.IAR_algorithm = IvimModelSubtracted(gtab) + self.IAR_algorithm = IvimModelSubtracted(gtab, bounds=self.bounds, initial_guess=self.initial_guess) fit_results = self.IAR_algorithm.fit(signals) diff --git a/src/standardized/OGC_AmsterdamUMC_Bayesian_biexp.py b/src/standardized/OGC_AmsterdamUMC_Bayesian_biexp.py index 1b8c8f94..430bddbf 100644 --- a/src/standardized/OGC_AmsterdamUMC_Bayesian_biexp.py +++ b/src/standardized/OGC_AmsterdamUMC_Bayesian_biexp.py @@ -28,6 +28,11 @@ class OGC_AmsterdamUMC_Bayesian_biexp(OsipiBase): accepted_dimensions = 1 # Not sure how to define this for the number of accepted dimensions. Perhaps like the thresholds, at least and at most? accepts_priors = True + # Supported inputs in the standardized class + supported_bounds = True + supported_initial_guess = True + supported_thresholds = True + def __init__(self, bvalues=None, thresholds=None, bounds=([0, 0, 0.005, 0.7],[0.005, 0.7, 0.2, 1.3]), initial_guess=None, fitS0=True, prior_in=None): """ Everything this algorithm requires should be implemented here. @@ -39,7 +44,7 @@ def __init__(self, bvalues=None, thresholds=None, bounds=([0, 0, 0.005, 0.7],[0. Args: datain is a 2D array with values of D, f, D* (and S0) that will form the prior. """ - super(OGC_AmsterdamUMC_Bayesian_biexp, self).__init__(bvalues, bounds, initial_guess) #, fitS0, prior_in) + super(OGC_AmsterdamUMC_Bayesian_biexp, self).__init__(bvalues=bvalues, bounds=bounds, thresholds=thresholds, initial_guess=initial_guess) #, fitS0, prior_in) self.OGC_algorithm = fit_bayesian self.initialize(bounds, initial_guess, fitS0, prior_in) @@ -74,7 +79,7 @@ def ivim_fit(self, signals, bvalues, initial_guess=None, **kwargs): if initial_guess is not None and len(initial_guess) == 4: self.initial_guess = initial_guess bvalues=np.array(bvalues) - fit_results = fit_segmented(bvalues, signals, bounds=self.bounds, cutoff=150, p0=self.initial_guess) + fit_results = fit_segmented(bvalues, signals, bounds=self.bounds, cutoff=self.thresholds, p0=self.initial_guess) fit_results=fit_results+(1,) fit_results = self.OGC_algorithm(bvalues, signals, self.neg_log_prior, x0=fit_results, fitS0=self.fitS0) diff --git a/src/standardized/OGC_AmsterdamUMC_biexp.py b/src/standardized/OGC_AmsterdamUMC_biexp.py index 66b9e6c0..ea59b885 100644 --- a/src/standardized/OGC_AmsterdamUMC_biexp.py +++ b/src/standardized/OGC_AmsterdamUMC_biexp.py @@ -27,6 +27,11 @@ class OGC_AmsterdamUMC_biexp(OsipiBase): required_initial_guess_optional = True accepted_dimensions = 1 # Not sure how to define this for the number of accepted dimensions. Perhaps like the thresholds, at least and at most? + # Supported inputs in the standardized class + supported_bounds = True + supported_initial_guess = True + supported_thresholds = False + def __init__(self, bvalues=None, thresholds=None, bounds=([0, 0, 0.005, 0.7],[0.005, 0.7, 0.2, 1.3]), initial_guess=None, fitS0=False): """ Everything this algorithm requires should be implemented here. diff --git a/src/standardized/OGC_AmsterdamUMC_biexp_segmented.py b/src/standardized/OGC_AmsterdamUMC_biexp_segmented.py index c452f7b5..43ab1818 100644 --- a/src/standardized/OGC_AmsterdamUMC_biexp_segmented.py +++ b/src/standardized/OGC_AmsterdamUMC_biexp_segmented.py @@ -27,6 +27,11 @@ class OGC_AmsterdamUMC_biexp_segmented(OsipiBase): required_initial_guess_optional = True accepted_dimensions = 1 # Not sure how to define this for the number of accepted dimensions. Perhaps like the thresholds, at least and at most? + # Supported inputs in the standardized class + supported_bounds = True + supported_initial_guess = True + supported_thresholds = True + def __init__(self, bvalues=None, thresholds=150, bounds=([0, 0, 0.005],[0.005, 0.7, 0.2]), initial_guess=[0.001, 0.01, 0.01,1]): """ Everything this algorithm requires should be implemented here. diff --git a/src/standardized/OJ_GU_seg.py b/src/standardized/OJ_GU_seg.py index af40be7a..bd55e63e 100644 --- a/src/standardized/OJ_GU_seg.py +++ b/src/standardized/OJ_GU_seg.py @@ -25,6 +25,11 @@ class OJ_GU_seg(OsipiBase): required_initial_guess = False required_initial_guess_optional = False accepted_dimensions = 1 # Not sure how to define this for the number of accepted dimensions. Perhaps like the thresholds, at least and at most? + + # Supported inputs in the standardized class + supported_bounds = False + supported_initial_guess = False + supported_thresholds = True def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=None, weighting=None, stats=False): """ diff --git a/src/standardized/PV_MUMC_biexp.py b/src/standardized/PV_MUMC_biexp.py index f08ddd1c..0e10d5d3 100644 --- a/src/standardized/PV_MUMC_biexp.py +++ b/src/standardized/PV_MUMC_biexp.py @@ -22,6 +22,11 @@ class PV_MUMC_biexp(OsipiBase): required_initial_guess = False required_initial_guess_optional = True accepted_dimensions = 1 # Not sure how to define this for the number of accepted dimensions. Perhaps like the thresholds, at least and at most? + + # Supported inputs in the standardized class + supported_bounds = True + supported_initial_guess = False + supported_thresholds = True def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=None, weighting=None, stats=False): """ @@ -31,7 +36,7 @@ def __init__(self, bvalues=None, thresholds=None, bounds=None, initial_guess=Non Our OsipiBase object could contain functions that compare the inputs with the requirements. """ - super(PV_MUMC_biexp, self).__init__(bvalues, None, bounds, None) + super(PV_MUMC_biexp, self).__init__(bvalues=bvalues, thresholds=thresholds, bounds=bounds, initial_guess=initial_guess) self.PV_algorithm = fit_least_squares @@ -46,8 +51,13 @@ def ivim_fit(self, signals, bvalues=None): _type_: _description_ """ - - fit_results = self.PV_algorithm(bvalues, signals) + if self.thresholds is None: + self.thresholds = 200 + + if self.bounds is None: + self.bounds = ([0.9, 0.0001, 0.0, 0.0025], [1.1, 0.003, 1, 0.2]) + + fit_results = self.PV_algorithm(bvalues, signals, bounds=self.bounds, cutoff=self.thresholds) results = {} results["f"] = fit_results[1] diff --git a/src/standardized/PvH_KB_NKI_IVIMfit.py b/src/standardized/PvH_KB_NKI_IVIMfit.py index 52eea8d4..66e201dd 100644 --- a/src/standardized/PvH_KB_NKI_IVIMfit.py +++ b/src/standardized/PvH_KB_NKI_IVIMfit.py @@ -27,6 +27,11 @@ class PvH_KB_NKI_IVIMfit(OsipiBase): required_initial_guess_optional =False accepted_dimensions = 1 # Not sure how to define this for the number of accepted dimensions. Perhaps like the thresholds, at least and at most? + # Supported inputs in the standardized class + supported_bounds = False + supported_initial_guess = False + supported_thresholds = False + def __init__(self, bvalues=None, thresholds=None,bounds=None,initial_guess=None): """ Everything this algorithm requires should be implemented here. @@ -35,7 +40,7 @@ def __init__(self, bvalues=None, thresholds=None,bounds=None,initial_guess=None) Our OsipiBase object could contain functions that compare the inputs with the requirements. """ - super(PvH_KB_NKI_IVIMfit, self).__init__(bvalues, thresholds,bounds,initial_guess) + super(PvH_KB_NKI_IVIMfit, self).__init__(bvalues=bvalues, thresholds=thresholds,bounds=bounds,initial_guess=initial_guess) self.NKI_algorithm = generate_IVIMmaps_standalone From 3f36ddcbf94f0b0f068b00f7cbbedc6af0e5857a Mon Sep 17 00:00:00 2001 From: IvanARashid Date: Fri, 7 Feb 2025 14:05:08 +0100 Subject: [PATCH 4/4] Delete, not relevant --- .../IAR_LundUniversity/simple_test_of_fits.py | 130 ------------------ 1 file changed, 130 deletions(-) delete mode 100644 src/original/IAR_LundUniversity/simple_test_of_fits.py diff --git a/src/original/IAR_LundUniversity/simple_test_of_fits.py b/src/original/IAR_LundUniversity/simple_test_of_fits.py deleted file mode 100644 index 4029b9dd..00000000 --- a/src/original/IAR_LundUniversity/simple_test_of_fits.py +++ /dev/null @@ -1,130 +0,0 @@ -import numpy as np -from dipy.core.gradients import gradient_table -from scipy.stats import norm -import matplotlib.pyplot as plt -import scienceplots -import ivim_fit_method_biexp -import ivim_fit_method_subtracted -import ivim_fit_method_sivim -import ivim_fit_method_linear -import ivim_fit_method_segmented_3step -import ivim_fit_method_segmented_2step -import ivim_fit_method_modified_mix -import ivim_fit_method_modified_topopro - -plt.style.use(["science", "ieee"]) - -def ivim_signal(b, S0, f, D_star, D): - return S0*(f*np.exp(-b*D_star) + (1-f)*np.exp(-b*D)) - -def diffusion_signal(b, S0, f, D): - return S0*(1-f)*np.exp(-b*D) - -def generate_noise(loc, sigma): - real_component = norm.rvs(loc=loc, scale=sigma/loc) - imaginary_component = norm.rvs(loc=loc, scale=sigma/loc) - return np.absolute(complex(real_component, imaginary_component)) - -def add_rician_noise(signal, SNR): - sigma = signal[-1]/SNR - # Sample real and imaginary noise components from gaussian distributions - # Use the last b-value as the SNR baseline in order to avoid the noise floor - noise = np.array([generate_noise(signal_value, sigma) for signal_value in signal]) - - # Add the two components to the signal and take the magniutde of the result - noised_signal = signal + noise - noised_signal = np.absolute(noised_signal) - - return noised_signal - -# Ground truth -factor = 1 -S0 = 1 -f = 0.1 -D_star = 30e-3 -D = 1e-3 -rescale_units = False - -# Settings -lower_bounds = (0, 5, 0) -upper_bounds = (1, 100, 4) -bounds_um = (lower_bounds, upper_bounds) - -lower_bounds = (0, 0.005, 0) -upper_bounds = (1, 0.1, 0.004) -bounds_mm = (lower_bounds, upper_bounds) -initial_guess_mm = (1, 0.2, 0.03, 0.001) - -# Create gtab containing b-value informations -bvals = np.array([0, 50, 240, 800])/factor -bvals = np.array([0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, \ - 150, 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800]) -bvals = np.array([0, 20, 40, 60, 80, 100, 150, 200, 300, 400, 500, 600, 700, 800]) -#bvals = np.array([0, 50, 240, 800]) -bvec = np.zeros((bvals.size, 3)) -bvec[:,2] = 1 -gtab = gradient_table(bvals, bvec, b0_threshold=0) - -# Signal -signal = ivim_signal(bvals, S0, f, D_star, D) -noised_signal = add_rician_noise(signal, 3) -noised_signal /= noised_signal[0] - -noised_signal6 = add_rician_noise(signal, 6) -noised_signal6 /= noised_signal6[0] - - - - - - -# biexp fit -biexp_model = ivim_fit_method_biexp.IvimModelBiExp(gtab, bounds=bounds_mm, initial_guess=initial_guess_mm, rescale_units=rescale_units) -biexp_fit = biexp_model.fit(noised_signal) - -# sIVIM fit -lower_bounds_sivim = (0, 0) -upper_bounds_sivim = (1, 4/factor) -bounds_mm_sivim = (lower_bounds_sivim, upper_bounds_sivim) -initial_guess_mm_sivim = (1, 0.2, 0.001) -sivim_model = ivim_fit_method_sivim.IvimModelsIVIM(gtab, b_threshold=0.2, bounds=bounds_mm_sivim, initial_guess=initial_guess_mm_sivim, rescale_units=rescale_units) -sivim_fit = sivim_model.fit(noised_signal) - -# linear fit -linear_model = ivim_fit_method_linear.IvimModelLinear(gtab, b_threshold=0.2, bounds=bounds_mm_sivim, rescale_units=rescale_units) -linear_fit = linear_model.fit(noised_signal) - -# Subtracted fit (Le Bihan 2019) -subtracted_model = ivim_fit_method_subtracted.IvimModelSubtracted(gtab, bounds=bounds_mm, initial_guess=initial_guess_mm, rescale_units=rescale_units)#, b_threshold_lower=0.2, b_threshold_upper=0.1) -subtracted_fit = subtracted_model.fit(noised_signal) - -# Segmented fit (3 step) (DIPY) -segmented_3step_model = ivim_fit_method_segmented_3step.IvimModelSegmented3Step(gtab, bounds=bounds_mm, initial_guess=initial_guess_mm, rescale_units=rescale_units)#, b_threshold_lower=0.2, b_threshold_upper=0.1) -segmented_3step_fit = segmented_3step_model.fit(noised_signal) - -# Segmented fit (2 step) (Conventional method) -segmented_2step_model = ivim_fit_method_segmented_2step.IvimModelSegmented2Step(gtab, bounds=bounds_mm, initial_guess=initial_guess_mm, rescale_units=rescale_units)#, b_threshold_lower=0.2) -segmented_2step_fit = segmented_2step_model.fit(noised_signal) -segmented_2step_fit6 = segmented_2step_model.fit(noised_signal6) - -# MIX (Farooq et al.) -mix_model = ivim_fit_method_modified_mix.IvimModelVP(gtab, bounds=bounds_mm, rescale_units=rescale_units, rescale_results_to_mm2_s=True) -mix_fit = mix_model.fit(noised_signal) -mix_fit6 = mix_model.fit(noised_signal6) - -# TopoPro (Fadnavis et al.) -topopro_model = ivim_fit_method_modified_topopro.IvimModelTopoPro(gtab, bounds=bounds_mm, rescale_units=rescale_units, rescale_results_to_mm2_s=True) -topopro_fit = topopro_model.fit(noised_signal) -topopro_fit6 = topopro_model.fit(noised_signal6) - -# Print estimates -print(f"Bi-exponential: {biexp_fit.model_params}") -print(f"Linear: {linear_fit.model_params}") -print(f"sIVIM: {sivim_fit.model_params}") -print(f"Subtracted: {subtracted_fit.model_params}") -print(f"3-step segmented: {segmented_3step_fit.model_params}") -print(f"2-step segmented: {segmented_2step_fit.model_params}") -print(f"MIX: {mix_fit.model_params}") -print(f"TopoPro: {topopro_fit.model_params}") - -