예제 #1
0
 def calc_B(self):
     try:
         ans = []
         for v1, v2, v3 in zip(self._Vpos, self['Epoch'], self['Kp']):
             date = Lgm_CTrans.dateToDateLong(v2)
             utc = Lgm_CTrans.dateToFPHours(v2)
             Lgm_Set_Coord_Transforms(
                 date, utc, self._mmi.c)  # dont need pointer as it is one
             B = Lgm_Vector.Lgm_Vector()
             self._mmi.Kp = v3
             retval = Lgm_B_T89c(pointer(v1), pointer(B),
                                 pointer(self._mmi))
             if retval != 1:
                 raise (RuntimeWarning('Odd return from Lgm_T89c'))
             ans.append(B)
         return ans
     except TypeError:
         date = Lgm_CTrans.dateToDateLong(self['Epoch'])
         utc = Lgm_CTrans.dateToFPHours(self['Epoch'])
         Lgm_Set_Coord_Transforms(
             date, utc, self._mmi.c)  # dont need pointer as it is one
         B = Lgm_Vector.Lgm_Vector()
         self._mmi.Kp = self['Kp']
         retval = Lgm_B_T89c(pointer(self._Vpos), pointer(B),
                             pointer(self._mmi))
         if retval != 1:
             raise (RuntimeWarning('Odd return from Lgm_T89c'))
         return B
예제 #2
0
    def calc_B(self):
        ans = []
#            for v1, v2, v3 in zip(self._Vpos, self['Epoch'], self['Kp']):
        date = Lgm_CTrans.dateToDateLong(self['Epoch'])
        utc = Lgm_CTrans.dateToFPHours(self['Epoch'])
        Lgm_Set_Coord_Transforms( date, utc, self._mmi.c) # dont need pointer as it is one
        B = Lgm_Vector.Lgm_Vector()
        self._mmi.Dst = self['Dst']
        self._mmi.By = self['By']
        self._mmi.Bz = self['Bz']
        arr_type = ctypes.c_double*6
        self._mmi.W = arr_type(*self['W'])
        
        #int Lgm_B_TS04_opt( Lgm_Vector *v, Lgm_Vector *B, Lgm_MagModelInfo *Info ) {
        retval = Lgm_B_TS04(pointer(self._Vpos), pointer(B), pointer(self._mmi))
        if retval != 1:
            raise(RuntimeWarning('Odd return from Lgm_T89') )
        ans.append(B)
        return ans
예제 #3
0
 def calc_B(self):
     try:
         ans = []
         for v1, v2 in zip(self._Vpos, self['Epoch'], ):
             date = Lgm_CTrans.dateToDateLong(v2)
             utc = Lgm_CTrans.dateToFPHours(v2)
             Lgm_Set_Coord_Transforms( date, utc, self._mmi.c) # don't need pointer as it is one
             B = Lgm_Vector.Lgm_Vector()
             retval = Lgm_B_Dungey(pointer(v1), pointer(B), pointer(self._mmi))
             if retval != 1:
                 raise(RuntimeWarning('Odd return from Lgm_B_Dungey.c') )
             ans.append(B)
         return ans
     except TypeError:
         date = Lgm_CTrans.dateToDateLong(self['Epoch'])
         utc = Lgm_CTrans.dateToFPHours(self['Epoch'])
         Lgm_Set_Coord_Transforms( date, utc, self._mmi.c) # don't need pointer as it is one
         B = Lgm_Vector.Lgm_Vector()
         retval = Lgm_B_Dungey(pointer(self._Vpos), pointer(B), pointer(self._mmi) )
         if retval != 1:
             raise(RuntimeWarning('Odd return from Lgm_B_Dungey.c') )
         return B
예제 #4
0
    def calc_B(self):
        ans = []
#            for v1, v2, v3 in zip(self._Vpos, self['Epoch'], self['Kp']):
        date = Lgm_CTrans.dateToDateLong(self['Epoch'])
        utc = Lgm_CTrans.dateToFPHours(self['Epoch'])
        Lgm_Set_Coord_Transforms( date, utc, self._mmi.c) # dont need pointer as it is one
        B = Lgm_Vector.Lgm_Vector()

        # Grab the QinDenton data
        # Lgm_get_QinDenton_at_JD( JD, &p, 1 );
        # JD = Lgm_Date_to_JD( Date, UTC, mInfo->c );
        JD = Lgm_Date_to_JD(date, utc, pointer(self._mmi.c))
        qd_one = lgmpy.Lgm_Wrap.Lgm_QinDentonOne()
        Lgm_get_QinDenton_at_JD( JD, pointer(qd_one), self.verbose)
        lgmpy.Lgm_Wrap.Lgm_set_QinDenton(pointer(qd_one), pointer(self._mmi.c))

        #int Lgm_B_TS04_opt( Lgm_Vector *v, Lgm_Vector *B, Lgm_MagModelInfo *Info ) {
        retval = Lgm_B_TS04(pointer(self._Vpos), pointer(B), pointer(self._mmi))
#        retval = Lgm_B_TS04_opt(pointer(self._Vpos), pointer(B), pointer(self._mmi))
        if retval != 1:
            raise(RuntimeWarning('Odd return from Lgm_TS04') )
        ans.append(B)
        return ans
예제 #5
0
def Closed_Field(*args, **kwargs):
    """
    Function to see if a field line is closed

    Either MagEphem or pos and date must be specified

    Parameters
    ----------
    MagEphem : Lgm_MagEphemInfo, optional
        If a populated Lgm_MagEphemInfo class is passed in the data is pulled
        from it
    pos : list, optional
        3-element list of the position in system coord_system
    date : datetime, optional
        date and time of the calculation
    height : float, optional
        height above the earth to consider a particle lost [km], default=100
    tol1 : float, optional
        TODO what do I set?  default=0.01
    tol2 : float, optional
        TODO what do I set?  default=1e-7
    bfield : str, optional
        The magnetic field model to use, default=Lgm_B_T89
    Kp : int, optional
        Kp index for the calculation, default=2
    coord_system : str
        the coordinate system of the input position, default=GSM
    extended_out : bool
        switch on extended vs regular output, see examples for details,
        default=False

    Returns
    -------
    out : str
        a string with the open of closed value for the input
            - LGM_OPEN_IMF
            - LGM_CLOSED
            - LGM_OPEN_N_LOBE
            - LGM_OPEN_S_LOBE
            - LGM_INSIDE_EARTH
            - LGM_TARGET_HEIGHT_UNREACHABLE

    Examples
    --------
    >>> from lgmpy import Closed_Field
    >>> import datetime
    >>> Closed_Field([3,1,0], datetime.datetime(2000, 12, 3))
    'LGM_CLOSED'
    >>> Closed_Field([6,1,12], datetime.datetime(2000, 12, 3))
    'LGM_OPEN_IMF'
    >>> Closed_Field([-16,1,5], datetime.datetime(2000, 12, 3))
    'LGM_OPEN_N_LOBE'
    """

    defaults = {
        'height': 100,
        'tol1': 0.01,
        'tol2': 1e-7,
        'bfield': 'Lgm_B_T89',
        'Kp': 2,
        'coord_system': 'GSM',
        'extended_out': False
    }

    #replace missing kwargs with defaults
    for dkey in defaults:
        if dkey not in kwargs:
            kwargs[dkey] = defaults[dkey]

    northern = Lgm_Vector.Lgm_Vector()
    southern = Lgm_Vector.Lgm_Vector()
    minB = Lgm_Vector.Lgm_Vector()
    #check for call w/ Lgm_MagModelInfo
    if len(args) == 1:
        MagEphemInfo = args[0]
        try:
            mmi = MagEphemInfo.LstarInfo.contents.mInfo.contents
        except AttributeError:
            raise (RuntimeError('Incorrect arguments specified'))
        dum = [MagEphemInfo.P.x, MagEphemInfo.P.y, MagEphemInfo.P.z]
        position = Lgm_Vector.Lgm_Vector(*dum)
    elif len(args) == 2:
        # input checking
        if kwargs['coord_system'] != 'GSM':
            #    raise(NotImplementedError('Different coord systems are not yet ready to use') )
            pos = magcoords.coordTrans(args[0], args[1],
                                       kwargs['coord_system'], 'GSM')
        else:
            pos = args[0]

        # could consider a Lgm_MagModelInfo param to use an existing one
        mmi = Lgm_MagModelInfo.Lgm_MagModelInfo()
        mmi.Kp = kwargs['Kp']
        try:
            Bfield_dict[kwargs['bfield']](pointer(mmi))
        except KeyError:
            raise (NotImplementedError("Only Bfield=%s currently supported" %
                                       Bfield_dict.keys()))

        datelong = Lgm_CTrans.dateToDateLong(args[1])
        utc = Lgm_CTrans.dateToFPHours(args[1])
        Lgm_Set_Coord_Transforms(datelong, utc,
                                 mmi.c)  # dont need pointer as it is one

        try:
            position = Lgm_Vector.Lgm_Vector(*pos)
        except TypeError:
            raise (TypeError('position must be an iterable'))
    else:
        raise (RuntimeError('Incorrect number of arguments specified'))

    ans = Lgm_Trace(pointer(position), pointer(southern), pointer(northern),
                    pointer(minB), kwargs['height'], kwargs['tol1'],
                    kwargs['tol2'], pointer(mmi))

    L = numpy.nan  #default to this is field not closed
    if ans == LGM_OPEN_IMF:
        retstr = 'LGM_OPEN_IMF'
    elif ans == LGM_CLOSED:
        retstr = 'LGM_CLOSED'
        L = _simpleL(northern, mmi)
    elif ans == LGM_OPEN_N_LOBE:
        retstr = 'LGM_OPEN_N_LOBE'
    elif ans == LGM_OPEN_S_LOBE:
        retstr = 'LGM_OPEN_S_LOBE'
    elif ans == LGM_INSIDE_EARTH:
        retstr = 'LGM_INSIDE_EARTH'
    elif ans == LGM_TARGET_HEIGHT_UNREACHABLE:
        retstr = 'LGM_TARGET_HEIGHT_UNREACHABLE'
    elif ans == LGM_BAD_TRACE:
        retstr = 'LGM_BAD_TRACE'
    if kwargs['extended_out']:
        return retstr, northern.tolist(), southern.tolist(), minB.tolist(), L
    else:
        return retstr
예제 #6
0
def get_Lstar2(pos, date, alpha = 90.,
                  params = None, coord_system='GSM',
                  Bfield = 'Lgm_B_OP77',
                  internal_model = 'Lgm_B_IGRF',
                  LstarThresh = 10.0,  # beyond this Lsimple don't compute Lstar;; not used in get_Lstar2
                  extended_out = False,
                  LstarQuality = 3, 
                  FootpointHeight=100., 
                  Colorize=False, 
                  cverbosity=0, QinDenton=False):    
