Beispiel #1
0
def CreateFrames(path, runName, runExt, t0, t1, plane, configFile):
    assert ((plane == 'xzplane') | (plane == 'xyplane'))

    planeSelect = {'xzplane': 'xzplane', 'xyplane': 'xyplane'}[plane]

    # Make sure the output directory exisits if not make it
    dirname = os.path.join(path, 'figs', plane)
    if not os.path.exists(dirname):
        os.makedirs(dirname)

    print(('Rendering ' + planeSelect + 'plane, storing frames at ' + dirname))
    #Now check to make sure the files are correct
    data = pyLTR.Models.LFM(path, runName, ext=runExt)
    modelVars = data.getVarNames()
    timeRange = data.getTimeRange()
    if len(timeRange) == 0:
        raise Exception((
            'No data files found.  Are you pointing to the correct run directory?'
        ))

    index0 = 0
    if t0:
        for i, t in enumerate(timeRange):
            if t0 >= t:
                index0 = i

    index1 = len(timeRange) - 1
    if t1:
        for i, t in enumerate(timeRange):
            if t1 >= t:
                index1 = i

    print(
        ('Extracting LFM MAG quantities for time series over %d time steps.' %
         (index1 - index0)))

    # Output a status bar displaying how far along the computation is.
    progress = pyLTR.StatusBar(0, index1 - index0)
    progress.start()

    # Deal with the plot options
    if (configFile == None):
        vxOpts = {'min': -800., 'max': 800., 'colormap': 'RdBu_r'}
        vyOpts = {'min': -100., 'max': 100., 'colormap': 'RdBu_r'}
        vzOpts = {'min': -100., 'max': 100., 'colormap': 'RdBu_r'}
        bxOpts = {'min': -10., 'max': 10.}
        byOpts = {'min': -10., 'max': 10.}
        bzOpts = {'min': -10., 'max': 10.}
        rhoOpts = {'min': 0, 'max': 50}
        optsObject = {
            'vx': vxOpts,
            'vy': vyOpts,
            'vz': vzOpts,
            'bx': bxOpts,
            'by': byOpts,
            'bz': bzOpts,
            'rho': rhoOpts
        }
        configFilename = os.path.join(dirname, 'MHDPlanes.config')
        print(("Writing plot config file at " + configFilename))
        f = open(configFilename, 'w')
        f.write(pyLTR.yaml.safe_dump(optsObject, default_flow_style=False))
        f.close()
    else:
        f = open(configFile, 'r')
        optsDict = pyLTR.yaml.safe_load(f.read())
        f.close()
        if ('vx' in optsDict):
            vxOpts = optsDict['vx']
        else:
            vxOpts = {'min': -800., 'max': 800., 'colormap': 'RdBu_r'}
        if ('vy' in optsDict):
            vyOpts = optsDict['vy']
        else:
            vyOpts = {'min': -100., 'max': 100., 'colormap': 'RdBu_r'}
        if ('vz' in optsDict):
            vzOpts = optsDict['vz']
        else:
            vzOpts = {'min': -100., 'max': 100., 'colormap': 'RdBu_r'}
        if ('bx' in optsDict):
            bxOpts = optsDict['bx']
        else:
            bxOpts = {'min': -10., 'max': 10.}
        if ('by' in optsDict):
            byOpts = optsDict['by']
        else:
            byOpts = {'min': -10., 'max': 10.}
        if ('bz' in optsDict):
            bzOpts = optsDict['bz']
        else:
            bzOpts = {'min': -10., 'max': 10.}
        if ('rho' in optsDict):
            bzOpts = optsDict['rho']
        else:
            rhoOpts = {'min': 0., 'max': 50.}

    vals = data.getEqSlice('X_grid', timeRange[0]) / 6.38e8
    xeq = {'data': vals, 'name': r'$X$', 'units': r'$R_E$'}
    vals = data.getEqSlice('Y_grid', timeRange[0]) / 6.38e8
    yeq = {'data': vals, 'name': r'$X$', 'units': r'$R_E$'}
    vals = data.getEqSlice('Z_grid', timeRange[0]) / 6.38e8
    zeq = {'data': vals, 'name': r'$X$', 'units': r'$R_E$'}
    vals = data.getMerSlice('X_grid', timeRange[0]) / 6.38e8
    xmer = {'data': vals, 'name': r'$X$', 'units': r'$R_E$'}
    vals = data.getMerSlice('Y_grid', timeRange[0]) / 6.38e8
    ymer = {'data': vals, 'name': r'$X$', 'units': r'$R_E$'}
    vals = data.getMerSlice('Z_grid', timeRange[0]) / 6.38e8
    zmer = {'data': vals, 'name': r'$X$', 'units': r'$R_E$'}
    for i, time in enumerate(timeRange[index0:index1]):
        try:
            #first read the data
            vals = data.getEqSlice('vx_', time) / 1000.0
            vx = {'data': vals, 'name': r'$V_X$', 'units': r'km/s'}
            vals = data.getEqSlice('vy_', time) / 1000.0
            vy = {'data': vals, 'name': r'$V_Y$', 'units': r'km/s'}
            vals = data.getEqSlice('vz_', time) / 1000.0
            vz = {'data': vals, 'name': r'$V_Z$', 'units': r'km/s'}
            vals = data.getEqSlice('bx_', time)
            bx = {'data': vals, 'name': r'$B_X$', 'units': r'nT'}
            vals = data.getEqSlice('by_', time)
            by = {'data': vals, 'name': r'$B_Y$', 'units': r'nT'}
            vals = -1.0 * data.getEqSlice('bz_', time)
            bz = {'data': vals, 'name': r'$B_Z$', 'units': r'S'}
            # Now onto the plot
            tt = time.timetuple()
            p.figure(figsize=(16, 12))
            p.figtext(0.5,
                      0.92,
                      'LFM ' + '\n%4d-%02d-%02d  %02d:%02d:%02d' %
                      (tt.tm_year, tt.tm_mon, tt.tm_mday, tt.tm_hour,
                       tt.tm_min, tt.tm_sec),
                      fontsize=14,
                      multialignment='center')
            ax = p.subplot(231)
            x = xeq['data']
            y = yeq['data']
            pyLTR.Graphics.CutPlane.CutPlaneDict(x, y, vx, vxOpts, userAxes=ax)
            ax = p.subplot(234)
            pyLTR.Graphics.CutPlane.CutPlaneDict(x, y, vy, vyOpts, userAxes=ax)
            ax = p.subplot(232)
            pyLTR.Graphics.CutPlane.CutPlaneDict(x, y, vz, vzOpts, userAxes=ax)
            ax = p.subplot(235)
            pyLTR.Graphics.CutPlane.CutPlaneDict(x, y, bx, bxOpts, userAxes=ax)
            ax = p.subplot(233)
            pyLTR.Graphics.CutPlane.CutPlaneDict(x, y, by, byOpts, userAxes=ax)
            ax = p.subplot(236)
            pyLTR.Graphics.CutPlane.CutPlaneDict(x, y, bz, bzOpts, userAxes=ax)
            savefigName = os.path.join(path, 'figs', plane,
                                       'frame_%05d.png' % i)
            p.savefig(savefigName, dpi=100)
            p.close()
            progress.increment()
        except KeyboardInterrupt:
            # Exit when the user hits CTRL+C.
            progress.stop()
            progress.join()
            print('Exiting.')
            import sys
            sys.exit(0)
        except:
            # Cleanup progress bar if something bad happened.
            progress.stop()
            progress.join()
            raise
    progress.stop()
    progress.join()

    return os.path.join(path, 'figs', plane)
