Esempio n. 1
0
def kinetic_entropy(sc, mode, start_date, end_date, **kwargs):

    # Read the data
    b = fgm.load_data(sc, mode, start_date, end_date)
    dis_moms = fpi.load_moms(sc, mode, 'i', start_date, end_date)
    des_moms = fpi.load_moms(sc, mode, 'e', start_date, end_date)
    dis_dist = fpi.load_dist(sc, mode, 'i', start_date, end_date)
    des_dist = fpi.load_dist(sc, mode, 'e', start_date, end_date)

    # Equivalent Maxwellian distribution
    dis_max_dist = fpi.maxwellian_distribution(dis_dist,
                                               N=dis_moms['density'],
                                               bulkv=dis_moms['velocity'],
                                               T=dis_moms['t'])
    des_max_dist = fpi.maxwellian_distribution(des_dist,
                                               N=des_moms['density'],
                                               bulkv=des_moms['velocity'],
                                               T=des_moms['t'])

    # Entropy density
    si_dist = fpi.entropy(dis_dist, **kwargs)
    se_dist = fpi.entropy(des_dist, **kwargs)

    #    si_max = fpi.maxwellian_entropy(dis_moms['density'], dis_moms['p'])
    #    se_max = fpi.maxwellian_entropy(des_moms['density'], des_moms['p'])
    si_max = fpi.entropy(dis_max_dist, **kwargs)
    se_max = fpi.entropy(des_max_dist, **kwargs)

    # Velcoity space entropy density
    siv_dist = fpi.vspace_entropy(dis_dist,
                                  N=dis_moms['density'],
                                  s=si_dist,
                                  **kwargs)
    sev_dist = fpi.vspace_entropy(des_dist,
                                  N=des_moms['density'],
                                  s=se_dist,
                                  **kwargs)

    siv_max = fpi.vspace_entropy(des_max_dist,
                                 N=dis_moms['density'],
                                 s=si_max,
                                 **kwargs)
    sev_max = fpi.vspace_entropy(des_max_dist,
                                 N=des_moms['density'],
                                 s=se_max,
                                 **kwargs)

    # M-bar
    mi_bar = np.abs(si_max - si_dist) / si_max
    me_bar = np.abs(se_max - se_dist) / se_max

    miv_bar = np.abs(siv_max - siv_dist) / siv_max
    mev_bar = np.abs(sev_max - sev_dist) / sev_max

    # Epsilon
    ei = fpi.epsilon(dis_dist,
                     N=dis_moms['density'],
                     V=dis_moms['velocity'],
                     T=dis_moms['t'],
                     **kwargs)
    ee = fpi.epsilon(des_dist,
                     N=des_moms['density'],
                     V=des_moms['velocity'],
                     T=des_moms['t'],
                     **kwargs)

    # Setup the plot
    nrows = 9
    ncols = 1
    figsize = (5.5, 7.0)
    fig, axes = plt.subplots(nrows=nrows,
                             ncols=ncols,
                             figsize=figsize,
                             squeeze=False)

    # B
    ax = axes[0, 0]
    ax = util.plot([b['B'][:, 3], b['B'][:, 0], b['B'][:, 1], b['B'][:, 2]],
                   ax=ax,
                   labels=['|B|', 'Bx', 'By', 'Bz'],
                   xaxis='off',
                   ylabel='B\n(nT)')

    # Ion entropy density
    ax = axes[1, 0]
    ax = util.plot([si_max, si_dist],
                   ax=ax,
                   labels=['$s_{i,max}$', '$s_{i}$'],
                   xaxis='off',
                   ylabel='s\n$J/K/m^{3}$ $ln(s^{3}/m^{6})$')

    # Electron entropy density
    ax = axes[2, 0]
    ax = util.plot([se_max, se_dist],
                   ax=ax,
                   labels=['$s_{e,max}$', '$s_{e}$'],
                   xaxis='off',
                   ylabel='s')

    # Ion M-bar
    ax = axes[3, 0]
    ax = util.plot(mi_bar,
                   ax=ax,
                   legend=False,
                   xaxis='off',
                   ylabel='$\overline{M}_{i}$')

    # Ion Epsilon
    ax = ax.twinx()
    ei.plot(ax=ax, color='g')
    ax.set_ylabel('$\epsilon_{i}$\n$(s/m)^{3/2}$')
    ax.yaxis.label.set_color('g')
    ax.tick_params(axis='y', colors='g')
    ax.set_xticklabels([])

    # Electron M-bar
    ax = axes[4, 0]
    ax = util.plot(me_bar,
                   ax=ax,
                   legend=False,
                   xaxis='off',
                   ylabel='$\overline{M}_{e}$')

    # Electron Epsilon
    ax = ax.twinx()
    ee.plot(ax=ax, color='r')
    ax.set_ylabel('$\epsilon_{e}$\n$(s/m)^{3/2}$')
    ax.yaxis.label.set_color('r')
    ax.tick_params(axis='y', colors='r')
    ax.set_xticklabels([])

    # Velocity space ion entropy density
    ax = axes[5, 0]
    ax = util.plot([siv_max, siv_dist],
                   ax=ax,
                   labels=['$s_{i,V,max}$', '$s_{i,V}$'],
                   xaxis='off',
                   ylabel='$s_{V}$\n$J/K/m^{3}$ $ln()$')

    # Velocity space electron entropy density
    ax = axes[6, 0]
    ax = util.plot([sev_max, sev_dist],
                   ax=ax,
                   labels=['$s_{e,V,max}$', '$s_{e,V}$'],
                   xaxis='off',
                   ylabel='$s_{V}$')

    # Velocity space ion M-bar
    ax = axes[7, 0]
    ax = util.plot(miv_bar,
                   ax=ax,
                   legend=False,
                   xaxis='off',
                   ylabel='$\overline{M}_{i,V}$')

    # Velocity space electron M-bar
    ax = axes[8, 0]
    ax = util.plot(mev_bar, ax=ax, legend=False, ylabel='$\overline{M}_{e,V}$')

    fig.suptitle('Total and Velocity Space Entropy Density')
    plt.subplots_adjust(left=0.2, right=0.85, top=0.95, hspace=0.4)
    #    plt.setp(axes, xlim=xlim)
    return fig, axes