## void Lgm_ComputeLstarVersusPA( long int Date, double UTC, Lgm_Vector *u, int nAlpha, double *Alpha, int Quality, int Colorize, Lgm_MagEphemInfo *MagEphemInfo ) {

    # setup a datamodel object to hold the answer
    ans = Lstar_Data()

    # change datetime to Lgm Datelong and UTC
    try:
        datelong = Lgm_CTrans.dateToDateLong(date)
        utc = Lgm_CTrans.dateToFPHours(date)
    except AttributeError:
        raise(TypeError("Date must be a datetime object"))
    else:
        ans['Epoch'] = datamodel.dmarray([date])

    # pitch angles to calculate
    if isinstance(alpha, numbers.Real):
        Alpha = numpy.asanyarray([alpha], dtype=float)
    else:
        Alpha = numpy.asanyarray(alpha, dtype=float)

    # required setup
    MagEphemInfo = Lgm_MagEphemInfo.Lgm_MagEphemInfo(len(Alpha), cverbosity)

    # setup a shortcut to MagModelInfo
    mmi = MagEphemInfo.LstarInfo.contents.mInfo.contents
    Lgm_Set_Coord_Transforms( datelong, utc, mmi.c) # dont think mmi.c needs a pointer()

    # setup a shortcut to LstarInfo
    MagEphemInfo.LstarInfo.contents.VerbosityLevel = cverbosity
    MagEphemInfo.LstarQuality = LstarQuality
    MagEphemInfo.LstarInfo.contents.SaveShellLines = False
    MagEphemInfo.LstarInfo.contents.FindShellPmin = extended_out
    MagEphemInfo.LstarInfo.contents.LSimpleMax = 10.0;
    mmi.VerbosityLevel = 0;
    mmi.Lgm_LossConeHeight = FootpointHeight;

    #MagEphemInfo->LstarInfo->mInfo->Bfield        = Lgm_B_T89;
#    mmi.Bfield = Lgm_Wrap.__getattribute__(Bfield)
    Lgm_Wrap.__getattribute__('Lgm_Set_'+Bfield)(MagEphemInfo.LstarInfo.contents.mInfo)
    Lgm_Wrap.__getattribute__('Lgm_Set_'+internal_model+'_InternalModel')(MagEphemInfo.LstarInfo.contents.mInfo)    
    
    MagEphemInfo.nAlpha = len(Alpha)
    #if len(Alpha) > 1 and Bfield == 'Lgm_B_TS04':
    #    raise(NotImplementedError('TS04 is not thread safe!! Can only do 1 PA at a time'))

    for i in range(len(Alpha)):
        MagEphemInfo.Alpha[i] = Alpha[i]
        
    # convert to **GSM**
    if coord_system == 'GSM':
        try:
            Pgsm = Lgm_Vector.Lgm_Vector(*pos)
        except TypeError:
            raise(TypeError("Position must be listlike" ) )
        ans['position']['GSM'] = datamodel.dmarray(pos, attrs={'units':'Re'})
    elif coord_system == 'SM':
        try:
            Psm = Lgm_Vector.Lgm_Vector(*pos)
        except TypeError:
            raise(TypeError("Position must be listlike" ) )
        Pgsm = Lgm_Vector.Lgm_Vector()
        Lgm_Convert_Coords( pointer(Psm), pointer(Pgsm), SM_TO_GSM, mmi.c )
        ans['position']['SM'] = datamodel.dmarray(pos, attrs={'units':'Re'})
        ans['position']['GSM'] = datamodel.dmarray(Pgsm.tolist(), attrs={'units':'Re'})
    else:
        raise(NotImplementedError("Only GSM or SM input currently supported"))
    
## void Lgm_ComputeLstarVersusPA( long int Date, double UTC, Lgm_Vector *u, int nAlpha, 
##                                 double *Alpha, int Quality, int Colorize, Lgm_MagEphemInfo *MagEphemInfo ) {


    if QinDenton:# and Bfield == 'Lgm_B_TS04': # these are the params we will use.
        # Grab the QinDenton data
        # Lgm_get_QinDenton_at_JD( JD, &p, 1 );
        # JD = Lgm_Date_to_JD( Date, UTC, mInfo->c );
        JD = Lgm_Wrap.Lgm_Date_to_JD(datelong, utc, pointer(mmi.c))
        qd_one = Lgm_Wrap.Lgm_QinDentonOne()
        Lgm_Wrap.Lgm_get_QinDenton_at_JD( JD, pointer(qd_one), cverbosity, 0)
        Lgm_Wrap.Lgm_set_QinDenton(pointer(qd_one), pointer(mmi.c))
        
        ans['params'] = dm.SpaceData()
        for att in dir(qd_one):
            if att[0] != '_':
                ans['params'][att] = getattr(qd_one, att)
    else:
        # save params
        ans['params'] = params
        if params == None:
            params = {}
        # step through the params dict and populate MagEphemInfo
        for key in params:
            if key == 'W':
                double6 = c_double*6
                W = double6(*params[key])
                MagEphemInfo.LstarInfo.contents.mInfo.contents.__setattr__(key, W)
            else:
                MagEphemInfo.LstarInfo.contents.mInfo.contents.__setattr__(key, params[key])
    
    Lgm_ComputeLstarVersusPA( ctypes.c_long(datelong), ctypes.c_double(utc), ctypes.pointer(Pgsm), 
                             ctypes.c_int(len(Alpha)), 
                             np.require(Alpha, requirements=['C']).ctypes.data_as(ctypes.POINTER(ctypes.c_double)), 
                             ctypes.c_int(Colorize), ctypes.pointer(MagEphemInfo) )

    for ii, pa in enumerate(Alpha):
        if int(pa) == pa:
            pa = int(pa)
        ans[pa] = dm.SpaceData()
        ans[pa]['LHilton'] = MagEphemInfo.LHilton[ii]
        ans[pa]['LMcIlwain'] = MagEphemInfo.LMcIlwain[ii]
        ans[pa]['Lstar'] = MagEphemInfo.Lstar[ii]

        # think in here, there are not owned by pyhton so there is no easy way to free the memory...
        if extended_out:
            ans[pa]['Bmin'] = dm.dmarray(np.zeros([MagEphemInfo.nShellPoints[ii], 3]))
            ans[pa]['I'] = dm.dmarray(np.zeros([MagEphemInfo.nShellPoints[ii]]))
            ans[pa]['Pmin'] = dm.dmarray(np.zeros([MagEphemInfo.nShellPoints[ii], 3]))
            ans[pa]['Bmin'][:, 0] = [val.x for val in MagEphemInfo.Shell_Bmin[ii][0:MagEphemInfo.nShellPoints[ii]]] 
            ans[pa]['Bmin'][:, 1] = [val.y for val in MagEphemInfo.Shell_Bmin[ii][0:MagEphemInfo.nShellPoints[ii]]] 
            ans[pa]['Bmin'][:, 2] = [val.z for val in MagEphemInfo.Shell_Bmin[ii][0:MagEphemInfo.nShellPoints[ii]]] 
            ans[pa]['I'][:] = [val for val in MagEphemInfo.ShellI[ii][0:MagEphemInfo.nShellPoints[ii]]]
            ans[pa]['Pmin'][:, 0] = [val.x for val in MagEphemInfo.Shell_Pmin[ii][0:MagEphemInfo.nShellPoints[ii]]] 
            ans[pa]['Pmin'][:, 1] = [val.y for val in MagEphemInfo.Shell_Pmin[ii][0:MagEphemInfo.nShellPoints[ii]]] 
            ans[pa]['Pmin'][:, 2] = [val.z for val in MagEphemInfo.Shell_Pmin[ii][0:MagEphemInfo.nShellPoints[ii]]] 
        
    return ans
