# Path: spiceminer/extra.py
# def angle(v0, v1):
#     '''Calculate the angle between 2 vectors.
# 
#     Parameters
#     ----------
#     v0, v1: array-like
#         The vectors to measure the angle between. Must have shape (n>1,) or
#         (n>1, m) where n is the dimension of the vector and m the number of
#         vectors.
# 
#     Returns
#     -------
#     array-like
#         The angles between `v0` and `v1` in radians.
# 
#     Raises
#     ------
#     ValueError
#         If one or both vector-arrays do not fit the requirements.
#     '''
#     def iangle(v0, v1):
#         v0 = v0 / norm(v0, axis=0)
#         v1 = v1 / norm(v1, axis=0)
#         for x, y in zip(v0.T, v1.T):
#             radians = np.arccos(np.dot(x, y))
#             if np.isnan(radians):
#                 if (x == y).all():
#                     radians = 0.0
#                 else:
#                     radians = np.pi
#             yield radians
# 
#     if v0.shape != v1.shape:
#         msg = 'shapes {} and {} not equal'
#         raise ValueError(msg.format(v0.shape, v1.shape))
#     if v0.shape[0] < 2:
#         msg = 'vectors must havew at least 2 dimensions, got {}'
#         raise ValueError(msg.format(v0.shape[0]))
#     if len(v0.shape) > 2:
#         msg = 'v0 and v1 may only be 1-D or 2-D, got {}-D'
#         raise ValueError(msg.format(len(v0.shape)))
#     if len(v0.shape) == 1:
#         v0 = np.array([[item] for item in v0])
#         v1 = np.array([[item] for item in v1])
#     return np.fromiter(iangle(v0, v1), dtype=float, count=v0.shape[1])


import numpy as np
import spiceminer as sm
import matplotlib.pyplot as plt
from spiceminer.extra import angle

# Load the necessary data (this example requires parts of the packages 'base'
# and 'msl', which you can download with getdata.py)
sm.load('data')

# Get necessary bodies
mars = sm.Body('mars')
rover = sm.Body('msl_rover')

# Let's look at a month shortly after landing
times = np.arange(sm.Time(2013), sm.Time(2013, 2), sm.Time.HOUR)

# Get position on mars surface
position = rover.position(times, observer=mars, frame=mars)
dist, theta, phi = car2sphere(position[1:])

X, Y, Z = np.identity(3)
# Get the angle of the mars rover on the surface (obvious method)
rotation = rover.rotation(times, target=mars)
rover_x = np.array([r.dot(X) for r in rotation[1]])
rover_y = np.array([r.dot(-Y) for r in rotation[1]])
rover_z = np.array([r.dot(-Z) for r in rotation[1]])
radians = np.array([angle(z, p) for z, p in zip(rover_z, position[1:].T)])
radians_x = np.array([angle(x, p) - np.pi/2 for x, p in zip(rover_x, position[1:].T)])
radians_y = np.array([angle(y, p) - np.pi/2 for y, p in zip(rover_y, position[1:].T)])

# Get the angle of the mars rover on the surface (fast, absolute)
points = mars.position(times, observer=rover, frame=rover)
radians2 = np.array([angle(Z, p) for p in points[1:].T])
radians2_x = np.array([angle(Z[1:], p) for p in points[1::2].T])

# Path: spiceminer/extra.py
# def angle(v0, v1):
#     '''Calculate the angle between 2 vectors.
# 
#     Parameters
#     ----------
#     v0, v1: array-like
#         The vectors to measure the angle between. Must have shape (n>1,) or
#         (n>1, m) where n is the dimension of the vector and m the number of
#         vectors.
# 
#     Returns
#     -------
#     array-like
#         The angles between `v0` and `v1` in radians.
# 
#     Raises
#     ------
#     ValueError
#         If one or both vector-arrays do not fit the requirements.
#     '''
#     def iangle(v0, v1):
#         v0 = v0 / norm(v0, axis=0)
#         v1 = v1 / norm(v1, axis=0)
#         for x, y in zip(v0.T, v1.T):
#             radians = np.arccos(np.dot(x, y))
#             if np.isnan(radians):
#                 if (x == y).all():
#                     radians = 0.0
#                 else:
#                     radians = np.pi
#             yield radians
# 
#     if v0.shape != v1.shape:
#         msg = 'shapes {} and {} not equal'
#         raise ValueError(msg.format(v0.shape, v1.shape))
#     if v0.shape[0] < 2:
#         msg = 'vectors must havew at least 2 dimensions, got {}'
#         raise ValueError(msg.format(v0.shape[0]))
#     if len(v0.shape) > 2:
#         msg = 'v0 and v1 may only be 1-D or 2-D, got {}-D'
#         raise ValueError(msg.format(len(v0.shape)))
#     if len(v0.shape) == 1:
#         v0 = np.array([[item] for item in v0])
#         v1 = np.array([[item] for item in v1])
#     return np.fromiter(iangle(v0, v1), dtype=float, count=v0.shape[1])


# Path: docs/source/examples/marsrover.py
import numpy as np
import spiceminer as sm
import matplotlib.pyplot as plt
from spiceminer.extra import angle


# Load the necessary data (this example requires parts of the packages 'base'
# and 'msl', which you can download with getdata.py)
sm.load('data')

# Get necessary bodies
mars = sm.Body('mars')
rover = sm.Body('msl_rover')

# Let's look at a month shortly after landing
times = np.arange(sm.Time(2013), sm.Time(2013, 2), sm.Time.HOUR)

# Get position on mars surface
position = rover.position(times, observer=mars, frame=mars)
dist, theta, phi = car2sphere(position[1:])

X, Y, Z = np.identity(3)
# Get the angle of the mars rover on the surface (obvious method)
rotation = rover.rotation(times, target=mars)
rover_x = np.array([r.dot(X) for r in rotation[1]])
rover_y = np.array([r.dot(-Y) for r in rotation[1]])
rover_z = np.array([r.dot(-Z) for r in rotation[1]])
radians = np.array([angle(z, p) for z, p in zip(rover_z, position[1:].T)])
radians_x = np.array([angle(x, p) - np.pi/2 for x, p in zip(rover_x, position[1:].T)])
radians_y = np.array([angle(y, p) - np.pi/2 for y, p in zip(rover_y, position[1:].T)])

# Get the angle of the mars rover on the surface (fast, absolute)
points = mars.position(times, observer=rover, frame=rover)
radians2 = np.array([angle(Z, p) for p in points[1:].T])
radians2_x = np.array([angle(Z[1:], p) for p in points[1::2].T])

radians2_y = np.array([angle(Z[1:], p) for p in points[2:].T])