def kfold_xval_MD_mod(data, bvals, bvecs, mask, func, n, factor = 1000, initial="preset", bounds = "preset", params_file='temp', signal="relative_signal"): """ Finds the parameters of the given function to the given data that minimizes the sum squared errors using kfold cross validation. Parameters ---------- data: 4 dimensional array Diffusion MRI data bvals: 1 dimensional array All b values bvecs: 3 dimensional array All the b vectors mask: 3 dimensional array Brain mask of the data func: function handle Mean model to perform kfold cross-validation on. initial: tuple Initial values for the parameters. n: int Integer indicating the percent of vertices that you want to predict factor: int Integer indicating the scaling factor for the b values bounds: list List containing tuples indicating the bounds for each parameter in the mean model function. Returns ------- cod: 1 dimensional array Coefficent of Determination between data and predicted values predicted: 2 dimensional array Predicted mean for the vertices left out of the fit """ if isinstance(func, str): # Grab the function handle for the desired mean model func = globals()[func] # Get the initial values for the desired mean model if (bounds == "preset") | (initial == "preset"): all_params = initial_params(data, bvecs, bvals, func, mask=mask, params_file=params_file) if bounds == "preset": bounds = all_params[0] if initial == "preset": func_initial = all_params[1] else: this_initial = initial bval_list, b_inds, unique_b, rounded_bvals = ozu.separate_bvals(bvals) all_b_idx, b0_inds = _diffusion_inds(bvals, b_inds, rounded_bvals) b_scaled = bvals/factor flat_data = data[np.where(mask)] # Pre-allocate outputs ss_err = np.zeros(int(np.sum(mask))) predict_out = np.zeros((int(np.sum(mask)),len(all_b_idx))) # Setting up for creating combinations of directions for kfold cross # validation: # Number of directions to leave out at a time. num_choose = (n/100.)*len(all_b_idx) # Find the indices to all the non-b = 0 directions and shuffle them. vec_pool = np.arange(len(all_b_idx)) np.random.shuffle(vec_pool) all_inc_0 = np.arange(len(rounded_bvals)) # Start cross-validation for combo_num in np.arange(np.floor(100./n)): (si, vec_combo, vec_combo_rm0, vec_pool_inds, these_bvecs, these_bvals, this_data, these_inc0) = ozu.create_combos(bvecs, bvals, data, all_b_idx, np.arange(len(all_b_idx)), all_b_idx, vec_pool, num_choose, combo_num) this_flat_data = this_data[np.where(mask)] for vox in np.arange(np.sum(mask)).astype(int): s0 = np.mean(flat_data[vox, b0_inds], -1) these_b = b_scaled[vec_combo] # b values to predict if initial == "preset": this_initial = func_initial[vox] input_signal = flat_data[vox, these_inc0]/s0 if signal == "log": input_signal = np.log(input_signal) # Fit mean model to part of the data params, _ = opt.leastsq(err_func, this_initial, args=(b_scaled[these_inc0], input_signal, func)) if bounds == None: params, _ = opt.leastsq(err_func, this_initial, args=(b_scaled[these_inc0], input_signal, func)) else: lsq_b_out = lsq.leastsqbound(err_func, this_initial, args = (b_scaled[these_inc0], input_signal, func), bounds = bounds) params = lsq_b_out[0] # Predict the mean values of the left out b values using the # parameters from fitting to part of the b values. predict = func(these_b, *params) predict_out[vox, vec_combo_rm0] = func(these_b, *params) # Find the relative diffusion signal. s0 = np.mean(flat_data[:, b0_inds], -1).astype(float) input_signal = flat_data[:, all_b_idx]/s0[..., None] if signal == "log": input_signal = np.log(input_signal) cod = ozu.coeff_of_determination(input_signal, predict_out, axis=-1) return cod, predict_out
def kfold_xval_MD_mod(data, bvals, bvecs, mask, func, n, factor=1000, initial="preset", bounds="preset", params_file='temp', signal="relative_signal"): """ Finds the parameters of the given function to the given data that minimizes the sum squared errors using kfold cross validation. Parameters ---------- data: 4 dimensional array Diffusion MRI data bvals: 1 dimensional array All b values bvecs: 3 dimensional array All the b vectors mask: 3 dimensional array Brain mask of the data func: function handle Mean model to perform kfold cross-validation on. initial: tuple Initial values for the parameters. n: int Integer indicating the percent of vertices that you want to predict factor: int Integer indicating the scaling factor for the b values bounds: list List containing tuples indicating the bounds for each parameter in the mean model function. Returns ------- cod: 1 dimensional array Coefficent of Determination between data and predicted values predicted: 2 dimensional array Predicted mean for the vertices left out of the fit """ if isinstance(func, str): # Grab the function handle for the desired isotropic model func = globals()[func] # Get the initial values for the desired isotropic model if (bounds == "preset") | (initial == "preset"): all_params = initial_params(data, bvecs, bvals, func, mask=mask, params_file=params_file) if bounds == "preset": bounds = all_params[0] if initial == "preset": func_initial = all_params[1] else: this_initial = initial bval_list, b_inds, unique_b, rounded_bvals = ozu.separate_bvals(bvals) all_b_idx, b0_inds = _diffusion_inds(bvals, b_inds, rounded_bvals) b_scaled = bvals / factor flat_data = data[np.where(mask)] # Pre-allocate outputs ss_err = np.zeros(int(np.sum(mask))) predict_out = np.zeros((int(np.sum(mask)), len(all_b_idx))) # Setting up for creating combinations of directions for kfold cross # validation: # Number of directions to leave out at a time. num_choose = (n / 100.) * len(all_b_idx) # Find the indices to all the non-b = 0 directions and shuffle them. vec_pool = np.arange(len(all_b_idx)) np.random.shuffle(vec_pool) all_inc_0 = np.arange(len(rounded_bvals)) # Start cross-validation for combo_num in np.arange(np.floor(100. / n)): (si, vec_combo, vec_combo_rm0, vec_pool_inds, these_bvecs, these_bvals, this_data, these_inc0) = ozu.create_combos(bvecs, bvals, data, all_b_idx, np.arange(len(all_b_idx)), all_b_idx, vec_pool, num_choose, combo_num) these_b = b_scaled[vec_combo] # b values to predict for vox in np.arange(np.sum(mask)).astype(int): s0 = np.mean(flat_data[vox, b0_inds], -1) if initial == "preset": this_initial = func_initial[vox] input_signal = flat_data[vox, these_inc0] / s0 if signal == "log": input_signal = np.log(input_signal) # Fit mean model to part of the data params, _ = opt.leastsq(err_func, this_initial, args=(b_scaled[these_inc0], input_signal, func)) if bounds == None: params, _ = opt.leastsq(err_func, this_initial, args=(b_scaled[these_inc0], input_signal, func)) else: lsq_b_out = lsq.leastsqbound(err_func, this_initial, args=(b_scaled[these_inc0], input_signal, func), bounds=bounds) params = lsq_b_out[0] predict_out[vox, vec_combo_rm0] = func(these_b, *params) # Find the relative diffusion signal. s0 = np.mean(flat_data[:, b0_inds], -1).astype(float) input_signal = flat_data[:, all_b_idx] / s0[..., None] if signal == "log": input_signal = np.log(input_signal) cod = ozu.coeff_of_determination(input_signal, predict_out, axis=-1) return cod, predict_out