예제 #7
0
def get_Lstar(pos, date, alpha = 90.,
                  Kp = 2, coord_system='GSM',
                  Bfield = 'Lgm_B_OP77',
                  LstarThresh = 10.0,  # beyond this Lsimple don't compute Lstar
                  extended_out = False,
                  LstarQuality = 3):
    """
    This method does all the work for the calculation of Lstar.

    There are many options to set and a lot of output.  We have tried to describe
    it well here but certainly have missed something, if you can't understand something
    please contact the authors.

    Parameters
    ==========
    pos : list or array
        The position that Lstar should be calculated for
    date : datetime
        The date and time that Lstar should be calculated for
    alpha : float, optional
        Local pitch angle at ``pos`` to calculate Lstar, default (90)
    Kp : int, optional
        The Kp index to pass to the magnetic field model, used in T89, ignored
        in OP77, default (2)
    coord_system : str, optional
        The coordinate system of the input position, default (GSM)
    Bfield : str, optional
        The Magnetic field model to use for the calculation, default (Lgm_B_T89)
    LstarThresh : float, optional
        The calculation computes a simple L value and does not calculation Lstar
        if simple L is beyond this, default (10)
    extended_out : bool, optional
        Keyword that enables the output of significantly more information into
        the Lstar_Data output, default (False).  The extra information allows
        the points along the Lstar trace to be used since Lstar is the same at
        each point along the trace.
    LstarQuality : int
        The quality flag for the integrators in the calculation, this can have
        serious impact on run speed and Lstar value

    Returns
    =======
    out : Lstar_Data
        Returns a datamodel object that contains all the information for the run.
        See examples for the contents of this object for extended_out=False and True

    Examples
    ========
    >>> from lgmpy import Lstar
    >>> import datetime
    >>> dat = Lstar.get_Lstar([1,2,0], datetime.datetime(2000, 1, 2), extended_out=False)
    >>> print(dat)
    +
    |____90.0 (spacepy.datamodel.SpaceData [8])
         |____Bmin (spacepy.datamodel.dmarray ())
             :|____units (str [2])
         |____Bmirror (spacepy.datamodel.dmarray ())
             :|____coord_system (str [3])
             :|____units (str [2])
         |____I (spacepy.datamodel.dmarray ())
         |____LHilton (float)
         |____LMcIlwain (float)
         |____Lsimple (spacepy.datamodel.dmarray (1,))
         |____Lstar (spacepy.datamodel.dmarray (1,))
             :|____info (str [4])
         |____Pmin (spacepy.datamodel.dmarray (3,))
             :|____coord_system (str [3])
             :|____units (str [3])
    |____Bcalc (spacepy.datamodel.dmarray (3,))
        :|____Kp (int)
        :|____coord_system (str [3])
        :|____model (str [10])
        :|____units (str [2])
    |____Epoch (spacepy.datamodel.dmarray (1,))
    |____Kp (spacepy.datamodel.dmarray (1,))
    |____MLT (spacepy.datamodel.dmarray ())
        :|____coord_system (str [5])
    |____position (dict [1])
         |____GSM (spacepy.datamodel.dmarray (3,))
             :|____units (str [2])
    ...

    The data object is a dictionary with keys:
        - 90.0 : this is the pitch angle specified (multiple can be specified)
            - Bmin : the minimum B for that pitch angle and position
            - BMirror : the position of the mirror point for that position
            - I : the I value for that position
            - LHilton : L value calculated with the Hilton approximation
            - LMcIlwain: L values calculated with the McIlwain formula
            - Lsimple : a simple L value
            - Lstar : the value of Lstar for that position and pitch angle
            - Pmin : TODO what is Pmin?
        - Bcalc : information about the magnetic field model
        - Epoch : the time of the calculation
        - Kp : Kp used for the calculation
        - MLT : MLT value for the position and coord_system
        - position : the position of the calculation
            - GSM : the value in this system, if conversions are done they all appear here

    >>> from lgmpy import Lstar
    >>> import datetime
    >>> dat = Lstar.get_Lstar([1,2,0], datetime.datetime(2000, 1, 2), extended_out=True)
    >>> print(dat)
    +
    |____90.0 (spacepy.datamodel.SpaceData [21])
        :|____Calc_Time (float)
         |____Bmag (numpy.ndarray (100, 1000))
         |____Bmin (spacepy.datamodel.dmarray ())
             :|____units (str [2])
         |____Bmirror (spacepy.datamodel.dmarray ())
             :|____coord_system (str [3])
             :|____units (str [2])
         |____I (spacepy.datamodel.dmarray ())
         |____LHilton (float)
         |____LMcIlwain (float)
         |____Lsimple (spacepy.datamodel.dmarray (1,))
         |____Lstar (spacepy.datamodel.dmarray (1,))
             :|____info (str [4])
         |____Pmin (spacepy.datamodel.dmarray (3,))
             :|____coord_system (str [3])
             :|____units (str [3])
         |____ShellEllipsoidFootprint_Pn (numpy.ndarray (100,))
         |____ShellEllipsoidFootprint_Ps (numpy.ndarray (100,))
         |____ShellI (spacepy.datamodel.dmarray (100,))
         |____ShellMirror_Pn (numpy.ndarray (100,))
         |____ShellMirror_Ps (numpy.ndarray (100,))
         |____ShellMirror_Sn (float)
         |____ShellMirror_Ss (float)
         |____nFieldPnts (numpy.ndarray (100,))
         |____s_gsm (numpy.ndarray (100, 1000))
         |____x_gsm (numpy.ndarray (100, 1000))
         |____y_gsm (numpy.ndarray (100, 1000))
         |____z_gsm (numpy.ndarray (100, 1000))
    |____Bcalc (spacepy.datamodel.dmarray (3,))
        :|____Kp (int)
        :|____coord_system (str [3])
        :|____model (str [10])
        :|____units (str [2])
    |____Epoch (spacepy.datamodel.dmarray (1,))
    |____Kp (spacepy.datamodel.dmarray (1,))
    |____MLT (spacepy.datamodel.dmarray ())
        :|____coord_system (str [5])
    |____position (dict [1])
         |____GSM (spacepy.datamodel.dmarray (3,))
             :|____units (str [2])
    ...

    The data object is a dictionary with keys:
        - 90.0 : this is the pitch angle specified (multiple can be specified)
            - Calc_Time : the clock time that the calculation took to run
            - Bmag : the magnitude of B along the Lstar trace
            - Bmin : the minimum B for that pitch angle and position
            - BMirror : the position of the mirror point for that position
            - I : the I value for that position
            - LHilton : L value calculated with the Hilton approximation
            - LMcIlwain: L values calculated with the McIlwain formula
            - Lsimple : a simple L value
            - Lstar : the value of Lstar for that position and pitch angle
            - Pmin : TODO what am I?
            - ShellEllipsoidFootprint_Pn : TODO what am I?
            - ShellEllipsoidFootprint_Ps : TODO what am I?
            - ShellI : TODO what am I?
            - ShellMirror_Pn : TODO what am I?
            - ShellMirror_Ps : TODO what am I?
            - ShellMirror_Sn : TODO what am I?
            - ShellMirror_Ss : TODO what am I?
            - nFieldPnts : TODO what am I?
            - s_gsm : TODO what am I?
            - x_gsm : TODO what am I?
            - y_gsm : TODO what am I?
            - z_gsm : TODO what am I?
        - Bcalc : information about the magnetic field model
        - Epoch : the time of the calculation
        - Kp : Kp used for the calculation
        - MLT : MLT value for the position and coord_system
        - position : the position of the calculation
            - GSM : the value in this system, if conversions are done they all appear here


    """

    # setup a datamodel object to hold the answer
    ans = Lstar_Data()

    # change datetime to Lgm Datelong and UTC
    try:
        datelong = Lgm_CTrans.dateToDateLong(date)
        utc = Lgm_CTrans.dateToFPHours(date)
    except AttributeError:
        raise(TypeError("Date must be a datetime object"))
    else:
        ans['Epoch'] = datamodel.dmarray([date])

    # pitch angles to calculate
    try:
        Alpha = list(alpha)
    except TypeError:
        Alpha = [alpha]

    # required setup
    MagEphemInfo = Lgm_MagEphemInfo.Lgm_MagEphemInfo(len(Alpha), 0)

    # setup a shortcut to MagModelInfo
    mmi = MagEphemInfo.LstarInfo.contents.mInfo.contents
    Lgm_Set_Coord_Transforms( datelong, utc, mmi.c) # dont need pointer as it is one

    # convert to **GSM**
    if coord_system == 'GSM':
        try:
            Pgsm = Lgm_Vector.Lgm_Vector(*pos)
        except TypeError:
            raise(TypeError("Position must be listlike" ) )
        ans['position']['GSM'] = datamodel.dmarray(pos, attrs={'units':'Re'})
    elif coord_system == 'SM':
        try:
            Psm = Lgm_Vector.Lgm_Vector(*pos)
        except TypeError:
            raise(TypeError("Position must be listlike" ) )
        Pgsm = Lgm_Vector.Lgm_Vector()
        Lgm_Convert_Coords( pointer(Psm), pointer(Pgsm), SM_TO_GSM, mmi.c )
        ans['position']['SM'] = datamodel.dmarray(pos, attrs={'units':'Re'})
        ans['position']['GSM'] = datamodel.dmarray(Pgsm.tolist(), attrs={'units':'Re'})
    else:
        raise(NotImplementedError("Only GSM or SM input currently supported"))

    Pwgs = Lgm_Vector.Lgm_Vector()
    Pmlt = Lgm_Vector.Lgm_Vector()
    Lgm_Convert_Coords( pointer(Pgsm), pointer(Pwgs), GSM_TO_WGS84, mmi.c )
    Lgm_Convert_Coords( pointer(Pwgs), pointer(Pmlt), WGS84_TO_EDMAG, mmi.c )
    R, MLat, MLon, MLT = c_double(), c_double(), c_double(), c_double(),
    Lgm_EDMAG_to_R_MLAT_MLON_MLT( pointer(Pmlt),  pointer(R), pointer(MLat), pointer(MLon),
        pointer(MLT), mmi.c)
    ans['MLT'] = datamodel.dmarray(MLT.value, attrs={'coord_system': 'EDMAG'})

    # save Kp
    # TODO maybe add some Kp checking
    ans['Kp'] = datamodel.dmarray([Kp])

    # Set the LstarQuality, TODO add a comment here on what each does
    MagEphemInfo.LstarQuality = LstarQuality

    # L* in one place is L* in lots of places (for GPS set to False)
    MagEphemInfo.SaveShellLines = extended_out
    # TODO maybe not hardcoded, but for now its fine
    MagEphemInfo.LstarInfo.contents.VerbosityLevel = 0
    MagEphemInfo.LstarInfo.contents.mInfo.contents.VerbosityLevel = 0

    #MagEphemInfo->LstarInfo->mInfo->Bfield        = Lgm_B_T89;
    #MagEphemInfo->LstarInfo->mInfo->Bfield        = Lgm_B_cdip;
    #MagEphemInfo->LstarInfo->mInfo->Bfield        = Lgm_B_OP77;
    #MagEphemInfo->LstarInfo->mInfo->InternalModel = LGM_CDIP;

    ## decide which field model to use, this is a keyword
    try:
        Bfield_dict[Bfield](MagEphemInfo.LstarInfo.contents.mInfo)
    except KeyError:
        raise(NotImplementedError("Only Bfield=%s currently supported" % Bfield_dict.keys()))

    # Save Date, UTC to MagEphemInfo structure ** is this needed?
    MagEphemInfo.Date   = datelong
    MagEphemInfo.UTC    = utc
    MagEphemInfo.LstarInfo.contents.mInfo.contents.Kp = Kp

    # Save nAlpha, and Alpha array to MagEphemInfo structure
    MagEphemInfo.nAlpha = len(Alpha)
    for i in range(len(Alpha)):
        MagEphemInfo.Alpha[i] = Alpha[i]

    # Set Tolerances
    Lgm_SetLstarTolerances(LstarQuality, 24, MagEphemInfo.LstarInfo )
    # *  Blocal at sat location
    MagEphemInfo.P = Pgsm

    Bvec = Lgm_Vector.Lgm_Vector()
    # Get B at the point in question
    MagEphemInfo.LstarInfo.contents.mInfo.contents.Bfield(pointer(Pgsm), pointer(Bvec),
                                                          MagEphemInfo.LstarInfo.contents.mInfo)
    ans['Bcalc'] = datamodel.dmarray(Bvec.tolist(), attrs={'units':'nT'})
    ans['Bcalc'].attrs['model'] = Bfield
    ans['Bcalc'].attrs['Kp'] = Kp
    ans['Bcalc'].attrs['coord_system'] = 'GSM'

    # save its magnitude in the structure
    MagEphemInfo.B = Bvec.magnitude()

    # check and see if the field line is closed before doing much work
    trace, northern, southern, minB, Lsimple = Closed_Field.Closed_Field(MagEphemInfo, extended_out=True)

    # presetup the ans[Angle] so that it can be filled correctly
    for pa in Alpha:
        ans[pa] = datamodel.SpaceData()
        ans[pa]['Lsimple'] = datamodel.dmarray([Lsimple])
        #sets up nans in case of Lstar failure
        ans[pa]['I'] = datamodel.dmarray([numpy.nan])
        ans[pa]['Lstar'] = datamodel.dmarray([numpy.nan], attrs={'info':trace})
        ans[pa]['LMcIlwain'] = datamodel.dmarray([numpy.nan])
        ans[pa]['LHilton'] = datamodel.dmarray([numpy.nan])
        ans[pa]['Bmin'] = datamodel.dmarray([numpy.nan], attrs={'units':'nT'})
        ans[pa]['Bmirror'] = datamodel.dmarray([numpy.nan], attrs={'units':'nT'})
    
    if trace != 'LGM_CLOSED':
        return ans
        # if this is not LGM_CLOSED then don't both with any pitch angle?  true?

    #  Save field-related quantities for each Pitch Angle.
    MagEphemInfo.Pmin = Lgm_Vector.Lgm_Vector(*minB)
    MagEphemInfo.Bmin = MagEphemInfo.LstarInfo.contents.mInfo.contents.Bmin
    ans[pa]['Pmin'] = datamodel.dmarray(minB, attrs={'units':'R_E'})
    ans[pa]['Pmin'].attrs['coord_system'] = 'GSM'
    ans[pa]['Bmin'] = datamodel.dmarray(MagEphemInfo.Bmin, attrs={'units':'nT'})
    # LOOP OVER PITCH ANGLES
    for i, pa in enumerate(Alpha):

        tnow = datetime.datetime.now()
        PreStr = MagEphemInfo.LstarInfo.contents.PreStr
        PostStr = MagEphemInfo.LstarInfo.contents.PostStr

        # ***********************************************
        # *** not sure I fully understand this chunk, B at the mirror point*****
        # Set Pitch Angle, sin, sin^2, and Bmirror
        sa = math.sin( pa*RadPerDeg )
        sa2 = sa*sa

        # print("{0}Computing L* for Pitch Angle: Alpha[{1}] = {2} Date: {3}   UTC: {4}   Lsimple = {5:4.3}{6}\n").format(PreStr, i, MagEphemInfo.Alpha[i], date, utc, Lsimple, PostStr )
        
        if sa2!=0: #non-zero pitch angle
            MagEphemInfo.LstarInfo.contents.mInfo.contents.Bm = MagEphemInfo.B/sa2
        else:
            continue
        ans[pa]['Bmirror'] = datamodel.dmarray(MagEphemInfo.LstarInfo.contents.mInfo.contents.Bm, attrs={'units':'nT'})
        ans[pa]['Bmirror'].attrs['coord_system'] = 'GSM'
        # ***********************************************
        
        # I tink this is already done
        # Lgm_Set_Coord_Transforms( Date, UTC, MagEphemInfo.LstarInfo.contents.mInfo.contents.c )

        MagEphemInfo.LstarInfo.contents.PitchAngle = pa
        MagEphemInfo.Bm[i] = MagEphemInfo.LstarInfo.contents.mInfo.contents.Bm
        # Compute L*
        if Lsimple < LstarThresh:
            Ls_vec = Lgm_Vector.Lgm_Vector(*minB)

            LS_Flag = Lgm_Lstar( pointer(Ls_vec), MagEphemInfo.LstarInfo)

            lstarinf = MagEphemInfo.LstarInfo.contents #shortcut
            MagEphemInfo.LHilton.contents.value = LFromIBmM_Hilton(c_double(lstarinf.I[0]),
                                                c_double(MagEphemInfo.Bm[i]),
                                                c_double(lstarinf.mInfo.contents.c.contents.M_cd))
            ans[pa]['LHilton'] = MagEphemInfo.LHilton.contents.value
            MagEphemInfo.LMcIlwain.contents.value = LFromIBmM_McIlwain(c_double(lstarinf.I[0]),
                                                c_double(MagEphemInfo.Bm[i]),
                                                c_double(lstarinf.mInfo.contents.c.contents.M_cd))
            ans[pa]['LMcIlwain'] = MagEphemInfo.LMcIlwain.contents.value
            if LS_Flag == -2: # mirror below southern hemisphere mirror alt
                ans[pa]['Lstar'] = datamodel.dmarray([numpy.nan], attrs={'info':'S_LOSS'})
            elif LS_Flag == -1: # mirror below northern hemisphere mirror alt
                ans[pa]['Lstar'] = datamodel.dmarray([numpy.nan], attrs={'info':'N_LOSS'})
            elif LS_Flag >= 0: # valid calc
                ans[pa]['Lstar'] = datamodel.dmarray([lstarinf.LS], attrs={'info':'GOOD'}) # want better word?

            MagEphemInfo.Lstar[i] = lstarinf.LS

            # Save results to the MagEphemInfo structure.
            MagEphemInfo.nShellPoints[i] = lstarinf.nPnts
            ## pull all this good extra info into numpy arrays
            ans[pa]['I'] = datamodel.dmarray(lstarinf.I[0])

            if extended_out:
                ans[pa]['ShellI'] = \
                    datamodel.dmarray(numpy.ctypeslib.ndarray([len(lstarinf.I)],
                                            dtype=c_double, buffer=lstarinf.I) ).copy()
                ans[pa]['ShellEllipsoidFootprint_Pn'] = \
                    numpy.ctypeslib.ndarray(len(lstarinf.Ellipsoid_Footprint_Pn),
                                            dtype=c_double,
                                            buffer=lstarinf.Ellipsoid_Footprint_Pn).copy()
                ans[pa]['ShellEllipsoidFootprint_Ps'] = \
                    numpy.ctypeslib.ndarray(len(lstarinf.Ellipsoid_Footprint_Ps),
                                            dtype=c_double,
                                            buffer=lstarinf.Ellipsoid_Footprint_Ps).copy()

                ans[pa]['ShellMirror_Pn'] = \
                    numpy.ctypeslib.ndarray(len(lstarinf.Mirror_Pn),
                                            dtype=c_double,
                                            buffer=lstarinf.Mirror_Pn).copy()
                ans[pa]['ShellMirror_Ps'] = \
                    numpy.ctypeslib.ndarray(len(lstarinf.Mirror_Ps),
                                            dtype=c_double,
                                            buffer=lstarinf.Mirror_Ps).copy()
                ans[pa]['ShellMirror_Ss'] = lstarinf.mInfo.contents.Sm_South
                ans[pa]['ShellMirror_Sn'] = lstarinf.mInfo.contents.Sm_North
                ans[pa]['nFieldPnts'] = \
                    numpy.ctypeslib.ndarray(len(lstarinf.nFieldPnts),
                                            dtype=c_int,
                                            buffer=lstarinf.nFieldPnts).copy()

                ans[pa]['s_gsm'] = \
                    numpy.ctypeslib.ndarray([len(lstarinf.s_gsm),
                                             len(lstarinf.s_gsm[0])],
                                            dtype=c_double,
                                            buffer=lstarinf.s_gsm).copy()
                ans[pa]['Bmag'] = \
                    numpy.ctypeslib.ndarray([len(lstarinf.Bmag),
                                             len(lstarinf.Bmag[0])],
                                            dtype=c_double,
                                            buffer=lstarinf.Bmag).copy()
                ans[pa]['x_gsm'] = \
                    numpy.ctypeslib.ndarray([len(lstarinf.x_gsm),
                                             len(lstarinf.x_gsm[0])],
                                            dtype=c_double,
                                            buffer=lstarinf.x_gsm).copy()
                ans[pa]['y_gsm'] = \
                    numpy.ctypeslib.ndarray([len(lstarinf.y_gsm),
                                             len(lstarinf.y_gsm[0])],
                                            dtype=c_double,
                                            buffer=lstarinf.y_gsm).copy()
                ans[pa]['z_gsm'] = \
                    numpy.ctypeslib.ndarray([len(lstarinf.z_gsm),
                                             len(lstarinf.z_gsm[0])],
                                            dtype=c_double,
                                            buffer=lstarinf.z_gsm).copy()
                delT = datetime.datetime.now() - tnow
                ans[pa].attrs['Calc_Time'] = delT.seconds + delT.microseconds/1e6

    Lgm_FreeMagEphemInfo_Children(pointer(MagEphemInfo))
    return ans
