def subsample_trajectory(traj: Trajectory, step=1, step_in_seconds=False): """ Sample the trajectory ``traj`` by removing evenly spaced points according to ``step``. Parameters ---------- traj : Trajectory Input trajectory. step : int, optional Number of sample points or period, depending on the value of ``step_in_seconds``. By default 1. step_in_seconds : bool, optional If True, ``step`` is considered as the number of sample points. Otherwise, ``step`` is interpreted as the sample period, in seconds. By default False. Returns ------- Trajectory Output trajectory. """ if step_in_seconds: step = int(step / traj.dt) points = traj.r[::step] ang = traj.ang[::step] if traj.ang is not None else None t = traj.t[::step] if traj.t is not None else None return Trajectory(points=points, t=t, ang=ang, dt=step * traj.dt)
def test_load(): # Wrong trajectory file extension at loading with pytest.raises(ValueError): t1 = Trajectory.load('t1.abc') # Loading json t1 = Trajectory.load('t1.json') for tp, point in zip(t1, [[1, 4], [2, 5], [3, 6]]): assert (np.array(point) == tp.r).all() # Loading csv t1 = Trajectory.load('t1.csv') for tp, point in zip(t1, [[1, 4], [2, 5], [3, 6]]): assert (np.array(point) == tp.r).all() os.remove('t1.json') os.remove('t1.csv')
def test_save(): t1 = Trajectory(x=[1, 2, 3], y=[4, 5, 6]) # Wrong trajectory file extension at saving with pytest.raises(ValueError): t1.save('t1', file_type='abc') # Saving json t1.save('t1', file_type='json') # Saving csv t1.save('t1', file_type='csv')
def test_creation_with_time(): Trajectory(x=[1, 2], y=[2, 3], t=[0, 0.1]) Trajectory(x=[1, 2], y=[2, 3], dt=0.1) Trajectory(x=[1, 2], y=[2, 3], t=[0, 0.1], dt=0.1) Trajectory(x=[1, 2], y=[2, 3], t=[0.4, 0.5]) Trajectory(x=[1, 2], y=[2, 3], t=[0.4, 0.5], dt=0.1, t0=0.4) with pytest.raises(ValueError): Trajectory(x=[1, 2], y=[2, 3], t=[0]) with pytest.raises(ValueError): Trajectory(x=[1, 2], y=[2, 3], t=[0, 0.1], dt=0.2) with pytest.raises(ValueError): Trajectory(x=[1, 2], y=[2, 3], t=[0.4, 0.5], dt=0.1)
def generate(self): # Get position vectors r = self._get_r() # Generate RandomWalk object trajs = [] for i in range(self.N): points = r[:, :, i] trajs.append( Trajectory(points=points, dt=self.dt, t=self.t, traj_id=f"Random Walker {i + 1}")) return trajs
def test_creation_by_dimensions(): Trajectory(dimensions=[[1, 2]]) Trajectory(dimensions=[[1, 2], [2, 3]]) Trajectory(dimensions=[[1, 2], [2, 3], [1, 4]]) Trajectory(dimensions=[[1, 2], [2, 3], [1, 4], [7, 8]]) with pytest.raises(ValueError): Trajectory(dimensions=[[1, 2], [2]]) with pytest.raises(ValueError): Trajectory(dimensions=[[1, 2], [2], [2, 5]]) with pytest.raises(ValueError): Trajectory(dimensions=[[1, 2], [2, 6], [5]]) with pytest.raises(ValueError): Trajectory(dimensions=[[2], [2, 6], [5, 8]])
def test_creation_by_points(): Trajectory(points=[[1, 2]]) Trajectory(points=[[1, 2], [2, 3]]) Trajectory(points=[[1, 2, 4], [2, 3, 2], [1, 4, 8]]) Trajectory(points=[[1, 2, 7, 3], [2, 3, 5, 3]]) with pytest.raises(ValueError): Trajectory(points=[[1, 2], [2]]) with pytest.raises(ValueError): Trajectory(points=[[1, 2], [2], [2, 5]])
def generate(self): self._simulate() self.r *= self.r_scale self.v *= self.v_scale self.t *= self.t_scale self.dt *= self.t_scale trajs = [] for i in range(self.N): points = self.r[:, :, i] trajs.append( Trajectory(points=points, dt=self.dt, t=self.t, traj_id=f"LangevinSolution {i + 1}")) return trajs
def test_creation_by_xyz(): Trajectory(x=[1, 2]) Trajectory(x=[1, 2], y=[2, 3]) Trajectory(x=[1, 2], y=[2, 3], z=[1, 4]) with pytest.raises(ValueError): Trajectory(x=[1, 2], y=[2]) with pytest.raises(ValueError): Trajectory(x=[1, 2], y=[2], z=[2, 5]) with pytest.raises(ValueError): Trajectory(x=[1, 2], y=[2, 6], z=[5]) with pytest.raises(ValueError): Trajectory(x=[2], y=[2, 6], z=[5, 8])
def traj(x): return Trajectory(x=x)
def add_dynamic_reference(traj: Trajectory, reference: Tuple[np.ndarray, np.ndarray, np.ndarray], start_at_origin=True): """ This function fuses the information of a trajectory with an external reference of the motion of the Frame of Reference (FoR). It allows to remap the information gathered in local SoRs to a more general FoR. Parameters ---------- traj : Trajectory Input trajectory. reference : Tuple[np.ndarray,np.ndarray,np.ndarray] Angular and translational parameters of the form ``(ang:np.ndarray, tx:np.ndarray, ty:np.ndarray)`` that accounts for the orientation and displacement of the reference. start_at_origin : bool, optional If True, set initial position at the origin. By default True. Returns ------- Trajectory Output trajectory in the lab frame of reference. """ def affine2camera(theta, tx, ty): x_cl, y_cl, theta_cl = np.zeros((3, theta.size + 1)) theta_cl[1:] = np.cumsum(theta) for i in range(theta.size): A = affine_matrix(theta_cl[i + 1], x_cl[i], y_cl[i], R_inv=True) x_cl[i + 1], y_cl[i + 1] = A @ [-tx[i], -ty[i], 1] x_cl, y_cl, theta_cl = x_cl[1:], y_cl[1:], theta_cl[1:] return x_cl, y_cl, theta_cl def camera2obj(x_ac, y_ac, x_cl, y_cl, theta_cl): x_al, y_al = np.empty((2, x_ac.size)) for i in range(x_ac.size): A = affine_matrix(theta_cl[i], x_cl[i], y_cl[i], R_inv=True) x_al[i], y_al[i] = A @ [x_ac[i], y_ac[i], 1] return x_al, y_al def affine2obj(theta, tx, ty, x_ac, y_ac): x_cl, y_cl, theta_cl = affine2camera(theta, tx, ty) x_al, y_al = camera2obj(x_ac, y_ac, x_cl, y_cl, theta_cl) return x_al, y_al theta, tx, ty = reference x_al, y_al = affine2obj(theta, tx, ty, traj.r.x, traj.r.y) if start_at_origin: x_al = x_al - x_al[0] y_al = y_al - y_al[0] traj.x = x_al traj.y = y_al return Trajectory(x=x_al, y=y_al, ang=traj.ang, t=traj.t, traj_id=traj.id)
def test_creation_general(): Trajectory(x=[1, 2], y=[2, 3], t=[0, 1], ang=[0, 0], traj_id='test') Trajectory(x=[1, 2], y=[2, 3], dt=0.5, ang=[0, 1.2], traj_id='test') Trajectory(points=[[1, 2], [2, 3]], dt=0.5, ang=[0, 1.2], traj_id='test') Trajectory(dimensions=[[1, 2], [2, 3]], dt=0.5, t=[1, 1.5], t0=1, traj_id='test')
def test_creation_with_ang(): Trajectory(x=[1, 2], y=[2, 3], ang=[0, 0.1]) with pytest.raises(ValueError): Trajectory(x=[1, 2], y=[2, 3], ang=[0.1])
from yupi import Trajectory from yupi.analyzing import plot_trajectory # Creation by assigning the axis directly # Data you got elsewhere x = [0, 1.0, 0.63, -0.37, -1.24, -1.5, -1.08, -0.19, 0.82, 1.63, 1.99, 1.85] y = [0, 0, 0.98, 1.24, 0.69, -0.3, -1.23, -1.72, -1.63, -1.01, -0.06, 0.94] # Generate the trajectory object track = Trajectory(x=x, y=y, traj_id="Spiral") # Plot the results plot_trajectory(track, title='Assigning the axis directly') # Creation by assigning the dimensions data # Data you got elsewhere dims = [[ 0, 1.0, 0.63, -0.37, -1.24, -1.5, -1.08, -0.19, 0.82, 1.63, 1.99, 1.85 ], [0, 0, 0.98, 1.24, 0.69, -0.3, -1.23, -1.72, -1.63, -1.01, -0.06, 0.94]] # Generate the trajectory object track = Trajectory(dimensions=dims, traj_id="Spiral") # Plot the results plot_trajectory(track, title='Assigning the dimensions data') # Creation by assigning the points data # Data you got elsewhere