def _compute_ft(self): self.S = np.zeros((len(self.K),), dtype=np.complex128) for i, k in enumerate(self.K): for r, q in zip(self.position, self.orientation): k_sq = np.dot(k, k) """ The FT of an object with orientation q at a given k-space point is the same as the FT of the unrotated object at a k-space point rotated the opposite way. The opposite of the rotation represented by a quaternion is the conjugate of the quaternion, found by inverting the sign of the imaginary components. """ k = rowan.rotate(rowan.inverse(q), k) f = 0 if k_sq == 0: f = self.volume else: for face_id, face in enumerate(self.faces): norm = self.norms[face_id] k_dot_norm = np.dot(norm, k) k_projected = k - k_dot_norm * norm k_projected_sq = np.dot(k_projected, k_projected) f2d = 0 if k_projected_sq == 0: f2d = self.areas[face_id] else: n_verts = len(face) for edge_id in range(n_verts): r0 = self.verts[face[edge_id]] r1 = self.verts[face[(edge_id + 1) % n_verts]] edge_vec = r1 - r0 edge_center = 0.5 * (r0 + r1) edge_cross_k = np.cross(edge_vec, k_projected) k_dot_center = np.dot(k_projected, edge_center) k_dot_edge = np.dot(k_projected, edge_vec) # Note that np.sinc(x) gives sin(pi*x)/(pi*x) f_n = ( np.dot(norm, edge_cross_k) * np.sinc(0.5 * k_dot_edge / np.pi) / k_projected_sq ) f2d -= f_n * 1j * np.exp(-1j * k_dot_center) d = self.d[face_id] exp_kr = np.exp(-1j * k_dot_norm * d) f += k_dot_norm * (1j * f2d * exp_kr) # end loop over faces f /= k_sq # end if/else, f is now calculated # S += rho * f * exp(-i k r) self.S[i] += ( self.density * f * np.exp(-1j * np.dot(k, rowan.rotate(rowan.inverse(q), r))) )
def test_inverse(self): """Test quaternion inverse.""" np.random.seed(0) shapes = [(4,), (5, 4), (5, 5, 4), (5, 5, 5, 4)] for shape in shapes: quats = np.random.random_sample(shape) quats_conj = quats.copy() quats_conj[..., 1:] *= -1 quats_conj /= rowan.norm(quats)[..., np.newaxis] ** 2 self.assertTrue(np.allclose(rowan.inverse(quats), quats_conj))
def test_divide(self): """Ensure division works""" shapes = [(4, ), (5, 4), (5, 5, 4), (5, 5, 5, 4)] np.random.seed(0) for shape_i in shapes: x = np.random.random_sample(shape_i) for shape_j in shapes: y = np.random.random_sample(shape_j) self.assertTrue( np.allclose(rowan.divide(x, y), rowan.multiply(x, rowan.inverse(y))))
def to_view(bod, view_orientation, image_size): lin_grid = np.linspace(-1, 1, image_size) x, y = np.meshgrid(lin_grid, lin_grid) y = -y r2 = x**2 + y**2 z = np.sqrt(np.clip(1 - r2, 0, None)) xyz = np.dstack((x, y, z)) xyz = rowan.rotate(rowan.inverse(view_orientation), xyz) x, y, z = xyz[:, :, 0], xyz[:, :, 1], xyz[:, :, 2] view = np.zeros((image_size, image_size)) phi = np.arccos(z) theta = np.arctan2(y, x) % (2 * np.pi) num_theta_bins, num_phi_bins = bod.nbins theta_bin_edges, phi_bin_edges = bod.bin_edges theta_bins = np.trunc(theta / (2 * np.pi) * num_theta_bins).astype(int) phi_bins = np.trunc(phi / np.pi * num_phi_bins).astype(int) view = bod.bond_order[theta_bins, phi_bins] view[r2 > 1] = np.nan return view
def read(self): "Read the frame data from the stream." self.stream.seek(self.start) i = line = None def _assert(assertion): assert i is not None assert line is not None if not assertion: raise ParserError("Failed to read line #{}: {}.".format( i, line)) monotype = False raw_frame = _RawFrameData() raw_frame.view_rotation = None for i, line in enumerate(self.stream): if _is_comment(line): continue if line.startswith('#'): if line.startswith('#[data]'): _assert(raw_frame.data is None) raw_frame.data_keys, raw_frame.data, j = \ self._read_data_section(line, self.stream) i += j else: raise ParserError(line) else: tokens = line.rstrip().split() if not tokens: continue # empty line elif tokens[0] in TOKENS_SKIP: continue # skip these lines if tokens[0] == 'eof': logger.debug("Reached end of frame.") break elif tokens[0] == 'def': definition, data, end = line.strip().split('"') _assert(len(end) == 0) name = definition.split()[1] type_shape = self._parse_shape_definition(data) if name not in raw_frame.types: raw_frame.types.append(name) raw_frame.type_shapes.append(type_shape) else: typeid = raw_frame.type_shapes.index(name) raw_frame.type_shapes[typeid] = type_shape warnings.warn( "Redefinition of type '{}'.".format(name)) elif tokens[0] == 'shape': # monotype data = line.strip().split('"')[1] raw_frame.types.append(self.default_type) type_shape = self._parse_shape_definition(data) raw_frame.type_shapes.append(type_shape) _assert(len(raw_frame.type_shapes) == 1) monotype = True elif tokens[0] in ('boxMatrix', 'box'): if len(tokens) == 10: raw_frame.box = np.array( [self._num(v) for v in tokens[1:]]).reshape((3, 3)) elif len(tokens) == 4: raw_frame.box = np.array([[self._num(tokens[1]), 0, 0], [0, self._num(tokens[2]), 0], [0, 0, self._num(tokens[3])] ]).reshape((3, 3)) elif tokens[0] == 'rotation': euler_angles = np.array([float(t) for t in tokens[1:]]) euler_angles *= np.pi / 180 raw_frame.view_rotation = rowan.from_euler( *euler_angles, axis_type='extrinsic', convention='xyz') else: # assume we are reading positions now if not monotype: name = tokens[0] if name not in raw_frame.types: raw_frame.types.append(name) type_shape = self._parse_shape_definition(' '.join( tokens[:3])) raw_frame.type_shapes.append(type_shape) else: name = self.default_type typeid = raw_frame.types.index(name) type_shape = raw_frame.type_shapes[typeid] if len(tokens) == 7 and isinstance(type_shape, ArrowShape): xyz = tokens[-6:-3] quat = tokens[-3:] + [0] elif len(tokens) >= 7: xyz = tokens[-7:-4] quat = tokens[-4:] elif len(tokens) >= 3: xyz = tokens[-3:] quat = None else: raise ParserError(line) raw_frame.typeid.append(typeid) raw_frame.position.append([self._num(v) for v in xyz]) if quat is None: raw_frame.orientation.append(quat) else: raw_frame.orientation.append( [self._num(v) for v in quat]) # Perform inverse rotation to recover original coordinates if raw_frame.view_rotation is not None: pos = rowan.rotate(rowan.inverse(raw_frame.view_rotation), raw_frame.position) else: pos = np.asarray(raw_frame.position) # If all the z coordinates are close to zero, set box dimension to 2 if np.allclose(pos[:, 2], 0.0, atol=1e-7): raw_frame.box_dimensions = 2 # If no valid orientations have been added, the array should be empty if all([quat is None for quat in raw_frame.orientation]): raw_frame.orientation = [] else: # Replace values of None with an identity quaternion for i in range(len(raw_frame.orientation)): if raw_frame.orientation[i] is None: raw_frame.orientation[i] = [1, 0, 0, 0] return raw_frame
def f(self, X, Z, A, t, logentry=None): # x = X[0] # y = X[1] # z = X[2] # xdot = X[3] # ydot = X[4] # zdot = X[5] # qw = X[6] # qx = X[7] # qy = X[8] # qz = X[9] # wx = X[10] # wy = X[11] # wz = X[12] a = Z**2 # a = A J = self.J dxdt = np.zeros(13) q = X[6:10] q = rowan.normalize(q) omega = X[10:] B0 = self.B0 * self.params['C_T'] # B0 = self.B0 eta = np.dot(B0, a) f_u = np.array([0, 0, eta[0]]) tau_u = np.array([eta[1], eta[2], eta[3]]) dxdt[0:3] = X[3:6] # dxdt[3:6] = -9.81 + rowan.rotate(q, f_u) / self.params['m'] dxdt[3:6] = np.array([0., 0., -9.81 ]) + rowan.rotate(q, f_u) / self.params['m'] Vinf = self.params['Vwind_mean'] - np.linalg.norm(X[3:6]) Vinf_B = rowan.rotate(rowan.inverse(q), Vinf) Vz_B = np.array([0.0, 0.0, Vinf_B[2]]) Vs_B = Vinf_B - Vz_B alpha = np.arcsin(np.linalg.norm(Vz_B) / np.linalg.norm(Vinf_B)) n = np.sqrt( np.multiply(a, self.B0[0, :]) / (self.params['C_T'] * self.params['rho'] * self.params['D']**4)) Fs_B = (Vs_B / np.linalg.norm(Vs_B) ) * self.params['C_s'] * self.params['rho'] * sum( n**self.params['k1']) * (np.linalg.norm(Vinf)**( 2 - self.params['k1'])) * (self.params['D']**( 2 + self.params['k1'])) * ( (np.pi / 2)**2 - alpha**2) * (alpha + self.params['k2']) # Fs_B = [0,0,0] dxdt[3:6] += rowan.rotate(q, Fs_B) / self.mass qnew = rowan.calculus.integrate(q, omega, self.ave_dt) if qnew[0] < 0: qnew = -qnew dxdt[6:10] = (qnew - q) / self.ave_dt dxdt[10:] = 1 / J * (np.cross(J * omega, omega) + tau_u) dxdt[10:] += 1 / J * np.cross( np.array([0.0, 0.0, self.params['D'] / 4]), Fs_B) euler_o = rowan.to_euler(q, 'xyz') if logentry is not None: logentry['f_u'] = f_u logentry['tau'] = tau_u logentry['euler_o'] = euler_o return dxdt.reshape((len(dxdt), 1))