예제 #8
0
def Closed_Field(*args, **kwargs):
    """
    Function to see if a field line is closed

    Either MagEphem or pos and date must be specified

    Parameters
    ----------
    MagEphem : Lgm_MagEphemInfo, optional
        If a populated Lgm_MagEphemInfo class is passed in the data is pulled
        from it
    pos : list, optional
        3-element list of the position in system coord_system
    date : datetime, optional
        date and time of the calculation
    height : float, optional
        height above the earth to consider a particle lost [km], default=100
    tol1 : float, optional
        TODO what do I set?  default=0.01
    tol2 : float, optional
        TODO what do I set?  default=1e-7
    bfield : str, optional
        The magnetic field model to use, default=Lgm_B_T89
    Kp : int, optional
        Kp index for the calculation, default=2
    coord_system : str
        the coordinate system of the input position, default=GSM
    extended_out : bool
        switch on extended vs regular output, see examples for details,
        default=False

    Returns
    -------
    out : str
        a string with the open of closed value for the input
            - LGM_OPEN_IMF
            - LGM_CLOSED
            - LGM_OPEN_N_LOBE
            - LGM_OPEN_S_LOBE
            - LGM_INSIDE_EARTH
            - LGM_TARGET_HEIGHT_UNREACHABLE

    Examples
    --------
    >>> from lgmpy import Closed_Field
    >>> import datetime
    >>> Closed_Field([3,1,0], datetime.datetime(2000, 12, 3))
    'LGM_CLOSED'
    >>> Closed_Field([6,1,12], datetime.datetime(2000, 12, 3))
    'LGM_OPEN_IMF'
    >>> Closed_Field([-16,1,5], datetime.datetime(2000, 12, 3))
    'LGM_OPEN_N_LOBE'
    """

    defaults = {'height': 100,
                'tol1': 0.01,
                'tol2': 1e-7,
                'bfield': 'Lgm_B_T89',
                'Kp': 2,
                'coord_system': 'GSM',
                'extended_out': False}

    #replace missing kwargs with defaults
    for dkey in defaults:
        if dkey not in kwargs:
            kwargs[dkey] = defaults[dkey]

    northern = Lgm_Vector.Lgm_Vector()
    southern = Lgm_Vector.Lgm_Vector()
    minB = Lgm_Vector.Lgm_Vector()
    #check for call w/ Lgm_MagModelInfo
    if len(args) == 1:
        MagEphemInfo = args[0]
        try:
            mmi = MagEphemInfo.LstarInfo.contents.mInfo.contents
        except AttributeError:
            raise(RuntimeError('Incorrect arguments specified'))
        dum = [MagEphemInfo.P.x, MagEphemInfo.P.y, MagEphemInfo.P.z]
        position = Lgm_Vector.Lgm_Vector(*dum)
    elif len(args) == 2:
        # input checking
        if kwargs['coord_system'] != 'GSM':
        #    raise(NotImplementedError('Different coord systems are not yet ready to use') )
            pos = magcoords.coordTrans(args[0], args[1], kwargs['coord_system'],'GSM')
        else:
            pos = args[0]
        
        # could consider a Lgm_MagModelInfo param to use an existing one
        mmi = Lgm_MagModelInfo.Lgm_MagModelInfo()
        mmi.Kp = kwargs['Kp']
        try:
            Bfield_dict[kwargs['bfield']](pointer(mmi))
        except KeyError:
            raise(NotImplementedError("Only Bfield=%s currently supported" % Bfield_dict.keys()))

        datelong = Lgm_CTrans.dateToDateLong(args[1])
        utc = Lgm_CTrans.dateToFPHours(args[1])
        Lgm_Set_Coord_Transforms( datelong, utc, mmi.c) # dont need pointer as it is one

        try:
            position = Lgm_Vector.Lgm_Vector(*pos)
        except TypeError:
            raise(TypeError('position must be an iterable') )
    else:
        raise(RuntimeError('Incorrect number of arguments specified'))

    ans = Lgm_Trace(pointer(position),
            pointer(southern),
            pointer(northern),
            pointer(minB), kwargs['height'], kwargs['tol1'], kwargs['tol2'], pointer(mmi) )

    L = numpy.nan #default to this is field not closed
    if ans == LGM_OPEN_IMF:
        retstr = 'LGM_OPEN_IMF'
    elif ans == LGM_CLOSED:
        retstr = 'LGM_CLOSED'
        L = _simpleL(northern, mmi)
    elif ans == LGM_OPEN_N_LOBE:
        retstr = 'LGM_OPEN_N_LOBE'
    elif ans == LGM_OPEN_S_LOBE:
        retstr = 'LGM_OPEN_S_LOBE'
    elif ans == LGM_INSIDE_EARTH:
        retstr = 'LGM_INSIDE_EARTH'
    elif ans == LGM_TARGET_HEIGHT_UNREACHABLE:
        retstr = 'LGM_TARGET_HEIGHT_UNREACHABLE'
    elif ans == LGM_BAD_TRACE:
        retstr = 'LGM_BAD_TRACE'
    if kwargs['extended_out']:
        return retstr, northern.tolist(), southern.tolist(), minB.tolist(), L
    else:
        return retstr