Beispiel #2
0
def CreateFrames(path, runName, t0, t1, hemisphere, configFile):
    assert( (hemisphere == 'north') | (hemisphere == 'south') )

    hemiSelect = {'north': 'North', 'south': 'South'}[hemisphere]

    # Make sure the output directory exisits if not make it
    dirname = os.path.join(path, 'figs', hemisphere)
    if not os.path.exists(dirname):
        os.makedirs( dirname )

    print(('Rendering ' + hemiSelect + 'ern hemisphere, storing frames at ' + dirname))        
    #Now check to make sure the files are correct
    data = pyLTR.Models.MIX(path, runName)
    modelVars = data.getVarNames()
    for v in ['Grid X', 'Grid Y', 
              'Potential North [V]', 'Potential South [V]', 
              'FAC North [A/m^2]', 'FAC South [A/m^2]',
              'Pedersen conductance North [S]', 'Pedersen conductance South [S]', 
              'Hall conductance North [S]', 'Hall conductance South [S]', 
              'Average energy North [keV]', 'Average energy South [keV]',
              'Number flux North [1/cm^2 s]', 'Number flux South [1/cm^2 s]']:
        assert( v in modelVars )

    timeRange = data.getTimeRange()
    if len(timeRange) == 0:
        raise Exception(('No data files found.  Are you pointing to the correct run directory?'))

    index0 = 0
    if t0:
        for i,t in enumerate(timeRange):
            if t0 >= t:
                index0 = i

    index1 = len(timeRange)
    if t1:
        for i,t in enumerate(timeRange):
            if t1 >= t:
                index1 = i                

    print(( 'Extracting MIX quantities for time series over %d time steps.' % (index1-index0) ))
        
    # Output a status bar displaying how far along the computation is.
    progress = pyLTR.StatusBar(0, index1-index0)
    progress.start()

    # Pre-compute r and theta
    x = data.read('Grid X', timeRange[index0])
    y = data.read('Grid Y', timeRange[index0])
    theta=n.arctan2(y,x)
    theta[theta<0]=theta[theta<0]+2*n.pi
    # plotting routines now rotate local noon to point up
    #theta=theta+n.pi/2 # to put noon up
    r=n.sqrt(x**2+y**2)
    # plotting routines now expect longitude and colatitude, in radians, stored in dictionaries
    longitude = {'data':theta,'name':r'\phi','units':r'rad'}
    colatitude = {'data':n.arcsin(r),'name':r'\theta','units':r'rad'}
    
    # Deal with the plot options
    if (configFile == None): 
       potOpts={'min':-100.,'max':100.,'colormap':'bwr'} #'RdBu_r'}
       facOpts={'min':-1.,'max':1.,'colormap':'bwr'} #'RdBu_r'}
       pedOpts={'min':1.,'max':20.,'colormap':'plasma'}
       halOpts={'min':1.,'max':20.,'colormap':'plasma'}
       engOpts={'min':0.,'max':20.}
       flxOpts={'min':0.,'max':1.0e9,'format_str':'%.1e','colormap':'jet'}
       optsObject = {'pot':potOpts,
                     'fac':facOpts,
                     'ped':pedOpts,
                     'hall':halOpts,
                     'energy':engOpts,
                     'flux':flxOpts}
       configFilename=os.path.join(dirname,'IonSum.config')
       print(("Writing plot config file at " + configFilename))
       f=open(configFilename,'w')
       f.write(pyLTR.yaml.safe_dump(optsObject,default_flow_style=False))
       f.close()
    else:
       f=open(configFile,'r')
       optsDict=pyLTR.yaml.safe_load(f.read())
       f.close()
       if ('pot' in optsDict):
          potOpts = optsDict['pot']
       else:
          potOpts={'min':-100.,'max':100.,'colormap':'RdBu_r'}
       if ('fac' in optsDict):
          facOpts = optsDict['fac']
       else:
          facOpts={'min':-1.,'max':1.,'colormap':'RdBu_r'}
       if ('ped' in optsDict):
          pedOpts = optsDict['ped']
       else:
          pedOpts={'min':1.,'max':8.}
       if ('hall' in optsDict):
          halOpts = optsDict['hall']
       else:
          halOpts={'min':1.,'max':8.}
       if ('energy' in optsDict):
          engOpts = optsDict['energy']
       else:
          engOpts={'min':0.,'max':20.}
       if ('flux' in optsDict):
          flxOpts = optsDict['flux']
       else:
          flxOpts={'min':0.,'max':1.0e9,'format_str':'%.1e'}
          
     

    for i,time in enumerate(timeRange[index0:index1]):
        try:
           #first read the data
           vals=data.read('Potential '+hemiSelect+' [V]',time)/1000.0
           psi={'data':vals,'name':r'$\Phi$','units':r'kV'}
           vals=data.read('FAC '+hemiSelect+' [A/m^2]',time)*1.0e6
           fac={'data':vals,'name':r'$J_{||}$',
                  'units':r'$\mu\mathrm{A/m^2}$'}
           vals1=data.read('Average energy '+hemiSelect+' [keV]',time)
           eng={'data':vals1,'name':r'Energy','units':r'keV'}
           vals2=data.read('Number flux '+hemiSelect+' [1/cm^2 s]',time)
           flx={'data':vals2,'name':r'Flux','units':r'$\mathrm{1/cm^2s}$'}
           hal={'data':vals1*vals2/10,'name':r'EFlux','units':r'??'}
           vals=data.read('Pedersen conductance '+hemiSelect+' [S]',time)
           ped={'data':vals,'name':r'$\Sigma_{P}$','units':r'S'}
           vals=data.read('Hall conductance '+hemiSelect+' [S]',time)
           #hal={'data':vals,'name':r'$\Sigma_{H}$','units':r'S'}
           # Now onto the plot
           tt=time.timetuple()
           p.figure(figsize=(16,12))
           p.figtext(0.5,0.92,'MIX '+hemiSelect+
                     '\n%4d-%02d-%02d  %02d:%02d:%02d' %
                  (tt.tm_year,tt.tm_mon,tt.tm_mday,
                  tt.tm_hour,tt.tm_min,tt.tm_sec),
                  fontsize=14,multialignment='center')
           ax=p.subplot(231,polar=True)
           pyLTR.Graphics.PolarPlot.BasicPlotDict(longitude,colatitude,psi,
                  potOpts,userAxes=ax,useMesh=True)
           ax=p.subplot(234,polar=True)
           pyLTR.Graphics.PolarPlot.BasicPlotDict(longitude,colatitude,fac,
                  facOpts,userAxes=ax)
           ax=p.subplot(232,polar=True)
           pyLTR.Graphics.PolarPlot.BasicPlotDict(longitude,colatitude,ped,
                  pedOpts,userAxes=ax)
           ax=p.subplot(235,polar=True)
           pyLTR.Graphics.PolarPlot.BasicPlotDict(longitude,colatitude,hal,
                  flxOpts,userAxes=ax)
           ax=p.subplot(233,polar=True)
           pyLTR.Graphics.PolarPlot.BasicPlotDict(longitude,colatitude,eng,
                  engOpts,userAxes=ax)
           ax=p.subplot(236,polar=True)
           pyLTR.Graphics.PolarPlot.BasicPlotDict(longitude,colatitude,flx,
                  flxOpts,userAxes=ax)
           savefigName = os.path.join(path,'figs',hemisphere,'frame_summary_%05d.png'%i)
           p.savefig(savefigName,dpi=100)
           p.close()
           progress.increment()
        except KeyboardInterrupt:
            # Exit when the user hits CTRL+C.
            progress.stop()
            progress.join()            
            print('Exiting.')
            import sys
            sys.exit(0)
        except:
            # Cleanup progress bar if something bad happened.
            progress.stop()
            progress.join()
            raise
    progress.stop()
    progress.join()

    return  os.path.join(path,'figs',hemisphere)
Beispiel #3
0
def extractQuantities(path, run, t0, t1):
    """
    Extract MIX quantities from the input path.
    
    Execute `mixTimeSeries.py --help` for details on the function parameters (path,run,t0,t1).
    
    Outputs a pyLTR.TimeSeries object containing the data.
    """
    data = pyLTR.Models.MIX(path, run)

    # hard-coded input for testing & debugging:
    #data = pyLTR.Models.LFM('/hao/aim2/schmitt/data/LTR-2_0_1b/r1432/March1995/LR/single', 'LRs')

    #Make sure variables are defined in the model.
    modelVars = data.getVarNames()
    for v in [
            'Grid X', 'Grid Y', 'Poynting flux North [???]',
            'Poynting flux South [???]', 'FAC North [A/m^2]',
            'FAC South [A/m^2]', 'Number flux North [1/cm^2 s]',
            'Number flux South [1/cm^2 s]', 'BBE average energy North [keV]',
            'BBE average energy South [keV]',
            'BBE number flux North [1/cm^2 s]',
            'BBE number flux South [1/cm^2 s]',
            'Cusp average energy North [keV]',
            'Cusp average energy South [keV]',
            'Cusp number flux North [1/cm^2 s]',
            'Cusp number flux South [1/cm^2 s]'
    ]:
        #        print v
        assert (v in modelVars)

    timeRange = data.getTimeRange()
    if len(timeRange) == 0:
        raise Exception((
            'No data files found.  Are you pointing to the correct run directory?'
        ))

    index0 = 0
    if t0:
        for i, t in enumerate(timeRange):
            if t0 >= t:
                index0 = i

    index1 = len(timeRange) - 1
    if t1:
        for i, t in enumerate(timeRange):
            if t1 >= t:
                index1 = i

    print(('Extracting MIX quantities for time series over %d time steps.' %
           (index1 - index0)))

    # Output a status bar displaying how far along the computation is.
    progress = pyLTR.StatusBar(0, index1 - index0)
    progress.start()

    t_doy = []
    isparNorth = []
    isparSouth = []
    hpNorth = []
    hpSouth = []
    asparNorth = []
    asparSouth = []
    bbe = 0
    cusp = 0

    # Pre-compute area of the grid.
    x = data.read('Grid X', timeRange[index0])
    y = data.read('Grid Y', timeRange[index0])
    # Fix singularity at the pole
    x[:, 0] = 0.0
    y[:, 0] = 0.0
    z = numpy.sqrt(1.0 - x**2 - y**2)
    ri = 6500.0e3  # Radius of ionosphere in meters
    areaMixGrid = pyLTR.math.integrate.calcFaceAreas(x, y, z) * ri * ri

    for i, time in enumerate(timeRange[index0:index1]):
        try:
            # -- Day of Year
            tt = time.timetuple()
            t_doy.append(tt.tm_yday + tt.tm_hour / 24.0 + tt.tm_min / 1440.0 +
                         tt.tm_sec / 86400.0)

            # --- Cross Polar Cap Potential
            psi = data.read('Poynting flux North [???]', time)
            psi[psi < 0] = 0.
            spar = areaMixGrid * psi[:-1, :-1]
            # is MIX grid in m^2? spar is in mW/m^2
            # mW to GW
            isparNorth.append(spar.sum() * 1.e-12)
            spar = psi[psi > 0.1].mean()
            asparNorth.append(spar.sum())

            psi = data.read('Poynting flux South [???]', time)
            psi[psi > 0] = 0.
            spar = areaMixGrid * psi[:-1, :-1]
            # is MIX grid in m^2? spar is in mW/m^2
            # mW to GW
            isparSouth.append(spar.sum() * -1.e-12)
            spar = psi[psi < -0.1].mean()
            asparSouth.append(spar.sum() * -1.)

            # --- Hemispheric Power
            energy = data.read('Average energy North [keV]', time)
            flux = data.read('Number flux North [1/cm^2 s]', time)
            mhp = areaMixGrid * energy[:-1, :-1] * flux[:-1, :-1]
            flux = data.read('BBE number flux North [1/cm^2 s]', time)
            energy = data.read('BBE average energy North [keV]', time)
            bbe = areaMixGrid * energy[:-1, :-1] * flux[:-1, :-1]
            flux = data.read('Cusp number flux North [1/cm^2 s]', time)
            energy = data.read('Cusp average energy North [keV]', time)
            cusp = areaMixGrid * energy[:-1, :-1] * flux[:-1, :-1]
            hp = mhp + bbe + cusp
            # KeV/cm^2s to mW/m^2 to GW
            hpNorth.append(hp.sum() * 1.6e-21)

            energy = data.read('Average energy South [keV]', time)
            flux = data.read('Number flux South [1/cm^2 s]', time)
            mhp = areaMixGrid * energy[:-1, :-1] * flux[:-1, :-1]
            flux = data.read('BBE number flux South [1/cm^2 s]', time)
            energy = data.read('BBE average energy South [keV]', time)
            bbe = areaMixGrid * energy[:-1, :-1] * flux[:-1, :-1]
            flux = data.read('Cusp number flux South [1/cm^2 s]', time)
            energy = data.read('Cusp average energy South [keV]', time)
            cusp = areaMixGrid * energy[:-1, :-1] * flux[:-1, :-1]
            hp = mhp + bbe + cusp
            # KeV/cm^2s to mW/m^2 to GW
            hpSouth.append(hp.sum() * 1.6e-21)

            progress.increment()
        except KeyboardInterrupt:
            # Exit when the user hits CTRL+C.
            progress.stop()
            progress.join()
            print('Exiting.')
            import sys
            sys.exit(0)
        except:
            # Cleanup progress bar if something bad happened.
            progress.stop()
            progress.join()
            raise
    progress.stop()
    progress.join()

    dataNorth = pyLTR.TimeSeries()
    dataSouth = pyLTR.TimeSeries()
    dataNorth.append('datetime', 'Date & Time', '', timeRange[index0:index1])
    dataSouth.append('datetime', 'Date & Time', '', timeRange[index0:index1])
    dataNorth.append('doy', 'Day of Year', '', t_doy)
    dataSouth.append('doy', 'Day of Year', '', t_doy)

    # "N" and "S" label subscripts are redundant here, potentially leading to
    # mis-labeling of plots
    #dataNorth.append('cpcp', r'$\Phi_N$', 'kV', cpcpNorth)
    #dataSouth.append('cpcp', r'$\Phi_S$', 'kV', cpcpSouth)
    #
    #dataNorth.append('hp', r'$HP_N$', 'GW', hpNorth)
    #dataSouth.append('hp', r'$HP_S$', 'GW', hpSouth)
    #
    #dataNorth.append('ipfac', r'$FAC_N$', 'MA', ipfacNorth)
    #dataSouth.append('ipfac', r'$FAC_S$', 'MA', ipfacSouth)

    dataNorth.append('ispar', r'$Integrated S||$', 'GW', isparNorth)
    dataSouth.append('ispar', r'$Integrated S||$', 'GW', isparSouth)

    dataNorth.append('hp', r'$THP$', 'GW', hpNorth)
    dataSouth.append('hp', r'$THP$', 'GW', hpSouth)

    dataNorth.append('aspar', r'$Mean S||r$', 'mW/m^2', asparNorth)
    dataSouth.append('aspar', r'$Mean S||$', 'mW/m^2', asparSouth)

    return (dataNorth, dataSouth)
