def _pred_sig(self, theta, phi, beta, lambda1, lambda2): """ The predicted signal for a particular setting of the parameters """ Q = np.array([[lambda1, 0, 0], [0, lambda2, 0], [0, 0, lambda2]]) # If for some reason this is not symmetrical, then something is wrong # (in all likelihood, this means that the optimization process is # trying out some crazy value, such as nan). In that case, abort and # return a nan: if not np.allclose(Q.T, Q): return np.nan response_function = ozt.Tensor(Q, self.bvecs[:, self.b_idx], self.bvals[:, self.b_idx]) # Convert theta and phi to cartesian coordinates: x, y, z = geo.sphere2cart(1, theta, phi) bvec = [x, y, z] evals, evecs = response_function.decompose rot_tensor = ozt.tensor_from_eigs( evecs * ozu.calculate_rotation(bvec, evecs[0]), evals, self.bvecs[:, self.b_idx], self.bvals[:, self.b_idx]) iso_sig = np.exp(-self.bvals[self.b_idx][0] * lambda1) tensor_sig = rot_tensor.predicted_signal(1) return beta * iso_sig + (1 - beta) * tensor_sig
def _pred_sig(self, theta, phi, beta, lambda1, lambda2): """ The predicted signal for a particular setting of the parameters """ Q = np.array([[lambda1, 0, 0], [0, lambda2, 0], [0, 0, lambda2]]) # If for some reason this is not symmetrical, then something is wrong # (in all likelihood, this means that the optimization process is # trying out some crazy value, such as nan). In that case, abort and # return a nan: if not np.allclose(Q.T, Q): return np.nan response_function = ozt.Tensor(Q, self.bvecs[:,self.b_idx], self.bvals[:,self.b_idx]) # Convert theta and phi to cartesian coordinates: x,y,z = geo.sphere2cart(1, theta, phi) bvec = [x,y,z] evals, evecs = response_function.decompose rot_tensor = ozt.tensor_from_eigs( evecs * ozu.calculate_rotation(bvec, evecs[0]), evals, self.bvecs[:,self.b_idx], self.bvals[:,self.b_idx]) iso_sig = np.exp(-self.bvals[self.b_idx][0] * lambda1) tensor_sig = rot_tensor.predicted_signal(1) return beta * iso_sig + (1-beta) * tensor_sig
def rotate_to_vector(vector, evals, evecs, bvecs, bvals): """ Rotate the tensor to align with the input vector and return another Tensor class instance with that rotation (and the original bvecs/bvals). Parameters ---------- vector: A unit length 3-vector evals: The eigen-values of the tensor to rotate evecs: The corresponding eigen-vectors of the tensor to rotate. bvecs, bvals: inputs to create the new Tensor (presumably these are taken from the Tensor from which you got evals and evecs, but doesn't have to be). Returns ------- Tensor class instance rotated to the input vector. """ e1 = evecs[0] rot_tensor_e = np.dot(ozu.calculate_rotation(vector, e1), evecs) return tensor_from_eigs(rot_tensor_e, evals, bvecs, bvals)
def subsample(bvecs, n_dirs, elec_points=None): """ Generate a sub-sample of size n of directions from the provided bvecs Parameters ---------- bvecs: int array (n by 3), a set of cartesian coordinates for a set of bvecs n_dirs: int, how many bvecs to sub-sample from this set. elec_points: optional, a set of points read from the camino points, using Jones (2003) algorithm for electro-static repulsion Returns ------- [x,y,z]: The coordinates of the sub-sample bvec_idx: The indices into the original bvecs that would give this sub-sample Notes ----- Directions are chosen from the camino-generated electro-static repulsion points in the directory camino_pts. """ if elec_points is None: # We need a n by 3 here: xyz = ozu.get_camino_pts(n_dirs).T else: xyz = elec_points.copy() # Rotate all the points to align with the seed, the bvec relative to which # all the rest are chosen (lots going on in this one line): new_points = np.array(bvecs * ozu.calculate_rotation( bvecs[np.ceil(np.random.rand() * xyz.shape[0]).astype(int)], xyz[0])) sample_bvecs = np.zeros((3, n_dirs)) bvec_idx = [] for vec in xrange(n_dirs): this = new_points[vec] delta = np.zeros(bvecs.shape[0]) for j in xrange(bvecs.shape[0]): delta[j] = ozu.vector_angle(this, bvecs[j]) this_idx = np.where(delta==np.min(delta)) bvec_idx.append(this_idx) sample_bvecs[:, vec] = bvecs[this_idx] return sample_bvecs, np.array(bvec_idx).squeeze()
def _tensor_helper(self, theta, phi): """ This code is used in all three error functions, so we write it out only once here """ # Convert to cartesian coordinates: x, y, z = geo.sphere2cart(1, theta, phi) bvec = [x, y, z] # decompose is an auto-attr of the tensor object, so is only run once # and then cached: evals, evecs = self.response_function.decompose rot = ozu.calculate_rotation(bvec, evecs[0]) rot_evecs = evecs * rot rot_tensor = ozt.tensor_from_eigs(rot_evecs, evals, self.bvecs[:, self.b_idx], self.bvals[self.b_idx]) return rot_tensor
def _tensor_helper(self, theta, phi): """ This code is used in all three error functions, so we write it out only once here """ # Convert to cartesian coordinates: x,y,z = geo.sphere2cart(1, theta, phi) bvec = [x,y,z] # decompose is an auto-attr of the tensor object, so is only run once # and then cached: evals, evecs = self.response_function.decompose rot = ozu.calculate_rotation(bvec, evecs[0]) rot_evecs = evecs * rot rot_tensor = ozt.tensor_from_eigs(rot_evecs, evals, self.bvecs[:,self.b_idx], self.bvals[:,self.b_idx]) return rot_tensor
def rotations(self): """ Calculate the response function for alignment with each one of the b vectors """ out = [] for idx, bvec in enumerate(self.bvecs.T): rot = ozu.calculate_rotation(bvec, [1, 0, 0]) bvecs = np.asarray(np.dot(rot, self.bvecs)).squeeze() r, theta, phi = geo.cart2sphere(bvecs[0], bvecs[1], bvecs[2]) sph_harm_set = [] degree = 0 for order in np.arange(0, 2 * self.n_coeffs, 2): sph_harm_set.append(np.real(sph_harm(degree, order, theta, phi))) sph_harm_set = np.array(sph_harm_set) out.append(np.dot(self.coeffs, sph_harm_set)) return np.array(out)
def rotations(self): """ Calculate the response function for alignment with each one of the b vectors """ out = [] for idx, bvec in enumerate(self.bvecs.T): rot = ozu.calculate_rotation(bvec, [1, 0, 0]) bvecs = np.asarray(np.dot(rot, self.bvecs)).squeeze() r, theta, phi = geo.cart2sphere(bvecs[0], bvecs[1], bvecs[2]) sph_harm_set = [] degree = 0 for order in np.arange(0, 2 * self.n_coeffs, 2): sph_harm_set.append( np.real(sph_harm(degree, order, theta, phi))) sph_harm_set = np.array(sph_harm_set) out.append(np.dot(self.coeffs, sph_harm_set)) return np.array(out)
def subsample(bvecs, n_dirs, elec_points=None): """ Generate a sub-sample of size n of directions from the provided bvecs Parameters ---------- bvecs: int array (n by 3), a set of cartesian coordinates for a set of bvecs n_dirs: int, how many bvecs to sub-sample from this set. elec_points: optional, a set of points read from the camino points, using Jones (2003) algorithm for electro-static repulsion Returns ------- [x,y,z]: The coordinates of the sub-sample bvec_idx: The indices into the original bvecs that would give this sub-sample Notes ----- Directions are chosen from the camino-generated electro-static repulsion points in the directory camino_pts. """ if elec_points is None: # We need a n by 3 here: xyz = ozu.get_camino_pts(n_dirs).T else: xyz = elec_points.copy() # Rotate all the points to align with the seed, the bvec relative to which # all the rest are chosen (lots going on in this one line): rot_to_first = ozu.calculate_rotation( bvecs[:, np.ceil(np.random.randint(xyz.shape[0]))], xyz[0]) new_points = np.dot(rot_to_first, bvecs).T sample_bvecs = np.zeros((3, n_dirs)) bvec_idx = [] potential_indices = np.arange(bvecs.shape[-1]) for vec in xrange(n_dirs): this = new_points[vec] delta = np.zeros(potential_indices.shape) for j in range(delta.shape[0]): delta[j] = ozu.vector_angle(this, bvecs[:, j]) this_idx = np.where(delta==np.min(delta)) bvec_idx.append(potential_indices[this_idx]) sample_bvecs[:, vec] = np.squeeze(bvecs[:, this_idx]) # Remove bvecs that you've used, so that you don't have them more than # once: bvecs = np.hstack([bvecs[:, :this_idx[0]],bvecs[:, this_idx[0]+1:]]) potential_indices = np.hstack([potential_indices[:this_idx[0]], potential_indices[this_idx[0]+1:]]) return sample_bvecs, np.array(bvec_idx).squeeze()
def subsample(bvecs, n_dirs, elec_points=None): """ Generate a sub-sample of size n of directions from the provided bvecs Parameters ---------- bvecs: int array (n by 3), a set of cartesian coordinates for a set of bvecs n_dirs: int, how many bvecs to sub-sample from this set. elec_points: optional, a set of points read from the camino points, using Jones (2003) algorithm for electro-static repulsion Returns ------- [x,y,z]: The coordinates of the sub-sample bvec_idx: The indices into the original bvecs that would give this sub-sample Notes ----- Directions are chosen from the camino-generated electro-static repulsion points in the directory camino_pts. """ if elec_points is None: # We need a n by 3 here: xyz = ozu.get_camino_pts(n_dirs).T else: xyz = elec_points.copy() # Rotate all the points to align with the seed, the bvec relative to which # all the rest are chosen (lots going on in this one line): rot_to_first = ozu.calculate_rotation( bvecs[:, np.ceil(np.random.randint(xyz.shape[0]))], xyz[0]) new_points = np.dot(rot_to_first, bvecs).T sample_bvecs = np.zeros((3, n_dirs)) bvec_idx = [] potential_indices = np.arange(bvecs.shape[-1]) for vec in xrange(n_dirs): this = new_points[vec] delta = np.zeros(potential_indices.shape) for j in range(delta.shape[0]): delta[j] = ozu.vector_angle(this, bvecs[:, j]) this_idx = np.where(delta == np.min(delta)) bvec_idx.append(potential_indices[this_idx]) sample_bvecs[:, vec] = np.squeeze(bvecs[:, this_idx]) # Remove bvecs that you've used, so that you don't have them more than # once: bvecs = np.hstack([bvecs[:, :this_idx[0]], bvecs[:, this_idx[0] + 1:]]) potential_indices = np.hstack([ potential_indices[:this_idx[0]], potential_indices[this_idx[0] + 1:] ]) return sample_bvecs, np.array(bvec_idx).squeeze()