예제 #9
0
    def __init__(self, pos, time, direction='NORTH', coord_system = 'GSM', INTERNAL_MODEL='LGM_IGRF', EXTERNAL_MODEL='LGM_EXTMODEL_T89', MAGMODEL_ARGS=None, TargetHeight=120, tol=1e-7):
        super(Lgm_TraceToEarth_py, self).__init__(Position=pos, Epoch=time, direction=direction, coord_system = coord_system, INTERNAL_MODEL=INTERNAL_MODEL, EXTERNAL_MODEL=EXTERNAL_MODEL,
                                               TargetHeight=TargetHeight,
                                               tol=tol)
        if not isinstance(pos, Lgm_Vector.Lgm_Vector) and \
            not isinstance(pos, list):
            raise(TypeError('pos must be a Lgm_Vector or list') )
        self._Vpos = pos2Lgm_Vector(pos)
        # time must be a datetime
        if not isinstance(time, datetime.datetime) and \
            not isinstance(time, list):
            raise(TypeError('time must be a datetime or list of datetime') )

        if direction[0].upper() == 'N':
            direction=1.0
        elif direction[0].upper() == 'S':
            direction=-1.0
        else:
            raise(ValueError("Did not understand direction, must be N or S"))

                    
        if INTERNAL_MODEL not in (LGM_CDIP,
                                  LGM_EDIP,
                                  LGM_IGRF) and \
            INTERNAL_MODEL not in ('LGM_CDIP',
                                  'LGM_EDIP',
                                  'LGM_IGRF'):
            raise(ValueError('INTERNAL_MODEL must be LGM_CDIP, LGM_EDIP, or LGM_IGRF') )
        if isinstance(INTERNAL_MODEL, str):
            INTERNAL_MODEL = eval(INTERNAL_MODEL)
        self.attrs['internal_model'] = INTERNAL_MODEL

        if coord_system != 'GSM':
            raise(NotImplementedError('Different coord systems are not yet ready to use') )

        self._mmi = Lgm_MagModelInfo.Lgm_MagModelInfo()
        
        # and actually set the internal model in Lgm
        if self.attrs['internal_model'] == LGM_CDIP:
            Lgm_Set_Lgm_B_cdip_InternalModel(pointer(self._mmi))
        elif self.attrs['internal_model'] == LGM_EDIP:
            Lgm_Set_Lgm_B_edip_InternalModel(pointer(self._mmi))
        elif self.attrs['internal_model'] == LGM_IGRF:
            Lgm_Set_Lgm_B_IGRF_InternalModel(pointer(self._mmi))

        # set the external field model
        if EXTERNAL_MODEL not in (LGM_EXTMODEL_NULL,
                                  LGM_EXTMODEL_T87,
                                  LGM_EXTMODEL_T89,
                                  LGM_EXTMODEL_T89c,
                                  LGM_EXTMODEL_T96,
                                  LGM_EXTMODEL_T01S,
                                  LGM_EXTMODEL_T02,
                                  LGM_EXTMODEL_TS04,
                                  LGM_EXTMODEL_TS07,
                                  LGM_EXTMODEL_OP77) and \
          EXTERNAL_MODEL not in ('LGM_EXTMODEL_NULL',
                                  'LGM_EXTMODEL_T87',
                                  'LGM_EXTMODEL_T89',
                                  'LGM_EXTMODEL_T89c',
                                  'LGM_EXTMODEL_T96',
                                  'LGM_EXTMODEL_T01S',
                                  'LGM_EXTMODEL_T02',
                                  'LGM_EXTMODEL_TS04',
                                  'LGM_EXTMODEL_TS07',
                                  'LGM_EXTMODEL_OP77'):
            raise(ValueError('INTERNAL_MODEL must be {0}'.format('LGM_EXTMODEL_NULL',
                                  'LGM_EXTMODEL_T87',
                                  'LGM_EXTMODEL_T89',
                                  'LGM_EXTMODEL_T89c',
                                  'LGM_EXTMODEL_T96',
                                  'LGM_EXTMODEL_T01S',
                                  'LGM_EXTMODEL_T02',
                                  'LGM_EXTMODEL_TS04',
                                  'LGM_EXTMODEL_TS07',
                                  'LGM_EXTMODEL_OP77')) )
        if isinstance(EXTERNAL_MODEL, str):
            EXTERNAL_MODEL = eval(EXTERNAL_MODEL)
        self.attrs['external_model'] = EXTERNAL_MODEL
          
        # and actually set the internal model in Lgm
        if self.attrs['external_model'] == LGM_EXTMODEL_T89:
            Lgm_Set_Lgm_B_T89(pointer(self._mmi))
            self._mmi.Kp = MAGMODEL_ARGS['Kp']
        elif self.attrs['external_model'] == LGM_EXTMODEL_OP77:
            Lgm_Set_Lgm_B_OP77(pointer(self._mmi))
        else:
            raise(NotImplementedError("The external model has not yet been implemented: {0}".format(self.attrs['external_model'])))

                        
        # either they are all one element or they are compatible lists no 1/2 way
        try:
            if len(self._Vpos) != len(self['Kp']) or \
                len(self._Vpos) != len(self['Epoch']) or \
                len(self['Epoch']) != len(self['Kp']):
                raise(ValueError('Inputs must be the same length, scalars or lists'))
        except TypeError:
            if isinstance(self._Vpos, list) and not isinstance(self['Kp'], list) \
                and not isinstance(self['Epoch'], list):
                    raise(ValueError('Inputs must be the same length, scalars or lists'))

        date = Lgm_CTrans.dateToDateLong(self['Epoch'])
        utc = Lgm_CTrans.dateToFPHours(self['Epoch'])
        Lgm_Set_Coord_Transforms( date, utc, self._mmi.c) # dont need pointer as it is one

                    
        ans = Lgm_Vector.Lgm_Vector(-1, -1, -1)

        retval = Lgm_TraceToEarth(pointer(self._Vpos),
                                ctypes.pointer(ans),
                                ctypes.c_double(TargetHeight),
                                ctypes.c_double(direction),
                                ctypes.c_double(tol),
                                pointer(self._mmi) )

        if retval == LGM_CLOSED:
            self['footpoint'] = ans
            self.attrs['retcode'] = retval
        elif retval == LGM_OPEN_IMF:
            self['footpoint'] = np.nan
            warnings.warn("LGM_OPEN_IMF")
            self.attrs['retcode'] = retval
        elif retval == LGM_OPEN_N_LOBE:
            self['footpoint'] = np.nan
            warnings.warn("LGM_OPEN_N_LOBE")
            self.attrs['retcode'] = retval
        elif retval == LGM_OPEN_S_LOBE:
            self['footpoint'] = np.nan
            warnings.warn("LGM_OPEN_S_LOBE")
            self.attrs['retcode'] = retval
        elif retval == LGM_INSIDE_EARTH:
            self['footpoint'] = np.nan
            warnings.warn("LGM_INSIDE_EARTH")
            self.attrs['retcode'] = retval
        elif retval == LGM_TARGET_HEIGHT_UNREACHABLE:
            self['footpoint'] = np.nan
            warnings.warn("LGM_TARGET_HEIGHT_UNREACHABLE")
            self.attrs['retcode'] = retval
        elif retval == LGM_BAD_TRACE:
            self['footpoint'] = np.nan
            warnings.warn("LGM_BAD_TRACE")
            self.attrs['retcode'] = retval
예제 #10
0
def get_Lstar2(pos, date, alpha = 90.,
                  params = None, coord_system='GSM',
                  Bfield = 'Lgm_B_OP77',
                  internal_model = 'Lgm_B_IGRF',
                  LstarThresh = 10.0,  # beyond this Lsimple don't compute Lstar;; not used in get_Lstar2
                  extended_out = False,
                  LstarQuality = 3, 
                  FootpointHeight=100., 
                  Colorize=False, 
                  cverbosity=0, QinDenton=False):    
## void Lgm_ComputeLstarVersusPA( long int Date, double UTC, Lgm_Vector *u, int nAlpha, double *Alpha, int Quality, int Colorize, Lgm_MagEphemInfo *MagEphemInfo ) {

    # setup a datamodel object to hold the answer
    ans = Lstar_Data()

    # change datetime to Lgm Datelong and UTC
    try:
        datelong = Lgm_CTrans.dateToDateLong(date)
        utc = Lgm_CTrans.dateToFPHours(date)
    except AttributeError:
        raise(TypeError("Date must be a datetime object"))
    else:
        ans['Epoch'] = datamodel.dmarray([date])

    # pitch angles to calculate
    if isinstance(alpha, numbers.Real):
        Alpha = numpy.asanyarray([alpha], dtype=float)
    else:
        Alpha = numpy.asanyarray(alpha, dtype=float)

    # required setup
    MagEphemInfo = Lgm_MagEphemInfo.Lgm_MagEphemInfo(len(Alpha), cverbosity)

    # setup a shortcut to MagModelInfo
    mmi = MagEphemInfo.LstarInfo.contents.mInfo.contents
    Lgm_Set_Coord_Transforms( datelong, utc, mmi.c) # dont think mmi.c needs a pointer()

    # setup a shortcut to LstarInfo
    MagEphemInfo.LstarInfo.contents.VerbosityLevel = cverbosity
    MagEphemInfo.LstarQuality = LstarQuality
    MagEphemInfo.LstarInfo.contents.SaveShellLines = False
    MagEphemInfo.LstarInfo.contents.FindShellPmin = extended_out
    MagEphemInfo.LstarInfo.contents.LSimpleMax = 10.0;
    mmi.VerbosityLevel = 0;
    mmi.Lgm_LossConeHeight = FootpointHeight;

    #MagEphemInfo->LstarInfo->mInfo->Bfield        = Lgm_B_T89;
#    mmi.Bfield = Lgm_Wrap.__getattribute__(Bfield)
    Lgm_Wrap.__getattribute__('Lgm_Set_'+Bfield)(MagEphemInfo.LstarInfo.contents.mInfo)
    Lgm_Wrap.__getattribute__('Lgm_Set_'+internal_model+'_InternalModel')(MagEphemInfo.LstarInfo.contents.mInfo)    
    
    MagEphemInfo.nAlpha = len(Alpha)
    #if len(Alpha) > 1 and Bfield == 'Lgm_B_TS04':
    #    raise(NotImplementedError('TS04 is not thread safe!! Can only do 1 PA at a time'))

    for i in range(len(Alpha)):
        MagEphemInfo.Alpha[i] = Alpha[i]
        
    # convert to **GSM**
    if coord_system == 'GSM':
        try:
            Pgsm = Lgm_Vector.Lgm_Vector(*pos)
        except TypeError:
            raise(TypeError("Position must be listlike" ) )
        ans['position']['GSM'] = datamodel.dmarray(pos, attrs={'units':'Re'})
    elif coord_system == 'SM':
        try:
            Psm = Lgm_Vector.Lgm_Vector(*pos)
        except TypeError:
            raise(TypeError("Position must be listlike" ) )
        Pgsm = Lgm_Vector.Lgm_Vector()
        Lgm_Convert_Coords( pointer(Psm), pointer(Pgsm), SM_TO_GSM, mmi.c )
        ans['position']['SM'] = datamodel.dmarray(pos, attrs={'units':'Re'})
        ans['position']['GSM'] = datamodel.dmarray(Pgsm.tolist(), attrs={'units':'Re'})
    else:
        raise(NotImplementedError("Only GSM or SM input currently supported"))
    