Beispiel #4
0
def getDst(path, runName, t0, t1):
   """
   Returns a pyLTR.TimeSeries object containing the DST index
   
   Parameters:
     path: path to run 
     runName: name of run we wish to compute DST for.
   """
   data = pyLTR.Models.LFM(path, runName)
   
   # Hard-code a subset (useful for testing & debugging):
   #data = pyLTR.Models.LFM('/Users/schmitt/paraview/testData/March1995_LM_r1432_single', 'LMs')

   # Make sure variables are defined in the model.
   modelVars = data.getVarNames()
   for v in ['X_grid', 'Y_grid', 'Z_grid',
             'bi_', 'bj_', 'bk_', 
             'bx_', 'by_', 'bz_', 
             'c_', 
             'ei_', 'ej_', 'ek_', 
             'rho_', 'vx_', 'vy_', 'vz_']:
      assert( v in modelVars )

   timeRange = data.getTimeRange()
   if len(timeRange) == 0:
       raise Exception(('No data files found.  Are you pointing to the correct run directory?'))

   index0 = 0
   if t0:
      for i,t in enumerate(timeRange):
         if t0 >= t:
            index0 = i
            
   index1 = len(timeRange)-1
   if t1:
      for i,t in enumerate(timeRange):
         if t1 >= t:
            index1 = i                

   t_doy = []
   dst = []

   # Pre-compute some quantities
   #FIXME:  Should this be a configurable parameter?
   earthRadius = 6.38e8
   #earthRadius = 6340e5
   x = data.read('X_grid', timeRange[index0]) / earthRadius
   y = data.read('Y_grid', timeRange[index0]) / earthRadius
   z = data.read('Z_grid', timeRange[index0]) / earthRadius

   dipStr = data.readAttribute('dipole_moment', timeRange[index0])
   dipStr = dipStr.split('=')[1].strip().split()[0]
   gauss_2_nT = 1.0e5
   dipoleMoment = float(dipStr) / (earthRadius**3) * gauss_2_nT

   print('Reticulating splines')
   #FIXME:  nPoints and radius should be configurable
   nPoints = 4
   radius = 3.0
   (xc, yc, zc) = getCellCenters(x,y,z)
   ijk = getDstIndices(xc,yc,zc, nPoints, radius)

   print(( 'Extracting DST from MHD files for time series over %d time steps.' % (index1-index0) ))
   
   # Output a status bar displaying how far along the computation is.   
   progress = pyLTR.StatusBar(0, index1-index0)
   progress.start()
   for i,time in enumerate(timeRange[index0:index1]):
      try:
         tt = time.timetuple()
         dayFraction = (tt.tm_hour+tt.tm_min/60.+tt.tm_sec/(60.*60.))/24.
         t_doy.append( float(tt.tm_yday) + dayFraction )

         ## Skip the file if it can't be read.
         try:
            data.readAttribute('time', time)
         except HDF4Error as msg:
            sys.stderr.write('HDF4Error: Trouble "' + data._LFM__io.filename + '"\n')
            sys.stderr.write('HDF4 Error message: "' + str(msg) + '"\n')
            sys.stderr.write('Skipping file.\n')
            sys.stderr.flush()
         
            #FIXME: What's the correct behavior here for the dst
            #       value? Set to last known good value?  Pop array values?
            dst.append(dst[len(dst)-1])
            continue      

         # Calculate DST
         dstVal = 0.0
         for idx in ijk:               
            #FIXME: when count=[1,1,1], data.read(...) returns a 3d
            #       array with just one element!            
            #FIXME: setting a particular start index doesn't work
            #       because dimensions are transposed because Fortran
            #       does the I/O... so just read all the data :-(
            #bz = data.read('bz_', time, start=idx, count=(1,1,1))
            bz = data.read('bz_', time)
                              
            # scale to nT
            bz = bz[idx[0], idx[1], idx[2]] * gauss_2_nT
            
            dip = dipole( (xc[idx[0],idx[1],idx[2]],
                           yc[idx[0],idx[1],idx[2]],
                           zc[idx[0],idx[1],idx[2]]),
                          dipoleMoment)
            
            dstVal += bz - dip[2]

         dstVal /= len(ijk)
         dst.append( dstVal )

         progress.increment()

      except KeyboardInterrupt:
         # Exit when the user hits CTRL+C.
         progress.stop()
         progress.join()            
         print('Exiting.')
         sys.exit(0)
      except:
         # Cleanup progress bar if something bad happened.
         progress.stop()
         progress.join()
         raise
   progress.stop()
   progress.join()

   if len(dst) == 0:
      raise Exception(('No data computed.  Did you specify a valid run path?'))    
   
   data = pyLTR.TimeSeries()
   data.append('datetime',     'Date & Time', '', timeRange[index0:index1])
   data.append('doy', 'Day of Year', '',      t_doy)
   data.append('dst', 'Disturbance Storm Time Index', 'nT', dst)

   return data
