コード例 #1
0
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
コード例 #2
0
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
コード例 #3
0
def st_derivative(r, b, mva, crossing_times):
    """
    Computes velocity of the structure using spatio-temporal derivative method
    """

    b_xyz = avg_4sc(b)

    # Gradient of the magnetic field
    grad_b = c_4_grad(r, b)
    db_dt = gradient(b_xyz)

    # Transform gradient to LMN frame
    l_grad_b = np.matmul(grad_b.data, mva[:, 0])
    m_grad_b = np.matmul(grad_b.data, mva[:, 1])
    n_grad_b = np.matmul(grad_b.data, mva[:, 2])

    # Compute velocity of the structure using MDD
    v_str = np.zeros(db_dt.shape)
    v_str[:, 0] = np.sum(db_dt * l_grad_b, axis=1) / np.linalg.norm(l_grad_b,
                                                                    axis=1)**2
    v_str[:, 1] = np.sum(db_dt * m_grad_b, axis=1) / np.linalg.norm(m_grad_b,
                                                                    axis=1)**2
    v_str[:, 2] = np.sum(db_dt * n_grad_b, axis=1) / np.linalg.norm(n_grad_b,
                                                                    axis=1)**2

    dt = calc_dt(b_xyz)
    y_m = np.abs(np.cumsum(-v_str[:, 1]) * dt)
    z_n = np.cumsum(-v_str[:, 2]) * dt

    v_str = ts_vec_xyz(b_xyz.time.data, -v_str)
    y_m = ts_scalar(b_xyz.time.data, y_m)
    z_n = ts_scalar(b_xyz.time.data, z_n)

    z_off = resample(t_eval(z_n, crossing_times), y_m)
    z_n -= z_off

    return v_str, y_m, z_n
コード例 #4
0
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()
コード例 #5
0
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
コード例 #6
0
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()
コード例 #7
0
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()