Esempio n. 2
0
def kinetic_entropy(sc, mode, start_date, end_date, **kwargs):
    
    # Read the data
    b = fgm.load_data(sc=sc, mode=mode,
                      start_date=start_date, end_date=end_date)
    dis_dist = fpi.load_dist(sc=sc, mode=mode, optdesc='dis-dist',
                             start_date=start_date, end_date=end_date)
    des_dist = fpi.load_dist(sc=sc, mode=mode, optdesc='des-dist',
                             start_date=start_date, end_date=end_date)
    
    # Precondition the distributions
    dis_kwargs = fpi.precond_params(sc, mode, 'l2', 'dis-dist',
                                    start_date, end_date,
                                    time=dis_dist['time'])
    des_kwargs = fpi.precond_params(sc, mode, 'l2', 'des-dist',
                                    start_date, end_date,
                                    time=des_dist['time'])
    f_dis = fpi.precondition(dis_dist['dist'], **dis_kwargs)
    f_des = fpi.precondition(des_dist['dist'], **des_kwargs)
    
    # Calculate Moments
    Ni = fpi.density(f_dis)
    Vi = fpi.velocity(f_dis, N=Ni)
    Ti = fpi.temperature(f_dis, N=Ni, V=Vi)
    Pi = fpi.pressure(f_dis, N=Ni, T=Ti)
    ti = ((Ti[:,0,0] + Ti[:,1,1] + Ti[:,2,2]) / 3.0).drop(['t_index_dim1', 't_index_dim2'])
    pi = ((Pi[:,0,0] + Pi[:,1,1] + Pi[:,2,2]) / 3.0).drop(['t_index_dim1', 't_index_dim2'])
    
    Ne = fpi.density(f_des)
    Ve = fpi.velocity(f_des, N=Ne)
    Te = fpi.temperature(f_des, N=Ne, V=Ve)
    Pe = fpi.pressure(f_des, N=Ne, T=Te)
    te = ((Te[:,0,0] + Te[:,1,1] + Te[:,2,2]) / 3.0).drop(['t_index_dim1', 't_index_dim2'])
    pe = ((Pe[:,0,0] + Pe[:,1,1] + Pe[:,2,2]) / 3.0).drop(['t_index_dim1', 't_index_dim2'])
    
    # Equivalent (preconditioned) Maxwellian distributions
    fi_max = fpi.maxwellian_distribution(f_dis, N=Ni, bulkv=Vi, T=ti)
    fe_max = fpi.maxwellian_distribution(f_des, N=Ne, bulkv=Ve, T=te)
    
    # Entropy density
    si_dist = fpi.entropy(f_dis)
    se_dist = fpi.entropy(f_des)
    si_max = fpi.entropy(fi_max)
    se_max = fpi.entropy(fe_max)
    
    # Velcoity space entropy density
    siv_dist = fpi.vspace_entropy(f_dis, N=Ni, s=si_dist)
    sev_dist = fpi.vspace_entropy(f_des, N=Ne, s=se_dist)
    
    # The Maxwellian is already preconditioned
    #   - There are three options for calculating the v-space entropy of
    #     the Maxwellian distribution: using
    #        1) FPI integrated moments,
    #        2) Custom moments of the measured distribution
    #        3) Custom moments of the equivalent Maxwellian distribution
    #     Because the Maxwellian is built with discrete v-space bins, its
    #     density, velocity, and temperature do not match that of the
    #     measured distribution on which it is based. If NiM is used, the
    #     M-bar term will be negative, which is unphysical, so here we use
    #     the density of the measured distribution and the entropy of the
    #     equivalent Maxwellian.
    siv_max = fpi.vspace_entropy(fi_max, N=Ni, s=si_max)
    sev_max = fpi.vspace_entropy(fe_max, N=Ne, s=se_max)
    
    # M-bar
    mi_bar = np.abs(si_max - si_dist) / si_max
    me_bar = np.abs(se_max - se_dist) / se_max
    
    miv_bar = np.abs(siv_max - siv_dist) / siv_max
    mev_bar = np.abs(sev_max - sev_dist) / sev_max
    
    # Epsilon
    ei = fpi.epsilon(f_dis, N=Ni, V=Vi, T=ti)
    ee = fpi.epsilon(f_des, N=Ne, V=Ve, T=te)
    
    # Setup the plot
    nrows = 9
    ncols = 1
    figsize = (5.5, 7.0)
    fig, axes = plt.subplots(nrows=nrows, ncols=ncols,
                             figsize=figsize, squeeze=False)
    
    # B
    ax = axes[0,0]
    ax = util.plot([b['B_GSE'][:,3], b['B_GSE'][:,0],
                    b['B_GSE'][:,1], b['B_GSE'][:,2]],
                   ax=ax, labels=['|B|', 'Bx', 'By', 'Bz'],
                   xaxis='off', ylabel='B\n(nT)'
                   )
    
    # Ion entropy density
    ax = axes[1,0]
    ax = util.plot([si_max, si_dist],
                   ax=ax, labels=['$s_{i,max}$', '$s_{i}$'],
                   xaxis='off', ylabel='s\n$J/K/m^{3}$ $ln(s^{3}/m^{6})$'
                   )
    
    # Electron entropy density
    ax = axes[2,0]
    ax = util.plot([se_max, se_dist],
                   ax=ax, labels=['$s_{e,max}$', '$s_{e}$'],
                   xaxis='off', ylabel='s'
                   )
    
    # Ion M-bar
    ax = axes[3,0]
    ax = util.plot(mi_bar,
                   ax=ax, legend=False,
                   xaxis='off', ylabel='$\overline{M}_{i}$'
                   )
    
    # Ion Epsilon
    ax = ax.twinx()
    ei.plot(ax=ax, color='g')
    ax.set_ylabel('$\epsilon_{i}$\n$(s/m)^{3/2}$')
    ax.yaxis.label.set_color('g')
    ax.tick_params(axis='y', colors='g')
    ax.set_xticklabels([])
    ax.set_title('')
    
    # Electron M-bar
    ax = axes[4,0]
    ax = util.plot(me_bar,
                   ax=ax, legend=False,
                   xaxis='off', ylabel='$\overline{M}_{e}$'
                   )
    
    # Electron Epsilon
    ax = ax.twinx()
    ee.plot(ax=ax, color='r')
    ax.set_ylabel('$\epsilon_{e}$\n$(s/m)^{3/2}$')
    ax.yaxis.label.set_color('r')
    ax.tick_params(axis='y', colors='r')
    ax.set_xticklabels([])
    ax.set_title('')
    
    # Velocity space ion entropy density
    ax = axes[5,0]
    ax = util.plot([siv_max, siv_dist],
                   ax=ax, labels=['$s_{i,V,max}$', '$s_{i,V}$'],
                   xaxis='off', ylabel='$s_{V}$\n$J/K/m^{3}$ $ln()$'
                   )
    
    # Velocity space electron entropy density
    ax = axes[6,0]
    ax = util.plot([sev_max, sev_dist],
                   ax=ax, labels=['$s_{e,V,max}$', '$s_{e,V}$'],
                   xaxis='off', ylabel='$s_{V}$'
                   )
    
    # Velocity space ion M-bar
    ax = axes[7,0]
    ax = util.plot(miv_bar,
                   ax=ax, legend=False,
                   xaxis='off', ylabel='$\overline{M}_{i,V}$'
                   )
    
    # Velocity space electron M-bar
    ax = axes[8,0]
    ax = util.plot(mev_bar,
                   ax=ax, legend=False,
                   ylabel='$\overline{M}_{e,V}$'
                   )
    
    
    fig.suptitle('Total and Velocity Space Entropy Density')
    plt.subplots_adjust(left=0.2, right=0.85, top=0.95, hspace=0.4)