Beispiel #5
0
def extractQuantities(path, run, t0, t1):
    """
    Extract MIX quantities from the input path.
    
    Execute `mixTimeSeries.py --help` for details on the function parameters (path,run,t0,t1).
    
    Outputs a pyLTR.TimeSeries object containing the data.
    """
    data = pyLTR.Models.MIX(path, run)

    # hard-coded input for testing & debugging:
    #data = pyLTR.Models.LFM('/hao/aim2/schmitt/data/LTR-2_0_1b/r1432/March1995/LR/single', 'LRs')

    #Make sure variables are defined in the model.
    modelVars = data.getVarNames()
    for v in [
            'Grid X', 'Grid Y', 'Potential North [V]', 'Potential South [V]',
            'FAC North [A/m^2]', 'FAC South [A/m^2]',
            'Pedersen conductance North [S]', 'Pedersen conductance South [S]',
            'Hall conductance North [S]', 'Hall conductance South [S]',
            'Average energy North [keV]', 'Average energy South [keV]',
            'Number flux North [1/cm^2 s]', 'Number flux South [1/cm^2 s]'
    ]:
        assert (v in modelVars)

    timeRange = data.getTimeRange()
    if len(timeRange) == 0:
        raise Exception((
            'No data files found.  Are you pointing to the correct run directory?'
        ))

    index0 = 0
    if t0:
        for i, t in enumerate(timeRange):
            if t0 >= t:
                index0 = i

    index1 = len(timeRange) - 1
    if t1:
        for i, t in enumerate(timeRange):
            if t1 >= t:
                index1 = i

    print(('Extracting MIX quantities for time series over %d time steps.' %
           (index1 - index0)))

    # Output a status bar displaying how far along the computation is.
    progress = pyLTR.StatusBar(0, index1 - index0)
    progress.start()

    t_doy = []
    mhpNorth = []
    mhpSouth = []
    bhpNorth = []
    bhpSouth = []
    chpNorth = []
    chpSouth = []

    # Pre-compute area of the grid.
    x = data.read('Grid X', timeRange[index0])
    y = data.read('Grid Y', timeRange[index0])
    # Fix singularity at the pole
    x[:, 0] = 0.0
    y[:, 0] = 0.0
    z = numpy.sqrt(1.0 - x**2 - y**2)
    ri = 6500.0e3  # Radius of ionosphere
    areaMixGrid = pyLTR.math.integrate.calcFaceAreas(x, y, z) * ri * ri
    doBBEaverage = 1
    doCUSPaverage = 1
    averagesize = 5

    for i, time in enumerate(timeRange[index0:index1]):
        try:
            # -- Day of Year
            tt = time.timetuple()
            t_doy.append(tt.tm_yday + tt.tm_hour / 24.0 + tt.tm_min / 1440.0 +
                         tt.tm_sec / 86400.0)

            # --- MonoDiffuse Hemispheric Power
            energy = data.read('Average energy North [keV]', time)
            flux = data.read('Number flux North [1/cm^2 s]', time)
            hp = areaMixGrid * energy[:-1, :-1] * flux[:-1, :-1]
            # KeV/cm^2s to mW/m^2 to GW
            mhpNorth.append(hp.sum() * 1.6e-21)

            energy = data.read('Average energy South [keV]', time)
            flux = data.read('Number flux South [1/cm^2 s]', time)
            hp = areaMixGrid * energy[:-1, :-1] * flux[:-1, :-1]
            # KeV/cm^2s to mW/m^2 to GW
            mhpSouth.append(hp.sum() * 1.6e-21)

            # --- BBE Hemispheric Power
            flux = data.read('BBE number flux North [1/cm^2 s]', time)
            energy = data.read('BBE average energy North [keV]', time)
            hp = areaMixGrid * energy[:-1, :-1] * flux[:-1, :-1]
            # KeV/cm^2s to mW/m^2 to GW
            if doBBEaverage and i > averagesize:
                bhpNorth.append(
                    (sum(bhpNorth[-averagesize:-1]) + hp.sum() * 1.6e-21) /
                    averagesize)
            else:
                bhpNorth.append(hp.sum() * 1.6e-21)

            flux = data.read('BBE number flux South [1/cm^2 s]', time)
            energy = data.read('BBE average energy South [keV]', time)
            hp = areaMixGrid * energy[:-1, :-1] * flux[:-1, :-1]
            # KeV/cm^2s to mW/m^2 to GW
            if doBBEaverage and i > averagesize:
                bhpSouth.append(
                    (sum(bhpSouth[-averagesize:-1]) + hp.sum() * 1.6e-21) /
                    averagesize)
            else:
                bhpSouth.append(hp.sum() * 1.6e-21)

            # --- Cusp Hemispheric Power
            flux = data.read('Cusp number flux North [1/cm^2 s]', time)
            energy = data.read('Cusp average energy North [keV]', time)
            hp = areaMixGrid * energy[:-1, :-1] * flux[:-1, :-1]
            # KeV/cm^2s to mW/m^2 to GW
            if doCUSPaverage and i > averagesize:
                chpNorth.append(
                    (sum(chpNorth[-averagesize:-1]) + hp.sum() * 1.6e-21) /
                    averagesize)
            else:
                chpNorth.append(hp.sum() * 1.6e-21)

            flux = data.read('Cusp number flux South [1/cm^2 s]', time)
            energy = data.read('Cusp average energy South [keV]', time)
            hp = areaMixGrid * energy[:-1, :-1] * flux[:-1, :-1]
            # KeV/cm^2s to mW/m^2 to GW
            if doCUSPaverage and i > averagesize:
                chpSouth.append(
                    (sum(chpSouth[-averagesize:-1]) + hp.sum() * 1.6e-21) /
                    averagesize)
            else:
                chpSouth.append(hp.sum() * 1.6e-21)

            progress.increment()
        except KeyboardInterrupt:
            # Exit when the user hits CTRL+C.
            progress.stop()
            progress.join()
            print('Exiting.')
            import sys
            sys.exit(0)
        except:
            # Cleanup progress bar if something bad happened.
            progress.stop()
            progress.join()
            raise
    progress.stop()
    progress.join()

    dataNorth = pyLTR.TimeSeries()
    dataSouth = pyLTR.TimeSeries()
    dataNorth.append('datetime', 'Date & Time', '', timeRange[index0:index1])
    dataSouth.append('datetime', 'Date & Time', '', timeRange[index0:index1])
    dataNorth.append('doy', 'Day of Year', '', t_doy)
    dataSouth.append('doy', 'Day of Year', '', t_doy)

    # "N" and "S" label subscripts are redundant here, potentially leading to
    # mis-labeling of plots
    #dataNorth.append('cpcp', r'$\Phi_N$', 'kV', cpcpNorth)
    #dataSouth.append('cpcp', r'$\Phi_S$', 'kV', cpcpSouth)
    #
    #dataNorth.append('hp', r'$HP_N$', 'GW', hpNorth)
    #dataSouth.append('hp', r'$HP_S$', 'GW', hpSouth)
    #
    #dataNorth.append('ipfac', r'$FAC_N$', 'MA', ipfacNorth)
    #dataSouth.append('ipfac', r'$FAC_S$', 'MA', ipfacSouth)

    dataNorth.append('diffusemono', r'$DiffuseMono$', 'GW', mhpNorth)
    dataSouth.append('diffusemono', r'$DiffuseMono$', 'GW', mhpSouth)

    dataNorth.append('bbe', r'$BBE$', 'GW', bhpNorth)
    dataSouth.append('bbe', r'$BBE$', 'GW', bhpSouth)

    dataNorth.append('cusp', r'$Cusp$', 'GW', chpNorth)
    dataSouth.append('cusp', r'$Cusp$', 'GW', chpSouth)

    return (dataNorth, dataSouth)
Beispiel #6
0
def extractQuantities(path, run, runExt, t0, t1):
    """
    Extract LFM ION quantities from the input path.
    
    Execute `lfmionTimeSeries.py --help` for details on the function parameters (path,run,t0,t1).
    
    Outputs a pyLTR.TimeSeries object containing the data.
    """
    data = pyLTR.Models.LFMION(path, run, ext=runExt)

    # hard-coded input for testing & debugging:
    #data = pyLTR.Models.LFM('/hao/aim2/schmitt/data/LTR-2_0_1b/r1432/March1995/LR/single', 'LRs')

    #Make sure variables are defined in the model.
    modelVars = data.getVarNames()
    for v in [
            'x_interp', 'y_interp', 'potnorth', 'potsouth', 'curnorth',
            'cursouth', 'SigmaP_north', 'SigmaP_south', 'SigmaH_north',
            'SigmaH_south', 'avE_north', 'avE_south', 'fluxnorth', 'fluxsouth'
    ]:
        assert (v in modelVars)

    timeRange = data.getTimeRange()
    if len(timeRange) == 0:
        raise Exception((
            'No data files found.  Are you pointing to the correct run directory?'
        ))

    index0 = 0
    if t0:
        for i, t in enumerate(timeRange):
            if t0 >= t:
                index0 = i

    index1 = len(timeRange) - 1
    if t1:
        for i, t in enumerate(timeRange):
            if t1 >= t:
                index1 = i

    print(
        ('Extracting LFM ION quantities for time series over %d time steps.' %
         (index1 - index0)))

    # Output a status bar displaying how far along the computation is.
    progress = pyLTR.StatusBar(0, index1 - index0)
    progress.start()

    t_doy = []
    cpcpNorth = []
    cpcpSouth = []
    hpNorth = []
    hpSouth = []
    ipfacNorth = []
    ipfacSouth = []

    # Pre-compute area of the grid.
    x = data.read('x_interp', timeRange[index0])
    y = data.read('y_interp', timeRange[index0])
    # Fix singularity at the pole
    x[:, 0] = 0.0
    y[:, 0] = 0.0
    z = numpy.sqrt(1.0 - x**2 - y**2)
    ri = 6370.0e3  # Radius of ionosphere
    areaMixGrid = pyLTR.math.integrate.calcFaceAreas(x, y, z) * ri * ri

    for i, time in enumerate(timeRange[index0:index1]):
        try:
            # -- Day of Year
            tt = time.timetuple()
            t_doy.append(tt.tm_yday + tt.tm_hour / 24.0 + tt.tm_min / 1440.0 +
                         tt.tm_sec / 86400.0)

            # --- Cross Polar Cap Potential
            psiNorth = data.read('potnorth', time) / 1000.0
            cpcpNorth.append(psiNorth.max() - psiNorth.min())

            psiSouth = data.read('potsouth', time) / 1000.0
            cpcpSouth.append(psiSouth.max() - psiSouth.min())

            # --- Hemispheric Power
            energy = data.read('avE_north', time)
            flux = data.read('fluxnorth', time)
            hp = areaMixGrid * energy[:-1, :-1] * flux[:-1, :-1]
            # KeV/cm^2s to mW/m^2 to GW
            hpNorth.append(hp.sum() * 1.6e-21)

            energy = data.read('avE_south', time)
            flux = data.read('fluxsouth', time)
            hp = areaMixGrid * energy[:-1, :-1] * flux[:-1, :-1]
            # KeV/cm^2s to mW/m^2 to GW
            hpSouth.append(hp.sum() * 1.6e-21)

            # --- Positive current density
            fac = data.read('curnorth', time)
            fac[fac <= 0] = 0.0
            pfac = areaMixGrid * fac[:-1, :-1]
            ipfacNorth.append(pfac.sum() / 1.0e6)

            fac = data.read('cursouth', time)
            fac[fac <= 0] = 0.0
            pfac = areaMixGrid * fac[:-1, :-1]
            ipfacSouth.append(pfac.sum() / 1.0e6)

            progress.increment()
        except KeyboardInterrupt:
            # Exit when the user hits CTRL+C.
            progress.stop()
            progress.join()
            print('Exiting.')
            import sys
            sys.exit(0)
        except:
            # Cleanup progress bar if something bad happened.
            progress.stop()
            progress.join()
            raise
    progress.stop()
    progress.join()

    dataNorth = pyLTR.TimeSeries()
    dataSouth = pyLTR.TimeSeries()
    dataNorth.append('datetime', 'Date & Time', '', timeRange[index0:index1])
    dataSouth.append('datetime', 'Date & Time', '', timeRange[index0:index1])
    dataNorth.append('doy', 'Day of Year', '', t_doy)
    dataSouth.append('doy', 'Day of Year', '', t_doy)

    dataNorth.append('cpcp', r'$\Phi_N$', 'kV', cpcpNorth)
    dataSouth.append('cpcp', r'$\Phi_S$', 'kV', cpcpSouth)

    dataNorth.append('hp', r'$HP_N$', 'GW', hpNorth)
    dataSouth.append('hp', r'$HP_S$', 'GW', hpSouth)

    dataNorth.append('ipfac', r'$FAC_N$', 'MA', ipfacNorth)
    dataSouth.append('ipfac', r'$FAC_S$', 'MA', ipfacSouth)

    return (dataNorth, dataSouth)
