Ejemplo 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
Ejemplo n.º 2
0
def kinetic_entropy(sc, mode, start_date, end_date):
    
    # 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)
    
    # Philosopy
    #   - For the Maxwellian distributions, use the FPI moments data
    #     whenever possible
    #   - For the integrated moments, do not mix them with FPI moments
    
    # 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'])
    
    # Spacecraft potential correction
    edp_mode = mode if mode == 'brst' else 'fast'
    scpot = edp.load_scpot(sc, edp_mode, start_date, end_date)
    scpot_dis = scpot.interp_like(dis_moms, method='nearest')
    scpot_des = scpot.interp_like(des_moms, method='nearest')
    
    # Maxwellian entropy density
    #   - Calculated from FPI moments to stick with philosophy
#    si_dist = fpi.entropy(dis_dist, scpot=scpot_dis)
#    se_dist = fpi.entropy(des_dist, scpot=scpot_des)
    
    si_max = fpi.maxwellian_entropy(dis_moms['density'], dis_moms['p'])
    se_max = fpi.maxwellian_entropy(des_moms['density'], des_moms['p'])
    
    # Velocity space entropy density
    siv_dist = fpi.vspace_entropy(dis_dist,
#                                  N=dis_moms['density'],
#                                  s=si_dist,
                                  scpot=scpot_dis)
    sev_dist = fpi.vspace_entropy(des_dist,
#                                  N=des_moms['density'],
#                                  s=se_dist,
                                  scpot=scpot_des)
    
    siv_max = fpi.vspace_entropy(dis_max_dist,
                                 N=dis_moms['density'],
                                 s=si_max,
                                 scpot=scpot_dis)
    sev_max = fpi.vspace_entropy(des_max_dist,
                                 N=des_moms['density'],
                                 s=se_max,
                                 scpot=scpot_des)
    
    # M-bar
    miv_bar = np.abs(siv_max - siv_dist) / siv_max
    mev_bar = np.abs(sev_max - sev_dist) / sev_max
    
    # Anisotropy
    Ai = dis_moms['temppara'] / dis_moms['tempperp'] - 1
    Ae = des_moms['temppara'] / des_moms['tempperp'] - 1
    
    nrows = 8
    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)'
                   )
    
    # N
    ax = axes[1,0]
    ax = util.plot([dis_moms['density'], des_moms['density']],
                   ax=ax, labels=['Ni', 'Ne'],
                   xaxis='off', ylabel='N\n($cm^{-3}$)'
                   )
    
    # Velocity space ion entropy density
    ax = axes[2,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[3,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 M-bar
    ax = axes[4,0]
    ax = util.plot([miv_bar, mev_bar],
                   ax=ax, labels=['$\overline{M}_{i,V}$', '$\overline{M}_{e,V}$'],
                   xaxis='off', ylabel='$\overline{M}_{V}$'
                   )
    
    # Ion temperature
    ax = axes[5,0]
    ax = util.plot([dis_moms['temppara'], dis_moms['tempperp'], dis_moms['t']],
                   ax=ax, labels=['$T_{\parallel}$', '$T_{\perp}$, $T$'],
                   xaxis='off', ylabel='$T_{i}$\n(eV)'
                   )
    
    # Electron temperature
    ax = axes[6,0]
    ax = util.plot([des_moms['temppara'], des_moms['tempperp'], des_moms['t']],
                   ax=ax, labels=['$T_{\parallel}$', '$T_{\perp}$, $T$'],
                   xaxis='off', ylabel='$T_{e}$\n(eV)'
                   )
    
    # Anisotropy
    ax = axes[7,0]
    ax = util.plot([Ai, Ae],
                   ax=ax, labels=['$A_{i}$', '$A_{e}$'],
                   ylabel='A'
                   )
    
    fig.suptitle('Plasma Parameters for Kinetic and Boltzmann Entropy')
    plt.subplots_adjust(left=0.2, right=0.85, top=0.95, hspace=0.4)
#    plt.setp(axes, xlim=xlim)
    return fig, axes
Ejemplo n.º 3
0
def vspace_entropy(sc, mode, start_date, end_date):
    
    # Read the data
    b = fgm.load_data(sc, mode, start_date, end_date)
    dis_moms = fpi.load_moms(sc, mode, optdesc='dis-moms',
                             start_date=start_date, end_date=end_date)
    des_moms = fpi.load_moms(sc, mode, optdesc='des-moms',
                             start_date=start_date, end_date=end_date)
    dis_dist = fpi.load_dist(sc, mode, optdesc='dis-dist',
                             start_date=start_date, end_date=end_date)
    des_dist = fpi.load_dist(sc, 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
    #  - Use calculated moments for the Maxwellian distribution
    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)
    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)
    
    # Analytically derived Maxwellian entropy density
    # si_max = fpi.maxwellian_entropy(Ni, pi)
    # se_max = fpi.maxwellian_entropy(Ne, pe)
    si_max = fpi.entropy(fi_max)
    se_max = fpi.entropy(fe_max)
    
    # Velocity space entropy density
    siv_dist = fpi.vspace_entropy(f_dis)
    sev_dist = fpi.vspace_entropy(f_des)
    
    # 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
    miv_bar = (siv_max - siv_dist) / siv_max
    mev_bar = (sev_max - sev_dist) / sev_max
    
    # Anisotropy
    Ai = dis_moms['temppara'] / dis_moms['tempperp'] - 1
    Ae = des_moms['temppara'] / des_moms['tempperp'] - 1
    
    nrows = 8
    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)'
                   )
    
    # N
    ax = axes[1,0]
    ax = util.plot([dis_moms['density'], des_moms['density']],
                   ax=ax, labels=['Ni', 'Ne'],
                   xaxis='off', ylabel='N\n($cm^{-3}$)'
                   )
    
    # Velocity space ion entropy density
    ax = axes[2,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}$'
                   )
    
    # Velocity space electron entropy density
    ax = axes[3,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 M-bar
    ax = axes[4,0]
    ax = util.plot([miv_bar, mev_bar],
                   ax=ax, labels=['$\overline{M}_{i,V}$', '$\overline{M}_{e,V}$'],
                   xaxis='off', ylabel='$\overline{M}_{V}$'
                   )
    
    # Ion temperature
    ax = axes[5,0]
    ax = util.plot([dis_moms['temppara'], dis_moms['tempperp'], dis_moms['t']],
                   ax=ax, labels=['$T_{\parallel}$', '$T_{\perp}$', 'T'],
                   xaxis='off', ylabel='$T_{i}$\n(eV)'
                   )
    
    # Electron temperature
    ax = axes[6,0]
    ax = util.plot([des_moms['temppara'], des_moms['tempperp'], des_moms['t']],
                   ax=ax, labels=['$T_{\parallel}$', '$T_{\perp}$', 'T'],
                   xaxis='off', ylabel='$T_{e}$\n(eV)'
                   )
    
    # Anisotropy
    ax = axes[7,0]
    ax = util.plot([Ai, Ae],
                   ax=ax, labels=['$A_{i}$', '$A_{e}$'],
                   ylabel='A'
                   )
    
    fig.suptitle('Velocity Space Entropy')
    plt.subplots_adjust(left=0.2, right=0.85, top=0.95, hspace=0.4)
    return fig, axes
Ejemplo n.º 4
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
Ejemplo n.º 5
0
def overview(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)
    e = edp.load_data(sc=sc, mode=mode,
                      start_date=start_date, end_date=end_date)
    dis_moms = fpi.load_moms(sc=sc, mode=mode, optdesc='dis-moms',
                             start_date=start_date, end_date=end_date)
    des_moms = fpi.load_moms(sc=sc, mode=mode, optdesc='des-moms',
                             start_date=start_date, end_date=end_date)
    
    nrows = 7
    ncols = 1
    figsize = (6.0, 7.0)
    fig, axes = plt.subplots(nrows=nrows, ncols=ncols,
                             figsize=figsize, squeeze=False)
    locator = mdates.AutoDateLocator()
    formatter = mdates.ConciseDateFormatter(locator)
    
    # B
    ax = axes[0,0]
    b['B_GSE'][:,3].plot(ax=ax, label='|B|')
    b['B_GSE'][:,0].plot(ax=ax, label='Bx')
    b['B_GSE'][:,1].plot(ax=ax, label='By')
    b['B_GSE'][:,2].plot(ax=ax, label='Bz')
    ax.set_xlabel('')
    ax.set_xticklabels([])
    ax.set_ylabel('B [nT]')
    ax.set_title('')
    
    # 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 legend text the same color as the lines
    for line, text in zip(ax.get_lines(), leg.get_texts()):
        text.set_color(line.get_color())
    
    # Ion energy spectrogram
    nt = dis_moms['omnispectr'].shape[0]
    nE = dis_moms['omnispectr'].shape[1]
    x0 = mdates.date2num(dis_moms['time'])[:, np.newaxis].repeat(nE, axis=1)
    x1 = dis_moms['energy']

    y = np.where(dis_moms['omnispectr'] == 0, 1, dis_moms['omnispectr'])
    y = np.log(y[0:-1,0:-1])

    ax = axes[1,0]
    im = ax.pcolorfast(x0, x1, y, cmap='nipy_spectral')
    ax.images.append(im)
    ax.xaxis.set_major_locator(locator)
    ax.xaxis.set_major_formatter(formatter)
    ax.set_xticklabels([])
    ax.set_xlabel('')
    ax.set_yscale('log')
    ax.set_ylabel('E ion\n(eV)')

    cbaxes = inset_axes(ax,
                        width='2%', height='100%', loc=4,
                        bbox_to_anchor=(0, 0, 1.05, 1),
                        bbox_transform=ax.transAxes,
                        borderpad=0)
    cb = plt.colorbar(im, cax=cbaxes, orientation='vertical')
    cb.set_label('$log_{10}$DEF\nkeV/($cm^{2}$ s sr keV)')

    # Electron energy spectrogram
    nt = des_moms['omnispectr'].shape[0]
    nE = des_moms['omnispectr'].shape[1]
    x0 = mdates.date2num(des_moms['time'])[:, np.newaxis].repeat(nE, axis=1)
    x1 = des_moms['energy']

    y = np.where(des_moms['omnispectr'] == 0, 1, des_moms['omnispectr'])
    y = np.log(y[0:-1,0:-1])

    ax = axes[2,0]
    im = ax.pcolorfast(x0, x1, y, cmap='nipy_spectral')
    ax.images.append(im)
    ax.xaxis.set_major_locator(locator)
    ax.xaxis.set_major_formatter(formatter)
    ax.set_xticklabels([])
    ax.set_xlabel('')
    ax.set_yscale('log')
    ax.set_ylabel('E e-\n(eV)')

    cbaxes = inset_axes(ax,
                        width='2%', height='100%', loc=4,
                        bbox_to_anchor=(0, 0, 1.05, 1),
                        bbox_transform=ax.transAxes,
                        borderpad=0)
    cb = plt.colorbar(im, cax=cbaxes, orientation='vertical')
    cb.set_label('$log_{10}$DEF')
    
    
    # N
    ax = axes[3,0]
    dis_moms['density'].plot(ax=ax, label='Ni')
    des_moms['density'].plot(ax=ax, label='Ne')
    ax.set_xlabel('')
    ax.set_xticklabels([])
    ax.set_ylabel('N\n($cm^{-3}$)')
    ax.set_title('')
    
    leg = ax.legend(bbox_to_anchor=(1.05, 1),
                    borderaxespad=0.0,
                    frameon=False,
                    handlelength=0,
                    handletextpad=0,
                    loc='upper left')
    
    for line, text in zip(ax.get_lines(), leg.get_texts()):
        text.set_color(line.get_color())
    
    # Vi
    ax = axes[4,0]
    dis_moms['velocity'][:,0].plot(ax=ax, label='Vx')
    dis_moms['velocity'][:,1].plot(ax=ax, label='Vy')
    dis_moms['velocity'][:,2].plot(ax=ax, label='Vz')
    ax.set_xlabel('')
    ax.set_xticklabels([])
    ax.set_ylabel('Vi\n(km/s)')
    ax.set_title('')
    
    leg = ax.legend(bbox_to_anchor=(1.05, 1),
                    borderaxespad=0.0,
                    frameon=False,
                    handlelength=0,
                    handletextpad=0,
                    loc='upper left')
    
    for line, text in zip(ax.get_lines(), leg.get_texts()):
        text.set_color(line.get_color())
    
    # Ve
    ax = axes[5,0]
    des_moms['velocity'][:,0].plot(ax=ax, label='Vx')
    des_moms['velocity'][:,1].plot(ax=ax, label='Vy')
    des_moms['velocity'][:,2].plot(ax=ax, label='Vz')
    ax.set_xlabel('')
    ax.set_xticklabels([])
    ax.set_ylabel('Ve\n(km/s)')
    ax.set_title('')
    
    leg = ax.legend(bbox_to_anchor=(1.05, 1),
                    borderaxespad=0.0,
                    frameon=False,
                    handlelength=0,
                    handletextpad=0,
                    loc='upper left')
    
    for line, text in zip(ax.get_lines(), leg.get_texts()):
        text.set_color(line.get_color())
    
    # E
    ax = axes[6,0]
    e['E_GSE'][:,0].plot(ax=ax, label='Ex')
    e['E_GSE'][:,1].plot(ax=ax, label='Ey')
    e['E_GSE'][:,2].plot(ax=ax, label='Ez')
    ax.set_xlabel('')
    ax.set_xticklabels([])
    ax.set_ylabel('E\n(mV/m)')
    ax.set_title('')
    
    ax.xaxis.set_major_locator(locator)
    ax.xaxis.set_major_formatter(formatter)
    for tick in ax.get_xticklabels():
        tick.set_rotation(45)
    
    leg = ax.legend(bbox_to_anchor=(1.05, 1),
                    borderaxespad=0.0,
                    frameon=False,
                    handlelength=0,
                    handletextpad=0,
                    loc='upper left')
    
    for line, text in zip(ax.get_lines(), leg.get_texts()):
        text.set_color(line.get_color())
    
    fig.suptitle(sc.upper())
    plt.subplots_adjust(left=0.2, right=0.8, top=0.95, hspace=0.2)
    return fig, axes
Ejemplo n.º 6
0
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
Ejemplo n.º 7
0
def plot_photocurrent():

    # Download the data
    scpot = edp.load_scpot(sc=sc,
                           mode=mode,
                           start_date=orbit_t0,
                           end_date=orbit_t1)
    dis_moms = fpi.load_moms(sc=sc,
                             mode=mode,
                             optdesc='dis-moms',
                             start_date=orbit_t0,
                             end_date=orbit_t1)
    des_moms = fpi.load_moms(sc=sc,
                             mode=mode,
                             optdesc='des-moms',
                             start_date=orbit_t0,
                             end_date=orbit_t1)
    aspoc = mms_util.load_data(sc=sc,
                               instr='aspoc',
                               mode='srvy',
                               level='l2',
                               start_date=orbit_t0,
                               end_date=orbit_t1)

    # Bin data into FPI time stamps
    t_bins = np.append(
        dis_moms['time'].data - dis_moms['Epoch_minus_var'].data,
        dis_moms['time'].data[-1] + dis_moms['Epoch_plus_var'].data)
    Vsc, edges, binnum = binned_statistic(scpot['time'].astype('i8'),
                                          scpot['Vsc'],
                                          statistic='mean',
                                          bins=t_bins.astype('i8'))

    asp1, edges, binnum = binned_statistic(aspoc['Epoch'].astype('i8'),
                                           aspoc[sc + '_asp1_ionc'],
                                           statistic='mean',
                                           bins=t_bins.astype('i8'))

    idx = 0
    data_bin = []
    asp2 = np.empty_like(asp1)
    asp_on = np.zeros(asp1.shape, dtype='?')
    ref_idx = binnum[0]

    for aspoc_idx, bin_idx in enumerate(binnum):
        if (bin_idx == 0) | (bin_idx == len(aspoc[sc + '_asp1_ionc'])):
            continue
        elif ref_idx == 0:
            ref_idx = bin_idx

        if bin_idx == ref_idx:
            data_bin.append(aspoc_idx)
        else:
            asp2[idx] = aspoc[sc + '_asp2_ionc'][data_bin].mean()
            asp_on[idx] = aspoc[sc + '_aspoc_status'][data_bin, 3].max() > 0
            idx += 1
            ref_idx = bin_idx
            data_bin = [aspoc_idx]

    Vsc = xr.DataArray(Vsc, dims='time', coords={'time': dis_moms['time']})
    asp = xr.Dataset(
        {
            'asp1': (['time'], asp1),
            'asp2': (['time'], asp2),
            'asp': (['time'], asp1 + asp2)
        },
        coords={'time': dis_moms['time']})

    # Electron current
    Ie = electron_current(des_moms['density'], des_moms['t'], Vsc)

    # Flag the data
    flag = xr.DataArray(asp_on.astype('int'),
                        dims='time',
                        coords={'time': dis_moms['time']})
    flag += (((Ie < 1e-11) & (Vsc > 8) & (Vsc < 11)) * 2**1)
    flag += (((Vsc > 14.75) & (Ie > 7.9e-12) & (Ie < 2e-11)) * 2**2)
    flag += (((Vsc > 12.6) & (Vsc <= 14.75) & (Ie > 9.2e-12) & (Ie < 2e-11)) *
             2**2)

    #
    # Fit the data
    #

    # Ie = Iph0 exp(-Vsc/Vph0)
    # y = a exp(b * x)
    # log(y) = log(a) + b*x
    b, a = np.polyfit(Vsc[flag == 0],
                      np.log(Ie[flag == 0]),
                      1,
                      w=np.sqrt(Ie[flag == 0]))
    Ie_fit = np.exp(a) * np.exp(b * Vsc[flag == 0])
    str_fit = ('Ie = {0:0.3e} exp(-Vsc/{1:0.3e})'.format(
        np.exp(a), 1 / np.exp(b)))

    # Fit density to the spacecraft potential
    c, b, a = np.polyfit(Vsc[flag == 0], des_moms['density'][flag == 0], 2)
    Ne_fit2 = c * Vsc[flag == 0]**2 + b * Vsc[flag == 0] + a
    str_Ne_fit2 = ('Ne = {0:0.3e}Vsc^2 + {1:0.3e}Vsc^1 + {2:0.3e})'.format(
        c, b, a))

    e, d, c, b, a = np.polyfit(Vsc[flag == 0], des_moms['density'][flag == 0],
                               4)
    Ne_fit4 = e * Vsc[flag == 0]**4 + d * Vsc[flag == 0]**3 + c * Vsc[
        flag == 0]**2 + b * Vsc[flag == 0] + a
    str_Ne_fit4 = (
        'Ne = {0:0.3e}Vsc^4 + {1:0.3e}Vsc^3 + {2:0.3e}Vsc^2 + {3:0.3e}Vsc + {4:0.3e})'
        .format(e, d, c, b, a))

    # Fit density to the inverse of the spacecraft potential
    c, b, a = np.polyfit(1 / Vsc[flag == 0], des_moms['density'][flag == 0], 2)
    invV_fit2 = c / Vsc[flag == 0]**2 + b / Vsc[flag == 0] + a
    str_invV_fit2 = ('Ne = {0:0.3e}/Vsc^2 + {1:0.3e}/Vsc + {2:0.3e})'.format(
        c, b, a))

    e, d, c, b, a = np.polyfit(1 / Vsc[flag == 0],
                               des_moms['density'][flag == 0], 4)
    invV_fit4 = e / Vsc[flag == 0]**4 + d / Vsc[flag == 0]**3 + c / Vsc[
        flag == 0]**2 + b / Vsc[flag == 0] + a
    str_invV_fit4 = (
        'Ne = {0:0.3e}/Vsc^4 + {1:0.3e}/Vsc^3 + {2:0.3e}/Vsc^2 + {3:0.3e}/Vsc + {4:0.3e})'
        .format(e, d, c, b, a))

    #
    # Plot: Time Series
    #

    # Plot current-related data
    fig1, axes1 = plt.subplots(nrows=8,
                               ncols=1,
                               sharex=True,
                               figsize=(5, 6.5),
                               squeeze=False)
    plt.subplots_adjust(left=0.17, right=0.85, bottom=0.14, top=0.95)

    # Ion energy spectrogram
    nt = dis_moms['omnispectr'].shape[0]
    nE = dis_moms['omnispectr'].shape[1]
    x0 = mdates.date2num(dis_moms['time'])[:, np.newaxis].repeat(nE, axis=1)
    x1 = dis_moms['energy']

    y = np.where(dis_moms['omnispectr'] == 0, 1, dis_moms['omnispectr'])
    y = np.log(y[0:-1, 0:-1])

    ax = axes1[0, 0]
    im = ax.pcolorfast(x0, x1, y, cmap='nipy_spectral')
    ax.images.append(im)
    ax.set_title(sc.upper())
    ax.set_yscale('log')
    ax.set_ylabel('E (ion)\n(eV)')
    util.format_axes(ax, xaxis='off')
    cb = util.add_colorbar(ax, im)
    cb.set_label('$log_{10}$DEF\nkeV/($cm^{2}$ s sr keV)')

    # Electron energy spectrogram
    nt = des_moms['omnispectr'].shape[0]
    nE = des_moms['omnispectr'].shape[1]
    x0 = mdates.date2num(des_moms['time'])[:, np.newaxis].repeat(nE, axis=1)
    x1 = des_moms['energy']

    y = np.where(des_moms['omnispectr'] == 0, 1, des_moms['omnispectr'])
    y = np.log(y[0:-1, 0:-1])

    ax = axes1[1, 0]
    im = ax.pcolorfast(x0, x1, y, cmap='nipy_spectral')
    ax.images.append(im)
    ax.set_yscale('log')
    ax.set_ylabel('E (e-)\n(eV)')
    util.format_axes(ax, xaxis='off')
    cb = util.add_colorbar(ax, im)
    cb.set_label('$log_{10}$DEF\nkeV/($cm^{2}$ s sr keV)')

    # Density
    ax = axes1[2, 0]
    l1 = dis_moms['density'].plot(ax=ax, label='$N_{i}$')
    l2 = des_moms['density'].plot(ax=ax, label='$N_{e}$')
    ax.set_title('')
    ax.set_ylabel('N\n($cm^{3}$)')
    ax.set_yscale('log')
    util.format_axes(ax, xaxis='off')
    util.add_legend(ax, [l1[0], l2[0]])

    # Temperature
    ax = axes1[3, 0]
    l1 = dis_moms['t'].plot(ax=ax, label='$T_{i}$')
    l2 = des_moms['t'].plot(ax=ax, label='$T_{e}$')
    util.format_axes(ax, xaxis='off')
    util.add_legend(ax, [l1[0], l2[0]])
    ax.set_title('')
    ax.set_ylabel('T\n(eV)')
    ax.set_yscale('log')

    # Spacecraft potential
    ax = axes1[4, 0]
    Vsc[~asp_on].plot(ax=ax)
    Vsc[asp_on].plot(ax=ax, color='red')
    util.format_axes(ax, xaxis='off')
    ax.set_title('')
    ax.set_ylabel('$V_{S/C}$\n(V)')

    # Electron current
    ax = axes1[5, 0]
    Ie.plot(ax=ax)
    ax.set_title('')
    ax.set_ylabel('$I_{e}$\n($\mu A$)')
    ax.set_yscale('log')
    ax.set_ylim([1e-12, 1e-10])
    util.format_axes(ax, xaxis='off')

    # Aspoc Status
    ax = axes1[6, 0]
    l1 = asp['asp1'].plot(ax=ax, label='$ASP_{1}$')
    l2 = asp['asp2'].plot(ax=ax, label='$ASP_{2}$')
    l3 = asp['asp'].plot(ax=ax, label='$ASP_{tot}$')
    util.format_axes(ax, xaxis='off')
    util.add_legend(ax, [l1[0], l2[0], l3[0]])
    ax.set_title('')
    ax.set_xlabel('')
    ax.set_ylabel('$I_{ASPOC}$\n($\mu A$)')

    # Flag
    ax = axes1[7, 0]
    flag.plot(ax=ax)
    util.format_axes(ax)
    ax.set_title('')
    ax.set_xlabel('')
    ax.set_ylabel('Flag')

    #
    # Plot: Photocurrent Fit
    #

    # Plot the data
    fig2, axes = plt.subplots(nrows=3,
                              ncols=1,
                              figsize=[5, 5.5],
                              squeeze=False)
    plt.subplots_adjust(left=0.15, right=0.95, top=0.94)

    # I_ph = I_ph0 exp(Vsc/Vph0)
    ax = axes[0, 0]
    ax.scatter(Vsc[flag == 0], Ie[flag == 0], marker='o')
    ax.scatter(Vsc[np.bitwise_and(flag, 2**0) > 0],
               Ie[np.bitwise_and(flag, 2**0) > 0],
               marker='o',
               color='red')
    ax.scatter(Vsc[np.bitwise_and(flag, 2**1) > 0],
               Ie[np.bitwise_and(flag, 2**1) > 0],
               marker='o',
               color='purple')
    ax.scatter(Vsc[np.bitwise_and(flag, 2**2) > 0],
               Ie[np.bitwise_and(flag, 2**2) > 0],
               marker='o',
               color='green')
    ax.plot(Vsc[flag == 0], Ie_fit, color='black')
    ax.set_title(
        'Photocurrent Parameters $I_{e} = -I_{ph0} \exp(V_{S/C}/V_{ph0})$')
    ax.set_xlabel('$V_{S/C}$ (V)')
    ax.set_ylabel('$I_{e}$\n($\mu A$)')
    ax.set_yscale('log')
    ax.set_ylim([
        10**np.floor(np.log10(Ie.min().values)),
        10**np.ceil(np.log10(Ie.max().values))
    ])
    ax.text(0.9 * ax.get_xlim()[1],
            0.7 * ax.get_ylim()[1],
            str_fit,
            horizontalalignment='right',
            verticalalignment='bottom',
            color='black')

    # Ne = \Sum a_i * V^i
    ax = axes[1, 0]
    ax.scatter(Vsc[flag == 0], des_moms['density'][flag == 0], marker='o')
    ax.scatter(Vsc[np.bitwise_and(flag, 2**0) > 0],
               des_moms['density'][np.bitwise_and(flag, 2**0) > 0],
               marker='o',
               color='red')
    ax.scatter(Vsc[np.bitwise_and(flag, 2**1) > 0],
               des_moms['density'][np.bitwise_and(flag, 2**1) > 0],
               marker='o',
               color='purple')
    ax.scatter(Vsc[np.bitwise_and(flag, 2**2) > 0],
               des_moms['density'][np.bitwise_and(flag, 2**2) > 0],
               marker='o',
               color='green')
    ax.plot(Vsc[flag == 0], Ne_fit2, color='black')
    ax.plot(Vsc[flag == 0], Ne_fit4, color='grey')
    ax.set_title('')
    ax.set_xlabel('$V_{S/C}$ (V)')
    ax.set_ylabel('$N_{e}$\n($cm^{-3}$)')
    ax.text(0.98 * ax.get_xlim()[1],
            0.85 * ax.get_ylim()[1],
            str_Ne_fit2,
            horizontalalignment='right',
            verticalalignment='bottom',
            color='black')
    ax.text(0.98 * ax.get_xlim()[1],
            0.75 * ax.get_ylim()[1],
            str_Ne_fit4,
            horizontalalignment='right',
            verticalalignment='bottom',
            color='grey')

    # Ne = \Sum a_i * V^-i
    ax = axes[2, 0]
    ax.scatter(1 / Vsc[flag == 0], des_moms['density'][flag == 0], marker='o')
    ax.scatter(1 / Vsc[np.bitwise_and(flag, 2**0) > 0],
               des_moms['density'][np.bitwise_and(flag, 2**0) > 0],
               marker='o',
               color='red')
    ax.scatter(1 / Vsc[np.bitwise_and(flag, 2**1) > 0],
               des_moms['density'][np.bitwise_and(flag, 2**1) > 0],
               marker='o',
               color='purple')
    ax.scatter(1 / Vsc[np.bitwise_and(flag, 2**2) > 0],
               des_moms['density'][np.bitwise_and(flag, 2**2) > 0],
               marker='o',
               color='green')
    ax.plot(Vsc[flag == 0], invV_fit2, color='black')
    ax.plot(Vsc[flag == 0], invV_fit4, color='grey')
    ax.set_title('')
    ax.set_xlabel('1/$V_{S/C}$ ($V^{-1}$)')
    ax.set_ylabel('$N_{e}$\n($cm^{-3}$)')
    ax.text(0.98 * ax.get_xlim()[1],
            0.85 * ax.get_ylim()[1],
            str_invV_fit2,
            horizontalalignment='right',
            verticalalignment='bottom',
            color='black')
    ax.text(0.98 * ax.get_xlim()[1],
            0.75 * ax.get_ylim()[1],
            str_invV_fit4,
            horizontalalignment='right',
            verticalalignment='bottom',
            color='grey')

    return [fig1, fig2], ax