## void Lgm_ComputeLstarVersusPA( long int Date, double UTC, Lgm_Vector *u, int nAlpha, 
##                                 double *Alpha, int Quality, int Colorize, Lgm_MagEphemInfo *MagEphemInfo ) {



    if QinDenton:# and Bfield == 'Lgm_B_TS04': # these are the params we will use.
        # Grab the QinDenton data
        # Lgm_get_QinDenton_at_JD( JD, &p, 1 );
        # JD = Lgm_Date_to_JD( Date, UTC, mInfo->c );
        JD = Lgm_Wrap.Lgm_Date_to_JD(datelong, utc, pointer(mmi.c))
        qd_one = Lgm_Wrap.Lgm_QinDentonOne()
        Lgm_Wrap.Lgm_get_QinDenton_at_JD( JD, pointer(qd_one), cverbosity)
        Lgm_Wrap.Lgm_set_QinDenton(pointer(qd_one), pointer(mmi.c))
        
        ans['params'] = dm.SpaceData()
        for att in dir(qd_one):
            if att[0] != '_':
                ans['params'][att] = getattr(qd_one, att)
    else:
        # save params
        ans['params'] = params
        if params == None:
            params = {}
        # step through the params dict and populate MagEphemInfo
        for key in params:
            if key == 'W':
                double6 = c_double*6
                W = double6(*params[key])
                MagEphemInfo.LstarInfo.contents.mInfo.contents.__setattr__(key, W)
            else:
                MagEphemInfo.LstarInfo.contents.mInfo.contents.__setattr__(key, params[key])
    
    Lgm_ComputeLstarVersusPA( ctypes.c_long(datelong), ctypes.c_double(utc), ctypes.pointer(Pgsm), 
                             ctypes.c_int(len(Alpha)), 
                             np.require(Alpha, requirements=['C']).ctypes.data_as(ctypes.POINTER(ctypes.c_double)), 
                             ctypes.c_int(LstarQuality), ctypes.c_int(Colorize), 
                             ctypes.pointer(MagEphemInfo) )

    for ii, pa in enumerate(Alpha):
        if int(pa) == pa:
            pa = int(pa)
        ans[pa] = dm.SpaceData()
        ans[pa]['LHilton'] = MagEphemInfo.LHilton[ii]
        ans[pa]['LMcIlwain'] = MagEphemInfo.LMcIlwain[ii]
        ans[pa]['Lstar'] = MagEphemInfo.Lstar[ii]

        # think in here, there are not owned by pyhton so there is no easy way to free the memory...
        if extended_out:
            ans[pa]['Bmin'] = dm.dmarray(np.zeros([MagEphemInfo.nShellPoints[ii], 3]))
            ans[pa]['I'] = dm.dmarray(np.zeros([MagEphemInfo.nShellPoints[ii]]))
            ans[pa]['Pmin'] = dm.dmarray(np.zeros([MagEphemInfo.nShellPoints[ii], 3]))
            ans[pa]['Bmin'][:, 0] = [val.x for val in MagEphemInfo.Shell_Bmin[ii][0:MagEphemInfo.nShellPoints[ii]]] 
            ans[pa]['Bmin'][:, 1] = [val.y for val in MagEphemInfo.Shell_Bmin[ii][0:MagEphemInfo.nShellPoints[ii]]] 
            ans[pa]['Bmin'][:, 2] = [val.z for val in MagEphemInfo.Shell_Bmin[ii][0:MagEphemInfo.nShellPoints[ii]]] 
            ans[pa]['I'][:] = [val for val in MagEphemInfo.ShellI[ii][0:MagEphemInfo.nShellPoints[ii]]]
            ans[pa]['Pmin'][:, 0] = [val.x for val in MagEphemInfo.Shell_Pmin[ii][0:MagEphemInfo.nShellPoints[ii]]] 
            ans[pa]['Pmin'][:, 1] = [val.y for val in MagEphemInfo.Shell_Pmin[ii][0:MagEphemInfo.nShellPoints[ii]]] 
            ans[pa]['Pmin'][:, 2] = [val.z for val in MagEphemInfo.Shell_Pmin[ii][0:MagEphemInfo.nShellPoints[ii]]] 
        
    return ans