Beispiel #7
0
def CreateFrames(path='./', run='', 
                 t0='', t1='', 
                 hemisphere='north', geoGrid=False, 
                 ignoreBinary=False, binaryType='pkl',
                 configFile=None):
    """
    Compute deltaBs hemispheric grid given LFM-MIX output files in path.
    
    Computes:
      pngFiles  - a list of PNG filenames, each corresponding to a snapshot in
                  time of LFM-MIX ground deltaB vector fields
                  NOTE: while the output is a list of filenames, the function
                        generates binary pkl/mat files that can be read in by
                        other software for further analysis.
                  FIXME: southern hemisphere summary plots are presented from a
                        point of view below the south pole, looking up. Likewise
                        for the data files. This is not technically a right-handed 
                        frame of reference, so any analysis of southern hemisphere 
                        data must rotate fields 180 degrees about the X axis, or 
                        0 longitude, 0 latitude line. This odd data file convention 
                        is consistent with how southern hemisphere data is stored 
                        in MIX files, but there is a strong argument to just store 
                        everything assuming the same (northern) POV, and rotate 
                        to a southern POV for display purposes only; this will 
                        require significant work.
                        
    Requires:
      Nothing, all inputs are optional
    
    Optional:
      path      - path to data directory holding LFM and MIX model output files
                  (default is current directory)
      run       - output filename prefix identifying LFM-MIX run (i.e., the part
                  of the filename prior to [mhd|mix]_yyyy-mm-ddTHH-MM-SSZ.hdf)
                  (default is any mhd|mix files in path)
      t0        - datetime object specifying the earliest of available time step
                  to include in the extraction
                  (default is earliest available)
      t1        - datetime object specfiying the latest of available time step
                  to include in the extraction
                  (default is last available)
      hemisphere - specify 'north' or 'south' hemisphere
                  (default is 'north')
      geoGrid   - if True, assume observatory coordinates are in geographic
                  coordinates rather than solar magnetic; same for outputs
                  (default is False)
      ignoreBinary - if True, ignore any pre-computed binary files and re-
                  compute everything from scratch; NOTE: individual binary files
                  will be ignored anyway if they are incompatible with specified
                  inputs, but this option avoids reading the binary file entirely.
                  (default is False)
      binaryType - binary type to generate, NOT to read in...routine looks for
                  PKL files first, then mat files, then proceeds to re-compute
                  if neither are available.
                  (default is 'pkl')
      configFile - specifies plotting config file; if None, default config file
                   is path/figs/north|south/deltaBSum.config; if this doesn't
                   exist, create new one with default config parameters.
    """
    
    assert( (hemisphere == 'north') | (hemisphere == 'south') )
    
    hemiSelect = {'north': 'North', 'south': 'South'}[hemisphere]

    # Make sure the output directory exisits if not make it
    dirname = os.path.join(path, 'figs', hemisphere)
    if not os.path.exists(dirname):
        os.makedirs( dirname )

    print(('Rendering ' + hemiSelect + 'ern hemisphere, storing frames at ' + dirname))        
    #Now check to make sure the MIX files are correct
    dMIX = pyLTR.Models.MIX(path, run)
    modelVars = dMIX.getVarNames()
    for v in ['Grid X', 'Grid Y', 
              'Potential North [V]', 'Potential South [V]', 
              'FAC North [A/m^2]', 'FAC South [A/m^2]',
              'Pedersen conductance North [S]', 'Pedersen conductance South [S]', 
              'Hall conductance North [S]', 'Hall conductance South [S]']:
        assert( v in modelVars )
    
    
    timeRange = dMIX.getTimeRange()
    
    #Now check to make sure the LFM files are correct
    dLFM = pyLTR.Models.LFM(path, run)
    modelVars = dLFM.getVarNames()
    for v in ['X_grid', 'Y_grid', 'Z_grid', 
              'bx_', 'by_', 'bz_']:
        assert( v in modelVars )

    # check that LFM output timeRanges are exactly the same as MIX output timeRanges
    trLFM = dLFM.getTimeRange()
    # _roundTime() rounds to nearest minute by default, which should suffice here
    # NOTE: we do NOT change the time stamps at all, just make sure they match
    #       to a 1-minute tolerance
    if list(map(_roundTime, timeRange)) != list(map(_roundTime, trLFM)):
       raise Exception(('Mismatched MIX and LFM output files'))
    
    
    if len(timeRange) == 0:
        raise Exception(('No data files found.  Are you pointing to the correct run directory?'))
    
    
    
    ## Original code defaulted to entire data set if the user-supplied time range
    ## fell outside of the available data, almost certainly not a desired result.
    ## Now if the user requests a time range that falls completely outside of the
    ## available data, and exception is raised.
    
    ##index0 = 0
    ##if t0:
    ##    for i,t in enumerate(timeRange):
    ##        if t0 >= t:
    ##            index0 = i
    ##
    ###index1 = len(timeRange)-1
    ##index1 = len(timeRange) # we were skipping the last valid time step
    ##if t1:
    ##    for i,t in enumerate(timeRange):
    ##        if t1 >= t:
    ##            #index1 = i
    ##            index1 = i + 1 # we were skipping the last valid time step
    
    
    if t0:
       if t1 and t1 < timeRange[0]: # upper time stamp below lowest available time stamp
          raise Exception('Requested time range falls outside available data')
       if t0 > timeRange[-1]: # lower time stamp above highest available time stamp
          raise Exception('Requested time range falls outside available data')
       
       for i,t in enumerate(timeRange):
          if t0 >= t:
             index0 = i
    else:
       index0 = 0
    
    
    if t1:
       if t0 and t0 > timeRange[-1]: # lower time stamp above highest available time stamp
          raise Exception('Requested time range falls outside available data')
       if t1 < timeRange[0]: # upper time stamp below lowest available time stamp
          raise Exception('Requested time range falls outside available data')
       
       for i,t in enumerate(timeRange):
          if t1 >= t:
             index1 = i+1
    else:
       index1 = len(timeRange)
    
    
    if index1 > index0:
       print(( 'Extracting LFM and MIX quantities for time series over %d time steps.' % (index1-index0) ))
    else:
       raise Exception('Requested time range is invalid')
    
    
    
    # Output a status bar displaying how far along the computation is.
    progress = pyLTR.StatusBar(0, index1-index0)
    progress.start()

    # Pre-compute r and theta
    x = dMIX.read('Grid X', timeRange[index0])
    xdict={'data':x*6500e3,'name':'X','units':r'm'}
    y = dMIX.read('Grid Y', timeRange[index0])
    ydict={'data':y*6500e3,'name':'Y','units':r'm'}
    theta=n.arctan2(y,x)
    theta[theta<0]=theta[theta<0]+2*n.pi
    # plotting routines now rotate local noon to point up
    #theta=theta+n.pi/2 # to put noon up
    r=n.sqrt(x**2+y**2)
    # plotting routines now expect longitude and colatitude, in radians, stored in dictionaries
    longitude = {'data':theta,'name':r'\phi','units':r'rad'}
    colatitude = {'data':n.arcsin(r),'name':r'\theta','units':r'rad'}
    
    
    # Deal with the plot options
    if (configFile == None and os.path.exists(os.path.join(dirname,'deltaBSum.config')) ):
       configFile = os.path.join(dirname,'deltaBSum.config')
    
    if configFile == None:
       # scalar radial magnetic pertubations
       dBradialTotOpts={'min':-100,'max':100,'colormap':'jet'}
       dBradialIonOpts={'min':-100,'max':100,'colormap':'jet'}
       dBradialFACOpts={'min':-100,'max':100,'colormap':'jet'}
       dBradialMagOpts={'min':-100,'max':100,'colormap':'jet'}
       
       # 2D vector horizontal perturbations
       dBhvecTotOpts={'width':.0025,'scale':1e3,'pivot':'middle'}
       dBhvecIonOpts={'width':.0025,'scale':1e3,'pivot':'middle'}
       dBhvecFACOpts={'width':.0025,'scale':1e3,'pivot':'middle'}
       dBhvecMagOpts={'width':.0025,'scale':1e3,'pivot':'middle'}
              
       # place all config dictionaries in one big dictionary
       optsObject = {'dBradialTot':dBradialTotOpts,
                     'dBradialIon':dBradialIonOpts,
                     'dBradialFAC':dBradialFACOpts,
                     'dBradialMag':dBradialMagOpts,
                     'dBhvecTot':dBhvecTotOpts,
                     'dBhvecIon':dBhvecIonOpts,
                     'dBhvecFAC':dBhvecFACOpts,
                     'dBhvecMag':dBhvecMagOpts,
                     'altPole':altPoleOpts}
       configFilename=os.path.join(dirname,'deltaBSum.config')
       print(("Writing plot config file at " + configFilename))
       f=open(configFilename,'w')
       f.write(pyLTR.yaml.safe_dump(optsObject,default_flow_style=False))
       f.close()
    else:
       f=open(configFile,'r')
       optsDict=pyLTR.yaml.safe_load(f.read())
       f.close()
       if ('dBradialTot' in optsDict):
          dBradialTotOpts = optsDict['dBradialTot']
       else:
          dBradialTotOpts={'min':-100.,'max':100.,'colormap':'jet'}
       
       if ('dBradialIon' in optsDict):
          dBradialIonOpts = optsDict['dBradialIon']
       else:
          dBradialIonOpts={'min':-100.,'max':100.,'colormap':'jet'}
           
       if ('dBradialFAC' in optsDict):
          dBradialFACOpts = optsDict['dBradialFAC']
       else:
          dBradialFACOpts={'min':-100.,'max':100.,'colormap':'jet'}
       
       if ('dBradialMag' in optsDict):
          dBradialMagOpts = optsDict['dBradialMag']
       else:
          dBradialMagOpts={'min':-100.,'max':100.,'colormap':'jet'}
       
       
       if ('dBhvecTot' in optsDict):
          dBhvecTotOpts = optsDict['dBhvecTot']
       else:
          dBhvecTotOpts={'min':-100.,'max':100.,'colormap':'jet'}
       
       if ('dBhvecIon' in optsDict):
          dBhvecIonOpts = optsDict['dBhvecIon']
       else:
          dBhvecIonOpts={'min':-100.,'max':100.,'colormap':'jet'}
           
       if ('dBhvecFAC' in optsDict):
          dBhvecFACOpts = optsDict['dBhvecFAC']
       else:
          dBhvecFACOpts={'min':-100.,'max':100.,'colormap':'jet'}
       
       if ('dBhvecMag' in optsDict):
          dBhvecMagOpts = optsDict['dBhvecMag']
       else:
          dBhvecMagOpts={'min':-100.,'max':100.,'colormap':'jet'}
       
       if ('altPole' in optsDict):
          altPoleOpts = optsDict['altPole']
       else:
          altPoleOpts = {'poleMarker1':'x', 'poleMarker2':'x',
                         'poleSize1':7, 'poleSize2':5,
                         'poleWidth1':3, 'poleWidth2':1,
                         'poleColor1':'blue', 'poleColor2':'white'}
       
    # initialize output list
    pngFilenames = []
    for i,time in enumerate(timeRange[index0:index1]):
        
        try:
           
           try:
              
              # ignore binary file even if one exists
              if ignoreBinary:
                 raise Exception
              
              # look for a .pkl file that already holds all the data required for
              # subsequent plots before recalculating all the derived data...if
              # this fails, look for a .mat file, if this fails, fall through to 
              # recalculate all summary data
              filePrefix = os.path.join(path,'figs',hemisphere)
              
              # this is a possible race condition, but try/except just doesn't do what I want
              if os.path.exists(os.path.join(filePrefix,
                                             'frame_deltaB_%04d-%02d-%02dT%02d-%02d-%02dZ.pkl'%
                                             (time.year,time.month,time.day,
                                              time.hour,time.minute,time.second))):
                 
                 binFilename = os.path.join(filePrefix,
                                            'frame_deltaB_%04d-%02d-%02dT%02d-%02d-%02dZ.pkl'%
                                            (time.year,time.month,time.day,
                                             time.hour,time.minute,time.second))
                 fh=open(binFilename,'rb')
                 allDict = pickle.load(fh)
                 fh.close()
                 
              elif os.path.exists(os.path.join(filePrefix,
                                               'frame_deltaB_%04d-%02d-%02dT%02d-%02d-%02dZ.mat'%
                                               (time.year,time.month,time.day,
                                                time.hour,time.minute,time.second))):
                 
                 binFilename = os.path.join(filePrefix,
                                            'frame_deltaB_%04d-%02d-%02dT%02d-%02d-%02dZ.mat'%
                                            (time.year,time.month,time.day,
                                             time.hour,time.minute,time.second))
                 fh=open(binFilename,'rb')
                 allDict = sio.loadmat(fh, squeeze_me=True)
                 fh.close()
                 
              
              else:
              
                 print(('No binary file found, recalculating '+
                        'frame_deltaB_%04d-%02d-%02dT%02d-%02d-%02dZ'%
                        (time.year,time.month,time.day,time.hour,time.minute,time.second)+
                        '...'))
                 raise Exception
              
              
              
              
              # ignore binary file if the coordinate system is not consistent with geoGrid
              if ((geoGrid and allDict['coordinates'] != 'Geographic') or
                  (not(geoGrid) and allDict['coordinates'] != 'Solar Magnetic')):
                 raise Exception
              
              phi_dict,theta_dict,rho_dict = allDict['dB_obs']            
              phi = phi_dict['data'] * 1. # '*1' forces array of floats, NOT objects
              theta = theta_dict['data'] * 1. # '*1' forces array of floats, NOT objects
              rho = rho_dict['data'] * 1. # '*1' forces array of floats, NOT objects
              
              if geoGrid:
                 phi_geo = phi
                 theta_geo = theta
                 rho_geo = rho
              
              dBphi_ion_dict,dBtheta_ion_dict,dBrho_ion_dict = allDict['dB_ion']
              dBphi_ion = dBphi_ion_dict['data'] / 1e9 # convert to Tesla
              dBtheta_ion = dBtheta_ion_dict['data'] / 1e9 # convert to Tesla
              dBrho_ion = dBrho_ion_dict['data'] / 1e9 # convert to Tesla
              
              dBphi_fac_dict,dBtheta_fac_dict,dBrho_fac_dict = allDict['dB_fac']
              dBphi_fac = dBphi_fac_dict['data'] / 1e9 # convert to Tesla
              dBtheta_fac = dBtheta_fac_dict['data'] / 1e9 # convert to Tesla
              dBrho_fac = dBrho_fac_dict['data'] / 1e9 # convert to Tesla
              
              dBphi_mag_dict,dBtheta_mag_dict,dBrho_mag_dict = allDict['dB_mag']
              dBphi_mag = dBphi_mag_dict['data'] / 1e9 # convert to Tesla
              dBtheta_mag = dBtheta_mag_dict['data'] / 1e9 # convert to Tesla
              dBrho_mag = dBrho_mag_dict['data'] / 1e9 # convert to Tesla
              
              
           except:
              
              
              # first read the MIX data
              vals=dMIX.read('Potential '+hemiSelect+' [V]',time)/1000.0
              psi_dict={'data':vals,'name':r'$\Phi$','units':r'kV'}
              vals=dMIX.read('Pedersen conductance '+hemiSelect+' [S]',time)
              sigmap_dict={'data':vals,'name':r'$\Sigma_{P}$','units':r'S'}
              vals=dMIX.read('Hall conductance '+hemiSelect+' [S]',time)
              sigmah_dict={'data':vals,'name':r'$\Sigma_{H}$','units':r'S'}
              vals=dMIX.read('FAC '+hemiSelect+' [A/m^2]',time)
              fac_dict={'data':vals*1e6,'name':r'$J_\parallel$','units':r'$\mu A/m^2$'}
              
              
              
              # then compute the electric field vectors
              ((phi_dict,theta_dict),
               (ephi_dict,etheta_dict)) = pyLTR.Physics.MIXCalcs.efieldDict(
                       xdict, ydict, psi_dict, ri=6500e3)
              
              
              # then compute total, Pedersen, and Hall current vectors
              if hemisphere=='north':
                 ((Jphi_dict,Jtheta_dict),
                  (Jpedphi_dict,Jpedtheta_dict),
                  (Jhallphi_dict,Jhalltheta_dict)) = pyLTR.Physics.MIXCalcs.jphithetaDict(
                          (ephi_dict,etheta_dict), sigmap_dict, sigmah_dict, colatitude['data'])
              else:
                 ((Jphi_dict,Jtheta_dict),
                  (Jpedphi_dict,Jpedtheta_dict),
                  (Jhallphi_dict,Jhalltheta_dict)) = pyLTR.Physics.MIXCalcs.jphithetaDict(
                          (ephi_dict,etheta_dict), sigmap_dict, sigmah_dict, n.pi-colatitude['data'])
               
              
              
              # then generate the SSECS, starting with min/max bounds of ionosphere
              # segments
              phi = phi_dict['data']
              theta = theta_dict['data']

              # caclulate MIX grid cell boundaries in phi and theta
              rion_min = [None] * 3 # initialize empty 3 list
              rion_min[0] = p.zeros(phi.shape)
              rion_min[0][1:,:] = phi[1:,:] - p.diff(phi, axis=0)/2.
              rion_min[0][0,:] = phi[0,:] - p.diff(phi[0:2,:], axis=0).squeeze()/2.

              rion_min[1] = p.zeros(theta.shape)
              rion_min[1][:,1:] = theta[:,1:] - p.diff(theta, axis=1)/2.
              rion_min[1][:,0] = theta[:,0] - p.diff(theta[:,0:2], axis=1).squeeze()/2.

              rion_min[2] = p.zeros(theta.shape)
              rion_min[2][:,:] = 6500.e3


              rion_max = [None] * 3 # initialize empty 3 list
              rion_max[0] = p.zeros(phi.shape)
              rion_max[0][:-1,:] = phi[:-1,:] + p.diff(phi, axis=0)/2.
              rion_max[0][-1,:] = phi[-1,:] + p.diff(phi[-2:,:], axis=0).squeeze()/2.

              rion_max[1] = p.zeros(theta.shape)
              rion_max[1][:,:-1] = theta[:,:-1] + p.diff(theta, axis=1)/2.
              rion_max[1][:,-1] = theta[:,-1] + p.diff(theta[:,-2:], axis=1).squeeze()/2.

              rion_max[2] = p.zeros(theta.shape)
              rion_max[2][:,:] = p.Inf
              
              
              
              # generate SSECS for ionospheric currents only
              (rv_ion, 
               Jv_ion, 
               dv_ion) = pyLTR.Physics.SSECS.ssecs_sphere([rion_min[0],rion_min[1],rion_min[2]], 
                                                          [rion_max[0],rion_max[1],rion_min[2]], 
                                                          (Jphi_dict['data']/1e6, 
                                                           Jtheta_dict['data']/1e6), 
                                                          10, False)
              
              # generate SSECS inside LFM inner boundary
              (rv_IBin, 
               Jv_IBin, 
               dv_IBin) = pyLTR.Physics.SSECS.ssecs_sphere([rion_min[0],rion_min[1],rion_min[2]], 
                                                           [rion_max[0],rion_max[1],2.5*rion_min[2]], 
                                                           (Jphi_dict['data']/1e6, 
                                                            Jtheta_dict['data']/1e6), 
                                                           10, False)
              
              # do NOT attempt to generate SSECS for FACs alone...this isn't possible
              # with existing code; However, the deltaB from FACs is the difference
              # between deltaBs calculated from the two SSECS above
              
              
              # generate SSECS outside LFM inner boundary
              # (this is serving as a proxy for magnetosphere currents for now)
              (rv_mag, 
               Jv_mag, 
               dv_mag) = pyLTR.Physics.SSECS.ssecs_sphere([rion_min[0],rion_min[1],2.5*rion_min[2]], 
                                                          [rion_max[0],rion_max[1],rion_min[2]],
                                                          (Jphi_dict['data']/1e6, 
                                                           Jtheta_dict['data']/1e6), 
                                                          10, False)
              
              # extract currents from MHD data
              # NOTE: LFM time stamps are not necessarily the same as MIX, so it
              #       is necessary to use the LFM's timeRange list (i.e., trLFM)
              x=dLFM.read('X_grid', trLFM[index0:index1][i]) # this is in cm
              y=dLFM.read('Y_grid', trLFM[index0:index1][i]) # this is in cm
              z=dLFM.read('Z_grid', trLFM[index0:index1][i]) # this is in cm
              Bx=dLFM.read('bx_', trLFM[index0:index1][i]) # this is in G
              By=dLFM.read('by_', trLFM[index0:index1][i]) # this is in G
              Bz=dLFM.read('bz_', trLFM[index0:index1][i]) # this is in G
              hgrid=pyLTR.Grids.HexahedralGrid(x,y,z)
              xB,yB,zB=hgrid.cellCenters()
              hgridcc=pyLTR.Grids.HexahedralGrid(xB,yB,zB) # B is at cell centers
              Jx,Jy,Jz = pyLTR.Physics.LFMCurrent(hgridcc,Bx,By,Bz,rion=1) # ...should be A/m^2 given default input units
              xJ,yJ,zJ = hgridcc.cellCenters() # ...and J is at the centers of these cells
              xJ = xJ/100 # ...and the coordinates should be in meters for BS.py
              yJ = yJ/100 # ...and the coordinates should be in meters for BS.py
              zJ = zJ/100 # ...and the coordinates should be in meters for BS.py
              ldV = hgridcc.cellVolume()/(100**3) # ...and we need dV in m^3 for BS.py
              
              if hemisphere=='south':
                 # it's easier to rotate the LFM grid than convert the MIX coordinates
                 # for southern hemisphere output
                 yJ = -yJ
                 zJ = -zJ
                 Jy = -Jy
                 Jz = -Jz
              
              
              
              #
              # This is a little ugly...Quad (and Oct) resolution LFM runs use
              # MIX grids that are different resoltions than Single and Double
              # runs; not surprising, but I was slow to figure this out. Anyway,
              # we need to visualize and cross-validate on similar grids, thus
              # the following kludge ('kludge' because the better answer is to
              # specify a useful grid without any reference to the MIX grid).
              #
              if phi.size == 181*27:
                 pass
              elif phi.size == 361*48:
                 phi = phi[::2,[0,1,2,3,4]+list(range(5,48,2))]
                 theta = theta[::2,[0,1,2,3,4]+list(range(5,48,2))]
              else:
                 raise Exception('Unrecognized MIX grid dimensions')
              
              
              
              # calculate deltaBs on a grid that decimates MIX grid by 2/3, and removes
              # the lowest 3 colatitutdes
              phi = phi[::3,3:]
              theta = theta[::3,3:]
              rho = p.tile(6378e3,phi.shape)
              
              if geoGrid:
                 phi_geo = phi
                 theta_geo = theta
                 rho_geo = rho
                 x,y,z = pyLTR.transform.SPHtoCAR(phi,theta,rho)
                 x,y,z = pyLTR.transform.GEOtoSM(x,y,z,time)
                 phi,theta,rho = pyLTR.transform.CARtoSPH(x,y,z)
              
              
              # deltaB for ionospheric currents
              (dBphi_ion, 
               dBtheta_ion, 
               dBrho_ion) = pyLTR.Physics.BS.bs_sphere(rv_ion, 
                                                       Jv_ion, 
                                                       dv_ion, 
                                                       (phi,theta,rho))
              
              
              # deltaB for currents inside IB
              (dBphi_IBin, 
               dBtheta_IBin, 
               dBrho_IBin) = pyLTR.Physics.BS.bs_sphere(rv_IBin, 
                                                        Jv_IBin, 
                                                        dv_IBin, 
                                                        (phi,theta,rho))
              # difference between dB*_IBin and dB*_ion is the FAC inside IB
              dBphi_fac = dBphi_IBin - dBphi_ion
              dBtheta_fac = dBtheta_IBin - dBtheta_ion
              dBrho_fac = dBrho_IBin - dBrho_ion
                            
              
              # deltaB from magnetospheric currents
              # convert cartesian positions and vectors to spherical
              lphi,ltheta,lrho,lJphi,lJtheta,lJrho=pyLTR.transform.CARtoSPH(xJ,yJ,zJ,Jx,Jy,Jz)
              (dBphi_mag, 
               dBtheta_mag, 
               dBrho_mag) = pyLTR.Physics.BS.bs_sphere((lphi,ltheta,lrho), 
                                                       (lJphi,lJtheta,lJrho), 
                                                       ldV, 
                                                       (phi,theta,rho))
              
              
              if geoGrid:
                 
                 # rotate ionospheric contribution from SM to GEO coordinates; leave
                 # position vectors unchanged for subsequent rotations
                 x,y,z,dx,dy,dz = pyLTR.transform.SPHtoCAR(phi,theta,rho,dBphi_ion,dBtheta_ion,dBrho_ion)
                 x,y,z = pyLTR.transform.SMtoGEO(x,y,z,time)
                 dx,dy,dz = pyLTR.transform.SMtoGEO(dx,dy,dz,time)
                 _, _, _, dBphi_ion, dBtheta_ion, dBrho_ion = pyLTR.transform.CARtoSPH(x,y,z,dx,dy,dz)
                 
                 # rotate FAC contribution from SM to GEO coordinates leave
                 # position vectors unchanged for subsequent rotations
                 x,y,z,dx,dy,dz = pyLTR.transform.SPHtoCAR(phi,theta,rho,dBphi_fac,dBtheta_fac,dBrho_fac)
                 x,y,z = pyLTR.transform.SMtoGEO(x,y,z,time)
                 dx,dy,dz = pyLTR.transform.SMtoGEO(dx,dy,dz,time)
                 _, _, _, dBphi_fac, dBtheta_fac, dBrho_fac = pyLTR.transform.CARtoSPH(x,y,z,dx,dy,dz)
                 
                 # rotate magnetospheric contribution from SM to GEO coordinates
                 x,y,z,dx,dy,dz = pyLTR.transform.SPHtoCAR(phi,theta,rho,dBphi_mag,dBtheta_mag,dBrho_mag)
                 x,y,z = pyLTR.transform.SMtoGEO(x,y,z,time)
                 dx,dy,dz = pyLTR.transform.SMtoGEO(dx,dy,dz,time)
                 _, _, _, dBphi_mag, dBtheta_mag, dBrho_mag = pyLTR.transform.CARtoSPH(x,y,z,dx,dy,dz)
                 
                 phi = phi_geo
                 theta = theta_geo
                 rho = rho_geo
              
              
              #
              # end of [re]processing 'except' block
              #
           
           
           
           
           # (re)create grid dictionary for subsequent plots and pickling
           toPickle={}
           
           if hemisphere=='south':
              toPickle['pov'] = 'south'
           else:
              toPickle['pov'] = 'north'
           
           if geoGrid:
              toPickle['coordinates'] = 'Geographic'
              
              # get geographic coordinates of sm pole
              x,y,z = pyLTR.transform.SPHtoCAR(0,0,1)
              x,y,z = pyLTR.transform.SMtoGEO(x,y,z,time)
              poleCoords = pyLTR.transform.CARtoSPH(x,y,z)
           else:
              toPickle['coordinates'] = 'Solar Magnetic'
              
              ## # get sm coordinates of geographic pole
              ## x,y,z = pyLTR.transform.SPHtoCAR(0,0,1)
              ## x,y,z = pyLTR.transform.GEOtoSM(x,y,z,time)
              ## poleCoords = pyLTR.transform.CARtoSPH(x,y,z)
              
              ## now that MapPlot is being used, and until it can properly
              ## plot in centered SM coordinates, we want to just plot the 
              ## magnetic pole;
              poleCoords = (0, 0, 1)
           
           phi_dict = {'data':phi,'name':r'$\phi$','units':r'rad'}
           theta_dict = {'data':theta,'name':r'$\theta$','units':r'rad'}
           rho_dict = {'data':rho,'name':r'$\rho$','units':r'm'}
           
           toPickle['dB_obs'] = (phi_dict,theta_dict,rho_dict)
           
           
           
           
           #####################################################################
           ##
           ## FIXME: move plots from this function into if __name__ == '__main__'
           ##        section like deltaBTimeSeries.py; plots will then only be
           ##        generated if user requests it, and this function may be
           ##        called as part of a module...
           ##        But note: one reason the plots are generated inside this
           ##                  function is that a long time series of gridded
           ##                  data becomes unmanageable memory-wise fairly
           ##                  quickly...think this through carefully. -EJR
           ##
           #####################################################################
           
           
           
           # Now onto the plots
           tt=time.timetuple()
           
           p.figure(1,figsize=(28,6))
           p.figtext(0.5,0.92,'Ground '+'$\Delta{\mathbf{B}}$'+' - '+hemiSelect+
                     '\n%4d-%02d-%02d  %02d:%02d:%02d' %
                  (tt.tm_year,tt.tm_mon,tt.tm_mday,
                  tt.tm_hour,tt.tm_min,tt.tm_sec),
                  fontsize=14,multialignment='center')
           
           
           # plot total deltaB
           ax=p.subplot(141)
           # temporary dictionaries
           dBphi_dict = {'data':(dBphi_ion + dBphi_fac + dBphi_mag)*1e9,'name':r'$\Delta \mathrm{B}_{\phi}$','units':'nT'}
           dBtheta_dict = {'data':(dBtheta_ion + dBtheta_fac + dBtheta_mag)*1e9,'name':r'$\Delta \mathrm{B}_{\theta}$','units':'nT'}
           dBrho_dict = {'data':(dBrho_ion + dBrho_fac + dBrho_mag)*1e9,'name':r'$\Delta \mathrm{B}_{\rho}$','units':'nT'}
           bm = pyLTR.Graphics.MapPlot.QuiverPlotDict(phi_dict,theta_dict, 
                                                      dBrho_dict,(dBphi_dict, dBtheta_dict),
                                                      dtUTC=time, coordSystem=toPickle['coordinates'],
                                                      plotOpts1=dBradialTotOpts,
                                                      plotOpts2=dBhvecTotOpts,
                                                      points=[(poleCoords[0],poleCoords[1])],
                                                      userAxes=ax, northPOV=hemisphere=='north')
           
           to=p.text(.05, .95, r"$\Delta \mathbf{B}_{\mathrm{Total}}$", 
                     fontsize=14, transform=ax.transAxes)
          
           
           
           
           
           # plot ionospheric deltaB
           ax=p.subplot(142)
           # temporary dictionaries
           dBphi_dict = {'data':(dBphi_ion)*1e9,'name':r'$\Delta \mathrm{B}_{\phi}$','units':'nT'}
           dBtheta_dict = {'data':(dBtheta_ion)*1e9,'name':r'$\Delta \mathrm{B}_{\theta}$','units':'nT'}
           dBrho_dict = {'data':(dBrho_ion)*1e9,'name':r'$\Delta \mathrm{B}_{\rho}$','units':'nT'}
           bm = pyLTR.Graphics.MapPlot.QuiverPlotDict(phi_dict,theta_dict, 
                                                      dBrho_dict,(dBphi_dict, dBtheta_dict),
                                                      dtUTC=time, coordSystem=toPickle['coordinates'],
                                                      plotOpts1=dBradialIonOpts,
                                                      plotOpts2=dBhvecIonOpts,
                                                      points=[(poleCoords[0],poleCoords[1])],
                                                      userAxes=ax, northPOV=hemisphere=='north')
                      
           to=p.text(.05, .95, r"$\Delta \mathbf{B}_{\mathrm{ion}}$", 
                     fontsize=14, transform=ax.transAxes)
           
           # for subsequent pickling
           toPickle['dB_ion'] = (dBphi_dict,dBtheta_dict,dBrho_dict)
           
           
           # plot FAC deltaB
           ax=p.subplot(143)
           # temporary dictionaries
           dBphi_dict = {'data':(dBphi_fac)*1e9,'name':r'$\Delta \mathrm{B}_{\phi}$','units':'nT'}
           dBtheta_dict = {'data':(dBtheta_fac)*1e9,'name':r'$\Delta \mathrm{B}_{\theta}$','units':'nT'}
           dBrho_dict = {'data':(dBrho_fac)*1e9,'name':r'$\Delta \mathrm{B}_{\rho}$','units':'nT'}
           bm = pyLTR.Graphics.MapPlot.QuiverPlotDict(phi_dict,theta_dict, 
                                                      dBrho_dict,(dBphi_dict, dBtheta_dict),
                                                      dtUTC=time, coordSystem=toPickle['coordinates'],
                                                      plotOpts1=dBradialFACOpts,
                                                      plotOpts2=dBhvecFACOpts,
                                                      points=[(poleCoords[0],poleCoords[1])],
                                                      userAxes=ax, northPOV=hemisphere=='north')
           
           to=p.text(.05, .95, r"$\Delta \mathbf{B}_{\mathrm{fac}}$", 
                     fontsize=14, transform=ax.transAxes)
           
           # for subsequent pickling
           toPickle['dB_fac'] = (dBphi_dict,dBtheta_dict,dBrho_dict)
           
           
           # plot magnetospheric deltaB
           ax=p.subplot(144)
           # temporary dictionaries
           dBphi_dict = {'data':(dBphi_mag)*1e9,r'name':'$\Delta \mathrm{B}_{\phi}$','units':'nT'}
           dBtheta_dict = {'data':(dBtheta_mag)*1e9,r'name':'$\Delta \mathrm{B}_{\theta}$','units':'nT'}
           dBrho_dict = {'data':(dBrho_mag)*1e9,'name':r'$\Delta \mathrm{B}_{\rho}$','units':'nT'}
           bm = pyLTR.Graphics.MapPlot.QuiverPlotDict(phi_dict,theta_dict, 
                                                      dBrho_dict,(dBphi_dict, dBtheta_dict),
                                                      dtUTC=time, coordSystem=toPickle['coordinates'],
                                                      plotOpts1=dBradialMagOpts,
                                                      plotOpts2=dBhvecMagOpts,
                                                      points=[(poleCoords[0],poleCoords[1])],
                                                      userAxes=ax, northPOV=hemisphere=='north')
                      
           to=p.text(.05, .95, r"$\Delta \mathbf{B}_{\mathrm{mag}}$", 
                     fontsize=14, transform=ax.transAxes)
           
           # for subsequent pickling
           toPickle['dB_mag'] = (dBphi_dict,dBtheta_dict,dBrho_dict)
           
           
           
           
           #savefigName = os.path.join(path,'figs',hemisphere,'frame_deltaB_%05d.png'%i)
           filePrefix = os.path.join(path,'figs',hemisphere)
           pngFilename = os.path.join(filePrefix,'frame_deltaB_%04d-%02d-%02dT%02d-%02d-%02dZ.png'%
                                                 (time.year,time.month,time.day,time.hour,time.minute,time.second))
           
           p.savefig(pngFilename,dpi=150)
           p.clf()
           
           
           if binaryType.lower() == 'pkl' or binaryType.lower() == '.pkl' or binaryType.lower() == 'pickle':
              # --- Dump a pickle!
              pklFilename = os.path.join(filePrefix,'frame_deltaB_%04d-%02d-%02dT%02d-%02d-%02dZ.pkl'%
                                                    (time.year,time.month,time.day,time.hour,time.minute,time.second))
              fh = open(pklFilename, 'wb')
              pickle.dump(toPickle, fh, protocol=2)
              fh.close()
           elif binaryType.lower() == 'mat' or binaryType.lower() == '.mat' or binaryType.lower() == 'matlab':
              # --- Dump a .mat file!
              matFilename = os.path.join(filePrefix,'frame_deltaB_%04d-%02d-%02dT%02d-%02d-%02dZ.mat'%
                                                    (time.year,time.month,time.day,time.hour,time.minute,time.second))
              sio.savemat(matFilename, toPickle)
           elif binaryType.lower() == 'none':
              pass
           else:
              print(('Unrecognized binary type '+binaryType+' requested'))
              raise Exception
              
              
           progress.increment()
           
           
        except KeyboardInterrupt:
            # Exit when the user hits CTRL+C.
            progress.stop()
            progress.join()            
            print('Exiting.')
            import sys
            sys.exit(0)
                
        except:
            # Cleanup progress bar if something bad happened.
            progress.stop()
            progress.join()
            raise
    
        
        # append pngFilename to list of fully qualified filenames 
        pngFilenames.append(pngFilename)
    
        
    progress.stop()
    progress.join()

    
    #return  os.path.join(path,'figs',hemisphere)
    return pngFilenames