def test_isoformat2(self): """can change the iso format '%Y-%m-%dT%H:%M:%SZ'""" t1 = t.Ticktock([ '2002-01-01T01:02:12Z', '2002-01-02T02:04:12Z', '2001-12-12T23:56:23Z' ]) t1.isoformat('microseconds') expected = [ '2002-01-01T01:02:12.000000', '2002-01-02T02:04:12.000000', '2001-12-12T23:56:23.000000' ] numpy.testing.assert_equal(t1.ISO, expected) self.assertRaises(ValueError, t1.isoformat, 'badval')
def omnirange(dbase='QDhourly'): '''Returns datetimes giving start and end times in the OMNI/Qin-Denton data The update function in toolbox retrieves all available hourly Qin-Denton data, and this function accesses that and looks up the start and end times, returning them as datetime objects. Parameters ========== dbase : string (optional) name of omni database to check. Currently 'QDhourly' and 'OMNI2hourly' Returns ======= omnirange : tuple containing two datetimes giving the start and end times of the available data Examples ======== >>> import spacepy.omni as om >>> om.omnirange() (datetime.datetime(1963, 1, 1, 0, 0), datetime.datetime(2011, 11, 30, 23, 0)) >>> om.omnirange(dbase='OMNI2hourly') (datetime.datetime(1963, 1, 1, 0, 0), datetime.datetime(2011, 11, 30, 23, 0)) ''' import h5py as h5 infile = {'QDhourly': omnifln, 'OMNI2hourly': omni2fln, 'Test': testfln} if dbase not in infile: raise NotImplementedError('') with h5.File(infile[dbase]) as hfile: start, end = hfile['RDT'][0], hfile['RDT'][-1] start = spt.Ticktock(start, 'RDT').UTC[0] end = spt.Ticktock(end, 'RDT').UTC[0] return start, end
def test_ISO(self): """converting to ISO format should work""" t0 = 1663236947 range_ex = list(numpy.linspace(t0, t0 + 4000, 4)) # make a TAI that is a leapsecond time tt2 = t.Ticktock.now() tt2tai = tt2.TAI taileaps = tt2.TAIleaps range_ex.append(taileaps[39]) range_ex.append(taileaps[38]) tt = t.Ticktock(range_ex, 'TAI') ans = ['2010-09-15T10:15:13', '2010-09-15T10:37:26', '2010-09-15T10:59:39', '2010-09-15T11:21:53', '2015-07-01T00:00:00', '2012-07-01T00:00:00'] numpy.testing.assert_equal(tt.ISO, ans)
def test_getSolarRotation_Bartels(self): """make sure getSolarRotation returns known values""" dates = spt.Ticktock([ dup.parse(t) for t in [ '1832-02-08T00:00:00', '2004-05-06T12:00:00', '2012-12-12T00:00:00' ] ]) real_ans = np.array([1, 2331, 2447]).astype(int) ans = em.getSolarRotation(dates, rtype='bartels') np.testing.assert_almost_equal(real_ans, ans) float_ans = np.array([1.0, 2331.0185185185187, 2447.3703703703704]) ans = em.getSolarRotation(dates, rtype='bartels', fp=True) np.testing.assert_almost_equal(float_ans, ans)
def get_kvec2(lon, lat, alt, ephtimes=None, tx_lon=-75.552, tx_lat=45.403, tx_alt=.07): """ Uses cartesian coordinates (GEO XYZ) to get absolute direction vector between two (lon, lat, alt) points. *** PARAMS *** lon (float or array): longitude of point(s) from transmitter lat (float or array): latitude of point(s) from transmitter altitude (float or array): altitude of point(s) from transmitter [tx_lon] (float): longitude of transmitter [deg] [tx_lat] (float): latitude of transmitter [deg] [tx_alt] (float): altitude of transmitter [km] *** RETURNS *** kv (float or array): vector(s) from transmitter to input point(s) """ import spacepy.coordinates as coord import spacepy.time as tm import datetime as dt b = coord.Coords([[alt + EARTH_RAD, lat, lon]],'GEO','sph') a = coord.Coords([[tx_alt + EARTH_RAD, tx_lat, tx_lon]], 'GEO', 'sph') if ephtimes is None: b.ticks = tm.Ticktock(dt.datetime.now()) # because it doesnt matter a.ticks = tm.Ticktock(dt.datetime.now()) # because it doesnt matter else: times = ephems_to_datetime(ephtimes) b.ticks = tm.Ticktock(times) a.ticks = tm.Ticktock(times) b = b.convert('GEO','car') a = a.convert('GEO','car') kv = (b.data - a.data)[0] kv = kv/np.linalg.norm(kv) logging.info("get_kvecs2 result: ", kv) return kv
def test_getSolarRotation_Carrington(self): """make sure getSolarRotation returns known values""" dates = spt.Ticktock([ dup.parse(t) for t in [ '1853-11-10T00:00:00', '1973-08-22T18:00:00', '2003-03-19T12:02:45' ] ]) real_ans = np.array([1, 1605, 2001]).astype(int) ans = em.getSolarRotation(dates, rtype='carrington') np.testing.assert_almost_equal(real_ans, ans) float_ans = np.array( [1.003596660715006, 1605.009785410243, 2001.000000356448]) ans = em.getSolarRotation(dates, rtype='carrington', fp=True) np.testing.assert_almost_equal(float_ans, ans)
def B_dir_3D(t, x, dtime, bmodel, extfield, direction): # p0 must be in GEO car in RE # dtime must be a datetime object pos = spc.Coords([x[0], x[1], x[2]], 'GEO', 'car') tv = spt.Ticktock(dtime) B = irbem.get_Bfield(tv, pos, extMag=extfield, options=[1, 0, 0, 0, bmodel], omnivals=None) Bmags = direction * B['Bvec'] / B['Blocal'] return [Bmags[0][0], Bmags[0][1], Bmags[0][2]]
def GSE2GSM_B(MFI): """ GSE转GSM函数 输入:字典格式数据 输出:np.ndarray格式数据 """ GSM = np.zeros((3, len(MFI["BZ"]))) for i in range(GSM.shape[1]): SM = spc.Coords([[MFI["BX"][i], MFI["BY"][i], MFI["BZ"][i]]], 'GSE', 'car') SM.ticks = spt.Ticktock(MFI["EPOCH"][i], 'ISO') SM = SM.convert('GSM', 'car') GSM[0][i] = SM.data[0][0] GSM[1][i] = SM.data[0][1] GSM[2][i] = SM.data[0][2] return GSM
def GSE2GSM(FPE): """ GSE转GSM函数 输入:字典格式数据 输出:np.ndarray格式数据 """ GSM = np.zeros((3, FPE["X_GSE"].shape[0])) for i in range(GSM.shape[1]): SM = spc.Coords([[FPE["X_GSE"][i], FPE["Y_GSE"][i], FPE["Z_GSE"][i]]], 'GSE', 'car') SM.ticks = spt.Ticktock(FPE["EPOCH"][i], 'ISO') SM = SM.convert('GSM', 'car') GSM[0][i] = SM.data[0][0] GSM[1][i] = SM.data[0][1] GSM[2][i] = SM.data[0][2] return GSM
def L_para(T_E): L1 = parser.get('mission_parameters', 'TLE_Line1') L2 = parser.get('mission_parameters', 'TLE_Line2') satellite = twoline2rv(L1, L2, wgs72) position, velocity = satellite.propagate(T_E[0], T_E[1], T_E[2], T_E[3], T_E[4], T_E[5]) Re = [(x / 6371.2) for x in position] spaco = spc.Coords(Re, 'GEI', 'car') spaco.ticks = spt.Ticktock([T_E[6]], 'ISO') q = [90] # q=spaco.convert('SM','sph') #default value of 90 is used as it returns the most data-points, other values of q have more instances when the value returned is NaN # q=q.data[0][1] L = ir.get_Lm(spaco.ticks, spaco, q, extMag='T01STORM', intMag='IGRF') return satellite.alta * 6371, satellite.altp * 6371, math.degrees( satellite.inclo), L.items()[2][1][0][0]
def omnirange(dbase='QDhourly'): '''Returns datetimes giving start and end times in the OMNI/Qin-Denton data The update function in toolbox retrieves all available hourly Qin-Denton data, and this function accesses that and looks up the start and end times, returning them as datetime objects. Parameters ========== dbase : string (optional) name of omni database to check. Currently 'QDhourly' and 'OMNI2hourly' Returns ======= omnirange : tuple containing two datetimes giving the start and end times of the available data Examples ======== >>> import spacepy.omni as om >>> om.omnirange() (datetime.datetime(1963, 1, 1, 0, 0), datetime.datetime(2011, 11, 30, 23, 0)) >>> om.omnirange(dbase='OMNI2hourly') (datetime.datetime(1963, 1, 1, 0, 0), datetime.datetime(2011, 11, 30, 23, 0)) ''' import h5py as h5 infile = {'QDhourly': omnifln, 'OMNI2hourly': omni2fln, 'Test': testfln} if dbase not in infile: raise NotImplementedError('') # Possible time variables in the HDF file and their ticktock dtype timeinfo = [('UTC', 'UTC'), ('Epoch', 'ISO'), ('RDT', 'RDT')] with h5.File(infile[dbase], mode='r') as hfile: for varname, dtype in timeinfo: if varname in hfile: tt = spt.Ticktock([hfile[varname][0], hfile[varname][-1]], dtype=dtype) break else: raise ValueError('Cannot find time variable in {}' .format(infile[dbase])) start, end = tt.UTC return start, end
def getTilt(t): """ gets the dipole tilt and adds it to the tsyganenko cusp model almost a direct copy of J. niehof's code This also somewhat necessitates that we do the rest of the analysis in the GSM frame t = the pandas list of times (I'm assuming MJD for this use case) """ t = spt.Ticktock(t, 'MJD') c_sm = coord.Coords([[0, 0, 1.0]] * len(t), 'SM', 'car') c_sm.ticks = t # convert to gsm c_gsm = c_sm.convert('GSM', 'car') # i set this to be negative as an experiment. return np.rad2deg(np.arctan2(c_gsm.x, c_gsm.z)) #changed from x,z to z,x
def test_resample2(self): '''resample should give consistent results (ticktock)''' ans = {} ans['a'] = [ 1., 3., 5., 7.] ans['b'] = [5., 7., 9., 11.] ans['Epoch'] = [datetime.datetime(2010, 1, 1, 1, 0), datetime.datetime(2010, 1, 1, 3, 0), datetime.datetime(2010, 1, 1, 5, 0), datetime.datetime(2010, 1, 1, 7, 0)] a = dm.SpaceData() a['a'] = dm.dmarray(range(10)) a['b'] = dm.dmarray(range(10)) + 4 a['c'] = dm.dmarray(range(3)) + 10 times = spt.Ticktock([datetime.datetime(2010, 1, 1) + datetime.timedelta(hours=i) for i in range(10)]) out = dm.resample(a, times, winsize=datetime.timedelta(hours=2), overlap=datetime.timedelta(hours=0)) for k, v in out.items(): np.testing.assert_equal(v, ans[k])
def test_resample2(self): '''resample should give consistent results (ticktock)''' ans = {} ans['a'] = [ 0.5, 2.5, 4.5, 6.5, 8.5] ans['b'] = [4.5, 6.5, 8.5, 10.5, 12.5] ans['Epoch'] = [datetime.datetime(2010, 1, 1, 1, 0), datetime.datetime(2010, 1, 1, 3, 0), datetime.datetime(2010, 1, 1, 5, 0), datetime.datetime(2010, 1, 1, 7, 0), datetime.datetime(2010, 1, 1, 9, 0)] #For justification of test results see test above (test_resample1) a = dm.SpaceData() a['a'] = dm.dmarray(range(10)) a['b'] = dm.dmarray(range(10)) + 4 a['c'] = dm.dmarray(range(3)) + 10 times = spt.Ticktock([datetime.datetime(2010, 1, 1) + datetime.timedelta(hours=i) for i in range(10)]) out = dm.resample(a, times, winsize=datetime.timedelta(hours=2), overlap=datetime.timedelta(hours=0)) for k, v in out.items(): np.testing.assert_equal(v, ans[k])
def julToDatetime(ndarray): """ **************************** adate = julToDatetime( ndarray ) Convert a julian date to a datetime object. INPUT: NDARRAY: single float64 or a numpy array of Julian Dates. Created by Nathaniel Frissell 20120810 ******************************* """ import datetime import dateutil.parser import numpy import spacepy.time as spt t = spt.Ticktock(ndarray, 'JD') dt = list() for iso in t.ISO: dt.append(dateutil.parser.parse(iso)) return dt
def plotMSBS(time=None, data=None, angles=(-125, 125), npts=30, mp=True, bs=True): """ Plot bow shock and magnetopause Sample compressed time: 2012-10-02T03:00:00 Sample "normal" time: 2012-07-22T12:00:00 """ import spacepy.omni as om import spacepy.empiricals as emp import spacepy.plot as splot import matplotlib.pyplot as plt if time is None and data is None: #use default time for "nominal" values time = spt.Ticktock('2012-10-02T03:00:00') omd = om.get_omni(time, dbase='OMNI2hourly') elif time is None and data is not None: omd = data elif time is not None and data is None: omd = om.get_omni(time, dbase='OMNI2hourly') else: raise ValueError('Use either "time" or "data" kwarg - not both.') fig, ax0 = plt.subplots(1) if mp: xmp, ymp = magnetopause(omd, np.linspace(angles[0], angles[1], npts)) ax0.plot(xmp, ymp, 'k:', label='Shue1997') if bs: x, y = get_BS_eq(omd, angles=angles, npts=npts) ax0.plot(x, y, 'k-.', label='Chao2002') ax0.set_aspect('equal') splot.dual_half_circle(ax=ax0) ax0.set_ylabel('Y$_{GSE}$ [R$_{E}$]') ax0.set_xlabel('X$_{GSE}$ [R$_{E}$]') # ax0.legend() ax0.set_xlim([-40, 40]) ax0.set_ylim([-45, 45]) return fig, ax0
############################################################################## from spacepy.coordinates import Coords import spacepy.time as spt import astropy.units as u from astropy.coordinates import SkyCoord from sunpy.coordinates import frames ############################################################################## # First, create a `SpacePy coordinate <https://spacepy.github.io/autosummary/spacepy.coordinates.Coords.html>`_ in the (Cartesian) Geographic # Coordinate System (GEO) and attach an observation time to the coordinate. # Units are in Earth radii (Re). coord = Coords([[1, 2, 4], [1, 2, 2]], 'GEO', 'car') coord.ticks = spt.Ticktock(['2002-02-02T12:00:00', '2002-02-02T12:00:00'], 'ISO') print(coord) # In SpacePy, the convert method can be used to easily convert coordinates into # one of the `10 coordinate systems <https://spacepy.github.io/coordinates.html>`_ supported. # For example, convert the coordinates to the (Cartesian) Solar Magnetic system. sm = coord.convert('SM', 'car') print(sm) ############################################################################## # Send the coordinates to an Astropy SkyCoord instance using the SpacePy # to_skycoord function. Units are converted to meters. # Note: this must be in the GEO system. skycoord = coord.to_skycoord() print(skycoord)
import datetime import time import timeit import numpy as np import spacepy.time as spt number = 200 gps = np.linspace(6.96556813e+08, 6.97334413e+08, 10) tt = spt.Ticktock(gps, 'GPS') print(tt) print(tt.TAI)
def trace_drift_shell(self,sm_loc,t_loc,Ech,sinA_loc,sim_dt,verbose=True,Vdip_inj=None): # This function is an improve version of trace_drift, it accept coordinates in SM as a vector # And the time as datetime parameter # Input parameters # 1- Date and time of the injection #-------------------------------------------------------------------------------# #_date = self.date _imod = self.imod # magnetic field model: 0=dipole, 1=T96_01, 2=T01_1, 3=T04_s _ipot = self.ipot # electric field model: 1=Weimer, 2=CIMI _itrace = self.itrace # 1=forward, -1=backward tracing #_tsec0 = self.tsec # initial time in second #_tend = self.tend # end time in second #_ro = self.ro # initial radial distance in RE #_mlt = self.mlt # initial mlt in hour _ekev0 = Ech # initial energy in keV _ion= self.ion # 1=ion, -1=electron _tf = self.tf # time resolution in seconds in updating omni parameters #-------------------------------------------------------------------------------# ### Main trace_drift subroutine pi=np.pi dra=_itrace*0.5*pi/180. # drift path tracing step size in radian iprint=1 # print result every iprint steps re=6.371e6 # Earth's radius (m) if (_ion == 1): Eo=9.38269e5 # proton rest energy if (_ion == -1): Eo=511. # electron rest energy Eo2=Eo*Eo pc_sq=(_ekev0+Eo)**2-Eo2 # (pc)^2 in keV^2 latmax=72.*pi/180. # max allowable latitude at the ionosphere reqmax=10. # max allowable equatorial distance istepmax=3000 # max allowable istep rc=1. #Find dipole moment iyear = t_loc.year dts = spt.Ticktock(t_loc) iday = dts.DOY tsec0_dt = t_loc parmod,nsw,vxgse,vygse,vzgse = self.TsyParmod(tsec0_dt,_imod)# vy and vz are 0 to ensure GSM coordinate system tsygFort.recalc_08(iyear,iday,tsec0_dt.hour,tsec0_dt.minute,tsec0_dt.second,vxgse,vygse,vzgse) GGG=tsygFort.geopack2.g HHH=tsygFort.geopack2.h DIPMOM=np.sqrt(GGG[1]**2+GGG[2]**2+HHH[2]**2) # DIPMOM in (nT RE^3) xme=DIPMOM*re**3*1.e-9 # dipole moment in (T m^3) #xme = np.exp(36.58626097) # Find the initial ionospheric projection (along field line) point #phi=_mlt*pi/12. #xeq=-_ro*np.cos(phi) # +x --> Sun #yeq=-_ro*np.sin(phi) #zeq=0. lati,mlti = self.mapping(_imod,parmod,sm_loc[0],sm_loc[1],sm_loc[2],0,0,1) x0 = np.zeros(2) x0[0]=lati # latitude in radian x0[1]=mlti # local time in radian xeq,yeq,zeq,iout=self.mapping(_imod,parmod,0,0,0,x0[0],x0[1],-1) # find Bmag, sinA at the initial position and the invariant pcy2B bx,by,bz,Bmag=self.Tsy_w_dip(_imod,parmod,xeq,yeq,zeq) # find B at magnetic equator bx,by,bz,Bloc=self.Tsy_w_dip(_imod,parmod,sm_loc[0],sm_loc[1],sm_loc[2]) # find B at local position _sinA=np.sqrt(Bmag/Bloc*sinA_loc*sinA_loc) # Pitch angle at the magnetic equator if _sinA > 1: _sinA = 1 print('Warning: B at the equator > B loc, possible orbit bifurcation. Temp solution make sin(PA)=1') #ipdb.set_trace() if (np.arcsin(_sinA) >= 80/180*pi): # if PA > 80 we consider as 90 degrees. print('Warning: real PA is %4.2f, as it is > 80 we assume 90' %(np.arcsin(_sinA)*180/pi) ) _sinA = 1 self.pcy2B=pc_sq*_sinA*_sinA/Bmag # First invariant, Bmag = B at equator self.K = 0. else: self.pcy2B=pc_sq*_sinA*_sinA/Bmag # First invariant, Bmag = B at equator self.K = self.KofAlpha(np.arcsin(_sinA),lati,mlti,_imod,parmod) # Second invariant K # Print the initial condition #ipdb.set_trace() pitchA=np.arcsin(_sinA)*180./pi Lshell=rc/(np.cos(lati))**2 mlti_d=mlti*12./pi # mlt at ionosphere in hour ro_loc=np.sqrt(sm_loc[0]*sm_loc[0]+sm_loc[1]*sm_loc[1]+sm_loc[2]*sm_loc[2]) phi=np.arctan2(sm_loc[1],sm_loc[0]) mlt_loc=phi*12./pi+12. print('Info: the first line show Ro local and mlt local, i.e at the pos of the S/C and not at the equator') print('%i %i %i %i %i %4.2f ! iyear,iday,imod,ipot,ion,tf' %(iyear,iday,_imod,_ipot,_ion,_tf)) print(' tsec Dst Lshell mlti ro mlto ekeV PA Vsw Pdyn') print('%s %7.0f %9.3f %9.3f %9.3f %6.3f %6.1f %6.2f' %(tsec0_dt.isoformat()\ ,parmod[1],Lshell,mlti_d,ro_loc,mlt_loc,_ekev0,pitchA)) #ipdb.set_trace() # Start drift path tracing epoch = dt.datetime(1970,1,1) _tend=(tsec0_dt-epoch).total_seconds() + _itrace*sim_dt # UTC seconds since epoch time tsec=(tsec0_dt-epoch).total_seconds() # UTC seconds since epoch time istep=0 iexit=0 lastprint=0 iexit=0 vswi=vxgse xnswi = nsw Dst0 = parmod[1] xeq0=0;yeq0=0;zeq0=0 ## roarr=np.zeros(istepmax) mltoarr=np.zeros(istepmax) #tsecarr=np.zeros(istepmax) tsecarr = [] Eoarr = np.zeros(istepmax) pitchAarr = np.zeros(istepmax) if Vdip_inj!=None: #ipdb.set_trace() vdip = self.Vdip_i(Vdip_inj,_imod,parmod) ## Added May 25, simulate injection else: vdip = 0 ## Start debugging while (iexit != 1): #ipdb.set_trace() xend,dtsec=self.rk4(_imod,_ipot,parmod,vswi,xnswi,_ion,dra,Eo,xme,x0,_sinA,veldip=vdip) if (np.arcsin(_sinA) < 80/180*pi): _Alpha,_Bmag = self.AlphaOfK(self.K,xend[0],xend[1],_imod,parmod) _sinA = np.sin(_Alpha) else: _sinA = 1 # update istep, tsec, Bmag istep=istep+1 tsec=tsec+dtsec xeq,yeq,zeq,iout=self.mapping(_imod,parmod,0,0,0,xend[0],xend[1],-1) req=np.sqrt(xeq*xeq+yeq*yeq) # test for exit or continue if (istep==istepmax): iexit=1 if (iout==1): iexit=1 if (xend[0]>=latmax): iexit=1 print('Warning: xend[0]>=latmax') if (req>=reqmax): iexit=1 if ((_itrace==1) and (tsec>=_tend)): iexit=1 if ((_itrace==-1) and (tsec<=_tend)): iexit=1 # Reasign values if iexit.eq.1 if (iexit==1): #ipdb.set_trace() tsec=tsec-dtsec xend=x0 parmod[1]=Dst0 xeq=xeq0 yeq=yeq0 zeq=zeq0 req=np.sqrt(xeq*xeq+yeq*yeq) if (tsec>=tprint): lastprint=1 # print result every iprint step and at the end of the trace if ((np.mod(istep,iprint)==0) or (lastprint==1)): bx,by,bz,Bmag = self.Tsy_w_dip(_imod,parmod,xeq,yeq,zeq) #ipdb.set_trace() pc_sq=self.pcy2B*Bmag/_sinA/_sinA ekev=np.sqrt(pc_sq+Eo2)-Eo pitchA=np.arcsin(_sinA)*180./pi Lshell=rc/(np.cos(xend[0]))**2 mlti_d=xend[1]*12./pi ## mlt at ionosphere in hour phi=np.arctan2(yeq,xeq) mlteq=phi*12./pi+12. tprint=tsec roarr[istep-1]=req ## variables for ploting mltoarr[istep-1]=mlteq #tsecarr[istep-1]= tsec tsecarr.append(epoch + timedelta(seconds=tsec)) Eoarr[istep-1]=ekev pitchAarr[istep-1] = pitchA if verbose == True: print('%s %7.0f %9.3f %9.3f %9.3f %6.3f %6.1f %6.2f %7.2f %6.4f'\ %(tsecarr[istep-1].isoformat(),parmod[1],Lshell,mlti_d,req,mlteq,ekev,pitchA,vswi,parmod[0])) # Save values Dst0=parmod[1] xeq0=xeq yeq0=yeq zeq0=zeq # Update x0 and Tsyganenko parmod x0=xend if istep==1: dstep = int(_tf/dtsec) # choose an aproximate dt step for changing SW parameters if np.mod(istep,dstep)==0: parmod,xnswi,vswi,vygse,vzgse = self.TsyParmod(tsecarr[istep-1],_imod) return tsecarr,mltoarr,roarr,Eoarr,pitchAarr,istep
def trace_drift(self): # Input parameters # 1- Date and time of the injection #-------------------------------------------------------------------------------# _date = self.date _imod = self.imod # magnetic field model: 0=dipole, 1=T96_01, 2=T01_1, 3=T04_s _ipot = self.ipot # electric field model: 1=Weimer, 2=CIMI _itrace = self.itrace # 1=forward, -1=backward tracing _tsec0 = self.tsec # initial time in second _tend = self.tend # end time in second _ro = self.ro # initial radial distance in RE _mlt = self.mlt # initial mlt in hour _ekev0 = self.ekev0 # initial energy in keV _Kin = 0 # K index, 0=equatorially mirroring (reserved, not used now) _ion= self.ion # 1=ion, -1=electron _tf = self.tf # time resolution in seconds in updating omni parameters #-------------------------------------------------------------------------------# ### Main trace_drift subroutine pi=np.pi dra=_itrace*0.5*pi/180. # drift path tracing step size in radian iprint=1 # print result every iprint steps re=6.371e6 # earth's radius (m) if (_ion == 1): Eo=9.38269e5 # proton rest energy if (_ion == -1): Eo=511. # electron rest energy Eo2=Eo*Eo pc_sq=(_ekev0+Eo)**2-Eo2 # (pc)^2 in keV^2 latmax=72.*pi/180. # max allowable latitude at the ionosphere reqmax=10. # max allowable equatorial distance istepmax=3000 # max allowable istep rc=1. #Find dipole moment iyear = _date.year dts = spt.Ticktock(_date) iday = dts.DOY tsec0_dt = _date+timedelta(seconds=_tsec0) parmod,nsw,vxgse,vygse,vzgse = self.TsyParmod(_date+timedelta(seconds=_tsec0),_imod)# vy and vz are 0 to ensure GSM coordinate system tsygFort.recalc_08(iyear,iday,tsec0_dt.hour,tsec0_dt.minute,tsec0_dt.second,vxgse,vygse,vzgse) GGG=tsygFort.geopack2.g HHH=tsygFort.geopack2.h DIPMOM=np.sqrt(GGG[1]**2+GGG[2]**2+HHH[2]**2) # DIPMOM in (nT RE^3) xme=DIPMOM*re**3*1.e-9 # dipole moment in (T m^3) #xme = np.exp(36.58626097) # Find the initial ionospheric projection (along field line) point phi=_mlt*pi/12. xeq=-_ro*np.cos(phi) # +x --> Sun yeq=-_ro*np.sin(phi) zeq=0. lati,mlti = self.mapping(_imod,parmod,xeq,yeq,zeq,0,0,1) x0 = np.zeros(2) x0[0]=lati # latitude in radian x0[1]=mlti # local time in radian # find Bmag, sinA at the initial position and the invariant pcy2B bx,by,bz,Bmag=self.Tsy_w_dip(_imod,parmod,xeq,yeq,zeq) _sinA=self.sinA #ipdb.set_trace() self.pcy2B=pc_sq*_sinA*_sinA/Bmag # First invariant, Bmag = B at equator self.K = self.KofAlpha(np.arcsin(_sinA),lati,mlti,_imod,parmod) # Second invariant K # Print the initial condition pitchA=np.arcsin(_sinA)*180./pi Lshell=rc/(np.cos(lati))**2 mlti_d=mlti*12./pi # mlt at ionosphere in hour print('%i %i %i %i %i %4.2f ! iyear,iday,imod,ipot,ion,tf' %(iyear,iday,_imod,_ipot,_ion,_tf)) print(' tsec Dst Lshell mlti ro mlto ekeV PA Vsw Pdyn') print('%6.2f %7.0f %9.3f %9.3f %9.3f %6.3f %6.1f %6.2f' %(_tsec0,parmod[1],Lshell,mlti_d,_ro,_mlt,_ekev0,pitchA)) # ipdb.set_trace() # Start drift path tracing tsec=_tsec0 istep=0 iexit=0 lastprint=0 iexit=0 vswi=vxgse xnswi = nsw Dst0 = parmod[1] xeq0=0;yeq0=0;zeq0=0 ## roarr=np.zeros(istepmax) mltoarr=np.zeros(istepmax) tsecarr=np.zeros(istepmax) Eoarr=np.zeros(istepmax) ## Start debugging while (iexit != 1): #ipdb.set_trace() xend,dtsec=self.rk4(_imod,_ipot,parmod,vswi,xnswi,_ion,dra,Eo,xme,x0,_sinA) if (_sinA!=1): _Alpha,_Bmag = self.AlphaOfK(self.K,xend[0],xend[1],_imod,parmod) _sinA = np.sin(_Alpha) # update istep, tsec, Bmag istep=istep+1 tsec=tsec+dtsec xeq,yeq,zeq,iout=self.mapping(_imod,parmod,0,0,0,xend[0],xend[1],-1) req=np.sqrt(xeq*xeq+yeq*yeq) # test for exit or continue if (istep==istepmax): iexit=1 if (iout==1): iexit=1 if (xend[0]>=latmax): iexit=1 print('Warning: xend[0]>=latmax') if (req>=reqmax): iexit=1 if ((_itrace==1) and (tsec>=_tend)): iexit=1 if ((_itrace==-1) and (tsec<=_tend)): iexit=1 # Reasign values if iexit.eq.1 if (iexit==1): #ipdb.set_trace() tsec=tsec-dtsec xend=x0 parmod[1]=Dst0 xeq=xeq0 yeq=yeq0 zeq=zeq0 req=np.sqrt(xeq*xeq+yeq*yeq) if (tsec>=tprint): lastprint=1 # print result every iprint step and at the end of the trace if ((np.mod(istep,iprint)==0) or (lastprint==1)): bx,by,bz,Bmag = self.Tsy_w_dip(_imod,parmod,xeq,yeq,zeq) ipdb.set_trace() pc_sq=self.pcy2B*Bmag/_sinA/_sinA ekev=np.sqrt(pc_sq+Eo2)-Eo pitchA=np.arcsin(_sinA)*180./pi Lshell=rc/(np.cos(xend[0]))**2 mlti_d=xend[1]*12./pi # mlt at ionosphere in hour phi=np.arctan2(yeq,xeq) mlteq=phi*12./pi+12. tprint=tsec print('%6.2f %7.0f %9.3f %9.3f %9.3f %6.3f %6.1f %6.2f %7.2f %6.4f'\ %(tsec,parmod[1],Lshell,mlti_d,req,mlteq,ekev,pitchA,vswi,parmod[0])) roarr[istep-1]=req ## variables for ploting mltoarr[istep-1]=mlteq tsecarr[istep-1]=tsec Eoarr[istep-1]=ekev # Save values Dst0=parmod[1] xeq0=xeq yeq0=yeq zeq0=zeq # Update x0 and Tsyganenko parmod x0=xend if istep==1: dstep = int(_tf/dtsec) # choose an aproximate dt step for changing SW parameters if np.mod(istep,dstep)==0: parmod,xnswi,vswi,vygse,vzgse = self.TsyParmod(_date+timedelta(seconds=tsec),_imod) return tsecarr,mltoarr,roarr,Eoarr,istep
def test_str(self): """TickTock __str__ should give known results""" t1 = t.Ticktock(['2002-01-01T01:00:00', '2002-01-02']) self.assertEqual(str(t1), "Ticktock( ['2002-01-01T01:00:00' '2002-01-02'], dtype=ISO)")
def test_UTCUNX(self): """testing get UTC from UNX""" t1 = t.Ticktock([1.00984680e+09, 1.00992960e+09], 'UNX') expected = t.Ticktock(['2002-01-01T01:00:00', '2002-01-02']) self.assertTrue((t1 == expected).all())
def test_UTCGPS(self): """testing get UTC from GPS""" t1 = t.Ticktock([6.93882013e+08, 6.93964813e+08], 'GPS') expected = t.Ticktock(['2002-01-01T01:00:00', '2002-01-02']) # numpy.testing.assert_array_equal(t1, expected) self.assertTrue((t1 == expected).all())
def test_GPS(self): """conversions to GPS should work""" t1 = t.Ticktock(['2002-01-01T01:00:00', '2002-01-02']) expected = numpy.asarray([6.93882013e+08, 6.93964813e+08]) numpy.testing.assert_almost_equal(t1.GPS, expected)
def test_MJD(self): """conversions to MJD should work""" t1 = t.Ticktock(['2002-01-01T01:00:00', '2002-01-02']) expected = numpy.asarray([52275.04166667, 52276.]) numpy.testing.assert_almost_equal(t1.MJD, expected)
def test_add(self): """TickTocks should add properly""" t1 = t.Ticktock(['2002-01-01T01:00:00', '2002-01-02']) expected = t.Ticktock(["2002-01-01T01:45:00", "2002-01-02T00:45:00"], dtype='UTC') self.assertTrue((t1 + datetime.timedelta(minutes=45) == expected).all()) self.assertTrue((datetime.timedelta(minutes=45) + t1 == expected).all())
def test_DOY(self): """DOY conversion should work""" t1 = t.Ticktock(['2002-01-01T01:00:00', '2002-01-02']) expected = [1., 2.] numpy.testing.assert_equal(expected, t1.DOY)
def test_callable_input(self): """can pass in a callable to convert to datetime""" times = ['2002-01-01T01:00:00', '2002-01-02T02:03:04'] tt = t.Ticktock(times, dtype=lambda x: datetime.datetime.strptime(x, '%Y-%m-%dT%H:%M:%S')) ans = [datetime.datetime(2002, 1, 1, 1, 0, 0), datetime.datetime(2002, 1, 2, 2, 3, 4)] numpy.testing.assert_equal(ans, tt.UTC)
def test_pickle(self): """TickTock objects should pickle""" t1 = t.Ticktock(['2002-01-01T01:00:00', '2002-01-02']) pkl = pickle.dumps(t1) t2 = pickle.loads(pkl) self.assertTrue((t1 == t2).all())
def test_eDOY(self): """eDOY conversio should work""" t1 = t.Ticktock(['2002-01-01T01:00:00', '2002-01-02']) expected = [0.04166667, 1.] numpy.testing.assert_almost_equal(expected, t1.eDOY)