예제 #11
0
def get_Lstar(pos, date, alpha = 90.,
                  Kp = 2, coord_system='GSM',
                  Bfield = 'Lgm_B_OP77',
                  LstarThresh = 10.0,  # beyond this Lsimple don't compute Lstar
                  extended_out = False,
                  LstarQuality = 3):
    """
    This method does all the work for the calculation of Lstar.

    There are many options to set and a lot of output.  We have tried to describe
    it well here but certainly have missed something, if you can't understand something
    please contact the authors.

    Parameters
    ==========
    pos : list or array
        The position that Lstar should be calculated for
    date : datetime
        The date and time that Lstar should be calculated for
    alpha : float, optional
        Local pitch angle at ``pos`` to calculate Lstar, default (90)
    Kp : int, optional
        The Kp index to pass to the magnetic field model, used in T89, ignored
        in OP77, default (2)
    coord_system : str, optional
        The coordinate system of the input position, default (GSM)
    Bfield : str, optional
        The Magnetic field model to use for the calculation, default (Lgm_B_T89)
    LstarThresh : float, optional
        The calculation computes a simple L value and does not calculation Lstar
        if simple L is beyond this, default (10)
    extended_out : bool, optional
        Keyword that enables the output of significantly more information into
        the Lstar_Data output, default (False).  The extra information allows
        the points along the Lstar trace to be used since Lstar is the same at
        each point along the trace.
    LstarQuality : int
        The quality flag for the integrators in the calculation, this can have
        serious impact on run speed and Lstar value

    Returns
    =======
    out : Lstar_Data
        Returns a datamodel object that contains all the information for the run.
        See examples for the contents of this object for extended_out=False and True

    Examples
    ========
    >>> from lgmpy import Lstar
    >>> import datetime
    >>> dat = Lstar.get_Lstar([1,2,0], datetime.datetime(2000, 1, 2), extended_out=False)
    >>> print(dat)
    +
    |____90.0 (spacepy.datamodel.SpaceData [8])
         |____Bmin (spacepy.datamodel.dmarray ())
             :|____units (str [2])
         |____Bmirror (spacepy.datamodel.dmarray ())
             :|____coord_system (str [3])
             :|____units (str [2])
         |____I (spacepy.datamodel.dmarray ())
         |____LHilton (float)
         |____LMcIlwain (float)
         |____Lsimple (spacepy.datamodel.dmarray (1,))
         |____Lstar (spacepy.datamodel.dmarray (1,))
             :|____info (str [4])
         |____Pmin (spacepy.datamodel.dmarray (3,))
             :|____coord_system (str [3])
             :|____units (str [3])
    |____Bcalc (spacepy.datamodel.dmarray (3,))
        :|____Kp (int)
        :|____coord_system (str [3])
        :|____model (str [10])
        :|____units (str [2])
    |____Epoch (spacepy.datamodel.dmarray (1,))
    |____Kp (spacepy.datamodel.dmarray (1,))
    |____MLT (spacepy.datamodel.dmarray ())
        :|____coord_system (str [5])
    |____position (dict [1])
         |____GSM (spacepy.datamodel.dmarray (3,))
             :|____units (str [2])
    ...

    The data object is a dictionary with keys:
        - 90.0 : this is the pitch angle specified (multiple can be specified)
            - Bmin : the minimum B for that pitch angle and position
            - BMirror : the position of the mirror point for that position
            - I : the I value for that position
            - LHilton : L value calculated with the Hilton approximation
            - LMcIlwain: L values calculated with the McIlwain formula
            - Lsimple : a simple L value
            - Lstar : the value of Lstar for that position and pitch angle
            - Pmin : TODO what is Pmin?
        - Bcalc : information about the magnetic field model
        - Epoch : the time of the calculation
        - Kp : Kp used for the calculation
        - MLT : MLT value for the position and coord_system
        - position : the position of the calculation
            - GSM : the value in this system, if conversions are done they all appear here

    >>> from lgmpy import Lstar
    >>> import datetime
    >>> dat = Lstar.get_Lstar([1,2,0], datetime.datetime(2000, 1, 2), extended_out=True)
    >>> print(dat)
    +
    |____90.0 (spacepy.datamodel.SpaceData [21])
        :|____Calc_Time (float)
         |____Bmag (numpy.ndarray (100, 1000))
         |____Bmin (spacepy.datamodel.dmarray ())
             :|____units (str [2])
         |____Bmirror (spacepy.datamodel.dmarray ())
             :|____coord_system (str [3])
             :|____units (str [2])
         |____I (spacepy.datamodel.dmarray ())
         |____LHilton (float)
         |____LMcIlwain (float)
         |____Lsimple (spacepy.datamodel.dmarray (1,))
         |____Lstar (spacepy.datamodel.dmarray (1,))
             :|____info (str [4])
         |____Pmin (spacepy.datamodel.dmarray (3,))
             :|____coord_system (str [3])
             :|____units (str [3])
         |____ShellEllipsoidFootprint_Pn (numpy.ndarray (100,))
         |____ShellEllipsoidFootprint_Ps (numpy.ndarray (100,))
         |____ShellI (spacepy.datamodel.dmarray (100,))
         |____ShellMirror_Pn (numpy.ndarray (100,))
         |____ShellMirror_Ps (numpy.ndarray (100,))
         |____ShellMirror_Sn (float)
         |____ShellMirror_Ss (float)
         |____nFieldPnts (numpy.ndarray (100,))
         |____s_gsm (numpy.ndarray (100, 1000))
         |____x_gsm (numpy.ndarray (100, 1000))
         |____y_gsm (numpy.ndarray (100, 1000))
         |____z_gsm (numpy.ndarray (100, 1000))
    |____Bcalc (spacepy.datamodel.dmarray (3,))
        :|____Kp (int)
        :|____coord_system (str [3])
        :|____model (str [10])
        :|____units (str [2])
    |____Epoch (spacepy.datamodel.dmarray (1,))
    |____Kp (spacepy.datamodel.dmarray (1,))
    |____MLT (spacepy.datamodel.dmarray ())
        :|____coord_system (str [5])
    |____position (dict [1])
         |____GSM (spacepy.datamodel.dmarray (3,))
             :|____units (str [2])
    ...

    The data object is a dictionary with keys:
        - 90.0 : this is the pitch angle specified (multiple can be specified)
            - Calc_Time : the clock time that the calculation took to run
            - Bmag : the magnitude of B along the Lstar trace
            - Bmin : the minimum B for that pitch angle and position
            - BMirror : the position of the mirror point for that position
            - I : the I value for that position
            - LHilton : L value calculated with the Hilton approximation
            - LMcIlwain: L values calculated with the McIlwain formula
            - Lsimple : a simple L value
            - Lstar : the value of Lstar for that position and pitch angle
            - Pmin : TODO what am I?
            - ShellEllipsoidFootprint_Pn : TODO what am I?
            - ShellEllipsoidFootprint_Ps : TODO what am I?
            - ShellI : TODO what am I?
            - ShellMirror_Pn : TODO what am I?
            - ShellMirror_Ps : TODO what am I?
            - ShellMirror_Sn : TODO what am I?
            - ShellMirror_Ss : TODO what am I?
            - nFieldPnts : TODO what am I?
            - s_gsm : TODO what am I?
            - x_gsm : TODO what am I?
            - y_gsm : TODO what am I?
            - z_gsm : TODO what am I?
        - Bcalc : information about the magnetic field model
        - Epoch : the time of the calculation
        - Kp : Kp used for the calculation
        - MLT : MLT value for the position and coord_system
        - position : the position of the calculation
            - GSM : the value in this system, if conversions are done they all appear here


    """

    # setup a datamodel object to hold the answer
    ans = Lstar_Data()

    # change datetime to Lgm Datelong and UTC
    try:
        datelong = Lgm_CTrans.dateToDateLong(date)
        utc = Lgm_CTrans.dateToFPHours(date)
    except AttributeError:
        raise(TypeError("Date must be a datetime object"))
    else:
        ans['Epoch'] = datamodel.dmarray([date])

    # pitch angles to calculate
    try:
        Alpha = list(alpha)
    except TypeError:
        Alpha = [alpha]

    # required setup
    MagEphemInfo = Lgm_MagEphemInfo.Lgm_MagEphemInfo(len(Alpha), 0)

    # setup a shortcut to MagModelInfo
    mmi = MagEphemInfo.LstarInfo.contents.mInfo.contents
    Lgm_Set_Coord_Transforms( datelong, utc, mmi.c) # dont need pointer as it is one

    # convert to **GSM**
    if coord_system == 'GSM':
        try:
            Pgsm = Lgm_Vector.Lgm_Vector(*pos)
        except TypeError:
            raise(TypeError("Position must be listlike" ) )
        ans['position']['GSM'] = datamodel.dmarray(pos, attrs={'units':'Re'})
    elif coord_system == 'SM':
        try:
            Psm = Lgm_Vector.Lgm_Vector(*pos)
        except TypeError:
            raise(TypeError("Position must be listlike" ) )
        Pgsm = Lgm_Vector.Lgm_Vector()
        Lgm_Convert_Coords( pointer(Psm), pointer(Pgsm), SM_TO_GSM, mmi.c )
        ans['position']['SM'] = datamodel.dmarray(pos, attrs={'units':'Re'})
        ans['position']['GSM'] = datamodel.dmarray(Pgsm.tolist(), attrs={'units':'Re'})
    else:
        raise(NotImplementedError("Only GSM or SM input currently supported"))

    Pwgs = Lgm_Vector.Lgm_Vector()
    Pmlt = Lgm_Vector.Lgm_Vector()
    Lgm_Convert_Coords( pointer(Pgsm), pointer(Pwgs), GSM_TO_WGS84, mmi.c )
    Lgm_Convert_Coords( pointer(Pwgs), pointer(Pmlt), WGS84_TO_EDMAG, mmi.c )
    R, MLat, MLon, MLT = c_double(), c_double(), c_double(), c_double(),
    Lgm_EDMAG_to_R_MLAT_MLON_MLT( pointer(Pmlt),  pointer(R), pointer(MLat), pointer(MLon),
        pointer(MLT), mmi.c)
    ans['MLT'] = datamodel.dmarray(MLT.value, attrs={'coord_system': 'EDMAG'})

    # save Kp
    # TODO maybe add some Kp checking
    ans['Kp'] = datamodel.dmarray([Kp])

    # Set the LstarQuality, TODO add a comment here on what each does
    MagEphemInfo.LstarQuality = LstarQuality

    # L* in one place is L* in lots of places (for GPS set to False)
    MagEphemInfo.SaveShellLines = extended_out
    # TODO maybe not hardcoded, but for now its fine
    MagEphemInfo.LstarInfo.contents.VerbosityLevel = 0
    MagEphemInfo.LstarInfo.contents.mInfo.contents.VerbosityLevel = 0

    #MagEphemInfo->LstarInfo->mInfo->Bfield        = Lgm_B_T89;
    #MagEphemInfo->LstarInfo->mInfo->Bfield        = Lgm_B_cdip;
    #MagEphemInfo->LstarInfo->mInfo->Bfield        = Lgm_B_OP77;
    #MagEphemInfo->LstarInfo->mInfo->InternalModel = LGM_CDIP;

    ## decide which field model to use, this is a keyword
    try:
        Bfield_dict[Bfield](MagEphemInfo.LstarInfo.contents.mInfo)
    except KeyError:
        raise(NotImplementedError("Only Bfield=%s currently supported" % Bfield_dict.keys()))

    # Save Date, UTC to MagEphemInfo structure ** is this needed?
    MagEphemInfo.Date   = datelong
    MagEphemInfo.UTC    = utc
    MagEphemInfo.LstarInfo.contents.mInfo.contents.Kp = Kp

    # Save nAlpha, and Alpha array to MagEphemInfo structure
    MagEphemInfo.nAlpha = len(Alpha)
    for i in range(len(Alpha)):
        MagEphemInfo.Alpha[i] = Alpha[i]

    # Set Tolerances
    Lgm_SetLstarTolerances(LstarQuality, 24, MagEphemInfo.LstarInfo )
    # *  Blocal at sat location
    MagEphemInfo.P = Pgsm

    Bvec = Lgm_Vector.Lgm_Vector()
    # Get B at the point in question
    MagEphemInfo.LstarInfo.contents.mInfo.contents.Bfield(pointer(Pgsm), pointer(Bvec),
                                                          MagEphemInfo.LstarInfo.contents.mInfo)
    ans['Bcalc'] = datamodel.dmarray(Bvec.tolist(), attrs={'units':'nT'})
    ans['Bcalc'].attrs['model'] = Bfield
    ans['Bcalc'].attrs['Kp'] = Kp
    ans['Bcalc'].attrs['coord_system'] = 'GSM'

    # save its magnitude in the structure
    MagEphemInfo.B = Bvec.magnitude()

    # check and see if the field line is closed before doing much work
    trace, northern, southern, minB, Lsimple = Closed_Field.Closed_Field(MagEphemInfo, extended_out=True)

    # presetup the ans[Angle] so that it can be filled correctly
    for pa in Alpha:
        ans[pa] = datamodel.SpaceData()
        ans[pa]['Lsimple'] = datamodel.dmarray([Lsimple])
        #sets up nans in case of Lstar failure
        ans[pa]['I'] = datamodel.dmarray([numpy.nan])
        ans[pa]['Lstar'] = datamodel.dmarray([numpy.nan], attrs={'info':trace})
        ans[pa]['LMcIlwain'] = datamodel.dmarray([numpy.nan])
        ans[pa]['LHilton'] = datamodel.dmarray([numpy.nan])
        ans[pa]['Bmin'] = datamodel.dmarray([numpy.nan], attrs={'units':'nT'})
        ans[pa]['Bmirror'] = datamodel.dmarray([numpy.nan], attrs={'units':'nT'})
    
    if trace != 'LGM_CLOSED':
        return ans
        # if this is not LGM_CLOSED then don't both with any pitch angle?  true?

    #  Save field-related quantities for each Pitch Angle.
    MagEphemInfo.Pmin = Lgm_Vector.Lgm_Vector(*minB)
    MagEphemInfo.Bmin = MagEphemInfo.LstarInfo.contents.mInfo.contents.Bmin
    ans[pa]['Pmin'] = datamodel.dmarray(minB, attrs={'units':'R_E'})
    ans[pa]['Pmin'].attrs['coord_system'] = 'GSM'
    ans[pa]['Bmin'] = datamodel.dmarray(MagEphemInfo.Bmin, attrs={'units':'nT'})
    # LOOP OVER PITCH ANGLES
    for i, pa in enumerate(Alpha):

        tnow = datetime.datetime.now()
        PreStr = MagEphemInfo.LstarInfo.contents.PreStr
        PostStr = MagEphemInfo.LstarInfo.contents.PostStr

        # ***********************************************
        # *** not sure I fully understand this chunk, B at the mirror point*****
        # Set Pitch Angle, sin, sin^2, and Bmirror
        sa = math.sin( pa*RadPerDeg )
        sa2 = sa*sa

        # print("{0}Computing L* for Pitch Angle: Alpha[{1}] = {2} Date: {3}   UTC: {4}   Lsimple = {5:4.3}{6}\n").format(PreStr, i, MagEphemInfo.Alpha[i], date, utc, Lsimple, PostStr )
        
        if sa2!=0: #non-zero pitch angle
            MagEphemInfo.LstarInfo.contents.mInfo.contents.Bm = MagEphemInfo.B/sa2
        else:
            continue
        ans[pa]['Bmirror'] = datamodel.dmarray(MagEphemInfo.LstarInfo.contents.mInfo.contents.Bm, attrs={'units':'nT'})
        ans[pa]['Bmirror'].attrs['coord_system'] = 'GSM'
        # ***********************************************
        
        # I tink this is already done
        # Lgm_Set_Coord_Transforms( Date, UTC, MagEphemInfo.LstarInfo.contents.mInfo.contents.c )

        MagEphemInfo.LstarInfo.contents.PitchAngle = pa
        MagEphemInfo.Bm[i] = MagEphemInfo.LstarInfo.contents.mInfo.contents.Bm
        # Compute L*
        if Lsimple < LstarThresh:
            Ls_vec = Lgm_Vector.Lgm_Vector(*minB)

            LS_Flag = Lgm_Lstar( pointer(Ls_vec), MagEphemInfo.LstarInfo)

            lstarinf = MagEphemInfo.LstarInfo.contents #shortcut
            MagEphemInfo.LHilton.contents.value = LFromIBmM_Hilton(c_double(lstarinf.I[0]),
                                                c_double(MagEphemInfo.Bm[i]),
                                                c_double(lstarinf.mInfo.contents.c.contents.M_cd))
            ans[pa]['LHilton'] = MagEphemInfo.LHilton.contents.value
            MagEphemInfo.LMcIlwain.contents.value = LFromIBmM_McIlwain(c_double(lstarinf.I[0]),
                                                c_double(MagEphemInfo.Bm[i]),
                                                c_double(lstarinf.mInfo.contents.c.contents.M_cd))
            ans[pa]['LMcIlwain'] = MagEphemInfo.LMcIlwain.contents.value
            if LS_Flag == -2: # mirror below southern hemisphere mirror alt
                ans[pa]['Lstar'] = datamodel.dmarray([numpy.nan], attrs={'info':'S_LOSS'})
            elif LS_Flag == -1: # mirror below northern hemisphere mirror alt
                ans[pa]['Lstar'] = datamodel.dmarray([numpy.nan], attrs={'info':'N_LOSS'})
            elif LS_Flag >= 0: # valid calc
                ans[pa]['Lstar'] = datamodel.dmarray([lstarinf.LS], attrs={'info':'GOOD'}) # want better word?

            MagEphemInfo.Lstar[i] = lstarinf.LS

            # Save results to the MagEphemInfo structure.
            MagEphemInfo.nShellPoints[i] = lstarinf.nPnts
            ## pull all this good extra info into numpy arrays
            ans[pa]['I'] = datamodel.dmarray(lstarinf.I[0])

            if extended_out:
                ans[pa]['ShellI'] = \
                    datamodel.dmarray(numpy.ctypeslib.ndarray([len(lstarinf.I)],
                                            dtype=c_double, buffer=lstarinf.I) ).copy()
                ans[pa]['ShellEllipsoidFootprint_Pn'] = \
                    numpy.ctypeslib.ndarray(len(lstarinf.Ellipsoid_Footprint_Pn),
                                            dtype=c_double,
                                            buffer=lstarinf.Ellipsoid_Footprint_Pn).copy()
                ans[pa]['ShellEllipsoidFootprint_Ps'] = \
                    numpy.ctypeslib.ndarray(len(lstarinf.Ellipsoid_Footprint_Ps),
                                            dtype=c_double,
                                            buffer=lstarinf.Ellipsoid_Footprint_Ps).copy()

                ans[pa]['ShellMirror_Pn'] = \
                    numpy.ctypeslib.ndarray(len(lstarinf.Mirror_Pn),
                                            dtype=c_double,
                                            buffer=lstarinf.Mirror_Pn).copy()
                ans[pa]['ShellMirror_Ps'] = \
                    numpy.ctypeslib.ndarray(len(lstarinf.Mirror_Ps),
                                            dtype=c_double,
                                            buffer=lstarinf.Mirror_Ps).copy()
                ans[pa]['ShellMirror_Ss'] = lstarinf.mInfo.contents.Sm_South
                ans[pa]['ShellMirror_Sn'] = lstarinf.mInfo.contents.Sm_North
                ans[pa]['nFieldPnts'] = \
                    numpy.ctypeslib.ndarray(len(lstarinf.nFieldPnts),
                                            dtype=c_int,
                                            buffer=lstarinf.nFieldPnts).copy()

                ans[pa]['s_gsm'] = \
                    numpy.ctypeslib.ndarray([len(lstarinf.s_gsm),
                                             len(lstarinf.s_gsm[0])],
                                            dtype=c_double,
                                            buffer=lstarinf.s_gsm).copy()
                ans[pa]['Bmag'] = \
                    numpy.ctypeslib.ndarray([len(lstarinf.Bmag),
                                             len(lstarinf.Bmag[0])],
                                            dtype=c_double,
                                            buffer=lstarinf.Bmag).copy()
                ans[pa]['x_gsm'] = \
                    numpy.ctypeslib.ndarray([len(lstarinf.x_gsm),
                                             len(lstarinf.x_gsm[0])],
                                            dtype=c_double,
                                            buffer=lstarinf.x_gsm).copy()
                ans[pa]['y_gsm'] = \
                    numpy.ctypeslib.ndarray([len(lstarinf.y_gsm),
                                             len(lstarinf.y_gsm[0])],
                                            dtype=c_double,
                                            buffer=lstarinf.y_gsm).copy()
                ans[pa]['z_gsm'] = \
                    numpy.ctypeslib.ndarray([len(lstarinf.z_gsm),
                                             len(lstarinf.z_gsm[0])],
                                            dtype=c_double,
                                            buffer=lstarinf.z_gsm).copy()
                delT = datetime.datetime.now() - tnow
                ans[pa].attrs['Calc_Time'] = delT.seconds + delT.microseconds/1e6

    Lgm_FreeMagEphemInfo_Children(pointer(MagEphemInfo))
    return ans
