Source code for spacepy.LANLstar

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Lstar and Lmax calculation using artificial neural network (ANN) technique.

This module requires the `ffnet <http://ffnet.sourceforge.net/>`_ package.

Authors: Josef Koller, Yiqun Yu
Institution: Los Alamos National Laboratory
Contact: jkoller@lanl.gov, yiqun@lanl.gov

Copyright 2012 Los Alamos National Security, LLC.

.. autosummary::
    :toctree: autosummary

    LANLstar
    LANLmax
"""
import os.path
import sys
import warnings

try:
    import ffnet
except ImportError:
    if 'sphinx' in sys.argv[0]:
        warnings.warn('LANLstar requires ffnet. '
                      'You appear to be building docs, so ignoring this error.')
    else:
        raise RuntimeError(
            'LANLstar requires ffnet (http://ffnet.sourceforge.net/)')
import numpy as np
from . import toolbox


def _get_net_path(filename):
    """Gets the full path for a network file given the filename"""
    fspec = os.path.join(
        os.path.split(__file__)[0], 'data', 'LANLstar', filename)
    if os.path.exists(fspec) or os.path.exists(fspec + '.gz'):
        return fspec
    else:
        raise RuntimeError("Could not find neural network file " + filename)

# ------------------------------------------------
def _LANLcommon(indict, extMag, domax):
    """
    Shared code between LANLstar and LANLmax

    domax is True for LANLmax, False for LANLstar
    """
    lstar_keylists = {
        'OPDYN': ['Year', 'DOY', 'Hr', 'Dst', 'dens', 'velo', 'BzIMF',
                  'Lm', 'Bmirr', 'PA', 'rGSM', 'latGSM', 'lonGSM'],
        'OPQUIET': ['Year', 'DOY', 'Hr', 'Dst', 'dens', 'velo','BzIMF',
                    'Lm', 'Bmirr', 'PA', 'rGSM', 'latGSM', 'lonGSM'],
        'T01QUIET': ['Year', 'DOY', 'Hr', 'Dst', 'Pdyn', 'ByIMF', 'BzIMF',
                     'G1', 'G2','Lm', 'Bmirr', 'PA', 'rGSM',
                     'latGSM', 'lonGSM'],
        'T01STORM': ['Year', 'DOY', 'Hr', 'Dst', 'Pdyn', 'ByIMF', 'BzIMF',
                     'G2', 'G3', 'Lm', 'Bmirr', 'PA', 'rGSM',
                     'latGSM', 'lonGSM'],
        'T05': ['Year', 'DOY', 'Hr', 'Dst', 'Pdyn', 'ByIMF','BzIMF',
                'W1','W2','W3','W4','W5','W6',
                'Lm', 'Bmirr', 'PA', 'rGSM', 'latGSM', 'lonGSM'],
        'T89': ['Year', 'DOY', 'Hr', 'Kp', 'Pdyn', 'ByIMF','BzIMF',
                'Lm', 'Bmirr', 'PA', 'rGSM', 'latGSM', 'lonGSM'],
        'T96': ['Year', 'DOY', 'Hr', 'Dst', 'Pdyn', 'ByIMF','BzIMF',
                'Lm', 'Bmirr', 'PA', 'rGSM', 'latGSM', 'lonGSM'],
        'RAMSCB':['Year','DOY','Hr', 'Dst', 'Pdyn', 'ByIMF', 'BzIMF',
                  'PA','SMx', 'SMy', 'SMz'],
         }
    lmax_keylists = {
        'OPDYN': ['Year', 'DOY', 'Hr', 'Dst', 'dens', 'velo', 'BzIMF', 'PA'],
        'OPQUIET': ['Year', 'DOY', 'Hr', 'Dst', 'dens', 'velo', 'BzIMF','PA'],
        'T01QUIET': ['Year', 'DOY', 'Hr', 'Dst', 'Pdyn', 'ByIMF', 'BzIMF',
                     'G1','G2','PA'],
        'T01STORM': ['Year', 'DOY', 'Hr', 'Dst', 'Pdyn', 'ByIMF', 'BzIMF',
                     'G2','G3','PA'],
        'T05': ['Year', 'DOY', 'Hr', 'Dst', 'Pdyn', 'ByIMF', 'BzIMF', 
                'W1','W2','W3','W4','W5','W6','PA'],
        'T89': ['Year', 'DOY', 'Hr', 'Kp', 'Pdyn', 'ByIMF', 'BzIMF', 'PA'],
        'T96': ['Year', 'DOY', 'Hr', 'Dst', 'Pdyn', 'ByIMF', 'BzIMF', 'PA'],
                 }
    lstar_nets = { 'OPDYN'   : 'LANLstar_OPDyn.net',
                   'OPQUIET' : 'LANLstar_OPQuiet.net',
                   'T01QUIET': 'LANLstar_T01QUIET.net',
                   'T01STORM': 'LANLstar_T01STORM.net',
                   'RAMSCB': 'LANLstar_RAMSCB.net',
                   'T05': 'LANLstar_T05.net',
                   'T89': 'LANLstar_T89.net',
                   'T96': 'LANLstar_T96.net',
                    }
    lmax_nets = {  'OPDYN'   : 'Lmax_OPDyn.net',
                   'OPQUIET' : 'Lmax_OPQuiet.net',
                   'T01QUIET': 'Lmax_T01QUIET.net',
                   'T01STORM': 'Lmax_T01STORM.net',
                   'T05': 'Lmax_T05.net',
                   'T89': 'Lmax_T89.net',
                   'T96': 'Lmax_T96.net',
                    }
    inputdict = indict.copy()
    npt = len(inputdict['Year'])
    Lstar_out = {} 
    if 'G' in inputdict:
        for n in range(1,4):
            dum = inputdict['G'][...,n-1]
            if dum.ndim == 0: dum = np.array([dum])
            inputdict['G{0}'.format(n)] = dum
        del inputdict['G']
    if 'W' in inputdict:
        for n in range(1,7):
            dum = inputdict['W'][...,n-1]
            if dum.ndim == 0: dum = np.array([dum])
            inputdict['W{0}'.format(n)] = dum
        del inputdict['W']
    if isinstance(extMag, str): extMag = [extMag]

    for modelkey in extMag:
        if domax:
            keylist = lmax_keylists[modelkey]
        else:
            keylist = lstar_keylists[modelkey]
        #T89 checks Kp, everything else Dst
        specialkey = 'Dst' if 'Dst' in keylist else 'Kp'
        if isinstance(inputdict[specialkey], float):
            arrayflag = False
            for key in list(inputdict.keys()):
                inputdict[key] = [inputdict[key]]
        else:
            arrayflag = True
            ncalc = len(inputdict['Dst'])
	
        ncalc = len(inputdict[specialkey])
        Lstar = np.zeros(ncalc)
        inpar = np.zeros(len(keylist))

        if domax:
            netfile = lmax_nets[modelkey]
        else:
            netfile = lstar_nets[modelkey]
        network = toolbox.loadpickle(_get_net_path(netfile))
        for i in range(ncalc):	
            # copy over keylist into inpar
            for ikey, key in enumerate(keylist):
                inpar[ikey] = inputdict[key][i]
            Lstar[i] = network(inpar)
            
        if arrayflag is False:
            Lstar_out[modelkey] = Lstar[0]
        else:
            Lstar_out[modelkey] = Lstar

    return Lstar_out

# ------------------------------------------------
[docs]def LANLstar(inputdict, extMag): """ Calculate Lstar Based on the L* artificial neural network (ANN) trained from different magnetospheric field models. Parameters ========== extMag : list of string(s) containing one or more of the following external magnetic field models: 'OPDYN', 'OPQUIET', 'T89', 'T96', 'T01QUIET', 'T01STORM', 'T05' inputdict : dictionary containing the following keys, each entry is a list or array. Note the keys for the above models are different. -- For OPDYN: ['Year', 'DOY', 'Hr', 'Dst', 'dens', 'velo', 'BzIMF', 'Lm', 'Bmirr', 'PA', 'rGSM', 'latGSM', 'lonGSM'] -- For OPQUIET: ['Year', 'DOY', 'Hr', 'Dst', 'dens', 'velo', 'BzIMF', 'Lm', 'Bmirr', 'PA', 'rGSM', 'latGSM', 'lonGSM'] -- For T89: ['Year', 'DOY', 'Hr', 'Kp', 'Pdyn', 'ByIMF', 'BzIMF', 'Lm', 'Bmirr', 'PA', 'rGSM', 'latGSM', 'lonGSM'] -- For T96: ['Year', 'DOY', 'Hr', 'Dst', 'Pdyn', 'ByIMF', 'BzIMF', 'Lm', 'Bmirr', 'PA', 'rGSM', 'latGSM', 'lonGSM'] -- For T01QUIET: ['Year', 'DOY', 'Hr', 'Dst', 'Pdyn', 'ByIMF', 'BzIMF', 'G1', 'G2', 'Lm', 'Bmirr', 'PA', 'rGSM', 'latGSM', 'lonGSM'] -- For T01STORM: ['Year', 'DOY', 'Hr', 'Dst', 'Pdyn', 'ByIMF', 'BzIMF', 'G2', 'G3', 'Lm', 'Bmirr', 'PA', 'rGSM', 'latGSM', 'lonGSM'] -- For T05: ['Year', 'DOY', 'Hr', 'Dst', 'Pdyn', 'ByIMF', 'BzIMF', 'W1','W2','W3','W4','W5','W6', 'Lm', 'Bmirr', 'PA', 'rGSM', 'latGSM', 'lonGSM'] -- For RAMSCB: ['Year', 'DOY', 'Hr', 'Dst', 'Pdyn', 'ByIMF', 'BzIMF', 'PA', 'SMx','SMy','SMz'] Dictionaries with numpy vectors are allowed. Returns ======= out : dictionary Lstar array for each key which corresponds to the specified magnetic field model. Examples ======== >>> import spacepy.LANLstar as LS >>> >>> inputdict = {} >>> inputdict['Kp'] = [2.7 ] # Kp index >>> inputdict['Dst'] = [7.7777 ] # Dst index (nT) >>> inputdict['dens'] = [4.1011 ] # solar wind density (/cc) >>> inputdict['velo'] = [400.1011 ] # solar wind velocity (km/s) >>> inputdict['Pdyn'] = [4.1011 ] # solar wind dynamic pressure (nPa) >>> inputdict['ByIMF'] = [3.7244 ] # GSM y component of IMF magnetic field (nT) >>> inputdict['BzIMF'] = [-0.1266 ] # GSM z component of IMF magnetic field (nT) >>> inputdict['G1'] = [1.029666 ] # as defined in Tsganenko 2003 >>> inputdict['G2'] = [0.549334 ] >>> inputdict['G3'] = [0.813999 ] >>> inputdict['W1'] = [0.122444 ] # as defined in Tsyganenko and Sitnov 2005 >>> inputdict['W2'] = [0.2514 ] >>> inputdict['W3'] = [0.0892 ] >>> inputdict['W4'] = [0.0478 ] >>> inputdict['W5'] = [0.2258 ] >>> inputdict['W6'] = [1.0461 ] >>> >>> inputdict['Year'] = [1996 ] >>> inputdict['DOY'] = [6 ] >>> inputdict['Hr'] = [1.2444 ] >>> >>> inputdict['Lm'] = [4.9360 ] # McIllwain L >>> inputdict['Bmirr'] = [315.6202 ] # magnetic field strength at the mirror point >>> inputdict['rGSM'] = [4.8341 ] # radial coordinate in GSM [Re] >>> inputdict['lonGSM'] = [-40.2663 ] # longitude coodrinate in GSM [deg] >>> inputdict['latGSM'] = [36.44696 ] # latitude coordiante in GSM [deg] >>> inputdict['PA'] = [57.3874 ] # pitch angle [deg] >>> inputdict['SMx'] = [3.9783 ] >>> inputdict['SMy'] = [-2.51335 ] >>> inputdict['SMz'] = [1.106617 ] >>> >>> LS.LANLstar(inputdict, ['OPDYN','OPQUIET','T01QUIET','T01STORM','T89','T96','T05','RAMSCB']) {'OPDYN': array([4.7171]), 'OPQUIET': array([4.6673]), 'T01QUIET': array([4.8427]), 'T01STORM': array([4.8669]), 'T89': array([4.5187]), 'T96': array([4.6439]), 'TS05': array([4.7174]), 'RAMSCB','array([5.9609])} """ return _LANLcommon(inputdict, extMag, False)
[docs]def LANLmax(inputdict, extMag): """ Calculate last closed drift shell (Lmax) Based on the L* artificial neural network (ANN) trained from different magnetospheric field models. Parameters ========== extMag : list of string(s) containing one or more of the following external Magnetic field models: 'OPDYN', 'OPQUIET', 'T89', 'T96', 'T01QUIET', 'T01STORM', 'T05' inputdict : dictionary containing the following keys, each entry is a list or array. Note the keys for the above models are different. -- For OPDYN: ['Year', 'DOY', 'Hr', 'Dst', 'dens', 'velo', 'BzIMF', 'PA'] -- For OPQUIET: ['Year', 'DOY', 'Hr', 'Dst', 'dens', 'velo', 'BzIMF', 'PA'] -- For T89: ['Year', 'DOY', 'Hr', 'Kp', 'Pdyn', 'ByIMF', 'BzIMF', 'PA'] -- For T96: ['Year', 'DOY', 'Hr', 'Dst', 'Pdyn', 'ByIMF', 'BzIMF','PA'] -- For T01QUIET: ['Year', 'DOY', 'Hr', 'Dst', 'Pdyn', 'ByIMF', 'BzIMF', 'G1', 'G2','PA'] -- For T01STORM: ['Year', 'DOY', 'Hr', 'Dst', 'Pdyn', 'ByIMF', 'BzIMF', 'G2', 'G3', 'PA'] -- For T05: ['Year', 'DOY', 'Hr', 'Dst', 'Pdyn', 'ByIMF', 'BzIMF', 'W1','W2','W3','W4','W5','W6', 'PA'] Dictionaries with numpy vectors are allowed. Returns ======= out : dictionary Lmax array for each key which corresponds to the specified magnetic field model. Examples ======== >>> import spacepy.LANLstar as LS >>> >>> inputdict = {} >>> inputdict['Kp'] = [2.7 ] # Kp index >>> inputdict['Dst'] = [7.7777 ] # Dst index (nT) >>> inputdict['dens'] = [4.1011 ] # solar wind density (/cc) >>> inputdict['velo'] = [400.1011 ] # solar wind velocity (km/s) >>> inputdict['Pdyn'] = [4.1011 ] # solar wind dynamic pressure (nPa) >>> inputdict['ByIMF'] = [3.7244 ] # GSM y component of IMF magnetic field (nT) >>> inputdict['BzIMF'] = [-0.1266 ] # GSM z component of IMF magnetic field (nT) >>> inputdict['G1'] = [1.029666 ] # as defined in Tsganenko 2003 >>> inputdict['G2'] = [0.549334 ] >>> inputdict['G3'] = [0.813999 ] >>> inputdict['W1'] = [0.122444 ] # as defined in Tsyganenko and Sitnov 2005 >>> inputdict['W2'] = [0.2514 ] >>> inputdict['W3'] = [0.0892 ] >>> inputdict['W4'] = [0.0478 ] >>> inputdict['W5'] = [0.2258 ] >>> inputdict['W6'] = [1.0461 ] >>> >>> inputdict['Year'] = [1996 ] >>> inputdict['DOY'] = [6 ] >>> inputdict['Hr'] = [1.2444 ] >>> >>> inputdict['PA'] = [57.3874 ] # pitch angle [deg] >>> >>> LS.LANLmax(inputdict, ['OPDYN','OPQUIET','T01QUIET','T01STORM','T89','T96','T05']) {'OPDYN': array([10.6278]), 'OPQUIET': array([9.3352]), 'T01QUIET': array([10.0538]), 'T01STORM': array([9.9300]), 'T89': array([8.2888]), 'T96': array([9.2410]), 'T05': array([9.9295])} """ return _LANLcommon(inputdict, extMag, True)
def addPA(indict, PA): '''Function to add pitch angle to input dictionary from, e.g., omni module Parameters ========== indict : dictionary-like containing keys required for LANLstar and LANLmax PA : float pitch angle Returns ======= out : dictionary input dictionary with input pitch angle added as 'PA' key having the length of other inputs Examples ======== >>> import spacepy.LANLstar as LS >>> >>> inputdict = {} ''' ll = len(indict['Year']) indict['PA'] = [PA]*ll return indict