#!/usr/bin/env python # coding: utf-8 # # DaViTpy - models # == # *** # # This notebook introduces useful space science models included in davitpy. # # Currently we have ported/wrapped the following models to python: # # - IGRF-11 # - IRI # - TSYGANENKO (T96) # - MSIS (NRLMSISE00) # - HWM-07 # - AACGM # In[1]: get_ipython().run_line_magic('pylab', 'inline') from datetime import datetime as dt from davitpy.models import * from davitpy import utils # *** # ###IGRF - International Geomagnetic Reference Field # [top] # In[2]: # INPUTS itype = 1 # Geodetic coordinates pyDate = dt(2006,2,23) date = utils.dateToDecYear(pyDate) # decimal year alt = 300. # altitude stp = 5. xlti, xltf, xltd = -90.,90.,stp # latitude start, stop, step xlni, xlnf, xlnd = -180.,180.,stp # longitude start, stop, step ifl = 0 # Main field # Call fortran subroutine lat,lon,d,s,h,x,y,z,f = igrf.igrf11(itype,date,alt,ifl,xlti,xltf,xltd,xlni,xlnf,xlnd) # In[3]: # Check that it worked by plotting magnetic dip angle contours on a map from mpl_toolkits.basemap import Basemap from mpl_toolkits.axes_grid1 import make_axes_locatable from numpy import meshgrid # Set figure fig = figure(figsize=(10,5)) ax = fig.add_subplot(111) rcParams.update({'font.size': 14}) # Set-up the map background map = Basemap(projection='cyl',llcrnrlat=-90,urcrnrlat=90,\ llcrnrlon=-180,urcrnrlon=180,resolution='c') map.drawmapboundary() map.drawcoastlines(color='0.5') # draw parallels and meridians. map.drawparallels(np.arange(-80.,81.,20.)) map.drawmeridians(np.arange(-180.,181.,20.)) # The igrf output needs to be reshaped to be plotted dip = s.reshape((180./stp+1,360./stp+1)) dec = d.reshape((180./stp+1,360./stp+1)) lo = lon[0:(360./stp+1)] la = lat[0::(360./stp+1)] x,y = meshgrid(lo,la) v = arange(0,90,20) # Plot dip angle contours and labels cs = map.contour(x, y, abs(dip), v, latlon=True, linewidths=1.5, colors='k') labs = plt.clabel(cs, inline=1, fontsize=10) # Plot declination and colorbar im = map.pcolormesh(x, y, dec, vmin=-40, vmax=40, cmap='coolwarm') divider = make_axes_locatable(ax) cax = divider.append_axes("right", "3%", pad="3%") colorbar(im, cax=cax) cax.set_ylabel('Magnetic field declination') cticks = cax.get_yticklabels() cticks = [t.__dict__['_text'] for t in cticks] cticks[0], cticks[-1] = 'W', 'E' _ = cax.set_yticklabels(cticks) savefig('dipdec.png') # In[4]: # Check that it worked by plotting magnetic dip angle contours on a map from mpl_toolkits.basemap import Basemap from mpl_toolkits.axes_grid1 import make_axes_locatable from numpy import meshgrid # Set figure fig = figure(figsize=(10,5)) ax = fig.add_subplot(111) rcParams.update({'font.size': 14}) # Set-up the map background map = Basemap(projection='cyl',llcrnrlat=-90,urcrnrlat=90,\ llcrnrlon=-180,urcrnrlon=180,resolution='c') map.drawmapboundary() map.drawcoastlines(color='0.5') # draw parallels and meridians. map.drawparallels(np.arange(-80.,81.,20.)) map.drawmeridians(np.arange(-180.,181.,20.)) # The igrf output needs to be reshaped to be plotted babs = f.reshape((180./stp+1,360./stp+1)) lo = lon[0:(360./stp+1)] la = lat[0::(360./stp+1)] x,y = meshgrid(lo,la) v = arange(0,90,20) # Plot declination and colorbar im = map.pcolormesh(x, y, babs, cmap='jet') divider = make_axes_locatable(ax) cax = divider.append_axes("right", "3%", pad="3%") colorbar(im, cax=cax) cax.set_ylabel('Magnetic field intensity [nT]') savefig('babs.png') # *** # ###IRI - International Reference Ionosphere # [top] # * **JF switches to turn off/on (True/False) several options** # # * [0] : True # * Ne computed # * Ne not computed # * [1] : True # * Te, Ti computed # * Te, Ti not computed # * [2] : True # * Ne & Ni computed # * Ni not computed # * [3] : False # * B0 - Table option # * B0 - other models jf[30] # * [4] : False # * foF2 - CCIR # * foF2 - URSI # * [5] : False # * Ni - DS-95 & DY-85 # * Ni - RBV-10 & TTS-03 # * [6] : True # * Ne - Tops: f10.7<188 # * f10.7 unlimited # * [7] : True # * foF2 from model # * foF2 or NmF2 - user input # * [8] : True # * hmF2 from model # * hmF2 or M3000F2 - user input # * [9] : True # * Te - Standard # * Te - Using Te/Ne correlation # * [10] : True # * Ne - Standard Profile # * Ne - Lay-function formalism # * [11] : True # * Messages to unit 6 # * to meesages.text on unit 11 # * [12] : True # * foF1 from model # * foF1 or NmF1 - user input # * [13] : True # * hmF1 from model # * hmF1 - user input (only Lay version) # * [14] : True # * foE from model # * foE or NmE - user input # * [15] : True # * hmE from model # * hmE - user input # * [16] : True # * Rz12 from file # * Rz12 - user input # * [17] : True # * IGRF dip, magbr, modip # * old FIELDG using POGO68/10 for 1973 # * [18] : True # * F1 probability model # * critical solar zenith angle (old) # * [19] : True # * standard F1 # * standard F1 plus L condition # * [20] : False # * ion drift computed # * ion drift not computed # * [21] : True # * ion densities in % # * ion densities in m-3 # * [22] : False # * Te_tops (Aeros,ISIS) # * Te_topside (TBT-2011) # * [23] : True # * D-region: IRI-95 # * Special: 3 D-region models # * [24] : True # * F107D from APF107.DAT # * F107D user input (oarr[41]) # * [25] : True # * foF2 storm model # * no storm updating # * [26] : True # * IG12 from file # * IG12 - user # * [27] : False # * spread-F probability # * not computed # * [28] : False # * IRI01-topside # * new options as def. by JF[30] # * [29] : False # * IRI01-topside corr. # * NeQuick topside model # * [28,29]: # * [t,t] IRIold, # * [f,t] IRIcor, # * [f,f] NeQuick, # * [t,f] Gulyaeva # * [30] : True # * B0,B1 ABT-2009 # * B0 Gulyaeva h0.5 # * [31] : True # * F10.7_81 from file # * PF10.7_81 - user input (oarr[45]) # * [32] : False # * Auroral boundary model on # * Auroral boundary model off # * [33] : True # * Messages on # * Messages off # * [34] : False # * foE storm model # * no foE storm updating # * [..] : .... # * [50] : .... # In[5]: # Inputs jf = [True]*50 jf[2:6] = [False]*4 jf[20] = False jf[22] = False jf[27:30] = [False]*3 jf[32] = False jf[34] = False jmag = 0. alati = 40. along = -80. iyyyy = 2012 mmdd = 806 dhour = 12. heibeg, heiend, heistp = 80., 500., 10. oarr = np.zeros(100) # Call fortran subroutine outf,oarr = iri.iri_sub(jf,jmag,alati,along,iyyyy,mmdd,dhour,heibeg,heiend,heistp,oarr) # In[6]: # Check that it worked by plotting vertical electron density profile figure(figsize=(5,8)) alt = np.arange(heibeg,heiend,heistp) ax = plot(outf[0,0:len(alt)],alt) xlabel(r'Electron density [m$^{-3}$]') ylabel('Altitude [km]') grid(True) rcParams.update({'font.size': 12}) # *** # ###Tsyganenko (Geopack and T96) # [top] # - **The "Porcelain" way** (recommended) # In[7]: lats = range(10, 90, 10) lons = zeros(len(lats)) rhos = 6372.*ones(len(lats)) trace = tsyganenko.tsygTrace(lats, lons, rhos) print trace ax = trace.plot() # - **The "Plumbing" way** # In[8]: # Inputs # Date and time year = 2000 doy = 1 hr = 1 mn = 0 sc = 0 # Solar wind speed vxgse = -400. vygse = 0. vzgse = 0. # Execution parameters lmax = 5000 rlim = 60. r0 = 1. dsmax = .01 err = .000001 # Direction of the tracing mapto = 1 # Magnetic activity [SW pressure (nPa), Dst, ByIMF, BzIMF] parmod = np.zeros(10) parmod[0:4] = [2, -8, -2, -5] # Start point (rh in Re) lat = 50. lon = 0. rh = 0. # This has to be called first tsyganenko.tsygFort.recalc_08(year,doy,hr,mn,sc,vxgse,vygse,vzgse) # Convert lat,lon to geographic cartesian and then gsw r,theta,phi, xgeo, ygeo, zgeo = tsyganenko.tsygFort.sphcar_08(1., np.radians(90.-lat), np.radians(lon), 0., 0., 0., 1) xgeo,ygeo,zgeo,xgsw,ygsw,zgsw = tsyganenko.tsygFort.geogsw_08(xgeo, ygeo, zgeo,0,0,0,1) # Trace field line xfgsw,yfgsw,zfgsw,xarr,yarr,zarr,l = tsyganenko.tsygFort.trace_08(xgsw,ygsw,zgsw,mapto,dsmax,err, rlim,r0,0,parmod,'T96_01','IGRF_GSW_08',lmax) # Convert back to spherical geographic coords xfgeo,yfgeo,zfgeo,xfgsw,yfgsw,zfgsw = tsyganenko.tsygFort.geogsw_08(0,0,0,xfgsw,yfgsw,zfgsw,-1) gcR, gdcolat, gdlon, xgeo, ygeo, zgeo = tsyganenko.tsygFort.sphcar_08(0., 0., 0., xfgeo, yfgeo, zfgeo, -1) print '** START: {:6.3f}, {:6.3f}, {:6.3f}'.format(lat, lon, 1.) print '** STOP: {:6.3f}, {:6.3f}, {:6.3f}'.format(90.-np.degrees(gdcolat), np.degrees(gdlon), gcR) # In[9]: # A quick checking plot from mpl_toolkits.mplot3d import proj3d import numpy as np fig = plt.figure(figsize=(10,10)) ax = fig.add_subplot(111, projection='3d') # Plot coordinate system ax.plot3D([0,1],[0,0],[0,0],'b') ax.plot3D([0,0],[0,1],[0,0],'g') ax.plot3D([0,0],[0,0],[0,1],'r') # First plot a nice sphere for the Earth u = np.linspace(0, 2 * np.pi, 179) v = np.linspace(0, np.pi, 179) tx = np.outer(np.cos(u), np.sin(v)) ty = np.outer(np.sin(u), np.sin(v)) tz = np.outer(np.ones(np.size(u)), np.cos(v)) ax.plot_surface(tx,ty,tz,rstride=10, cstride=10, color='grey', alpha=.5, zorder=2, linewidth=0.5) # Then plot the traced field line latarr = [10.,20.,30.,40.,50.,60.,70.,80.] lonarr = [0., 180.] rh = 0. for lon in lonarr: for lat in latarr: r,theta,phi, xgeo, ygeo, zgeo = tsyganenko.tsygFort.sphcar_08(1., np.radians(90.-lat), np.radians(lon), 0., 0., 0., 1) xgeo,ygeo,zgeo,xgsw,ygsw,zgsw = tsyganenko.tsygFort.geogsw_08(xgeo, ygeo, zgeo,0,0,0,1) xfgsw,yfgsw,zfgsw,xarr,yarr,zarr,l = tsyganenko.tsygFort.trace_08(xgsw,ygsw,zgsw,mapto,dsmax,err, rlim,r0,0,parmod,'T96_01','IGRF_GSW_08',lmax) for i in xrange(l): xgeo,ygeo,zgeo,dum,dum,dum = tsyganenko.tsygFort.geogsw_08(0,0,0,xarr[i],yarr[i],zarr[i],-1) xarr[i],yarr[i],zarr[i] = xgeo,ygeo,zgeo ax.plot3D(xarr[0:l],yarr[0:l],zarr[0:l], zorder=3, linewidth=2, color='y') # Set plot limits lim=4 ax.set_xlim3d([-lim,lim]) ax.set_ylim3d([-lim,lim]) ax.set_zlim3d([-lim,lim]) # *** # ###MSIS - Mass Spectrometer and Incoherent Scatter Radar # [top] # ####The fortran subroutine needed is gtd7: # * **INPUTS**: # * **IYD** - year and day as YYDDD (day of year from 1 to 365 (or 366)) (Year ignored in current model) # * **SEC** - UT (SEC) # * **ALT** - altitude (KM) # * **GLAT** - geodetic latitude (DEG) # * **GLONG** - geodetic longitude (DEG) # * **STL** - local aparent solar time (HRS; see Note below) # * **F107A** - 81 day average of F10.7 flux (centered on day DDD) # * **F107** - daily F10.7 flux for previous day # * **AP** - magnetic index (daily) OR when SW(9)=-1., array containing: # * (1) daily AP # * (2) 3 HR AP index FOR current time # * (3) 3 HR AP index FOR 3 hrs before current time # * (4) 3 HR AP index FOR 6 hrs before current time # * (5) 3 HR AP index FOR 9 hrs before current time # * (6) average of height 3 HR AP indices from 12 TO 33 HRS prior to current time # * (7) average of height 3 HR AP indices from 36 TO 57 HRS prior to current time # * **MASS** - mass number (only density for selected gass is calculated. MASS 0 is temperature. # MASS 48 for ALL. MASS 17 is Anomalous O ONLY.) # * **OUTPUTS**: # * **D(1)** - HE number density(CM-3) # * **D(2)** - O number density(CM-3) # * **D(3)** - N2 number density(CM-3) # * **D(4)** - O2 number density(CM-3) # * **D(5)** - AR number density(CM-3) # * **D(6)** - total mass density(GM/CM3) # * **D(7)** - H number density(CM-3) # * **D(8)** - N number density(CM-3) # * **D(9)** - Anomalous oxygen number density(CM-3) # * **T(1)** - exospheric temperature # * **T(2)** - temperature at ALT # In[10]: # Inputs import datetime as dt myDate = dt.datetime(2012, 7, 5, 12, 35) glat = 40. glon = -80. mass = 48 # First, MSIS needs a bunch of input which can be obtained from tabulated values # This function was written to access these values (not provided with MSIS by default) solInput = msis.getF107Ap(myDate) # Also, to switch to SI units: msis.meters(True) # Other input conversion iyd = (myDate.year - myDate.year/100*100)*100 + myDate.timetuple().tm_yday sec = myDate.hour*24. + myDate.minute*60. stl = sec/3600. + glon/15. # In[11]: altitude = linspace(0., 500., 100) temp = zeros(shape(altitude)) dens = zeros(shape(altitude)) N2dens = zeros(shape(altitude)) O2dens = zeros(shape(altitude)) Odens = zeros(shape(altitude)) Ndens = zeros(shape(altitude)) Ardens = zeros(shape(altitude)) Hdens = zeros(shape(altitude)) Hedens = zeros(shape(altitude)) for ia,alt in enumerate(altitude): d,t = msis.gtd7(iyd, sec, alt, glat, glon, stl, solInput['f107a'], solInput['f107'], solInput['ap'], mass) temp[ia] = t[1] dens[ia] = d[5] N2dens[ia] = d[2] O2dens[ia] = d[3] Ndens[ia] = d[7] Odens[ia] = d[1] Hdens[ia] = d[6] Hedens[ia] = d[0] Ardens[ia] = d[4] # In[12]: figure(figsize=(16,8)) #rcParams.update({'font.size': 12}) subplot(131) plot(temp, altitude) gca().set_xscale('log') xlabel('Temp. [K]') ylabel('Altitude [km]') subplot(132) plot(dens, altitude) gca().set_xscale('log') gca().set_yticklabels([]) xlabel(r'Mass dens. [kg/m$^3$]') subplot(133) plot(Odens, altitude, 'r-', O2dens, altitude, 'r--', Ndens, altitude, 'g-', N2dens, altitude, 'g--', Hdens, altitude, 'b-', Hedens, altitude, 'y-', Ardens, altitude, 'm-') gca().set_xscale('log') gca().set_yticklabels([]) xlabel(r'Density [m$^3$]') leg = legend( (r'O', r'O$_2$', r'N', r'N$_2$', r'H', r'He', r'Ar',), 'upper right') tight_layout() # *** # ###HWM07: Horizontal Wind Model # [top] # # * **Input arguments**: # * **iyd** - year and day as yyddd # * **sec** - ut(sec) # * **alt** - altitude(km) # * **glat** - geodetic latitude(deg) # * **glon** - geodetic longitude(deg) # * **stl** - not used # * **f107a** - not used # * **f107** - not used # * **ap** - two element array with # * ap(1) = not used # * ap(2) = current 3hr ap index # # * **Output argument**: # * **w(1)** = meridional wind (m/sec + northward) # * **w(2)** = zonal wind (m/sec + eastward) # In[13]: w = hwm.hwm07(11001, 0., 200., 40., -80., 0, 0, 0, [0, 0]) # In[14]: print w # *** # ###AACGM--Altitude Adjusted Corrected Geomagnetic Coordinates # AACGM Homepage
# [top] # # **models.aacgm.aacgmConv(lat,lon,alt,flg)** # # convert between geographic coords and aacgm # # * **Input arguments**: # * **lat** - latitude # * **lon** - longitude # * **alt** - altitude(km) # * **flg** - flag to indicate geo to AACGM (0) or AACGM to geo (1) # # * **Outputs**: # * **olat** = output latitude # * **olon** = output longitude # * **r** = the accuracy of the transform # In[15]: #geo to aacgm glat,glon,r = aacgm.aacgmConv(42.0,-71.4,300.,2000,0) print glat, glon, r # In[16]: #aacgm to geo glat,glon,r = aacgm.aacgmConv(52.7,6.6,300.,2000,1) print glat, glon, r # **models.aacgm.aacgmConvArr(lat,lon,alt,flg)** # # convert between geographic coords and aacgm (array form) # # * **Input arguments**: # * **lat** - latitude list # * **lon** - longitude list # * **alt** - altitude(km) list # * **flg** - flag to indicate geo to AACGM (0) or AACGM to geo (1) # # * **Outputs**: # * **olat** = output latitude list # * **olon** = output longitude list # * **r** = the accuracy of the transform # In[17]: #geo to aacgm olat,olon,r = aacgm.aacgmConvArr([10.,20.,30.,40.],[80.,90.,100.,110.],[100.,150.,200.,250.],2000,0) print olat print olon print r # **models.aacgm.mltFromEpoch(epoch,mlon)** # # calculate magnetic local time from epoch time and mag lon # # * **Input arguments**: # * **epoch** - the target time in epoch format # * **mlon** - the input magnetic longitude # # * **Outputs**: # * **mlt** = the magnetic local time # # In[18]: import datetime as dt myDate = dt.datetime(2012,7,10) epoch = utils.timeUtils.datetimeToEpoch(myDate) mlt = aacgm.mltFromEpoch(epoch,52.7) print mlt # **models.aacgm.mltFromYmdhms(yr,mo,dy,hr,mt,sc,mlon)** # # calculate magnetic local time from year, month, day, hour, minute, second and mag lon # # * **Input arguments**: # * **yr** - the year # * **mo** - the month # * **dy** - the day # * **hr** - the hour # * **mt** - the minute # * **sc** - the second # * **mlon** - the input magnetic longitude # # * **Outputs**: # * **mlt** = the magnetic local time # In[19]: mlt = aacgm.mltFromYmdhms(2012,7,10,0,0,0,52.7) print mlt # **models.aacgm.mltFromYrsec(yr,yrsec,mlon)** # # calculate magnetic local time from seconds elapsed in the year and mag lon # # * **Input arguments**: # * **yr** - the year # * **yrsec** - the year seconds # * **mlon** - the input magnetic longitude # # * **Outputs**: # * **mlt** = the magnetic local time # In[20]: yrsec = int(utils.timeUtils.datetimeToEpoch(dt.datetime(2012,7,10)) - utils.timeUtils.datetimeToEpoch(dt.datetime(2012,1,1))) print yrsec mlt = aacgm.mltFromYrsec(2013,yrsec,52.7) print mlt # In[ ]: