def load_def_omni(tint, cfg, data_path): """Loads Density Energy Flux spectrum Parameters ---------- tint : list of str Time interval cfg : dict Hash table from configuration file. Returns ------- """ ic = np.arange(1, 5) suf = "fpi_{}_{}".format(cfg["data_rate"], cfg["level"]) # Ion/electron omni directional energy flux def_omni_mms_i = [ get_data("DEFi_{}".format(suf), tint, i, data_path=data_path) for i in ic[:-1] ] def_omni_mms_e = [ get_data("DEFe_{}".format(suf), tint, i, data_path=data_path) for i in ic[:-1] ] def_omni_i, def_omni_e = [ avg_4sc(def_omni) for def_omni in [def_omni_mms_i, def_omni_mms_e] ] return def_omni_i, def_omni_e
def load_def_omni(tint, cfg): """Loads Density Energy Flux spectrum """ ic = np.arange(1, 5) suf = "fpi_{}_{}".format(cfg["data_rate"], cfg["level"]) # Ion/electron omni directional energy flux def_omni_mms_i = [ get_data("DEFi_{}".format(suf), tint, i) for i in ic[:-1] ] def_omni_mms_e = [ get_data("DEFe_{}".format(suf), tint, i) for i in ic[:-1] ] def_omni_i, def_omni_e = [ avg_4sc(def_omni) for def_omni in [def_omni_mms_i, def_omni_mms_e] ] return def_omni_i, def_omni_e
def grad_ni(r_mms, tint, cfg): r"""Compute density gradients Parameters ---------- r_mms : list Spacecraft positions. tint : list Time interval. cfg : dict Returns ------- grad_n_i : xarray.DataArray Density gradient time series. """ ic = np.arange(1, 5) if cfg["fpi"]["moments"] == "partial": part_idx_i = cfg["fpi"]["part_idx_i"] part_n_i_mms = [ get_data("partni_fpi_fast_l2", tint, i, data_path=cfg["data_path"]) for i in ic ] n_i_mms = [part_n_i_mms[i - 1][:, part_idx_i] for i in ic] elif cfg["fpi"]["moments"] == "full": n_i_mms = [ get_data("ni_fpi_fast_l2", tint, i, data_path=cfg["data_path"]) for i in ic ] else: raise ValueError("Invalid moments type") grad_n_i = 1e3 * c_4_grad(r_mms, n_i_mms) return grad_n_i
def main(args): """main function """ with open(args.config) as f: cfg = yaml.load(f, Loader=yaml.FullLoader) tint = cfg["tint"] # Spacecraft indices mms_ids = np.arange(1, 5) # Load spacecraft position and background magnetic field r_mms = [ get_data("R_gse", tint, i, args.verbose, data_path=cfg["data_path"]) for i in mms_ids ] # Load background magnetic field suf_b = "fgm_{}_{}".format(cfg["fgm"]["data_rate"], cfg["fgm"]["level"]) b_mms = [ get_data("B_gse_{}".format(suf_b), tint, i, args.verbose, data_path=cfg["data_path"]) for i in mms_ids ] # Remove offset on z component of the background magnetic field b_mms = remove_bz_offset(b_mms) # Compute current density j_xyz, div_b, b_xyz, _, _, _ = c_4_j(r_mms, b_mms) # j A.m^{-2}->nA.m^{-2} j_xyz *= 1e9 # Load moments moments_i, moments_e = load_moments(tint, cfg["fpi"], args, cfg["data_path"]) # Resample moments to magnetic field sampling moments_i = [resample(mom, b_xyz) for mom in moments_i] moments_e = [resample(mom, b_xyz) for mom in moments_e] lmn = lmn_cs(b_xyz, moments_i[1]) # Transform fields to MVA frame b_lmn, j_lmn = [new_xyz(field, lmn) for field in [b_xyz, j_xyz]] # Compute dispersion relation using either Jn of the timing # Estimate phase velocity using normal current density disprel_jn = calc_vph_current(b_lmn, j_lmn) # Load timing data timing_lr = load_timing(args.timing) timing_ts = load_timing(args.table_wei2019) # Unpack slowness vector m_xyz, _ = [timing_lr.m, timing_lr.dm] m_lmn = new_xyz(m_xyz, lmn) n_lmn = new_xyz(timing_lr.n, lmn) delta = np.arccos(n_lmn[:, 1] / np.linalg.norm(n_lmn.data[:, 1:], axis=1)) v_lmn = timing_lr.v.data[:, None] * n_lmn v_n = np.linalg.norm(v_lmn[:, 1:], axis=1) v_ph = v_n / np.cos(delta) v_ph[delta > np.pi / 2 - .01] = np.nan dv_ph = timing_lr.dv / np.cos(delta) dv_ph[delta > np.pi / 2 - .01] = np.nan # Crossing times crossing_times = m_xyz.time.data # Dispersion relation from timing disprel_lr = calc_disprel_tm(v_ph, dv_ph, 2 * timing_lr.tau, timing_lr.dtau, ci=95) disprel_ts = calc_disprel_tm(timing_ts.v, timing_ts.dv, 2 * timing_ts.tau, timing_ts.dtau) # d_i = 527.0 # Compute thickness of the CS using the lobe field corresponding to the # Harris like CS # Compute lobe field using Harris current sheet fit harris_fit = fit_harris_cs(b_lmn, j_lmn) # Compute thickness as h = B0/curl(B) = B0/(m0*J) and the error mu0 = constants.mu_0 # continuous thickness h_c = norm(harris_fit.B0) / (1e3 * mu0 * norm(j_lmn)) # discrete thickness h_d = t_eval(h_c, crossing_times) # curl of the magnetic field curl_b = c_4_grad(r_mms, b_mms, "curl") # Errors # relative error on curlometer technique dj_j = np.abs(div_b / norm(curl_b)) # relative error on the thickness dh_d = h_d * t_eval(dj_j / (1 + dj_j), crossing_times) # Thickness from Wei 2019 table h_ts, dh_ts = [timing_ts.h, timing_ts.dh] # Compute ion inertial length to normalize the thickness # unpack number densities n_i, n_e = moments_i[0], moments_e[0] # Unpack ion/electron temperature _, _, t_i = dec_temperature(b_xyz, moments_i) _, _, t_e = dec_temperature(b_xyz, moments_i) # Compute plasma parameters plasma_params = plasma_calc(harris_fit.B0, t_i, t_e, n_i, n_e) # Averaged ion inertial length d_i = np.mean(plasma_params.l_i).data r_p = np.mean(plasma_params.rho_p).data r_e = np.mean(plasma_params.rho_e).data # Outliers indices ols = cfg["outliers"] # Fit scaling wavelength CS thickness scaling_lr = scaling_h_lambda(h_d[~np.isnan(v_ph)], dh_d[~np.isnan(v_ph)], disprel_lr, ols["Richard2021"]) scaling_ts = scaling_h_lambda(h_ts, dh_ts, disprel_ts, ols["Wei2019"]) fig6 = plt.figure(**cfg["figure"]["main"]) gs6 = fig6.add_gridspec(2, 2, **cfg["figure"]["gridspec"]) gs60 = gs6[:, 0].subgridspec(2, 1) gs61 = gs6[:, 1].subgridspec(2, 1) axs0 = [fig6.add_subplot(gs60[i]) for i in range(2)] axs1 = [fig6.add_subplot(gs61[i]) for i in range(2)] axs0[0], caxs00 = plot_spectr(axs0[0], disprel_jn.hist, cscale="log", cmap="viridis") axs0[0].plot(disprel_jn.hires_dBdt, disprel_jn.pred_Jn, "k") axs0[0].fill_between(disprel_jn.hires_dBdt, disprel_jn.bound_upper, disprel_jn.bound_lower, color="lightgrey") labels = [ "$J_N=${:3.2f}*d$_t B_L$".format(disprel_jn.fit_db_dt_jn.data), "95% CI" ] axs0[0].legend(labels, frameon=True, loc="upper right") axs0[0].set_xlabel("d$_t B_L$ [nT s$^{-1}$]") axs0[0].set_ylabel("$J_N$ [nA m$^{-2}$]") caxs00.set_ylabel("Counts") axs0[0].grid(True, which="both") axs0[0].set_title("$\\rho = {:3.2f}$".format(disprel_jn.rho.data)) h_lambda = scaling_lr.h.data * scaling_lr.k.data / (2 * np.pi) dh_lambda = scaling_lr.h.data * scaling_lr.dk.data / (2 * np.pi) n_bins = optimize_nbins_1d(h_lambda) """ y, edges_ = np.histogram(h_lambda, bins=n_bins) axs0[1].bar(0.5 * (edges_[1:] + edges_[:-1]), y, width=edges_[1:] - edges_[:-1], facecolor='tab:blue', edgecolor="k", yerr=np.sqrt(y)) """ #axs0[1].axvspan(0.8 / (2 * np.pi), 1.8 / (2 * np.pi), color="tab:orange") _, _, _ = axs0[1].hist(h_lambda, bins=n_bins, **cfg["figure"]["hist"]) #axs0[1].errorbar(scaling_lr.scaling.data / (2 * np.pi), 16.5, # xerr=scaling_lr.sigma_scaling.data / (2 * np.pi),) axs0[1].axvline(scaling_lr.scaling.data / (2 * np.pi), color="k", linestyle="-") axs0[1].set_ylim([0, 17]) axs0[1].set_yticks(np.arange(0, 17, 2)) left_bound = (scaling_lr.scaling.data - 1.96 * scaling_lr.sigma_scaling.data) / (2 * np.pi) right_bound = (scaling_lr.scaling.data + 1.96 * scaling_lr.sigma_scaling.data) / (2 * np.pi) width = right_bound - left_bound _, ymax = axs0[1].get_ylim() height = .5 rect_drift = plt.Rectangle((0.8 / (2 * np.pi), ymax - .5), 1. / (2 * np.pi), .5, color='tab:orange') rect_sigma = plt.Rectangle((left_bound, ymax - 2.1 * height), width, height, color='lightgrey') axs0[1].add_patch(rect_drift) axs0[1].add_patch(rect_sigma) axs0[1].set_xlabel("$h/\\lambda$") axs0[1].set_ylabel("Counts") axs0[1].grid(True, which="both") axs1[0].errorbar(disprel_lr.k.data, disprel_lr.omega.data, disprel_lr.omega_err.data, disprel_lr.k_err.data, color="tab:blue", **cfg["figure"]["errorbar"]) axs1[0].errorbar(disprel_ts.k.data, disprel_ts.omega.data, disprel_ts.omega_err.data, disprel_ts.k_err.data, color="tab:red", **cfg["figure"]["errorbar"]) axs1[0].errorbar(disprel_lr.k.data[ols["Richard2021"]], disprel_lr.omega.data[ols["Richard2021"]], disprel_lr.omega_err.data[ols["Richard2021"]], disprel_lr.k_err.data[ols["Richard2021"]], color="k", **cfg["figure"]["errorbar"]) axs1[0].plot(disprel_lr.hires_k.data, disprel_lr.pred_omega.data, 'k-') axs1[0].fill_between(disprel_lr.hires_k.data, disprel_lr.bound_lower.data, disprel_lr.bound_upper.data, color="lightgrey") axs1[0].set_xlim([0, 2.6e-3]) axs1[0].set_ylim([0, 1]) axs1[0].set_xlabel("$k$ [km$^{-1}$]") axs1[0].set_ylabel("$\\omega$ [rad s$^{-1}$]") labels = [ "$\\omega$ = {:4.2f}*$k$".format(disprel_lr.vph.data[0]), "95% CI", "2019-09-14", "Table Wei2019" ] axs1[0].legend(labels, frameon=True, loc="upper right") axs1[0].yaxis.set_label_position("right") axs1[0].yaxis.tick_right() axs1[0].grid(True, which="both") axs1[1].errorbar(scaling_lr.k, scaling_lr.h, scaling_lr.dh, scaling_lr.dk, color="tab:blue", **cfg["figure"]["errorbar"]) axs1[1].errorbar(scaling_ts.k, scaling_ts.h, scaling_ts.dh, scaling_ts.dk, color="tab:red", **cfg["figure"]["errorbar"]) axs1[1].errorbar(scaling_lr.k_ols, scaling_lr.h_ols, scaling_lr.dh_ols, scaling_lr.dk_ols, color="k", **cfg["figure"]["errorbar"]) axs1[1].plot(scaling_lr.hires_k, scaling_lr.pred_h, "k") axs1[1].fill_between(scaling_lr.hires_k, scaling_lr.bound_lower, scaling_lr.bound_upper, color="lightgrey") axs1[1].set_xlabel("$k$ [km$^{-1}$]") axs1[1].set_ylabel("$h$ [km]") labels = [ f"$h=${scaling_lr.scaling.data / (2 * np.pi):3.2f}$*\\lambda$", "95% CI", "2019-09-14", "Table Wei2019" ] axs1[1].legend(labels, frameon=True, loc="upper right") axs1[1].plot(scaling_lr.hires_k, 0.8 / scaling_lr.hires_k, color="tab:orange") axs1[1].plot(scaling_lr.hires_k, 1.8 / scaling_lr.hires_k, color="tab:orange") axs1[1].yaxis.set_label_position("right") axs1[1].yaxis.tick_right() axs1[1].set_xlim([0, 2.6e-3]) axs1[1].set_ylim([0, 9000]) axs1[1].grid(True, which="both") # Add panels labels labels_pos = [0.032, 0.95] _ = make_labels(axs0 + axs1, labels_pos) if args.figname: fig6.savefig(args.figname, **cfg["figure"]["save"]) else: plt.show() if args.verbose: b_lobe = harris_fit.b_lobe.data sigma_b_lobe = harris_fit.sigma_b_lobe.data h_h = harris_fit.scale.data / d_i sigma_h_h = harris_fit.sigma_scale.data / d_i a_j = disprel_jn.fit_db_dt_jn.data sigma_a_j = disprel_jn.sigma.data v_ph_j = 1e-3 / (constants.mu_0 * a_j) sigma_v_ph_j = v_ph_j * (sigma_a_j / a_j) / (1 + (sigma_a_j / a_j)) v_ph = disprel_lr.vph.data[0] sigma_v_ph = disprel_lr.sigma_k_w.data[0] kh_ = scaling_lr.scaling.data sigma_kh = scaling_lr.sigma_scaling.data h_l = kh_ / (2 * np.pi) sigma_h_l = sigma_kh / (2 * np.pi) h_min = 1e3 * np.min(h_d.data) l_min = 1e3 * np.min(disprel_lr.lamb.data) l_lh = 2 * np.pi * np.sqrt(r_p * r_e) print(f"B_0 = {b_lobe:3.2f} \pm {sigma_b_lobe:3.2f} nT") print(f"h_H = {h_h:3.2f} \pm {sigma_h_h:3.2f} d_i") print(f"a = {a_j:3.2f} \pm {sigma_a_j:3.2f} s/H") print(f"v_ph = {v_ph_j:3.2f} \pm {sigma_v_ph_j:3.2f} km/s") print(f"v_ph = {v_ph:3.2f} \pm {sigma_v_ph:3.2f} km/s") print(f"kh = {kh_:3.2f} \pm {sigma_kh:3.2f}") print(f"h/\lambda = {h_l:3.2f} \pm {sigma_h_l:3.2f}") print(f"\lambda_min = {(l_min / d_i):3.2f} d_i") print(f"\lambda_min = {(l_min / r_p):3.2f} r_i") print(f"\lambda_LH = {(l_lh / d_i):3.2f}") print(f"h_min = {(h_min / d_i):3.2f} d_i") print(f"h_min = {(h_min / r_p):3.2f} r_i")
def main(args): """main function """ # Read time intervals with open(args.config) as f: cfg = yaml.load(f, Loader=yaml.FullLoader) tint_over = cfg["tints"]["overview"] tint_flap = cfg["tints"]["flapping"] mms_ids = np.arange(1, 5) # Load spacecraft position r_mms = [ get_data("R_gsm", tint_over, i, data_path=cfg["data_path"]) for i in mms_ids ] # Load background magnetic field suf_b = "fgm_{}_{}".format(cfg["fgm"]["data_rate"], cfg["fgm"]["level"]) b_mms = [ get_data("B_gsm_{}".format(suf_b), tint_over, i, args.verbose, data_path=cfg["data_path"]) for i in mms_ids ] # Earth radius r_earth = constants.R_earth.value * 1e-3 # Spacecraft position and magnetic field at the center of mass of the # tetrahedron r_xyz = avg_4sc(r_mms) / r_earth b_xyz = avg_4sc(b_mms) # Load moments of the velocity distribution function moments_i, moments_e = load_moments(tint_over, cfg["fpi"], args, cfg["data_path"]) # Load omni directional energy flux def_omni = load_def_omni(tint_over, cfg["fpi"], cfg["data_path"]) # Unpack moments v_xyz_i, t_xyz_i = moments_i[1:3] _, t_xyz_e = moments_e[1:3] v_gsm_i = cotrans(v_xyz_i, "gse>gsm") # Unpack energy flux def_omni_i, def_omni_e = def_omni # Compute temperature tensor in field aligned coordinates t_xyzfac_i = rotate_tensor(t_xyz_i, "fac", b_xyz, "pp") t_xyzfac_e = rotate_tensor(t_xyz_e, "fac", b_xyz, "pp") # Get parallel, perpendicular and total temperature t_para_i, t_perp_i = [t_xyzfac_i[:, 0, 0], t_xyzfac_i[:, 1, 1]] t_para_e, t_perp_e = [t_xyzfac_e[:, 0, 0], t_xyzfac_e[:, 1, 1]] # Figure options legend_options = dict(frameon=True, ncol=3) spectr_options = dict(yscale="log", cscale="log", cmap="Spectral_r") # Plot fig = plt.figure(**cfg["figure"]["main"]) gsp1 = fig.add_gridspec(12, 1, **cfg["figure"]["gridspec"]) gsp10 = gsp1[1:9].subgridspec(4, 1, hspace=0) gsp11 = gsp1[10:].subgridspec(1, 1, hspace=0) # Create axes in the grid spec axs10 = [fig.add_subplot(gsp10[i]) for i in range(4)] axs11 = [fig.add_subplot(gsp11[i]) for i in range(1)] # Magnetic field plot_line(axs10[0], b_xyz) axs10[0].legend(["$B_x$", "$B_y$", "$B_z$"], loc="upper right", **legend_options) axs10[0].set_ylim([-23, 23]) axs10[0].set_ylabel("$B$ [nT]") # Ions bulk velocity plot_line(axs10[1], v_gsm_i) axs10[1].legend(["$V_{ix}$", "$V_{iy}$", "$V_{iz}$"], loc="upper right", **legend_options) axs10[1].set_ylabel("$V_i$ [km s$^{-1}$]") axs10[1].grid(True, which="both") # Ions energy spectrum axs10[2], caxs02 = plot_spectr(axs10[2], def_omni_i, clim=[1e4, 1e6], **spectr_options) plot_line(axs10[2], t_perp_i, color="k") plot_line(axs10[2], t_para_i, color="tab:blue") axs10[2].legend(["$T_{i,\\perp}$", "$T_{i,\\parallel}$"], loc="lower right", **legend_options) axs10[2].set_ylabel("$E_i$ [eV]") caxs02.set_ylabel("DEF" + "\n" + "[keV/(cm$^2$ s sr keV)]") axs10[2].grid(False, which="both") # Electrons energy spectrum axs10[3], caxs11 = plot_spectr(axs10[3], def_omni_e, clim=[1e5, 3e7], **spectr_options) plot_line(axs10[3], t_perp_e, color="k") plot_line(axs10[3], t_para_e, color="tab:blue") axs10[3].legend(["$T_{e,\\perp}$", "$T_{e,\\parallel}$"], loc="lower right", **legend_options) axs10[3].set_ylabel("$E_e$ [eV]") caxs11.set_ylabel("DEF" + "\n" + "[keV/(cm$^2$ s sr keV)]") axs10[3].grid(False, which="both") axs10[-1].get_shared_x_axes().join(*axs10) fig.align_ylabels(axs10) for ax in axs10[:-1]: ax.xaxis.set_ticklabels([]) axs10[-1].set_xlim(mdates.datestr2num(tint_over)) # Zoom plot_line(axs11[0], b_xyz) axs11[0].legend(["$B_x$", "$B_y$", "$B_z$"], loc="upper right", **legend_options) axs11[0].set_ylim([-15, 15]) axs11[0].set_ylabel("$B$ [nT]") axs11[0].grid(True, which="both") axs11[0].set_xlim(mdates.datestr2num(tint_flap)) span_options = dict(linestyle="--", linewidth=0.8, facecolor="none", edgecolor="k") span_tint(axs10, tint_flap, **span_options) axr = set_rlabel(axs10[0], r_xyz, spine=0, position="top") axr.set_xlabel("$X_{GSM}$ [$R_E$]\n$Y_{GSM}$ [$R_E$]\n$Z_{GSM}$ [$R_E$]", fontsize=9) axr.xaxis.set_label_coords(-.13, 1.1) zoom(axs11[0], axs10[-1], ec="k") print(axs10[-1].get_xticklabels()) # number subplots labels_pos = [0.02, 0.83] _ = make_labels(axs10 + axs11, labels_pos) if args.figname: fig.savefig(args.figname) else: plt.show()
def main(args): """main function """ with open(args.config) as f: cfg = yaml.load(f, Loader=yaml.FullLoader) tint = cfg["tints"]["flapping"] # Spacecraft indices mms_ids = np.arange(1, 5) # Load spacecraft position and background magnetic field r_mms = [get_data("R_gse", tint, i, data_path=cfg["data_path"]) for i in mms_ids] # Load background magnetic field suf_b = "fgm_{}_{}".format(cfg["fgm"]["data_rate"], cfg["fgm"]["level"]) b_mms = [get_data("B_gse_{}".format(suf_b), tint, i, args.verbose, data_path=cfg["data_path"]) for i in mms_ids] # Remove offset on z component of the background magnetic field b_mms = remove_bz_offset(b_mms) # Load moments moments_i, moments_e = load_moments(tint, cfg["fpi"], args, cfg["data_path"]) # Compute current density j_xyz, div_b, b_xyz, _, _, _ = c_4_j(r_mms, b_mms) j_xyz *= 1e9 # Compute MVA frame _, _, lmn = mva(b_xyz) # Resample moments to magnetic field sampling moments_i = [resample(mom, b_xyz) for mom in moments_i] moments_e = [resample(mom, b_xyz) for mom in moments_e] # lmn = np.vstack([lmn[:, 0], -lmn[:, 2], lmn[:, 1]]).T l = lmn[:, 0] m = np.mean(moments_i[1].data, axis=0) m /= np.linalg.norm(m, axis=0) n = np.cross(l, m) / np.linalg.norm(np.cross(l, m)) m = np.cross(n, l) lmn = np.transpose(np.vstack([l, m, n])) # transform magnetic field and current density to LMN coordinates system b_lmn, j_lmn = [new_xyz(field, lmn) for field in [b_xyz, j_xyz]] # Load data from timing timing_lr = load_timing(args.timing) # Transform slowness vector to LMN frame m_lmn, dm_lmn = [new_xyz(vec, lmn) for vec in [timing_lr.m, timing_lr.dm]] # Transform normal from timing to LMN coordinates system n_lmn = new_xyz(timing_lr.n, lmn) slowness = xr.Dataset({"m": m_lmn, "dm": dm_lmn}) # Get crossing times crossing_times = m_lmn.time.data # Unpack ion/electron temperature _, _, t_i = dec_temperature(b_xyz, moments_i) _, _, t_e = dec_temperature(b_xyz, moments_i) v_xyz_i = moments_i[1] v_xyz_e = moments_e[1] v_lmn_i, v_lmn_e = [new_xyz(v_xyz, lmn) for v_xyz in [v_xyz_i, v_xyz_e]] # Compute velocity and geometry of the CS using spatio-temporal derivative b_mms_ds = [_downsample(b_xyz, 2.5) for b_xyz in b_mms] #v_str_lmn, y_m, z_n = st_derivative(r_mms, b_mms, lmn, crossing_times) v_str_lmn, y_m, z_n = st_derivative(r_mms, b_mms_ds, lmn, crossing_times) # filter velocity of the CS # change 257 to physical value #v_str_lmn_filtered = medfilt(v_str_lmn, 100) grad_b = c_4_grad(r_mms, b_mms_ds) grad_b_dete = ts_scalar(grad_b.time.data, np.abs(np.linalg.det(grad_b.data))) res_dete = grad_b_dete.data - medfilt(grad_b_dete, 5).data idx_ = np.abs(res_dete) > np.std(res_dete) v_str_lmn_filtered = v_str_lmn.copy() v_str_lmn_filtered.data[idx_, 1] = np.nan v_str_lmn_filtered.data[idx_, 2] = np.nan # Plot fig, axs = plt.subplots(4, **cfg["figure"]["main"]) fig.subplots_adjust(**cfg["figure"]["subplots"]) plot_line(axs[0], b_lmn) axs[0].legend(["$B_L$", "$B_M$", "$B_N$"], **cfg["figure"]["legend"]) axs[0].set_ylabel("$B$ [nT]") axs[0].grid(True, which="both") axs[1].quiver(timing_lr.tau.time.data, np.zeros(len(n_lmn)), n_lmn[:, 1], n_lmn[:, 2], color="tab:green", angles="uv") axs[1].set_ylabel("$n_{timing}^{MN}$") axs[1].grid(True, which="both") plot_line(axs[2], v_lmn_i[:, 1], color="tab:blue", label="Ions") plot_line(axs[2], v_str_lmn_filtered[:, 1], color="k", label="STD") axs[2].errorbar(slowness.time.data, slowness.m.data[:, 1], slowness.dm.data[:, 1], color="tab:green", label="Timing") axs[2].legend(**cfg["figure"]["legend"]) axs[2].set_ylim([-650, 650]) axs[2].set_ylabel("$V_M$ [km s$^{-1}$]") axs[2].grid(True, which="both") plot_line(axs[3], v_lmn_e[:, 2], color="tab:red", label="Electrons") plot_line(axs[3], v_str_lmn_filtered[:, 2], color="k", label="STD") axs[3].errorbar(slowness.time.data, slowness.m.data[:, 2], slowness.dm.data[:, 2], color="tab:green", label="Tining") axs[3].legend(**cfg["figure"]["legend"]) axs[3].set_ylim([-650, 650]) axs[3].set_ylabel("$V_N$ [km s$^{-1}$]") axs[3].grid(True, which="both") axs[-1].set_xlim(mdates.date2num(tint)) fig.align_ylabels(axs) labels_pos = [0.02, 0.92] _ = make_labels(axs, labels_pos) if args.figname: fig.savefig(args.figname, **cfg["figure"]["save"]) else: plt.show()
def load_moments(tint, cfg, args): """ Load FPI moments of the velocity distribution functions. If the option moments is set to "part" then use partial moments instead. """ ic = np.arange(1, 5) suf = "fpi_{}_{}".format(cfg["data_rate"], cfg["level"]) if cfg["moments"] == "partial": # index to split partial moments (from quasi-neutrality assumption) part_idx_i, part_idx_e = [cfg[f"part_idx_{s}"] for s in ["i", "e"]] # Load partial moments # number density part_n_i = [ get_data("partNi_{}".format(suf), tint, i, args.verbose) for i in ic[:-1] ] part_n_e = [ get_data("partNe_{}".format(suf), tint, i, args.verbose) for i in ic[:-1] ] # bulk velocity part_v_i = [ get_data("partVi_gse_{}".format(suf), tint, i, args.verbose) for i in ic[:-1] ] part_v_e = [ get_data("partVe_gse_{}".format(suf), tint, i, args.verbose) for i in ic[:-1] ] # temperature tensor part_t_i = [ get_data("partTi_gse_{}".format(suf), tint, i, args.verbose) for i in ic[:-1] ] part_t_e = [ get_data("partTe_gse_{}".format(suf), tint, i, args.verbose) for i in ic[:-1] ] # pressure tensor part_p_i = [ get_data("partPi_gse_{}".format(suf), tint, i, args.verbose) for i in ic[:-1] ] part_p_e = [ get_data("partPe_gse_{}".format(suf), tint, i, args.verbose) for i in ic[:-1] ] # split partial moments # number density n_i = [part_n_i[i - 1][:, part_idx_i] for i in ic[:-1]] n_e = [part_n_e[i - 1][:, part_idx_e] for i in ic[:-1]] # bulk velocity v_i = [part_v_i[i - 1][:, part_idx_i, ...] for i in ic[:-1]] v_e = [part_v_e[i - 1][:, part_idx_e, ...] for i in ic[:-1]] # temperature tensor t_i = [part_t_i[i - 1][:, part_idx_i, ...] for i in ic[:-1]] t_e = [part_t_e[i - 1][:, part_idx_e, ...] for i in ic[:-1]] # pressure tensor p_i = [part_p_i[i - 1][:, part_idx_i, ...] for i in ic[:-1]] p_e = [part_p_e[i - 1][:, part_idx_e, ...] for i in ic[:-1]] elif cfg["moments"] == "full": # number density n_i = [ get_data("Ni_{}".format(suf), tint, i, args.verbose) for i in ic[:-1] ] n_e = [ get_data("Ne_{}".format(suf), tint, i, args.verbose) for i in ic[:-1] ] # bulk velocity v_i = [ get_data("Vi_gse_{}".format(suf), tint, i, args.verbose) for i in ic[:-1] ] v_e = [ get_data("Ve_gse_{}".format(suf), tint, i, args.verbose) for i in ic[:-1] ] # temperature tensor t_i = [ get_data("Ti_gse_{}".format(suf), tint, i, args.verbose) for i in ic[:-1] ] t_e = [ get_data("Te_gse_{}".format(suf), tint, i, args.verbose) for i in ic[:-1] ] # pressure tensor p_i = [ get_data("Pi_gse_{}".format(suf), tint, i, args.verbose) for i in ic[:-1] ] p_e = [ get_data("Pe_gse_{}".format(suf), tint, i, args.verbose) for i in ic[:-1] ] else: raise ValueError("Invalid moments type") # Load spintone correction spintone_i = [ get_data("STi_gse_{}".format(suf), tint, i, args.verbose) for i in ic[:-1] ] spintone_e = [ get_data("STe_gse_{}".format(suf), tint, i, args.verbose) for i in ic[:-1] ] # remove spintone correction v_i = [v - spintone_i[i] for i, v in enumerate(v_i)] v_e = [v - spintone_e[i] for i, v in enumerate(v_e)] moments_i = [n_i, v_i, t_i, p_i] moments_e = [n_e, v_e, t_e, p_e] moments_i = [avg_4sc(moment) for moment in moments_i] moments_e = [avg_4sc(moment) for moment in moments_e] return moments_i, moments_e
def main(args): """main function """ with open(args.config) as f: cfg = yaml.load(f, Loader=yaml.FullLoader) # Spacecraft indices mms_ids = np.arange(1, 5) # Load spacecraft position and background magnetic field r_mms = [get_data("R_gse", cfg["tint"], i, data_path=cfg["data_path"]) for i in mms_ids] # Load background magnetic field suf_b = "fgm_{}_{}".format(cfg["fgm"]["data_rate"], cfg["fgm"]["level"]) b_mms = [get_data("B_gse_{}".format(suf_b), cfg["tint"], i, args.verbose, data_path=cfg["data_path"]) for i in mms_ids] # Remove offset on z component of the background magnetic field b_mms = remove_bz_offset(b_mms) # Load moments moments_i, moments_e = load_moments(cfg["tint"], cfg["fpi"], args, cfg["data_path"]) # Compute current density j_xyz, div_b, b_xyz, _, _, _ = c_4_j(r_mms, b_mms) j_xyz *= 1e9 # j A.m^{-2}->nA.m^{-2} # Resample moments to magnetic field sampling moments_i = [resample(mom, b_xyz) for mom in moments_i] moments_e = [resample(mom, b_xyz) for mom in moments_e] # Compute new coordinates system lmn = lmn_cs(b_xyz, moments_i[1]) # transform magnetic field and current density to LMN coordinates system b_lmn, j_lmn = [new_xyz(field, lmn) for field in [b_xyz, j_xyz]] # Fit J perp vs B as Harris like CS harris_fit = fit_harris_cs(b_lmn, j_lmn) # Load data from timing timing_lr = load_timing(args.timing) # Transform slowness vector to LMN frame m_lmn = new_xyz(timing_lr.m, lmn) # Get crossing times crossing_times = m_lmn.time.data # Use Harris like CS lobe field to estimate the thickness # Compute thickness as h = B0/curl(B) = B0/(m0*J) and the error mu0 = constants.mu_0 # continuous thickness h_c = norm(harris_fit.B0) / (1e3 * mu0 * norm(j_lmn)) # discrete thickness h_d = t_eval(h_c, crossing_times) # Errors # relative error on curlometer technique dj_j = np.abs(div_b / (mu0 * norm(1e-9 * j_xyz))) # relative error on the thickness dh_d = h_d * t_eval(dj_j / (1 + dj_j), crossing_times) # Compute ion inertial length to normalize the thickness # unpack number densities n_i, n_e = moments_i[0], moments_e[0] # Unpack ion/electron temperature _, _, t_i = dec_temperature(b_xyz, moments_i) _, _, t_e = dec_temperature(b_xyz, moments_i) # Compute plasma parameters plasma_params = plasma_calc(harris_fit.B0, t_i, t_e, n_i, n_e) # Averaged ion inertial length d_i = 1e-3 * np.mean(plasma_params.l_i).data r_p = 1e-3 * np.mean(plasma_params.rho_p).data r_e = 1e-3 * np.mean(plasma_params.rho_e).data # Normalize thickness by ion inertial length h_d, dh_d = [h_d / d_i, dh_d / d_i] # Compute velocity and geometry of the CS using spatio-temporal derivative v_str_lmn, y_m, z_n = st_derivative(r_mms, b_mms, lmn, crossing_times) geometry = xr.Dataset({"y_m": y_m / d_i, "z_n": z_n / d_i}) # Compute ym and zn at the crossings crossing_times = h_d.time.data yc_m, zc_n = [t_eval(x, crossing_times) for x in [geometry.y_m, geometry.z_n]] fig = plt.figure(**cfg["figure"]["main"]) gs0 = fig.add_gridspec(4, 2, **cfg["figure"]["gridspec"]) gs10 = gs0[:2, 0].subgridspec(1, 1) gs20 = gs0[:2, 1].subgridspec(2, 1, hspace=.4) gs30 = gs0[2:, :].subgridspec(1, 1) axs0 = [fig.add_subplot(gs10[i]) for i in range(1)] axs1 = [fig.add_subplot(gs20[i]) for i in range(2)] axs2 = [fig.add_subplot(gs30[i]) for i in range(1)] axs0[0], caxs0 = plot_spectr(axs0[0], harris_fit.hist, cscale="log", cmap="viridis") axs0[0].errorbar(harris_fit.bbins, harris_fit.medbin, harris_fit.medstd, marker="s", color="tab:red") axs0[0].plot(harris_fit.hires_b, harris_fit.pred_j_perp, color="tab:red", linestyle="--", linewidth=2) axs0[0].set_ylim([0, 18]) axs0[0].set_xlabel("$B_L$ [nT]") axs0[0].set_ylabel("$J_{MN}$ [nA m$^{-2}$]") caxs0.set_ylabel("Counts") labels0 = ["Harris fit $B_0$={:2.0f} nT".format(harris_fit.B0.data[0, 0]), "median"] axs0[0].legend(labels0, **cfg["figure"]["legend"]) for ax in axs1: ax.errorbar(yc_m.data, zc_n.data, h_d.data / 2, **cfg["figure"][ "errorbar"]) ax.plot(geometry.y_m.data, geometry.z_n.data, "tab:blue") ax.set_ylim([-6, 6]) ax.set_xlabel("$M/d_i$") ax.set_ylabel("$N/d_i$") axs1[0].legend(["CS", "h"], **cfg["figure"]["legend"]) axs1[1].set_xticks(yc_m.data) axs1[0].set_xlim([0, np.max(geometry.y_m.data)]) axs1[1].set_xlim([70, 105]) axs1[0].grid(True, which="both") axs1[1].grid(True, which="both") zoom(axs1[1], axs1[0], ec="k") # Label the panels axs0[0].text(0.02, 0.95, "({})".format("a"), transform=axs0[0].transAxes) axs1 = make_labels(axs1, [0.02, 0.86], 1) axs2[0].text(0.01, 0.95, "({})".format(string.ascii_lowercase[len(axs1) + 1]), transform=axs2[0].transAxes) axs2[0].axis("off") if args.figname: fig.savefig(args.figname, **cfg["figure"]["save"]) else: plt.show()
def main(args): """main function """ # Read time intervals with open(args.config) as f: cfg = yaml.load(f, Loader=yaml.FullLoader) tint_flap = cfg["tints"]["flapping"] tint_zoom = cfg["tints"]["close-up"] mms_ids = np.arange(1, 5) # Load spacecraft position and background magnetic field r_mms = [ get_data("R_gse", tint_flap, i, args.verbose, data_path=cfg["data_path"]) for i in mms_ids ] suf_b = "fgm_{}_{}".format(cfg["fgm"]["data_rate"], cfg["fgm"]["level"]) b_mms = [ get_data("B_gse_{}".format(suf_b), tint_flap, i, args.verbose, data_path=cfg["data_path"]) for i in mms_ids ] # Remove offset on z component of the background magnetic field b_mms = remove_bz_offset(b_mms) # Compute magnetic field at the center of mass of the tetrahedron j_xyz, _, b_xyz, _, _, _ = c_4_j(r_mms, b_mms) j_xyz *= 1e9 # j A.m^{-2}->nA.m^{-2} # Compute magnetic field at the center of mass of the tetrahedron b_xyz = avg_4sc(b_mms) # Compute MVA frame b_lmn, _, lmn = mva(b_xyz) # Correct minimum variance frame # lmn = np.vstack([lmn[:, 0], -lmn[:, 2], lmn[:, 1]]).T l = lmn[:, 0] m = np.mean(j_xyz.data, axis=0) / np.linalg.norm(np.mean(j_xyz, axis=0)) n = np.cross(l, m) / np.linalg.norm(np.cross(l, m)) m = np.cross(n, l) lmn = np.transpose(np.vstack([l, m, n])) b_xyz = time_clip(b_mms[args.mms_id - 1], tint_zoom) b_lmn = new_xyz(b_xyz, lmn) # Load electric field and magnetic field fluctuation # Load electric field suf_e = "edp_{}_{}".format(cfg["edp"]["data_rate"], cfg["edp"]["level"]) e_xyz = get_data("e_gse_{}".format(suf_e), tint_zoom, args.mms_id, args.verbose, data_path=cfg["data_path"]) # Load electric field suf_db = "scm_{}_{}".format(cfg["scm"]["data_rate"], cfg["scm"]["level"]) b_scm = get_data("b_gse_{}".format(suf_db), tint_zoom, args.mms_id, args.verbose, data_path=cfg["data_path"]) # Load density and pressure tensor moments_i, moments_e = load_moments(tint_flap, cfg["fpi"], args, data_path=cfg["data_path"]) # Unpack moments _, _, _, p_xyz_i = moments_i n_e, _, _, p_xyz_e = moments_e # Total pressure tensor p_xyz = p_xyz_i + resample(p_xyz_e, p_xyz_i) # Convert to field-aligned coordinates p_xyzfac = rotate_tensor(p_xyz, "fac", b_xyz, "pp") # Permittivity mu0 = constants.mu_0 # Thermal pressure (scalar) pth = 1e-9 * trace(p_xyzfac) / 3. # Magnetic pressure p_mag = 1e-18 * norm(b_xyz)**2 / (2 * mu0) # Plasma beta beta = resample(pth, b_xyz) / p_mag # Plasma parameters plasma_params = plasma_calc(b_xyz, n_e, n_e, n_e, n_e) # Convert electric field and magnetic field fluctuation to field aligned # coordinates e_xyzfac = convert_fac(e_xyz, b_xyz, [1, 0, 0]) # bandpass filter electric field and magnetic field fluctuation f_min = 4 e_xyzfac_hf = filt(e_xyzfac, f_min, 0, 3) cwt_options = dict(nf=100, f=[0.5, 1e3], plot=False) # Compute continuous wavelet transform of the electric field e_xyzfac_cwt = wavelet(e_xyzfac, **cwt_options) # Construct compressed spectrogram of E e_cwt_times, e_cwt_x, e_cwt_y, e_cwt_z = compress_cwt(e_xyzfac_cwt, nc=100) e_cwt = xr.DataArray(e_cwt_x + e_cwt_y + e_cwt_z, coords=[e_cwt_times, e_xyzfac_cwt.frequency], dims=["time", "frequency"]) # Compute continuous wavelet transform of the magnetic field fluctuations b_scm_cwt = wavelet(b_scm, **cwt_options) # Construct compressed spectrogram of E b_cwt_times, b_cwt_x, b_cwt_y, b_cwt_z = compress_cwt(b_scm_cwt, nc=100) b_cwt = xr.DataArray(b_cwt_x + b_cwt_y + b_cwt_z, coords=[b_cwt_times, b_scm_cwt.frequency], dims=["time", "frequency"]) # Plot fig, axs = plt.subplots(4, sharex="all", figsize=(6.5, 9)) fig.subplots_adjust(bottom=.05, top=.95, left=.15, right=.85, hspace=0.) kwargs_legend = dict(ncol=3, loc="upper right", frameon=True) kwargs_spectr = dict(cscale="log", yscale="log", cmap="Spectral_r", clim=[1e-7, 1e0]) plot_line(axs[0], b_lmn) axs[0].legend(["$B_L$", "$B_M$", "$B_N$"], **cfg["figure"]["legend"]) axs[0].set_ylabel("$B$ [nT]") axs[0].grid(True, which="both") plot_line(axs[1], e_xyzfac_hf) labels = ["$E_{\\perp 1}$", "$E_{\\perp 2}$", "$E_{\\parallel}$"] axs[1].legend(labels, **cfg["figure"]["legend"]) axs[1].set_ylabel("$E$ [mV m$^{-1}$]") axs[1].set_ylim([-9, 9]) axs[1].set_yticks([-6, 0, 6]) axs1b = axs[1].twinx() plot_line(axs1b, beta, color="k") axs1b.set_yscale("log") axs1b.set_ylabel("$\\beta$") axs1b.set_ylim([10**(.5) * 1e0, 10**(.5) * 1e3]) axs[1].grid(True, which="both") axs[2], caxs2 = plot_spectr(axs[2], e_cwt, **cfg["figure"]["spectrum"]) plot_line(axs[2], plasma_params.f_lh, color="k", label="$f_{lh}$") plot_line(axs[2], plasma_params.f_ce, color="w", label="$f_{ce}$") plot_line(axs[2], plasma_params.f_pp, color="red", label="$f_{pi}$") axs[2].set_ylim([0.5, 1e3]) axs[2].set_ylabel("$f$ [Hz]") caxs2.set_ylabel("$E^2$ " + "\n" + "[mV$^2$ m$^{-2}$ Hz$^{-1}$]") axs[2].legend(**cfg["figure"]["legend"]) axs[3], caxs3 = plot_spectr(axs[3], b_cwt, **cfg["figure"]["spectrum"]) plot_line(axs[3], plasma_params.f_lh, color="k", label="$f_{lh}$") plot_line(axs[3], plasma_params.f_ce, color="w", label="$f_{ce}$") plot_line(axs[3], plasma_params.f_pp, color="red", label="$f_{pi}$") axs[3].set_ylim([0.5, 1e3]) axs[3].set_ylabel("$f$ [Hz]") caxs3.set_ylabel("$B^2$ " + "\n" + "[nT$^2$ Hz$^{-1}$]") axs[3].legend(**cfg["figure"]["legend"]) fig.align_ylabels(axs) axs[1].text(.85, .15, "$f > ${:2.1f} Hz".format(f_min), transform=axs[1].transAxes) # Time interval of the flapping axs[-1].set_xlim(mdates.date2num(tint_zoom)) # Add panels labels labels_pos = [0.02, 0.90] _ = make_labels(axs, labels_pos) if args.figname: fig.savefig(args.figname, **cfg["figure"]["save"]) else: plt.show()
def main(args): """main function """ with open(args.config) as f: cfg = yaml.load(f, Loader=yaml.FullLoader) tint = cfg["tints"]["flapping"] # Spacecraft indices mms_ids = np.arange(1, 5) # Load spacecraft position and background magnetic field r_mms = [ get_data("R_gse", tint, i, args.verbose, data_path=cfg["data_path"]) for i in mms_ids ] # Load background magnetic field suf_b = "fgm_{}_{}".format(cfg["fgm"]["data_rate"], cfg["fgm"]["level"]) b_mms = [ get_data("B_gse_{}".format(suf_b), tint, i, args.verbose, data_path=cfg["data_path"]) for i in mms_ids ] # Remove offset on z component of the background magnetic field b_mms = remove_bz_offset(b_mms) # Compute magnetic field at the center of mass of the tetrahedron j_xyz, _, b_xyz, _, _, _ = c_4_j(r_mms, b_mms) j_xyz *= 1e9 # Load moments of the velocity distribution functions moments_i, moments_e = load_moments(tint, cfg["fpi"], args, cfg["data_path"]) # Unpack ion/electron temperature _, _, t_i = dec_temperature(b_xyz, moments_i) _, _, t_e = dec_temperature(b_xyz, moments_e) grad_n_i = grad_ni(r_mms, tint, cfg) # Compute new coordinates system lmn = lmn_cs(b_xyz, moments_i[1]) # Transform fields to MVA frame b_lmn, j_lmn = [new_xyz(field, lmn) for field in [b_xyz, j_xyz]] grad_n_i_lmn = new_xyz(grad_n_i, lmn) # Transform moments moments_lmn_i = [moments_i[0], None, None, None] moments_lmn_e = [moments_e[0], None, None, None] moments_lmn_i[1:] = [new_xyz(mom, lmn) for mom in moments_i[1:]] moments_lmn_e[1:] = [new_xyz(mom, lmn) for mom in moments_e[1:]] # Unpack number density n_i, n_e = [moments_lmn_i[0], moments_lmn_e[0]] # Unpack bulk velocity v_lmn_i, v_lmn_e = [moments_lmn_i[1], moments_lmn_e[1]] # Plot fig, axs = plt.subplots(6, **cfg["figure"]["main"]) fig.subplots_adjust(**cfg["figure"]["subplots"]) # B GSE plot_line(axs[0], b_lmn) plot_line(axs[0], norm(b_lmn)) axs[0].set_ylim([-14, 14]) axs[0].set_ylabel("$B$ [nT]") axs[0].legend(["$B_L$", "$B_M$", "$B_N$", "$|B|$"], **cfg["figure"]["legend"]) axs[0].grid(True, which="both") # ViM, VeM, B_L plot_line(axs[1], v_lmn_i[:, 1], color="tab:blue", label="Ions") plot_line(axs[1], v_lmn_e[:, 1], color="tab:red", label="Electrons") axs[1].set_ylim([-420, 420]) axs[1].set_yticks([-300, 0, 300]) axs[1].set_ylabel("$V_M$ [km s$^{-1}$]") axs[1].legend(**cfg["figure"]["legend"]) axs[1].grid(True, which="both") # ViN, VeN, B_L plot_line(axs[2], v_lmn_i[:, 2], color="tab:blue", label="Ions") plot_line(axs[2], v_lmn_e[:, 2], color="tab:red", label="Electrons") axs[2].set_ylim([-420, 420]) axs[2].set_yticks([-300, 0, 300]) axs[2].set_ylabel("$V_N$ [km s$^{-1}$]") axs[2].legend(**cfg["figure"]["legend"]) axs[2].grid(True, which="both") # Ni, Ne, B_L plot_line(axs[3], n_i, color="tab:blue") axs[3].set_ylim([0.06, 0.34]) axs[3].set_ylabel("$n_i$ [cm$^{-3}$]") axs[3].grid(True, which="both") plot_line(axs[4], grad_n_i_lmn[:, 2], color="tab:blue", label="$(\\nabla n_i)_N$") axs[4].set_ylim([-.84, .84]) axs[4].set_yticks([-.6, 0, .6]) axs[4].legend(**cfg["figure"]["legend"]) axs[4].set_ylabel("$\\nabla n_i$ [m$^{-4}$]") # JM, JN, B_L plot_line(axs[5], j_lmn[:, 1], color="tab:green", label="$J_M$") plot_line(axs[5], j_lmn[:, 2], color="tab:red", label="$J_N$") axs[5].set_ylim([-28, 28]) axs[5].set_ylabel("$J$ [nA m$^{-2}$]") axs[5].legend(**cfg["figure"]["legend"]) axs[5].grid(True, which="both") # Add magnetic field to all axes for ax in axs[1:]: axb = ax.twinx() plot_line(axb, b_lmn[:, 0], color="darkgrey") axb.set_ylim([-14, 14]) axb.set_ylabel("$B_L$ [nT]") axs[-1].set_xlim(mdates.date2num(tint)) fig.align_ylabels(axs) # Add panels labels labels_pos = [0.02, 0.85] _ = make_labels(axs, labels_pos) if args.figname: fig.savefig(args.figname, **cfg["figure"]["save"]) else: plt.show()
def main(args): """main function """ # Read time intervals with open(args.config) as f: cfg = yaml.load(f, Loader=yaml.FullLoader) tint_flap = cfg["tints"]["flapping"] tint_zoom = cfg["tints"]["close-up"] mms_ids = np.arange(1, 5) # Load spacecraft position r_mms = [ get_data("R_gse", tint_flap, i, data_path=cfg["data_path"]) for i in mms_ids ] # Load background magnetic field suf_b = "fgm_{}_{}".format(cfg["fgm"]["data_rate"], cfg["fgm"]["level"]) b_mms = [ get_data("B_gse_{}".format(suf_b), tint_flap, i, args.verbose, data_path=cfg["data_path"]) for i in mms_ids ] # Load electric field suf_e = "edp_{}_{}".format(cfg["edp"]["data_rate"], cfg["edp"]["level"]) e_mms = [ get_data("e_gse_{}".format(suf_e), tint_flap, i, args.verbose, data_path=cfg["data_path"]) for i in mms_ids ] # Load moments from FPI moments_i, moments_e = load_moments(tint_flap, cfg["fpi"], args, data_path=cfg["data_path"]) # Remove offset on z component of the background magnetic field b_mms = remove_bz_offset(b_mms) # Compute current density j_xyz, _, b_xyz, _, _, _ = c_4_j(r_mms, b_mms) j_xyz *= 1e9 # j A.m^{-2}->nA.m^{-2} # Compute electric field at the center of mass of the tetrahedron e_xyz = avg_4sc(e_mms) # Compute new coordinates system lmn = lmn_cs(b_xyz, moments_i[1]) # Resample magnetic field and current density to electric field sampling b_xyz, j_xyz = [resample(field, e_xyz) for field in [b_xyz, j_xyz]] # Transform fields to MVA frame b_lmn, e_lmn, j_lmn = [new_xyz(x_, lmn) for x_ in [b_xyz, e_xyz, j_xyz]] # Resample ion/electron moments to electric field sampling moments_i = [resample(mom, e_xyz) for mom in moments_i] moments_e = [resample(mom, e_xyz) for mom in moments_e] # Transform moments moments_lmn_i = [moments_i[0], None, None, None] moments_lmn_e = [moments_e[0], None, None, None] moments_lmn_i[1:] = [new_xyz(mom, lmn) for mom in moments_i[1:]] moments_lmn_e[1:] = [new_xyz(mom, lmn) for mom in moments_e[1:]] # Compute terms of the Ohm's law vxb_lmn_i, vxb_lmn_e, jxb_lmn = calc_ol_terms(b_lmn, j_lmn, moments_lmn_i, moments_lmn_e) # Compute ion scale total contribution s_lmn = -vxb_lmn_i + jxb_lmn # Plot fig = plt.figure(**cfg["figure"]["main"]) gs0 = fig.add_gridspec(2, 1, **cfg["figure"]["gridspec"]) gs00 = gs0[:1].subgridspec(4, 1, hspace=0) gs10 = gs0[1:].subgridspec(4, 1, hspace=0) axs0 = [fig.add_subplot(gs00[i]) for i in range(4)] axs1 = [fig.add_subplot(gs10[i]) for i in range(4)] for axs in [axs0, axs1]: plot_line(axs[0], b_lmn) axs[0].legend(["$B_L$", "$B_M$", "$B_N$"], **cfg["figure"]["legend"]) axs[0].set_ylabel("$B$" + "\n" + "[nT]") axs[0].grid(True, which="both") plot_line(axs[1], jxb_lmn[:, 1], label="$J\\times B / ne$") plot_line(axs[1], -vxb_lmn_i[:, 1], label="$-V_i\\times B$") plot_line(axs[1], s_lmn[:, 1], label="$J\\times B / ne -V_i\\times B$") plot_line(axs[1], e_lmn[:, 1], label="$E_{EDP}$") axs[1].set_ylim([-12, 12]) axs[1].set_ylabel("$E_M$" + "\n" + "[mV m$^{-1}$]") axs[1].grid(True, which="both") plot_line(axs[2], jxb_lmn[:, 2], label="$J\\times B / ne$") plot_line(axs[2], -vxb_lmn_i[:, 2], label="$-V_i\\times B$") plot_line(axs[2], s_lmn[:, 2], label="$J\\times B / ne -V_i\\times B$") plot_line(axs[2], e_lmn[:, 2], label="$E_{EDP}$") axs[2].legend(frameon=True, ncol=2, bbox_to_anchor=(1, 1.3), loc="upper right") axs[2].set_ylim([-12, 12]) axs[2].set_ylabel("$E_N$" + "\n" + "[mV m$^{-1}$]") axs[2].grid(True, which="both") plot_line(axs[3], norm(e_xyz + vxb_lmn_i), color="deeppink", label="$| E+V_{i}\\times B |$") plot_line(axs[3], norm(jxb_lmn), color="tab:blue", label="$|J\\times B / ne|$") axs[3].legend(**cfg["figure"]["legend"]) axs[3].set_ylim([0, 12]) axs[3].set_ylabel("$|E|$" + "\n" + "[mV m$^{-1}$]") axs[3].grid(True, which="both") axs[-1].get_shared_x_axes().join(*axs) fig.align_ylabels(axs) for ax in axs[:-1]: ax.xaxis.set_ticklabels([]) axs0[-1].set_xlim(mdates.date2num(tint_flap)) axs1[-1].set_xlim(mdates.date2num(tint_zoom)) # zoom zoom(axs1[0], axs0[-1], ec="k") span_options = dict(linestyle="--", linewidth=0.8, facecolor="none", edgecolor="k") span_tint(axs0, tint_zoom, **span_options) # number subplots labels_pos = [0.02, 0.83] _ = make_labels(axs0 + axs1, labels_pos) if args.figname: fig.savefig(args.figname, **cfg["figure"]["save"]) else: plt.show()