Source code for irfpy.vexpvat.ql.panels

"""

Most of the functions assumes the :mod:`irfpy.vexpvat.vexspice` module is initialized prior.

>>> from irfpy.vexpvat import vexspice as vs
>>> vs.init()
"""
import datetime

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mplpatches

from irfpy.vexpvat import vexspice as vs

from irfpy.util.intersection import isvisible
from irfpy.util import utc
from irfpy.util.nptools import unjump_periodic

from irfpy.venus import rv, icb, bowshock

[docs]class Panel_xr_orbit: """ Create a matplotlib axis. *Usage* 1. Import needed modules :: import datetime import matplotlib.pyplot as plt from irfpy.util import utc import irfpy.vexpvat.vexspice as vs vs.init() from irfpy.vexpvat.ql import Panel_xr_orbit 2-a. To plot a simple, default figure :: t0 = datetime.datetime(2006, 12, 1, 5, 0) t1 = datetime.datetime(2006, 12, 1, 8, 0) xrplot = Panel_xr_orbit(t0, t1) 2-b. To add some more data points, use the :meth:`add_orbit_curve`, :meth:`add_ticks`, :meth:`add_timelabel`. :: t2 = datetime.datetime(2006, 12, 1, 14, 0) t3 = datetime.datetime(2006, 12, 1, 16, 0) xrplot.add_orbit_curve(t2, t3, color='b') xrplot.add_ticks(utc.dtlinspace(t2, t3, 4), color='b', marker='x') xrplot.add_timelabel(utc.dtlinspace(t2, t3, 4), color='b', datefmt='(%H:%M)', va='center', fontsize=6) 2-c. To add some cosmetics, use ``xrplot.ax`` as a normal matplotlib axis object. :: ax = xrplot.ax ax.set_xlim(-4, 4) # Change the limit, for example, as usual for matplotlib. ax.text(0, 0, 'VENUS', color='k') 3. You can embed the panel to a figure. :: fig = plt.figure() ax = fig.add_subplot(2, 2, 2) # Plot goes to the top-right xrplot2 = Panel_xr_orbit(ax=ax) xrplot2.add_orbit_curve(t1, t2) xrplot2.add_venus() """ def __init__(self, t0=None, t1=None, ax=None, frame='VSO'): self.frame = frame if ax is None: self.ax = plt.gca() else: self.ax = ax # If t0 and t1 is given, default sets of plots are produced. if t0 is not None and t1 is not None: self.add_orbit_curve(t0, t1) self.add_ticks(utc.dtlinspace(t0, t1, 5)) self.add_timelabel(utc.dtlinspace(t0, t1, 5)) self.add_venus() self.add_bs() self.add_icb() self.ax.set_aspect('equal') self.ax.set_xlim(-6, 6) self.ax.set_ylim(0, 12) self.ax.set_xlabel('X [Rv; {}]'.format(frame)) self.ax.set_ylabel('R [Rv; {}]'.format(frame)) self.ax.set_title('VEX Orbit') def _xr(self, tlist, target='VEX'): poses = vs.get_positions(tlist, target=target, frame=self.frame, origin='VENUS') x = poses[:, 0] / rv r = np.sqrt(poses[:, 1] ** 2 + poses[:, 2] ** 2) / rv return (x, r)
[docs] def add_orbit_curve(self, t0, t1, resolution=180, target='VEX', **kwds): ax = self.ax # dt = (t1 - t0).total_seconds() # tlist = [t0 + datetime.timedelta(seconds=dt) * (i / (resolution - 1)) for i in range(resolution)] from irfpy.util.utc import dtlinspace tlist = dtlinspace(t0, t1, resolution) x, r = self._xr(tlist, target=target) ax.plot(x, r, **kwds)
[docs] def add_venus(self, facecolor='y', edgecolor='none', **kwds): venus = mplpatches.Circle([0, 0], 1, facecolor=facecolor, edgecolor=edgecolor) self.ax.add_patch(venus)
[docs] def add_ticks(self, tlist, target='VEX', marker='o', **kwds): ax = self.ax x, r = self._xr(tlist, target=target) ax.plot(x, r, marker=marker, ls='none', **kwds)
[docs] def add_timelabel(self, tlist, target='VEX', datefmt=' %T', **kwds): ax = self.ax x, r = self._xr(tlist, target=target) for _x, _r, _t in zip(x, r, tlist): ax.text(_x, _r, _t.strftime(datefmt), **kwds)
[docs] def add_icb(self, ls=':', color='y', **kwds): x, r = icb.xr_martinecz08() self.ax.plot(x, r, ls=ls, color=color, **kwds)
[docs] def add_bs(self, ls=':', color='y', **kwds): x, r = bowshock.xr_martinecz08() self.ax.plot(x, r, ls=ls, color=color, **kwds)
[docs]def axis_object(t, target, ax=None, marker='o', color='k', **kwds): """ Add a point to the axis! :param t: Time :param ax: Axis object :param kwds: Given to axes.text function :return: Axis object """ if ax is None: ax = plt.gca() vc = vs.get_position(t, target=target, origin='VEX', frame='VEX_ASPERA4_IMAS') theta = np.rad2deg(np.arcsin(vc[2] / np.sqrt((vc ** 2).sum()))) phi = np.rad2deg(np.arctan2(vc[1], vc[0])) # print(target, vc, theta, phi) ax.plot([phi - 360, phi, phi + 360], [theta, theta, theta], marker=marker, color=color, ls='None', **kwds) return ax, (phi, theta)
[docs]def axis_venus_limb(t, ax=None, color='y', **kwds): if ax is None: ax = plt.gca() # Direction of venus vc = vs.get_position(t, target='VENUS', origin='VEX', frame='VEX_ASPERA4_IMAS') # theta = np.rad2deg(np.arcsin(vc[2] / np.sqrt((vc ** 2).sum()))) # phi = np.rad2deg(np.arctan2(vc[1], vc[0])) vc_len = np.linalg.norm(vc) venus_angle = np.arcsin(rv / vc_len) #print('Venus angle:', np.rad2deg(venus_angle)) # Cone vectors from irfpy.util import cone vecs = cone.get_surface_vectors(vc, np.rad2deg(venus_angle), ndiv=60) # (3, 60) array ts = [] ps = [] for vec in vecs.T: t = np.rad2deg(np.arcsin(vec[2] / np.linalg.norm(vec))) p = np.rad2deg(np.arctan2(vec[1], vec[0])) #print(p, ps) if len(ps) > 0 and np.abs(ps[-1] - p) > 180: ts.append(np.nan) ps.append(np.nan) ts.append(t) ps.append(p) ts = np.array(ts) ps = np.array(ps) # print(ts, ps) ax.plot(ps, ts, color=color, **kwds) ax.plot(ps + 360, ts, color=color, **kwds) ax.plot(ps - 360, ts, color=color, **kwds) return ax, ()
[docs]def axis_venus_latitudes(t, latitudes=[-90, -60, -30, 0, 30, 60, 90], resolution=60, ax=None, color='y', **kwds): if ax is None: ax = plt.gca() segments = [] # Position of VEX is (0, 0, 0), the observer # Positoin of Venus is a center of sphere. vc = vs.get_position(t, target='VENUS', origin='VEX', frame='VEX_ASPERA4_IMAS') # Conversion matrix matx = vs.convert_matrix(t, fromframe='IAU_VENUS', toframe='VEX_ASPERA4_IMAS') for latitude_deg in latitudes: latitude = np.deg2rad(latitude_deg) longitudes = np.deg2rad(np.linspace(0, 360, resolution)) segment = [] for longitude in longitudes: x = np.cos(longitude) * np.cos(latitude) * rv * 1.001 # Slightly bigger than rv to avoid numerical errors y = np.sin(longitude) * np.cos(latitude) * rv * 1.001 z = np.sin(latitude) * rv * 1.001 target = matx.dot(np.array([x, y, z])) + vc if isvisible([0, 0, 0], target, vc, rv): theta = np.arcsin(target[2] / np.linalg.norm(target)) phi = np.arctan2(target[1], target[0]) segment.append([np.rad2deg(phi), np.rad2deg(theta)]) else: segment.append([np.nan, np.nan]) # Not visible, not plotted if not np.isnan(segment).all(): segments.append(np.array(segment)) for segment in segments: ps = unjump_periodic(segment[:, 0], 360) ts = segment[:, 1] ax.plot(ps, ts, color=color, **kwds) ax.plot(ps + 360, ts, color=color, **kwds) ax.plot(ps - 360, ts, color=color, **kwds) return ax, ()
[docs]def axis_venus_longitudes(t, longitudes=[-180, -135, -90, -45, 0, 45, 90, 135], resolution=45, ax=None, color='y', **kwds): if ax is None: ax = plt.gca() segments = [] # Position of VEX is (0, 0, 0), the observer # Positoin of Venus is a center of sphere. vc = vs.get_position(t, target='VENUS', origin='VEX', frame='VEX_ASPERA4_IMAS') # Conversion matrix matx = vs.convert_matrix(t, fromframe='IAU_VENUS', toframe='VEX_ASPERA4_IMAS') for longitude_deg in longitudes: longitude = np.deg2rad(longitude_deg) latitudes = np.deg2rad(np.linspace(-90, 90, resolution)) segment = [] for latitude in latitudes: x = np.cos(longitude) * np.cos(latitude) * rv * 1.001 # Slightly bigger than rv to avoid numerical errors y = np.sin(longitude) * np.cos(latitude) * rv * 1.001 z = np.sin(latitude) * rv * 1.001 target = matx.dot(np.array([x, y, z])) + vc if isvisible([0, 0, 0], target, vc, rv): theta = np.arcsin(target[2] / np.linalg.norm(target)) phi = np.arctan2(target[1], target[0]) segment.append([np.rad2deg(phi), np.rad2deg(theta)]) else: segment.append([np.nan, np.nan]) # Not visible, not plotted if not np.isnan(segment).all(): segments.append(np.array(segment)) for segment in segments: ps = unjump_periodic(segment[:, 0], 360) ts = segment[:, 1] ax.plot(ps, ts, color=color, **kwds) ax.plot(ps + 360, ts, color=color, **kwds) ax.plot(ps - 360, ts, color=color, **kwds) return ax, ()