def cv_map_to_csdm(self): # convert cv_map to csdm self.cv_map = cp.as_csdm(np.squeeze(self.cv_map.T.copy())) if len(self.cv_alphas) != 1: d0 = cp.as_dimension(-np.log10(self.cv_alphas), label="-log(α)") self.cv_map.dimensions[0] = d0 if len(self.cv_lambdas) == 1: return d1 = cp.as_dimension(-np.log10(self.cv_lambdas), label="-log(λ)") if len(self.cv_alphas) != 1: self.cv_map.dimensions[1] = d1 else: self.cv_map.dimensions[0] = d1
def _sol_to_csdm(self, s): """Pack solution as csdm object""" if not isinstance(s, cp.CSDM): return self.f = cp.as_csdm(self.f) for i, dim in enumerate(self.inverse_dimension): app = dim.application or {} if "com.github.deepanshs.mrinversion" in app: meta = app["com.github.deepanshs.mrinversion"] is_log = meta.get("log", False) if is_log: coords = np.log10(dim.coordinates.value) self.inverse_dimension[i] = cp.as_dimension( array=coords, label=meta["label"]) if len(s.dimensions) > 1 and len(self.f.shape) == 3: self.f.dimensions[2] = s.dimensions[1] self.f.dimensions[1] = self.inverse_dimension[1] self.f.dimensions[0] = self.inverse_dimension[0] elif len(s.dimensions) == 1 and len(self.f.shape) == 2: self.f.dimensions[1] = self.inverse_dimension[1] self.f.dimensions[0] = self.inverse_dimension[0] elif len(s.dimensions) > 1: self.f.dimensions[1] = s.dimensions[1] self.f.dimensions[0] = self.inverse_dimension[0]
def fit(self, K, s): r"""Fit the model using the coordinate descent method from scikit-learn for all alpha anf lambda values using the `n`-folds cross-validation technique. The cross-validation metric is the mean squared error. Args: K: A :math:`m \times n` kernel matrix, :math:`{\bf K}`. A numpy array of shape (m, n). s: A :math:`m \times m_\text{count}` signal matrix, :math:`{\bf s}` as a csdm object or a numpy array or shape (m, m_count). """ s_, self.scale = prepare_signal(s) sin_val = np.linalg.svd(K, full_matrices=False)[1] K_, s_ = np.asfortranarray(K), np.asfortranarray(s_) lipszit = sin_val[0]**2 # test train CV set k_train, s_train, k_test, s_test, m = test_train_set( K_, s_, self.folds, self.randomize, self.times) self.cv_map, self.std, _, _, _, self.prediction_error = fista_cv.fista( matrix=k_train, s=s_train, matrixtest=k_test, stest=s_test, lambdaval=self.cv_lambdas, maxiter=self.max_iterations, nonnegative=int(self.positive), linv=(1 / lipszit), tol=self.tolerance, npros=self.n_jobs, m=m, ) # subtract the variance. # self.cv_map -= (self.sigma / self.scale) ** 2 self.cv_map = np.abs(self.cv_map) lambdas = np.log10(self.cv_lambdas) l1_index, l2_index = calculate_opt_lambda(self.cv_map, self.std) lambda1, _ = lambdas[l1_index], lambdas[l2_index] self.hyperparameters["lambda"] = 10**lambda1 # Calculate the solution using the complete data at the optimized lambda self.opt = LassoFista( lambda1=self.hyperparameters["lambda"], max_iterations=self.max_iterations, tolerance=self.tolerance, positive=self.positive, inverse_dimension=self.inverse_dimension, ) self.opt.fit(K, s) self.f = self.opt.f # convert cv_map to csdm self.cv_map = cp.as_csdm(np.squeeze(self.cv_map.T.copy())) self.cv_map.y[0].component_labels = ["log10"] d0 = cp.as_dimension(np.log10(self.cv_lambdas), label="log(λ)") self.cv_map.dimensions[0] = d0 self.cross_validation_curve = self.cv_map
def fit(self, K, s, warm_start=False): s_, self.scale = prepare_signal(s) sin_val = np.linalg.svd(K, full_matrices=False)[1] K_, s_ = np.asfortranarray(K), np.asfortranarray(s_) self.f = np.asfortranarray(np.zeros((K_.shape[1], s_.shape[1]))) lipszit = sin_val[0]**2 if warm_start: self.f_1 = np.asfortranarray(np.zeros((K_.shape[1], 1))) _ = fista.fista( matrix=K_, s=s_.mean(axis=1), lambd=self.hyperparameters["lambda"], maxiter=self.max_iterations, f_k=self.f_1, nonnegative=int(self.positive), linv=(1 / lipszit), tol=self.tolerance, npros=1, ) self.f = np.asfortranarray(np.tile(self.f_1, s_.shape[1])) _ = fista.fista( matrix=K_, s=s_, lambd=self.hyperparameters["lambda"], maxiter=self.max_iterations, f_k=self.f, nonnegative=int(self.positive), linv=(1 / lipszit), tol=self.tolerance, npros=1, ) self.f *= self.scale if not isinstance(s, cp.CSDM): return # CSDM pack self.f = cp.as_csdm(np.squeeze(self.f.T)) app = self.inverse_dimension.application or {} if "com.github.deepanshs.mrinversion" in app: meta = app["com.github.deepanshs.mrinversion"] is_log = meta.get("log", False) if is_log: # unit = self.inverse_dimension.coordinates.unit coords = np.log10(self.inverse_dimension.coordinates.value) self.inverse_dimension = cp.as_dimension(array=coords, label=meta["label"]) if len(s.dimensions) > 1: self.f.dimensions[1] = s.dimensions[1] self.f.dimensions[0] = self.inverse_dimension
def __init__(self, kernel_dimension, inverse_dimension): minimum = inverse_dimension["minimum"] maximum = inverse_dimension["maximum"] count = inverse_dimension.get("count", 32) scale = inverse_dimension.get("scale", "linear") label = inverse_dimension.get("label", None) unit = kernel_dimension.coordinates[0].unit x_min = string_to_quantity(minimum).to(unit).value x_max = string_to_quantity(maximum).to(unit).value check_log = scale == "log" if check_log: x_min, x_max = np.log10(x_min), np.log10(x_max) coords = (np.arange(count) / (count - 1)) * (x_max - x_min) + x_min if check_log: coords = 10**(coords) lbl_ = f"log({self.__class__.__name__} / {unit})" if check_log else None label = label if label is not None else lbl_ inverse_dimension = cp.as_dimension(array=coords, unit=str(unit), label=label) meta = { "log": check_log, "label": f"log({self.__class__.__name__} / {unit})" if check_log else None, } inverse_dimension.application = { "com.github.deepanshs.mrinversion": meta } super().__init__(kernel_dimension, inverse_dimension, 1, 1)
cmap=cm.Oranges_r, # colormap box=False, # draw a box around the region ) ax.legend() plt.tight_layout() plt.show() # %% # Convert the 3D tensor distribution in Haeberlen parameters # ---------------------------------------------------------- # You may re-bin the 3D tensor parameter distribution from a # :math:`\rho(\delta_\text{iso}, x, y)` distribution to # :math:`\rho(\delta_\text{iso}, \zeta_\sigma, \eta_\sigma)` distribution as follows. # Create the zeta and eta dimensions,, as shown below. zeta = cp.as_dimension(np.arange(40) * 4 - 40, unit="ppm", label="zeta") eta = cp.as_dimension(np.arange(16) / 15, label="eta") # Use the `to_Haeberlen_grid` function to convert the tensor parameter distribution. fsol_Hae = to_Haeberlen_grid(f_sol, zeta, eta) # %% # The 3D plot # ''''''''''' plt.figure(figsize=(5, 4.4)) ax = plt.subplot(projection="3d") plot_3d(ax, fsol_Hae, x_lim=[0, 1], y_lim=[-40, 120], z_lim=[-60, -120],
import csdmpy as cp import numpy as np from mrinversion.kernel import T1 from mrinversion.kernel import T2 kernel_dimension = cp.Dimension(type="linear", count=5, increment="20 ms") count = 10 coords = 10**((np.arange(count) / (count - 1)) * (2 - (-3)) - 3) inverse_kernel_dimension = cp.as_dimension(array=coords, unit="s") print(inverse_kernel_dimension) def test_T2_kernel(): T2_obj = T2( kernel_dimension=kernel_dimension, inverse_dimension=dict( count=count, minimum="1e-3 s", maximum="1e2 s", scale="log", label="log (T2 / s)", ), ) K = T2_obj.kernel(supersampling=1) x = kernel_dimension.coordinates x_inverse = inverse_kernel_dimension.coordinates amp = np.exp(np.tensordot(-x, (1 / x_inverse), 0)) # amp /= amp.max()
def generate_data(): dv1 = cp.as_dependent_variable(np.random.rand(20)) dv2 = cp.as_dependent_variable(np.random.rand(20)) dv3 = cp.as_dependent_variable(np.random.rand(20)) dim = cp.as_dimension(np.arange(20)) return cp.CSDM(dependent_variables=[dv1, dv2, dv3], dimensions=[dim])