예제 #12
0
    def __init__(self,
                 pos,
                 time,
                 direction='NORTH',
                 coord_system='GSM',
                 INTERNAL_MODEL='LGM_IGRF',
                 EXTERNAL_MODEL='LGM_EXTMODEL_T89',
                 MAGMODEL_ARGS=None,
                 TargetHeight=120,
                 tol=1e-7):
        super(Lgm_TraceToEarth_py,
              self).__init__(Position=pos,
                             Epoch=time,
                             direction=direction,
                             coord_system=coord_system,
                             INTERNAL_MODEL=INTERNAL_MODEL,
                             EXTERNAL_MODEL=EXTERNAL_MODEL,
                             TargetHeight=TargetHeight,
                             tol=tol)
        if not isinstance(pos, Lgm_Vector.Lgm_Vector) and \
            not isinstance(pos, list):
            raise (TypeError('pos must be a Lgm_Vector or list'))
        self._Vpos = pos2Lgm_Vector(pos)
        # time must be a datetime
        if not isinstance(time, datetime.datetime) and \
            not isinstance(time, list):
            raise (TypeError('time must be a datetime or list of datetime'))

        if direction[0].upper() == 'N':
            direction = 1.0
        elif direction[0].upper() == 'S':
            direction = -1.0
        else:
            raise (ValueError("Did not understand direction, must be N or S"))


        if INTERNAL_MODEL not in (LGM_CDIP,
                                  LGM_EDIP,
                                  LGM_IGRF) and \
            INTERNAL_MODEL not in ('LGM_CDIP',
                                  'LGM_EDIP',
                                  'LGM_IGRF'):
            raise (ValueError(
                'INTERNAL_MODEL must be LGM_CDIP, LGM_EDIP, or LGM_IGRF'))
        if isinstance(INTERNAL_MODEL, str):
            INTERNAL_MODEL = eval(INTERNAL_MODEL)
        self.attrs['internal_model'] = INTERNAL_MODEL

        if coord_system != 'GSM':
            raise (NotImplementedError(
                'Different coord systems are not yet ready to use'))

        self._mmi = Lgm_MagModelInfo.Lgm_MagModelInfo()

        # and actually set the internal model in Lgm
        if self.attrs['internal_model'] == LGM_CDIP:
            Lgm_Set_Lgm_B_cdip_InternalModel(pointer(self._mmi))
        elif self.attrs['internal_model'] == LGM_EDIP:
            Lgm_Set_Lgm_B_edip_InternalModel(pointer(self._mmi))
        elif self.attrs['internal_model'] == LGM_IGRF:
            Lgm_Set_Lgm_B_IGRF_InternalModel(pointer(self._mmi))

        # set the external field model
        if EXTERNAL_MODEL not in (LGM_EXTMODEL_NULL,
                                  LGM_EXTMODEL_T87,
                                  LGM_EXTMODEL_T89,
                                  LGM_EXTMODEL_T89c,
                                  LGM_EXTMODEL_T96,
                                  LGM_EXTMODEL_T01S,
                                  LGM_EXTMODEL_T02,
                                  LGM_EXTMODEL_TS04,
                                  LGM_EXTMODEL_TS07,
                                  LGM_EXTMODEL_OP77) and \
          EXTERNAL_MODEL not in ('LGM_EXTMODEL_NULL',
                                  'LGM_EXTMODEL_T87',
                                  'LGM_EXTMODEL_T89',
                                  'LGM_EXTMODEL_T89c',
                                  'LGM_EXTMODEL_T96',
                                  'LGM_EXTMODEL_T01S',
                                  'LGM_EXTMODEL_T02',
                                  'LGM_EXTMODEL_TS04',
                                  'LGM_EXTMODEL_TS07',
                                  'LGM_EXTMODEL_OP77'):
            raise (ValueError('INTERNAL_MODEL must be {0}'.format(
                'LGM_EXTMODEL_NULL', 'LGM_EXTMODEL_T87', 'LGM_EXTMODEL_T89',
                'LGM_EXTMODEL_T89c', 'LGM_EXTMODEL_T96', 'LGM_EXTMODEL_T01S',
                'LGM_EXTMODEL_T02', 'LGM_EXTMODEL_TS04', 'LGM_EXTMODEL_TS07',
                'LGM_EXTMODEL_OP77')))
        if isinstance(EXTERNAL_MODEL, str):
            EXTERNAL_MODEL = eval(EXTERNAL_MODEL)
        self.attrs['external_model'] = EXTERNAL_MODEL

        # and actually set the internal model in Lgm
        if self.attrs['external_model'] == LGM_EXTMODEL_T89:
            Lgm_Set_Lgm_B_T89(pointer(self._mmi))
            self._mmi.Kp = MAGMODEL_ARGS['Kp']
        elif self.attrs['external_model'] == LGM_EXTMODEL_OP77:
            Lgm_Set_Lgm_B_OP77(pointer(self._mmi))
        else:
            raise (NotImplementedError(
                "The external model has not yet been implemented: {0}".format(
                    self.attrs['external_model'])))

        # either they are all one element or they are compatible lists no 1/2 way
        try:
            if len(self._Vpos) != len(self['Kp']) or \
                len(self._Vpos) != len(self['Epoch']) or \
                len(self['Epoch']) != len(self['Kp']):
                raise (ValueError(
                    'Inputs must be the same length, scalars or lists'))
        except TypeError:
            if isinstance(self._Vpos, list) and not isinstance(self['Kp'], list) \
                and not isinstance(self['Epoch'], list):
                raise (ValueError(
                    'Inputs must be the same length, scalars or lists'))

        date = Lgm_CTrans.dateToDateLong(self['Epoch'])
        utc = Lgm_CTrans.dateToFPHours(self['Epoch'])
        Lgm_Set_Coord_Transforms(date, utc,
                                 self._mmi.c)  # dont need pointer as it is one

        ans = Lgm_Vector.Lgm_Vector(-1, -1, -1)

        retval = Lgm_TraceToEarth(pointer(self._Vpos), ctypes.pointer(ans),
                                  ctypes.c_double(TargetHeight),
                                  ctypes.c_double(direction),
                                  ctypes.c_double(tol), pointer(self._mmi))

        if retval == LGM_CLOSED:
            self['footpoint'] = ans
            self.attrs['retcode'] = retval
        elif retval == LGM_OPEN_IMF:
            self['footpoint'] = np.nan
            warnings.warn("LGM_OPEN_IMF")
            self.attrs['retcode'] = retval
        elif retval == LGM_OPEN_N_LOBE:
            self['footpoint'] = np.nan
            warnings.warn("LGM_OPEN_N_LOBE")
            self.attrs['retcode'] = retval
        elif retval == LGM_OPEN_S_LOBE:
            self['footpoint'] = np.nan
            warnings.warn("LGM_OPEN_S_LOBE")
            self.attrs['retcode'] = retval
        elif retval == LGM_INSIDE_EARTH:
            self['footpoint'] = np.nan
            warnings.warn("LGM_INSIDE_EARTH")
            self.attrs['retcode'] = retval
        elif retval == LGM_TARGET_HEIGHT_UNREACHABLE:
            self['footpoint'] = np.nan
            warnings.warn("LGM_TARGET_HEIGHT_UNREACHABLE")
            self.attrs['retcode'] = retval
        elif retval == LGM_BAD_TRACE:
            self['footpoint'] = np.nan
            warnings.warn("LGM_BAD_TRACE")
            self.attrs['retcode'] = retval