Source code for pyrfu.mms.probe_align_times

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# 3rd party imports
import numpy as np
import xarray as xr

# Local imports
from ..pyrf.extend_tint import extend_tint
from ..pyrf.resample import resample
from ..pyrf.time_clip import time_clip
from ..pyrf.ts_scalar import ts_scalar

__author__ = "Louis Richard"
__email__ = "louisr@irfu.se"
__copyright__ = "Copyright 2020-2023"
__license__ = "MIT"
__version__ = "2.4.2"
__status__ = "Prototype"


[docs]def probe_align_times(e_xyz, b_xyz, sc_pot, z_phase): r"""Returns times when field-aligned electrostatic waves can be characterized using interferometry techniques. The same alignment conditions as Graham et al., JGR, 2015 are used. Optional figure produced showing E_FAC, probe fields, and probe potentials to view time delays between electric fields aligned with B. Currently p5-p6 are not used in this routine; the analysis is the same as the one used for Cluster. For the figure the panels are : * (a) B in DMPA Coordinates * (b) Magnitude of B in and out of the spin plane * (c) Angles between B and probes 1 and 3 in the spin plane (angle between 0 and 90 degrees) * (d) Spacecraft potential from probes perpendicular to B * (e) E fields from p1-p4 and SC for probes closely aligned with B * (f) E in field-aligned coordinates * (g) E from probes p1-p2 and p3-p4. Parameters ---------- e_xyz : xarray.DataArray Electric field in DSL coordinates, brst mode. b_xyz : xarray.DataArray Magnetic field in DMPA coordinates. sc_pot : xarray.DataArray L2 Spacecraft potential data. Timing corrections are applied in this z_phase : xarray.DataArray Spacecraft phase (z_phase). Obtained from ancillary_defatt. Returns ------- start_time1 : to fill Start times of intervals which satisfy the probe alignment conditions for probe combinates p1-p2. end_time1 : to fill End times of intervals which satisfy the probe alignment conditions for probe combinates p1-p2. start_time3 : to fill Start times of intervals which satisfy the probe alignment conditions for probe combinates p3-p4. end_time3 : to fill End times of intervals which satisfy the probe alignment conditions for probe combinates p3-p4. """ # Correct for timing in spacecraft potential data. e12 = ts_scalar( sc_pot.time.data, (sc_pot.data[:, 0] - sc_pot.data[:, 1]) / 0.120, ) e34 = ts_scalar( sc_pot.time.data, (sc_pot.data[:, 2] - sc_pot.data[:, 3]) / 0.120, ) e56 = ts_scalar( sc_pot.time.data, (sc_pot.data[:, 4] - sc_pot.data[:, 4]) / 0.0292, ) v_1 = ts_scalar(sc_pot.time.data, sc_pot.data[:, 0]) v_3 = ts_scalar( sc_pot.time.data + np.timedelta64(7629, "ns"), sc_pot.data[:, 2], ) v_5 = ts_scalar( sc_pot.time.data + np.timedelta64(15259, "ns"), sc_pot.data[:, 4], ) e12.time.data += np.timedelta64(26703, "ns") e34.time.data += np.timedelta64(30518, "ns") e56.time.data += np.timedelta64(34332, "ns") v_1, v_3, v_5 = [resample(v, v_1) for v in [v_1, v_3, v_5]] e12, e34, e56 = [resample(e, v_1) for e in [e12, e34, e56]] v_2 = v_1 - e12 * 0.120 v_4 = v_3 - e34 * 0.120 v_6 = v_5 - e56 * 0.0292 sc_pot = np.hstack( [v_1.data, v_2.data, v_3.data, v_4.data, v_5.data, v_6.data], ) sc_pot = xr.DataArray( sc_pot, coords=[v_1.time.data, np.arange(1, 7)], dims=["time", "probe"], ) t_limit = [sc_pot.time.data[0], sc_pot.time.data[-1]] t_limit = [np.datetime_as_string(time, "ns") for time in t_limit] t_limit_long = extend_tint(t_limit, [-10, 10]) b_xyz = time_clip(b_xyz, t_limit_long) b_xyz = resample(b_xyz, sc_pot) e_xyz = resample(e_xyz, sc_pot) z_phase = time_clip(z_phase, t_limit_long) # Remove repeated z_phase elements n_ph = len(z_phase) no_repeat = np.ones(n_ph) for i in range(1, n_ph): if z_phase.time.data[i] > z_phase.time.data[i - 1]: if z_phase.data[i] < z_phase.data[i - 1]: z_phase.data[i:] += 360.0 else: no_repeat[i] = 0 z_phase_time = z_phase.time[no_repeat == 1] z_phase_data = z_phase.data[no_repeat == 1] z_phase = ts_scalar(z_phase_time, z_phase_data) z_phase = resample(z_phase, sc_pot) # Probe angles in DSL or whatever phase_p = [] for i, j in zip([1, 7, 2, 5], [6, 6, 3, 3]): phase_p.append(np.deg2rad(z_phase.data) + i * np.pi / j) r_p = [60 * np.array([np.cos(phase), np.sin(phase)]) for phase in phase_p] # Calculate angles between probes and direction of B in the spin plane. theta_pb = [None] * 4 for i in [0, 2]: theta_pb[i] = r_p[i][:, 0] * b_xyz.data[:, 0] + r_p[i][:, 1] * b_xyz.data[:, 1] theta_pb[i] /= np.sqrt(r_p[i][:, 0] ** 2 + r_p[i][:, 1] ** 2) theta_pb[i] /= np.sqrt(b_xyz[:, 0] ** 2 + b_xyz[:, 1] ** 2) theta_pb[i] = np.arccos(abs(theta_pb[i])) * 180 / np.pi theta_pb[1] = theta_pb[0] theta_pb[3] = theta_pb[2] sc_v12 = (sc_pot.data[:, 0] + sc_pot.data[:, 1]) / 2 sc_v34 = (sc_pot.data[:, 2] + sc_pot.data[:, 3]) / 2 e_s = [None] * 4 e_s[0] = (sc_pot.data[:, 0] - sc_v34) * 1e3 / 60 e_s[1] = (sc_v34 - sc_pot.data[:, 0]) * 1e3 / 60 e_s[2] = (sc_pot.data[:, 2] - sc_v12) * 1e3 / 60 e_s[3] = (sc_v12 - sc_pot.data[:, 2]) * 1e3 / 60 e12 = (sc_pot.data[:, 0] - sc_pot.data[:, 1]) * 1e3 / 120 e34 = (sc_pot.data[:, 2] - sc_pot.data[:, 3]) * 1e3 / 120 idx_b = np.sqrt(b_xyz.data[:, 0] ** 2 + b_xyz.data[:, 1] ** 2) < abs( b_xyz.data[:, 2], ) thresh_ang = 25.0 for e_, theta in zip(e_s, theta_pb): e_[theta > thresh_ang] = np.nan e_[idx_b] = np.nan sc_v12[theta_pb[2] > thresh_ang] = np.nan sc_v34[theta_pb[0] > thresh_ang] = np.nan sc_v12[idx_b] = np.nan sc_v34[idx_b] = np.nan