#    plt.setp(axes, xlim=xlim)
    return fig, axes
Esempio n. 3
0
def moments_comparison(sc,
                       mode,
                       species,
                       start_date,
                       end_date,
                       scpot_correction=False,
                       ephoto_correction=False,
                       elimits=False):
    '''
    Compare moments derived from the 3D velocity distribution functions
    from three sources: official FPI moments, derived herein, and those
    of an equivalent Maxwellian distribution derived herein.
    
    Parameters
    ----------
    sc : str
        Spacecraft identifier. Choices are ('mms1', 'mms2', 'mms3', 'mms4')
    mode : str
        Data rate mode. Choices are ('fast', 'brst')
    species : str
        Particle species. Choices are ('i', 'e') for ions and electrons,
        respectively
    start_date, end_date : `datetime.datetime`
        Start and end dates and times of the time interval
    scpot_correction : bool
        Apply spacecraft potential correction to the distribution functions.
    ephoto : bool
        Subtract photo-electrons. Applicable to DES data only.
    elimits : bool
        Set upper and lower energy limits of integration
    
    Returns
    -------
    fig : `matplotlib.figure`
        Figure in which graphics are displayed
    ax : list
        List of `matplotlib.pyplot.axes` objects
    '''

    # Read the data
    moms_xr = fpi.load_moms(sc=sc,
                            mode=mode,
                            optdesc='d' + species + 's-moms',
                            start_date=start_date,
                            end_date=end_date)
    dist_xr = fpi.load_dist(sc=sc,
                            mode=mode,
                            optdesc='d' + species + 's-dist',
                            start_date=start_date,
                            end_date=end_date,
                            ephoto=ephoto_correction)

    # Precondition the distributions
    kwargs = fpi.precond_params(sc,
                                mode,
                                'l2',
                                'dis-dist',
                                start_date,
                                end_date,
                                time=dist_xr['time'])
    if scpot_correction is False:
        kwargs['scpot'] == None
    if elimits is False:
        kwargs['E_low'] = None
        kwargs['E_high'] = None
    f = fpi.precondition(dist_xr['dist'], **kwargs)

    # Moments distribution
    n_xr = fpi.density(f)
    s_xr = fpi.entropy(f)
    v_xr = fpi.velocity(f, N=n_xr)
    T_xr = fpi.temperature(f, N=n_xr, V=v_xr)
    P_xr = fpi.pressure(f, N=n_xr, T=T_xr)
    t_scalar_xr = (T_xr[:, 0, 0] + T_xr[:, 1, 1] + T_xr[:, 2, 2]) / 3.0
    p_scalar_xr = (P_xr[:, 0, 0] + P_xr[:, 1, 1] + P_xr[:, 2, 2]) / 3.0
    t_scalar_xr = t_scalar_xr.drop(['t_index_dim1', 't_index_dim2'])
    p_scalar_xr = p_scalar_xr.drop(['t_index_dim1', 't_index_dim2'])

    # Create an equivalent Maxwellian distribution
    f_max_xr = fpi.maxwellian_distribution(f, n_xr, v_xr, t_scalar_xr)
    n_max_dist = fpi.density(f_max_xr)
    s_max_dist = fpi.entropy(f_max_xr)
    s_max = fpi.maxwellian_entropy(n_xr, p_scalar_xr)
    v_max_dist = fpi.velocity(f_max_xr, N=n_max_dist)
    T_max_dist = fpi.temperature(f_max_xr, N=n_max_dist, V=v_max_dist)
    P_max_dist = fpi.pressure(f_max_xr, N=n_max_dist, T=T_max_dist)
    p_scalar_max_dist = (P_max_dist[:, 0, 0] + P_max_dist[:, 1, 1] +
                         P_max_dist[:, 2, 2]) / 3.0
    p_scalar_max_dist = p_scalar_max_dist.drop(
        ['t_index_dim1', 't_index_dim2'])

    # Epsilon
    e_xr = fpi.epsilon(f, dist_max=f_max_xr, N=n_xr)

    nrows = 6
    ncols = 3
    figsize = (10.0, 5.5)
    fig, axes = plt.subplots(nrows=nrows,
                             ncols=ncols,
                             figsize=figsize,
                             squeeze=False)

    # Density
    ax = axes[0, 0]
    moms_xr['density'].attrs['label'] = 'moms'
    n_xr.attrs['label'] = 'dist'
    n_max_dist.attrs['label'] = 'max'
    ax = util.plot([moms_xr['density'], n_xr, n_max_dist],
                   ax=ax,
                   labels=['moms', 'dist', 'max'],
                   xaxis='off',
                   ylabel='N\n($cm^{-3}$)')

    # Entropy
    ax = axes[1, 0]
    ax = util.plot([s_max, s_xr, s_max_dist],
                   ax=ax,
                   labels=['moms', 'dist', 'max dist'],
                   xaxis='off',
                   ylabel='S\n[J/K/$m^{3}$ ln($s^{3}/m^{6}$)]')

    # Epsilon
    ax = axes[1, 0].twinx()
    e_xr.plot(ax=ax, color='r')
    ax.spines['right'].set_color('red')
    ax.yaxis.label.set_color('red')
    ax.tick_params(axis='y', colors='red')
    ax.set_title('')
    ax.set_xticks([])
    ax.set_xlabel('')
    ax.set_ylabel('$\epsilon$\n$(s/m)^{3/2}$')

    # Vx
    ax = axes[2, 0]
    ax = util.plot([moms_xr['velocity'][:, 0], v_xr[:, 0], v_max_dist[:, 0]],
                   ax=ax,
                   labels=['moms', 'dist', 'max'],
                   xaxis='off',
                   ylabel='Vx\n(km/s)')

    # Vy
    ax = axes[3, 0]
    ax = util.plot([moms_xr['velocity'][:, 1], v_xr[:, 1], v_max_dist[:, 1]],
                   ax=ax,
                   labels=['moms', 'dist', 'max'],
                   xaxis='off',
                   ylabel='Vy\n(km/s)')

    # Vz
    ax = axes[4, 0]
    ax = util.plot([moms_xr['velocity'][:, 2], v_xr[:, 2], v_max_dist[:, 2]],
                   ax=ax,
                   labels=['moms', 'dist', 'max'],
                   xaxis='off',
                   ylabel='Vz\n(km/s)')

    # Scalar Pressure
    ax = axes[5, 0]
    ax = util.plot([moms_xr['p'], p_scalar_xr, p_scalar_max_dist],
                   ax=ax,
                   labels=['moms', 'dist', 'max'],
                   xlabel='',
                   ylabel='p\n(nPa)')

    # T_xx
    ax = axes[0, 1]
    ax = util.plot(
        [moms_xr['temptensor'][:, 0, 0], T_xr[:, 0, 0], T_max_dist[:, 0, 0]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xaxis='off',
        ylabel='Txx\n(eV)')

    # T_yy
    ax = axes[1, 1]
    ax = util.plot(
        [moms_xr['temptensor'][:, 1, 1], T_xr[:, 1, 1], T_max_dist[:, 1, 1]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xaxis='off',
        ylabel='Tyy\n(eV)')

    # T_zz
    ax = axes[2, 1]
    ax = util.plot(
        [moms_xr['temptensor'][:, 2, 2], T_xr[:, 2, 2], T_max_dist[:, 2, 2]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xaxis='off',
        ylabel='Tzz\n(eV)')

    # T_xy
    ax = axes[3, 1]
    ax = util.plot(
        [moms_xr['temptensor'][:, 0, 1], T_xr[:, 0, 1], T_max_dist[:, 0, 1]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xaxis='off',
        ylabel='Txy\n(eV)')

    # T_xz
    ax = axes[4, 1]
    ax = util.plot(
        [moms_xr['temptensor'][:, 0, 2], T_xr[:, 0, 2], T_max_dist[:, 0, 2]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xaxis='off',
        ylabel='Txz\n(eV)')

    # T_yz
    ax = axes[5, 1]
    ax = util.plot(
        [moms_xr['temptensor'][:, 1, 2], T_xr[:, 1, 2], T_max_dist[:, 1, 2]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xlabel='',
        ylabel='Txz\n(eV)')

    # P_xx
    ax = axes[0, 2]
    ax = util.plot(
        [moms_xr['prestensor'][:, 0, 0], P_xr[:, 0, 0], P_max_dist[:, 0, 0]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xaxis='off',
        ylabel='Pxx\n(nPa)')

    # P_yy
    ax = axes[1, 2]
    ax = util.plot(
        [moms_xr['prestensor'][:, 1, 1], P_xr[:, 1, 1], P_max_dist[:, 1, 1]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xaxis='off',
        ylabel='Pyy\n(nPa)')

    # P_zz
    ax = axes[2, 2]
    ax = util.plot(
        [moms_xr['prestensor'][:, 2, 2], P_xr[:, 2, 2], P_max_dist[:, 2, 2]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xaxis='off',
        ylabel='Pzz\n(nPa)')

    # P_xy
    ax = axes[3, 2]
    ax = util.plot(
        [moms_xr['prestensor'][:, 0, 1], P_xr[:, 0, 1], P_max_dist[:, 0, 1]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xaxis='off',
        ylabel='Pxy\n(nPa)')

    # P_xz
    ax = axes[4, 2]
    ax = util.plot(
        [moms_xr['prestensor'][:, 0, 2], P_xr[:, 0, 2], P_max_dist[:, 0, 2]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xaxis='off',
        ylabel='Pxz\n(nPa)')

    # P_yz
    ax = axes[5, 2]
    ax = util.plot(
        [moms_xr['prestensor'][:, 1, 2], P_xr[:, 1, 2], P_max_dist[:, 1, 2]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xlabel='',
        ylabel='Pyz\n(nPa)')

    fig.suptitle(
        'Comparing FPI Moments, Integrated Distribution, Equivalent Maxwellian'
    )
    plt.subplots_adjust(left=0.1,
                        right=0.90,
                        top=0.95,
                        bottom=0.12,
                        hspace=0.3,
                        wspace=0.8)
    return fig, axes
def compare_moments(sc,
                    mode,
                    species,
                    start_date,
                    end_date,
                    scpot_correction=False,
                    ephoto_correction=False):
    '''
    Compare moments derived from the 3D velocity distribution functions
    from three sources: official FPI moments, derived herein, and those
    of an equivalent Maxwellian distribution derived herein.
    
    Parameters
    ----------
    sc : str
        Spacecraft identifier. Choices are ('mms1', 'mms2', 'mms3', 'mms4')
    mode : str
        Data rate mode. Choices are ('fast', 'brst')
    species : str
        Particle species. Choices are ('i', 'e') for ions and electrons,
        respectively
    start_date, end_date : `datetime.datetime`
        Start and end dates and times of the time interval
    scpot_correction : bool
        Apply spacecraft potential correction to the distribution functions.
    ephoto : bool
        Subtract photo-electrons. Applicable to DES data only.
    
    Returns
    -------
    fig : `matplotlib.figure`
        Figure in which graphics are displayed
    ax : list
        List of `matplotlib.pyplot.axes` objects
    '''
    # Read the data
    moms_xr = fpi.load_moms(sc, mode, species, start_date, end_date)
    dist_xr = fpi.load_dist(sc,
                            mode,
                            species,
                            start_date,
                            end_date,
                            ephoto=ephoto_correction)

    # Spacecraft potential correction
    scpot = None
    if scpot_correction:
        edp_mode = mode if mode == 'brst' else 'fast'
        scpot = edp.load_scpot(sc, edp_mode, start_date, end_date)
        scpot = scpot.interp_like(moms_xr, method='nearest')

    # Create an equivalent Maxwellian distribution
    max_xr = fpi.maxwellian_distribution(dist_xr, moms_xr['density'],
                                         moms_xr['velocity'], moms_xr['t'])

    # Density
    ni_xr = fpi.density(dist_xr, scpot=scpot)
    ni_max_dist = fpi.density(max_xr, scpot=scpot)

    # Entropy
    s_xr = fpi.entropy(dist_xr, scpot=scpot)
    s_max_dist = fpi.entropy(max_xr, scpot=scpot)
    s_max = fpi.maxwellian_entropy(moms_xr['density'], moms_xr['p'])

    # Velocity
    v_xr = fpi.velocity(dist_xr, N=ni_xr, scpot=scpot)
    v_max_dist = fpi.velocity(max_xr, N=ni_max_dist, scpot=scpot)

    # Temperature
    T_xr = fpi.temperature(dist_xr, N=ni_xr, V=v_xr, scpot=scpot)
    T_max_dist = fpi.temperature(max_xr,
                                 N=ni_max_dist,
                                 V=v_max_dist,
                                 scpot=scpot)

    # Pressure
    P_xr = fpi.pressure(dist_xr, N=ni_xr, T=T_xr)
    P_max_dist = fpi.pressure(max_xr, N=ni_max_dist, T=T_max_dist)

    # Scalar pressure
    p_scalar_xr = (P_xr[:, 0, 0] + P_xr[:, 1, 1] + P_xr[:, 2, 2]) / 3.0
    p_scalar_max_dist = (P_max_dist[:, 0, 0] + P_max_dist[:, 1, 1] +
                         P_max_dist[:, 2, 2]) / 3.0

    p_scalar_xr = p_scalar_xr.drop(['t_index_dim1', 't_index_dim2'])
    p_scalar_max_dist = p_scalar_max_dist.drop(
        ['t_index_dim1', 't_index_dim2'])

    # Epsilon
    e_xr = fpi.epsilon(dist_xr, dist_max=max_xr, N=ni_xr)

    nrows = 6
    ncols = 3
    figsize = (10.0, 5.5)
    fig, axes = plt.subplots(nrows=nrows,
                             ncols=ncols,
                             figsize=figsize,
                             squeeze=False)
    '''
    locator = mdates.AutoDateLocator()
    formatter = mdates.ConciseDateFormatter(locator)
    
    ax.xaxis.set_major_locator(locator)
    ax.xaxis.set_major_formatter(formatter)
    for tick in ax.get_xticklabels():
        tick.set_rotation(45)
    
    # Denisty
    ax = axes[0,0]
    lines = []
    moms_xr['density'].plot(ax=ax, label='moms')
    ni_xr.plot(ax=ax, label='dist')
    ni_max_dist.plot(ax=ax, label='max')
    ax.set_xlabel('')
    ax.set_xticklabels([])
    ax.set_ylabel='N\n($cm^{-3}$)'
    
    # Create the legend outside the right-most axes
    leg = ax.legend(bbox_to_anchor=(1.05, 1),
                    borderaxespad=0.0,
                    frameon=False,
                    handlelength=0,
                    handletextpad=0,
                    loc='upper left')
    
    # Color the text the same as the lines
    for line, text in zip(lines, leg.get_texts()):
        text.set_color(line.get_color())
    '''

    # Density
    ax = axes[0, 0]
    moms_xr['density'].attrs['label'] = 'moms'
    ni_xr.attrs['label'] = 'dist'
    ni_max_dist.attrs['label'] = 'max'
    ax = util.plot([moms_xr['density'], ni_xr, ni_max_dist],
                   ax=ax,
                   labels=['moms', 'dist', 'max'],
                   xaxis='off',
                   ylabel='N\n($cm^{-3}$)')

    # Entropy
    ax = axes[1, 0]
    ax = util.plot([s_max, s_xr, s_max_dist],
                   ax=ax,
                   labels=['moms', 'dist', 'max dist'],
                   xaxis='off',
                   ylabel='S\n[J/K/$m^{3}$ ln($s^{3}/m^{6}$)]')

    # Epsilon
    ax = axes[1, 0].twinx()
    e_xr.plot(ax=ax, color='r')
    ax.spines['right'].set_color('red')
    ax.yaxis.label.set_color('red')
    ax.tick_params(axis='y', colors='red')
    ax.set_title('')
    ax.set_xticks([])
    ax.set_xlabel('')
    ax.set_ylabel('$\epsilon$\n$(s/m)^{3/2}$')

    # Vx
    ax = axes[2, 0]
    ax = util.plot([moms_xr['velocity'][:, 0], v_xr[:, 0], v_max_dist[:, 0]],
                   ax=ax,
                   labels=['moms', 'dist', 'max'],
                   xaxis='off',
                   ylabel='Vx\n(km/s)')

    # Vy
    ax = axes[3, 0]
    ax = util.plot([moms_xr['velocity'][:, 1], v_xr[:, 1], v_max_dist[:, 1]],
                   ax=ax,
                   labels=['moms', 'dist', 'max'],
                   xaxis='off',
                   ylabel='Vy\n(km/s)')

    # Vz
    ax = axes[4, 0]
    ax = util.plot([moms_xr['velocity'][:, 2], v_xr[:, 2], v_max_dist[:, 2]],
                   ax=ax,
                   labels=['moms', 'dist', 'max'],
                   xaxis='off',
                   ylabel='Vz\n(km/s)')

    # Scalar Pressure
    ax = axes[5, 0]
    ax = util.plot([moms_xr['p'], p_scalar_xr, p_scalar_max_dist],
                   ax=ax,
                   labels=['moms', 'dist', 'max'],
                   xlabel='',
                   ylabel='p\n(nPa)')

    # T_xx
    ax = axes[0, 1]
    ax = util.plot(
        [moms_xr['temptensor'][:, 0, 0], T_xr[:, 0, 0], T_max_dist[:, 0, 0]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xaxis='off',
        ylabel='Txx\n(eV)')

    # T_yy
    ax = axes[1, 1]
    ax = util.plot(
        [moms_xr['temptensor'][:, 1, 1], T_xr[:, 1, 1], T_max_dist[:, 1, 1]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xaxis='off',
        ylabel='Tyy\n(eV)')

    # T_zz
    ax = axes[2, 1]
    ax = util.plot(
        [moms_xr['temptensor'][:, 2, 2], T_xr[:, 2, 2], T_max_dist[:, 2, 2]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xaxis='off',
        ylabel='Tzz\n(eV)')

    # T_xy
    ax = axes[3, 1]
    ax = util.plot(
        [moms_xr['temptensor'][:, 0, 1], T_xr[:, 0, 1], T_max_dist[:, 0, 1]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xaxis='off',
        ylabel='Txy\n(eV)')

    # T_xz
    ax = axes[4, 1]
    ax = util.plot(
        [moms_xr['temptensor'][:, 0, 2], T_xr[:, 0, 2], T_max_dist[:, 0, 2]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xaxis='off',
        ylabel='Txz\n(eV)')

    # T_yz
    ax = axes[5, 1]
    ax = util.plot(
        [moms_xr['temptensor'][:, 1, 2], T_xr[:, 1, 2], T_max_dist[:, 1, 2]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xlabel='',
        ylabel='Txz\n(eV)')

    # P_xx
    ax = axes[0, 2]
    ax = util.plot(
        [moms_xr['prestensor'][:, 0, 0], P_xr[:, 0, 0], P_max_dist[:, 0, 0]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xaxis='off',
        ylabel='Pxx\n(nPa)')

    # P_yy
    ax = axes[1, 2]
    ax = util.plot(
        [moms_xr['prestensor'][:, 1, 1], P_xr[:, 1, 1], P_max_dist[:, 1, 1]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xaxis='off',
        ylabel='Pyy\n(nPa)')

    # P_zz
    ax = axes[2, 2]
    ax = util.plot(
        [moms_xr['prestensor'][:, 2, 2], P_xr[:, 2, 2], P_max_dist[:, 2, 2]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xaxis='off',
        ylabel='Pzz\n(nPa)')

    # P_xy
    ax = axes[3, 2]
    ax = util.plot(
        [moms_xr['prestensor'][:, 0, 1], P_xr[:, 0, 1], P_max_dist[:, 0, 1]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xaxis='off',
        ylabel='Pxy\n(nPa)')

    # P_xz
    ax = axes[4, 2]
    ax = util.plot(
        [moms_xr['prestensor'][:, 0, 2], P_xr[:, 0, 2], P_max_dist[:, 0, 2]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xaxis='off',
        ylabel='Pxz\n(nPa)')

    # P_yz
    ax = axes[5, 2]
    ax = util.plot(
        [moms_xr['prestensor'][:, 1, 2], P_xr[:, 1, 2], P_max_dist[:, 1, 2]],
        ax=ax,
        labels=['moms', 'dist', 'max'],
        xlabel='',
        ylabel='Pyz\n(nPa)')

    fig.suptitle(
        'Comparing FPI Moments, Integrated Distribution, Equivalent Maxwellian'
    )
    plt.subplots_adjust(left=0.1,
                        right=0.90,
                        top=0.95,
                        bottom=0.12,
                        hspace=0.3,
                        wspace=0.8)
    return fig, axes