This is closely related to #15.
Narrow question
@kyoung21b many bump-related items are created only after discovering basis="fourier". Should bumps actually be tied to the basis? The bump info is not saved with the basis object. But it's written as if other bases might use other bump types, or perhaps be unable to use bumps at all.
Broader issue
Also mostlly @kyoung21b. To what extent can we separate concerns into separate spheres? For example, it appears that some of the logic and parameters depend on the likelihood x prior distribution type. There are parameters defined on bifs that seem only to be relevant for some of those, e.g., Rician.
Example 1
The idea is that instead of
myShape = init_image.shape
if self.imdim == 1:
self.kdist = self.bas.kdist1D(*myShape)
self.k_image = self.bas.tx1(self.init_image) # Get k-space image
elif self.imdim == 2:
self.kdist = self.bas.kdist2D(*myShape)
self.k_image = self.bas.tx2(self.init_image) # Get k-space image
elif self.imdim == 3:
self.kdist = self.bas.kdist3D(*myShape)
self.k_image = self.bas.txn(self.init_image) # Get k-space image
(I've used Python's '*' operator to simplify the existing code) you'd have something like
self.k_image = self.basis.k_image(self)
where self.basis is some kind of basis object, self is an argument so basis.k_image() can get needed info from the bifs object, and k_image() returns an appropriate k-space image while setting kdist in self.basis.
There is an argument in favor of passing the needed components explicitly to basis.k_image() rather than having it extract them from the bifs object. The advantage of the formulation I gave is that it works better if different classes of basis objects need different info. That's all somewhat theoretical since our mainline only has one possible basis.
Example 2
if self.prior == "Gaussian" and self.likelihood == "Gaussian":
self.bifsk_image = self.bifs_map_gauss_gauss(self.prior_mean,self.prior_std2,self.mod_image,self.ksd2)
elif self.prior == "Gaussian" and self.likelihood == "Rician":
conj = self.bifs_map_gauss_gauss(self.prior_mean,self.prior_std2,self.mod_image,self.ksd2)
besind = np.zeros(self.init_image.shape,dtype=int)
besind[np.where(conj > self.bessel_approx_lims[1])] = 1
besind[np.where(conj > self.bessel_approx_lims[2])] = 2
besind[np.where(conj > self.bessel_approx_lims[3])] = 3
self.bsa = self.bessel_approx_array[besind,:]
self.bifsk_image = self.bifs_map_gauss_rice(self.prior_mean,self.prior_std,self.mod_image,self.likelihood_scale)
else:
becomes
self.bifsk_image = self.likelihood.bifs_map(self)
where self.likelihood is an object, not a string, with a class that depended on the type of prior and likelihood. The rician version would have all the bessel function machinery and Rician-specific parameters tucked away inside of it.
This is closely related to #15.
Narrow question
@kyoung21b many bump-related items are created only after discovering basis="fourier". Should bumps actually be tied to the basis? The bump info is not saved with the basis object. But it's written as if other bases might use other bump types, or perhaps be unable to use bumps at all.
Broader issue
Also mostlly @kyoung21b. To what extent can we separate concerns into separate spheres? For example, it appears that some of the logic and parameters depend on the likelihood x prior distribution type. There are parameters defined on bifs that seem only to be relevant for some of those, e.g., Rician.
Example 1
The idea is that instead of
(I've used Python's '*' operator to simplify the existing code) you'd have something like
where self.basis is some kind of basis object, self is an argument so
basis.k_image()can get needed info from the bifs object, and k_image() returns an appropriate k-space image while setting kdist in self.basis.There is an argument in favor of passing the needed components explicitly to
basis.k_image()rather than having it extract them from the bifs object. The advantage of the formulation I gave is that it works better if different classes of basis objects need different info. That's all somewhat theoretical since our mainline only has one possible basis.Example 2
becomes
where
self.likelihoodis an object, not a string, with a class that depended on the type of prior and likelihood. The rician version would have all the bessel function machinery and Rician-specific parameters tucked away inside of it.