diff --git a/pyglance/glance/imapp_plot.py b/pyglance/glance/imapp_plot.py
index 4db9aa4d0a11f1f35b6b74ece76bf065cefe4dce..bc40328f7fecdb3df37fb01992369246a5e208ea 100644
--- a/pyglance/glance/imapp_plot.py
+++ b/pyglance/glance/imapp_plot.py
@@ -20,6 +20,7 @@ import matplotlib.pyplot as plt
 import matplotlib.colors as colors
 from mpl_toolkits.basemap import Basemap
 
+import re
 import numpy as np
 
 import glance.data as dataobj
@@ -27,19 +28,31 @@ import glance.data as dataobj
 LOG = logging.getLogger(__name__)
 
 defaultValues   = {
-                    'longitudeVar': 'xtraj',
-                    'latitudeVar':  'ytraj',
-                    'initAODVar':   'aod_traj',
-                    'trajPressVar': 'ptraj',
-                    'timeVar':      'time',
-                    'nePiece':      'NE_',
-                    'swPiece':      'SW_',
-                    'latPiece':     'LAT',
-                    'lonPiece':     'LON',
-                    'figureName':   'frame.png',
-                    'figureDPI':    200
+                    'longitudeVar':  'xtraj',
+                    'latitudeVar':   'ytraj',
+                    'initAODVar':    'aod_traj',
+                    'trajPressVar':  'ptraj',
+                    'timeVar':       'time',
+                    'neName':        'TOP_RIGHT_LON_LAT', #TODO need to fix this? 'NE',
+                    'swName':        'BOTTOM_LEFT_LON_LAT', # TODO need to fix this? 'SW',
+                    'windLonName':   'Longitude',
+                    'windLatName':   'Latitude',
+                    'windTimeName':  'time',
+                    'windUName':     'uwind',
+                    'windVName':     'vwind',
+                    'emissNameBase': 'Cloud_Effective_Emissivity_',
+                    'aodNameBase':   'Optical_Depth_Land_And_Ocean_',
+                    'optLonBase':    'Lon_',
+                    'optLatBase':    'Lat_',
+                    'figureName':    'frame.png',
+                    'figureDPI':     200
                   }
 
+ACCEPTABLE_MAP_PROJECTIONS = ['cylindrical']
+
+LEVELS_FOR_BACKGROUND_PLOTS    = 20
+DEFAULT_WINDS_SUBDIVIDE_FACTOR = 1
+
 # a custom colormap or the Trajectory Pressures
 color_data = {
     'red'   : ( (0.0,  1.0,  1.0),
@@ -72,70 +85,299 @@ color_data = {
               }
 light_trajectory_pressure_color_map = matplotlib.colors.LinearSegmentedColormap('lightTrajPressCM', color_data, 256)
 
-def _create_imapp_figure (initAODdata,       initLongitudeData,       initLatitudeData,
-                          pressureData=None, pressLongitudeData=None, pressLatitudeData=None,
-                          baseMapInstance=None, figureTitle="MODIS AOD & AOD Trajectories",
-                          useDarkBackground=True, latRange=None, lonRange=None) :
+def _check_requested_projection (projection, doWarn=True, fileDescription="") :
     """
-    TODO, I'm still deciding how this funciton works so it will probably change drastically
+    Check the requested projection, issuing a warning if it is not available and doWarn is true
     """
     
-    # build the plot
-    figure = plt.figure()
-    tempColor = 'k' if useDarkBackground else 'w' # either use a black or white background
-    axes = figure.add_subplot(111, axisbg=tempColor)
+    LOG.debug("Requested map projection: " + str(projection))
+    if projection not in ACCEPTABLE_MAP_PROJECTIONS :
+        LOG.warn("The requested map projection in " + fileDescription + " (" + str(projection)
+                 + ") is not a projection that can be produced by this program. "
+                 + "A default projection will be produced. Output may not be displayed as expected.")
+
+def _get_matching_terms_from_list (list_of_strings, regular_expression_text, case_sensitive=False) :
+    """
+    given a list and a text regular expression in the form taken by the python re module,
+    return a list of all strings in the list that match that regular expression
     
-    # build extra info to go to the map plotting function
-    kwargs = { } 
+    TODO, there's probably a better way to do this, but this is what I've got for now
+    """
     
-    # draw the basic physical and geopolitical features
-    tempColor='w' if useDarkBackground else 'k' # either draw black or white lines
-    if baseMapInstance is not None :
-        baseMapInstance.drawcoastlines( color=tempColor, linewidth=0.5)
-        baseMapInstance.drawcountries(  color=tempColor, linewidth=0.5)
-        baseMapInstance.drawstates(     color=tempColor, linewidth=0.5)
-        baseMapInstance.drawmapboundary(color=tempColor, linewidth=0.5)
-    # draw the parallels and meridians
-    if latRange is not None :
-        parallels = arange(-80., 90.,  latRange / 4.0)
-        baseMapInstance.drawparallels(parallels,labels=[1,0,0,1], color=tempColor, linewidth=0.5)
-    if lonRange is not None :
-        meridians = arange(0.,   360., lonRange / 4.0)
-        baseMapInstance.drawmeridians(meridians,labels=[1,0,0,1], color=tempColor, linewidth=0.5)
+    tempExpression = re.compile(regular_expression_text) if case_sensitive else re.compile(regular_expression_text, re.IGNORECASE)
     
-    # translate the longitude and latitude data sets into map coordinates
-    pressX, pressY = None, None
-    if pressureData is not None :
-        pressX, pressY =  baseMapInstance(pressLongitudeData, pressLatitudeData)
-    initX,  initY  = baseMapInstance(initLongitudeData,  initLatitudeData)
+    toReturn = [ ]
+    for term in list_of_strings :
+        if tempExpression.match(term) is not None :
+            toReturn.append(term)
     
+    return toReturn
+
+def _find_most_current_index_at_time (times_array, current_time) :
+    """
+    figure out the index of the data in times_array that is most
+    current given that current_time is now
+    
+    if for some reason the data in the times_array is all after
+    current_time, return -1
+    otherwise, return the index of the most current data that
+    has happened or is happening now (no future indexes!)
+    
+    note: it is assumed that the times_array is arranged in
+    increasing order (earlier to later times) and no time is
+    repeated.
+    """
+    
+    toReturn = -1
+    
+    for indexNum in range(len(times_array)) :
+        tempTime = times_array[indexNum]
+        if tempTime <= current_time :
+            toReturn = indexNum
+    
+    return toReturn
+
+def _draw_contour_with_basemap (baseMapInstance, data, lonData, latData, levels=None, **kwargs) :
+    """
+    draw a contour plot of the data using the basemap and the provided lon and lat
+    """
+    
+    # translate into the coordinate system of the basemap
+    tempX, tempY = baseMapInstance(lonData, latData)
+    
+    # show the plot if there is data
+    if (data is not None) :
+        
+        if levels is not None :
+            p = baseMapInstance.contourf(tempX, tempY, data, levels, **kwargs)
+        else :
+            p = baseMapInstance.contourf(tempX, tempY, data, **kwargs)
+    
+    # TODO, do I need to return tempX and tempY in the future?
+
+def _draw_winds_with_basemap (baseMapInstance,
+                              uData,   vData,
+                              lonData, latData,
+                              valueData=None,
+                              **kwargs) :
+    """
+    draw the given wind vectors using the provided basemap
+    
+    if the value data isn't None, use it to control the color values plotted on the vectors
+    """
+    
+    # translate into the coordinate system of the basemap
+    tempX, tempY = baseMapInstance(lonData, latData)
+    
+    # show the quiver plot if there is data
+    if (uData is not None) and (vData is not None) :
+        
+        # TODO, it looks like there's a bug that can affect the data sent into quiver, for now copy it
+        # bug report can be found here: https://github.com/matplotlib/matplotlib/issues/625
+        tempUData = uData.copy()
+        tempVData = vData.copy()
+        
+        kwargs['width'] = 0.001
+        kwargs['headwidth'] = 4
+        
+        if valueData is None:
+            p = baseMapInstance.quiver(tempX, tempY, tempUData, tempVData, **kwargs)
+        else :
+            p = baseMapInstance.quiver(tempX, tempY, tempUData, tempVData, valueData, **kwargs)
+    
+    # TODO, do I need to return tempX and tempY in the future?
+
+def _plot_pressure_data (baseMapInstance, pressureLat, pressureLon, pressureData=None, colorMap=dark_trajectory_pressure_color_map) :
+    """
+    plot the pressure data and return the color bar so it can be moved around as needed
+    """
+    
+    colorBarToReturn = None
     
-    color_map_to_use = dark_trajectory_pressure_color_map if useDarkBackground else light_trajectory_pressure_color_map
     # if we have pressure data plot that
     if pressureData is not None :
+        
+        # translate the longitude and latitude into map coordinates
+        pressX, pressY =  baseMapInstance(pressureLon, pressureLat)
+        
         # I'm taking advantage of the fact that I can remove the black edge line with lw=0 (line width = 0) and scale the marker down with s=0.5
-        baseMapInstance.scatter(pressX, pressY, s=0.5, c=pressureData, marker='o', cmap=color_map_to_use, vmin=0, vmax=1000, lw=0)
+        baseMapInstance.scatter(pressX, pressY, s=3.0, c=pressureData, marker='o', cmap=colorMap, vmin=0, vmax=1000, lw=0)
         
         # create the pressure colorbar
-        cbar1 = colorbar(format='%.3g', orientation='horizontal', shrink=0.25)
-        cbar1.ax.set_position([0.1, -0.16, 0.25, 0.25])
-        for tempText in cbar1.ax.get_xticklabels():
-            #print(tempText)
+        colorBarToReturn = colorbar(format='%.3g', orientation='horizontal', shrink=0.25)
+        for tempText in colorBarToReturn.ax.get_xticklabels():
             tempText.set_fontsize(5)
-        cbar1.set_label("Trajectory Pressure (mb)")
+        colorBarToReturn.set_label("Trajectory Pressure (mb)")
+    
+    return colorBarToReturn
+
+def _plot_initial_modis_aod (baseMapInstance, longitude, latitude, initAODdata, colorMap=cm.jet) :
+    """
+    plot initial modis aod points using the provided base map, return the created
+    color bar so it can be moved around as needed
+    """
     
-    # plot the origin points after the pressure so they'll appear on top, I'm assuming we will always have this data
-    baseMapInstance.scatter(initX,  initY, s=10,  c=initAODdata,  marker='o', cmap=cm.jet, vmin=0.0, vmax=1.0, lw=0.5)
+    # translate the longitude and latitude into map coordinates
+    initX,  initY  = baseMapInstance(longitude,  latitude)
+    
+    # plot the origin points, these are being scaled to have a thin but visible black border line
+    baseMapInstance.scatter(initX,  initY, s=10,  c=initAODdata,  marker='o', cmap=colorMap, vmin=0.0, vmax=1.0, lw=0.5)
     
     # make a color bar
-    cbar2 = colorbar(format='%.3g', orientation='horizontal', shrink=0.25)
-    cbar2.ax.set_position([0.4, -0.16, 0.25, 0.25])
-    for tempText in cbar2.ax.get_xticklabels():
-        #print(tempText)
+    colorBarToReturn = colorbar(format='%.3g', orientation='horizontal', shrink=0.25)
+    for tempText in colorBarToReturn.ax.get_xticklabels():
         tempText.set_fontsize(5)
-    cbar2.set_label("MODIS AOD") # TODO, how do I get a second Trajectory Pressure colorbar in the right place?
+    colorBarToReturn.set_label("MODIS AOD")
+    
+    return colorBarToReturn
+
+def _build_basic_figure_with_map (baseMapInstance, latRange=None, lonRange=None, useDarkBackground=True,) :
+    """
+    create a figure with the longitude and latitude info given
+    """
+    
+    # create the empty figure
+    figure = plt.figure()
+    bkgdColor = 'k' if useDarkBackground else 'w' # either use a black or white background
+    axes = figure.add_subplot(111, axisbg=bkgdColor)
+    
+    # draw the basic physical and geopolitical features
+    lineColor = 'w' if useDarkBackground else 'k' # either draw black or white lines
+    if baseMapInstance is not None :
+        baseMapInstance.drawcoastlines( color=lineColor, linewidth=0.5)
+        baseMapInstance.drawcountries(  color=lineColor, linewidth=0.5)
+        baseMapInstance.drawstates(     color=lineColor, linewidth=0.5)
+        baseMapInstance.drawmapboundary(color=lineColor, linewidth=0.5)
+    # draw the parallels and meridians
+    if latRange is not None :
+        parallels = arange(-80.,  90., latRange / 4.0)
+        baseMapInstance.drawparallels(parallels,labels=[1,0,0,1], color=lineColor, linewidth=0.5)
+    if lonRange is not None :
+        meridians = arange(  0., 360., lonRange / 4.0)
+        baseMapInstance.drawmeridians(meridians,labels=[1,0,0,1], color=lineColor, linewidth=0.5)
+    
+    return axes, figure
+
+# todo, I hate this solution for making contourf show the number of levels that I want,
+# but I've searched repeatedly and can't find another way to get it to let me specify
+def _make_range_with_data_objects(list_of_data_objects, num_intervals, offset_to_range=0.0) :
+    """
+    get an array with numbers representing the bounds of a set of ranges
+    that covers all the valid data present in the data objects given
+    (these may be used for plotting the data)
+    if an offset is passed, the outtermost range will be expanded by that much
+    
+    note: the list of data objects may be 0 or more data objects, if it 0, this
+    method returns None since no useful range can be created
+    """
+    
+    if len(list_of_data_objects) <= 0 :
+        return None
+    
+    minVal = np.PINF # positive infinity
+    maxVal = np.NINF # negative infinity
+    
+    # include each data set in the min/max calculations
+    for each_data_object in list_of_data_objects :
+        minVal = min(each_data_object.get_min(), minVal)
+        maxVal = max(each_data_object.get_max(), maxVal)
+    
+    # TODO, there's the possibility for failure here if all data is fully masked out?
+    
+    # take any offsets into account
+    minVal = minVal - offset_to_range
+    maxVal = maxVal + offset_to_range
+    
+    return np.linspace(minVal, maxVal, num_intervals)
+
+# todo, I hate this solution for making contourf show the number of levels that I want,
+# but I've searched repeatedly and can't find another way to get it to let me specify
+def _make_range_with_masked_arrays(list_of_masked_arrays, num_intervals, offset_to_range=0.0) :
+    """
+    get an array with numbers representing the bounds of a set of ranges
+    that covers all the valid data present in the masked arrays given
+    (these may be used for plotting the data)
+    if an offset is passed, the outtermost range will be expanded by that much
+    
+    note: the list of masked arrays may be 0 or more masked arrays, if it 0, this
+    method returns None since no useful range can be created
+    """
+    
+    if len(list_of_masked_arrays) <= 0 :
+        return None
+    
+    minVal = np.PINF # positive infinity
+    maxVal = np.NINF # negative infinity
+    
+    # include each data set in the min/max calculations
+    for each_masked_array in list_of_masked_arrays :
+        minVal = min(each_masked_array.min(), minVal)
+        maxVal = max(each_masked_array.max(), maxVal)
+    
+    # TODO, there's the possibility for failure here if all data is fully masked out?
+    
+    # take any offsets into account
+    minVal = minVal - offset_to_range
+    maxVal = maxVal + offset_to_range
+    
+    return np.linspace(minVal, maxVal, num_intervals)
+
+def _create_imapp_figure (initAODdata,       initLongitudeData,       initLatitudeData,
+                          pressureData=None, pressLongitudeData=None, pressLatitudeData=None,
+                          baseMapInstance=None, figureTitle="MODIS AOD & AOD Trajectories",
+                          useDarkBackground=True, latRange=None, lonRange=None,
+                          windsDataU=None, windsDataV=None, windsDataLon=None, windsDataLat=None,
+                          backgroundDataSets={ }) :
+    """
+    TODO, I'm still deciding how this funciton works so it may change
+    
+    backgroundDataSets should be a dictionary in the form
+    {
+        1: [dataToContourPlot1, LatitudeData1, LongitudeData1, colorMap1, levels],
+        2: [dataToContourPlot2, LatitudeData2, LongitudeData2, colorMap2, levels],
+        ...
+        N: [dataToContourPlotN, LatitudeDataN, LongitudeDataN, colorMapN],
+    }
+    The keys should all be numbers and the data sets will be plotted in order from lowest key value to highest (allowing z-order control).
+    
+    """
+    
+    # create a figure and draw geopolitical features on it
+    axes, figure = _build_basic_figure_with_map (baseMapInstance,
+                                                 latRange=latRange, lonRange=lonRange,
+                                                 useDarkBackground=useDarkBackground)
+    
+    # choose the color map
+    color_map_to_use = dark_trajectory_pressure_color_map if useDarkBackground else light_trajectory_pressure_color_map
+    
+    # plot out any background data sets that we have
+    for orderKey in sorted(backgroundDataSets.keys()) :
+        tempDataSet, tempLatitude, tempLongitude, tempColorMap, tempLevelsList = backgroundDataSets[orderKey]
+        _draw_contour_with_basemap (baseMapInstance, tempDataSet, tempLongitude, tempLatitude, cmap=tempColorMap, levels=tempLevelsList, lw=0, antialiased=False)
+                                                                                # lw is line width, use 0 to hide the lines between contours
+                                                                                # there appears to be a bug in sub-pixel anti-aliasing that is making
+                                                                                # contour lines show up even with lw=0, so turn that off for now :(
+                                                                                # see also: http://stackoverflow.com/questions/8263769/hide-contour-linestroke-on-pyplot-contourf-to-get-only-fills
+    
+    # if we have winds to draw, draw those first so they're on the bottom under all the other data
+    if ((windsDataU is not None) and (windsDataV is not None) and (windsDataLon is not None) and (windsDataLat is not None)) :
+        tempColor = 'w' if useDarkBackground else 'k' # plot our winds in a color that will show up on the background
+        _draw_winds_with_basemap (baseMapInstance, windsDataU,   windsDataV, windsDataLon, windsDataLat, color=tempColor)
+    
+    # plot the pressure data if appropriate
+    pressColorBar = _plot_pressure_data(baseMapInstance, pressLatitudeData, pressLongitudeData, pressureData=pressureData, colorMap=color_map_to_use)
+    # if we got a color bar back, make sure it's in the right place
+    if pressColorBar is not None :
+        pressColorBar.ax.set_position([0.4, -0.16, 0.25, 0.25])
+    
+    # plot the initial modis AOD points after the pressure so the AOD points are always on top (and visible)
+    aodColorBar = _plot_initial_modis_aod(baseMapInstance, initLongitudeData, initLatitudeData, initAODdata)
+    # if we got a color bar back, make sure it's in the right place
+    if aodColorBar is not None :
+        aodColorBar.ax.set_position([0.1, -0.16, 0.25, 0.25])
     
     # now that we've moved everything around, make sure our main image is in the right place
+    # TODO, make sure this resizing/placement will work in more general cases
     axes.set_position([0.1, 0.15, 0.8, 0.8]) # why was this method so hard to find?
     
     # set up the figure title
@@ -151,7 +393,7 @@ def main():
 run "%prog help" to list commands
 examples:
 
-python -m glance.imapp_plot plot A.nc
+python -m glance.imapp_plot aodTraj A.nc
 
 """
     # the following represent options available to the user on the command line:
@@ -166,30 +408,38 @@ python -m glance.imapp_plot plot A.nc
     parser.add_option('-w', '--debug', dest="debug",
                     action="store_true", default=False, help="enable debug output")   
 
-    # file generation related options TODO, make this work
+    # file generation related options
     parser.add_option('-p', '--outpath', dest="outpath", type='string', default='./',
                     help="set path to output directory")
     
-    # file variable settings
+    # file variable settings TODO, do we need these?
     parser.add_option('-o', '--longitude', dest="longitudeVar", type='string',
                     help="set name of longitude variable")
     parser.add_option('-a', '--latitude', dest="latitudeVar", type='string',
                     help="set name of latitude variable")
     
+    # display related settings
+    parser.add_option('-d', '--windsSubdivideFactor', dest="subdivideFactor", type='int',
+                    default=1, help="factor to subdivide and filter out some winds data for visiblity; " +
+                                    "higher factors result in fewer winds; data is filtered evenly along the indices of the winds data grid")
+    
     # time related settings
     parser.add_option('-s', '--startTime', dest="startTime", type='int',
                     default=0, help="set first time to process")
     parser.add_option('-e', '--endTime', dest="endTime", type='int',
                     help="set last time to process")
     parser.add_option('-f', '--futureWindow', dest="futureWindow", type='int',
-                    default=6, help="set number of hours of future pressures to show")
+                    default=6, help="set number of hours of future pressures to show; 6 hours is the default")
+    parser.add_option('-j', '--jumpEmptyStartHours', dest="doJump",
+                      action="store_true", help="start generating images on the first hour with trajectory data that is after 0 (ie. not 0); if used this flag " +
+                                                "overrrides the start time option when determining which images will be created at the start of a series")
     
     parser.add_option('-t', '--test', dest="self_test",
                 action="store_true", default=False, help="run internal unit tests")
     
     # TODO will add this once we're out of alpha
     #parser.add_option('-n', '--version', dest='version',
-    #                  action="store_true", default=False, help="view the glance version")
+    #                  action="store_true", default=False, help="view the imapp plot version")
     
     
     # parse the uers options from the command line
@@ -218,13 +468,18 @@ python -m glance.imapp_plot plot A.nc
     The following functions represent available menu selections.
     """
     
-    def plot(*args):
-        """plot trajectory frames
+    def aodTraj(*args):
+        """plot AOD trajectory frames
         Given a file with trajectory possitions and pressures over time, plot out
         images of these trajectories on the Earth and save it to disk.
+        
+        optionally, if a second file with winds data and MODIS cloud effective
+        emissivity data is provided, this will also be plotted at comprable time
+        steps for each frame
         """
         
         LOG.debug("startTime:    " + str(options.startTime))
+        LOG.debug("will startTime be modified by jumping frames? " + str(options.doJump))
         LOG.debug("endTime:      " + str(options.endTime))
         LOG.debug("futureWindow: " + str(options.futureWindow))
         
@@ -253,23 +508,126 @@ python -m glance.imapp_plot plot A.nc
         trajectoryTimeData     = trajectoryFileObject.file_object[defaultValues['timeVar']]
         
         # get information on where we should display the data
-        northeastLon = trajectoryFileObject.file_object.get_global_attribute( defaultValues['nePiece'] + defaultValues['lonPiece'] )
-        northeastLat = trajectoryFileObject.file_object.get_global_attribute( defaultValues['nePiece'] + defaultValues['latPiece'] )
-        southwestLon = trajectoryFileObject.file_object.get_global_attribute( defaultValues['swPiece'] + defaultValues['lonPiece'] )
-        southwestLat = trajectoryFileObject.file_object.get_global_attribute( defaultValues['swPiece'] + defaultValues['latPiece'] )
-        latRange     = abs(northeastLat - southwestLat)
-        lonRange     = abs(southwestLon - northeastLon)
+        northeastLon, northeastLat = trajectoryFileObject.file_object.get_global_attribute( defaultValues['neName'] )
+        southwestLon, southwestLat = trajectoryFileObject.file_object.get_global_attribute( defaultValues['swName'] )
+        latRange = abs(northeastLat - southwestLat)
+        lonRange = abs(southwestLon - northeastLon)
+        LOG.debug ("Viewing window, northeast corner (lat / lon): " + str(northeastLat) + " / " + str(northeastLon))
+        LOG.debug ("Viewing window, southwest corner (lat / lon): " + str(southwestLat) + " / " + str(southwestLon))
+        
+        # double check the map projection
+        _check_requested_projection(trajectoryFileObject.file_object.get_global_attribute("MAP_PROJECTION"), fileDescription="the main trajectory file")
+        
+        # check to see if we have a second file for the optional data
+        LOG.info("Attempting to open optional file (if present)")
+        doOptionalWinds, doOptionalCloudEffectiveEmiss, doOptionalDepthLandAndOcean = False, False, False
+        optionalDataWindsLatitude, optionalDataWindsLongitude, optionalDataWindsTime, optionalDataWindU, optionalDataWindV = None, None, None, None, None
+        listOfCloudEffectiveEmissivityPasses, listOfOpticalDepthLandAndOcean, listOfOptionalLon, listOfOptionalLat = { }, { }, { }, { }
+        if len(args) > 1 :
+            optionalFilePath = str(args[1])
+            LOG.debug("Opening optional file: " + optionalFilePath)
+            optionalFileObject = dataobj.FileInfo(optionalFilePath)
+            if optionalFileObject is None :
+                LOG.warn("Optional file (" + optionalFilePath + ") could not be opened.")
+                LOG.warn("Optional winds and cloud effective emissivity data will not be loaded/plotted.")
+            else :
+                
+                # hang on to the list of variables for some checks later
+                tempVarList = optionalFileObject.file_object()
+                
+                # get info on where this data wants to be displayed
+                optionalNELon, optionalNELat = optionalFileObject.file_object.get_global_attribute( defaultValues['neName'] )
+                optionalSWLon, optionalSWLat = optionalFileObject.file_object.get_global_attribute( defaultValues['swName'] )
+                LOG.debug ("Viewing window in optional file, northeast corner (lat / lon): " + str(optionalNELat) + " / " + str(optionalNELon))
+                LOG.debug ("Viewing window in optional file, southwest corner (lat / lon): " + str(optionalSWLat) + " / " + str(optionalSWLon))
+                
+                # if the two viewing windows are not the same, we don't want to display this data TODO, confirm that this is the right strategy?
+                if ((optionalNELat != northeastLat) or (optionalNELon != northeastLon) or
+                    (optionalSWLat != southwestLat) or (optionalSWLon != southwestLon)) :
+                    LOG.debug ("Incompatable viewing area given in optional file. Optional data will not be displayed.")
+                    
+                else :
+                    
+                    # double check the map projection
+                    _check_requested_projection(optionalFileObject.file_object.get_global_attribute("MAP_PROJECTION"), fileDescription="the optional data file")
+                    
+                    # otherwise try to get the data we need if possible
+                    if ((defaultValues['windLonName']  in tempVarList) and (defaultValues['windLatName'] in tempVarList) and
+                        (defaultValues['windTimeName'] in tempVarList) and
+                        (defaultValues['windUName']    in tempVarList) and (defaultValues['windVName']   in tempVarList)) :
+                        
+                        # if we have all the winds related variables available, load the winds data
+                        # TODO, should the user be able to control these names?
+                        optionalDataWindsLatitude  = optionalFileObject.file_object[defaultValues['windLatName']]
+                        optionalDataWindsLongitude = optionalFileObject.file_object[defaultValues['windLonName']]
+                        optionalDataWindsTime      = optionalFileObject.file_object[defaultValues['windTimeName']]
+                        optionalDataWindU          = optionalFileObject.file_object[defaultValues['windUName']]
+                        optionalDataWindV          = optionalFileObject.file_object[defaultValues['windVName']]
+                        doOptionalWinds = True
+                        
+                        # TODO, I'd really rather not do this, for the moment I don't have a choice
+                        tempLatSize =  optionalDataWindsLatitude.size
+                        tempLonSize = optionalDataWindsLongitude.size
+                        tempLat     =  optionalDataWindsLatitude
+                        tempLon     = optionalDataWindsLongitude
+                        optionalDataWindsLatitude  = np.transpose(np.repeat([tempLat], tempLonSize, axis=0))
+                        optionalDataWindsLongitude =              np.repeat([tempLon], tempLatSize, axis=0)
+                    
+                    # if any cloud effective emissivity swaths are available load them
+                    possibleEmissNames = _get_matching_terms_from_list(tempVarList, defaultValues['emissNameBase'])
+                    if len(possibleEmissNames) > 0 :
+                        LOG.debug("cloud effective emissivity variables found: " + str(possibleEmissNames))
+                        for emissName in possibleEmissNames :
+                            tempEmissData    = optionalFileObject.file_object[emissName]
+                            tempMissingValue = optionalFileObject.file_object.missing_value(emissName)
+                            listOfCloudEffectiveEmissivityPasses[emissName] = ma.masked_where(tempEmissData == tempMissingValue, tempEmissData)
+                        doOptionalCloudEffectiveEmiss = True
+                    
+                    # load optical depth land and ocean if it's present
+                    possibleOpticalDepthNames = _get_matching_terms_from_list(tempVarList, defaultValues['aodNameBase'])
+                    if len(possibleOpticalDepthNames) > 0 :
+                        LOG.debug("optical depth land and ocean variables found: " + str(possibleOpticalDepthNames))
+                        for aodName in possibleOpticalDepthNames :
+                            tempAODData      = optionalFileObject.file_object[aodName]
+                            tempMissingValue = optionalFileObject.file_object.missing_value(aodName)
+                            listOfOpticalDepthLandAndOcean[aodName] = ma.masked_where(tempAODData == tempMissingValue, tempAODData)
+                        doOptionalDepthLandAndOcean = True
+                    
+                    # if either the cloud effective emissivity or the optical depth land and ocean were loaded,
+                    # then we need to load the associated lat and lon variables
+                    if doOptionalCloudEffectiveEmiss or doOptionalDepthLandAndOcean :
+                        possibleOptionalLatNames = _get_matching_terms_from_list(tempVarList, defaultValues['optLatBase'])
+                        possibleOptionalLonNames = _get_matching_terms_from_list(tempVarList, defaultValues['optLonBase'])
+                        LOG.debug ("optional longitude variables found: " + str(possibleOptionalLonNames))
+                        LOG.debug ("optional latitude  variables found: " + str(possibleOptionalLatNames))
+                        # if we can't find lon/lat, we can't plot these! Note: this still fails if we have partial lon/lat, could compare sizes in FUTURE
+                        if (len(possibleOptionalLatNames) <= 0) or (len(possibleOptionalLonNames) <= 0) :
+                            LOG.warn("Unable to find corresponding longitude and latitude data for some optional variables. "
+                                     + "Data without corresponding longitude and latitude data will not be plotted.")
+                            doOptionalDepthLandAndOcean   = False
+                            doOptionalCloudEffectiveEmiss = False
+                        else :
+                            # if we found lon and lat, load them
+                            for lonName in possibleOptionalLonNames :
+                                listOfOptionalLon[lonName] = optionalFileObject.file_object[lonName]
+                            for latName in possibleOptionalLatNames :
+                                listOfOptionalLat[latName] = optionalFileObject.file_object[latName]
         
         # build a basemap
         LOG.info("Building basemap object.")
-        projectionName = 'merc' # use the Mercator Projection
+        projectionName = 'merc' # use the Mercator Projection; TODO at some point this will need to be checked with a global attribute
         basemapObject  = Basemap (projection=projectionName,llcrnrlat=southwestLat,urcrnrlat=northeastLat,
                                   llcrnrlon=southwestLon, urcrnrlon=northeastLon, lat_ts=20, resolution='l') # TODO do I need to use lat_ts=20, ?
         
         # sort out the times we're using
         futureWindow = options.futureWindow
-        startTime    = options.startTime
-        endTime      = options.endTime if options.endTime is not None else trajectoryTimeData[-1]
+        startTime    = options.startTime if options.startTime >= 0      else 0
+        # if we need to jump to start at the first trajectory data after 0, do that now
+        if options.doJump :
+            startTimeTemp = trajectoryTimeData[0] if trajectoryTimeData[0] > 0 else trajectoryTimeData[1]
+            startTime = max(startTime, startTimeTemp)
+            # I am assuming that the time data will never be negative
+        endTime      = options.endTime   if options.endTime is not None else trajectoryTimeData[-1]
         # as a sanity check, it's not really productive to make frames for times after our data ends
         if endTime > trajectoryTimeData[-1] :
             endTime = trajectoryTimeData[-1]
@@ -280,41 +638,95 @@ python -m glance.imapp_plot plot A.nc
         initLatData =  latitudeData[0].ravel()
         for currentTime in range (startTime, endTime + 1) :
             
-            # select only the window of trajectory data we need
-            alreadyHappenedTimeIndex = 0
-            tooFarInFutureTimeIndex  = trajectoryTimeData.size
-            for tempIndex in range (0, trajectoryTimeData.size) :
-                
-                # first find the time that corresponds to the "most recently happened" index
-                if trajectoryTimeData[tempIndex] <= currentTime :
-                # TODO if time doesn't always increase, this needs another check
-                    alreadyHappenedTimeIndex = tempIndex
-                
-                # then figure out how much further we can go before we pass the futureWindow's edge
-                if (trajectoryTimeData[tempIndex] > (currentTime + futureWindow)) :
-                # TODO, if time data doesn't always increase I also need & (trajectoryTimeData[tempIndex] < trajectoryTimeData[tooFarInFutureTimeIndex])
-                    tooFarInFutureTimeIndex = tempIndex
-                    break # TODO, this assumes time data always increases; also breaks suck so eventually take this out
+            # TEMP for debugging during develpment
+            LOG.debug ("**********")
+            
+            # get the time that represents the most current trajectory data
+            mostCurrentTrajTimeIndex = _find_most_current_index_at_time (trajectoryTimeData, currentTime)
+            # get the time that represents the last point included in the future window
+            lastTimeIncludedIndex    = _find_most_current_index_at_time (trajectoryTimeData, (currentTime + futureWindow))
             
             # only get data to plot the trajectory points if there is some available
             thisFramePressures = None
             thisFramePressLon  = None
             thisFramePressLat  = None
-            if alreadyHappenedTimeIndex + 1 < tooFarInFutureTimeIndex :
+            if mostCurrentTrajTimeIndex <= lastTimeIncludedIndex :
                 
-                LOG.debug("Already happened index: " + str(alreadyHappenedTimeIndex))
-                LOG.debug("Too far future index:   " + str(tooFarInFutureTimeIndex))
+                # TODO , double check that this isn't off by one
+                LOG.debug("Most current time index:          " + str(mostCurrentTrajTimeIndex))
+                LOG.debug("Last data in future window index: " + str(lastTimeIncludedIndex))
+                LOG.debug("Most current time:                " + str(trajectoryTimeData[mostCurrentTrajTimeIndex]))
+                LOG.debug("Last data in future window time:  " + str(trajectoryTimeData[lastTimeIncludedIndex]))
                 
                 # now pull out the pressure data and related lon/lat info for plotting
-                thisFramePressures = trajectoryPressureData[alreadyHappenedTimeIndex + 1 : tooFarInFutureTimeIndex].ravel()
-                thisFramePressLon  =          longitudeData[alreadyHappenedTimeIndex + 1 : tooFarInFutureTimeIndex].ravel()
-                thisFramePressLat  =           latitudeData[alreadyHappenedTimeIndex + 1 : tooFarInFutureTimeIndex].ravel()
-                
+                thisFramePressures = trajectoryPressureData[mostCurrentTrajTimeIndex : lastTimeIncludedIndex+1].ravel()
+                thisFramePressLon  =          longitudeData[mostCurrentTrajTimeIndex : lastTimeIncludedIndex+1].ravel()
+                thisFramePressLat  =           latitudeData[mostCurrentTrajTimeIndex : lastTimeIncludedIndex+1].ravel()
+            
+            # we need to plot the winds under the other data so they don't cover it up
+            currentWindsU, currentWindsV, currentWindsLon, currentWindsLat = None, None, None, None
+            if doOptionalWinds :
+                # figure out which winds data we should use
+                mostCurrentWindsTimeIndex = _find_most_current_index_at_time (optionalDataWindsTime, currentTime)
+                LOG.debug("Optional winds most current time index: " + str(mostCurrentWindsTimeIndex))
+                LOG.debug("Time of most recent optional winds:     " + str(optionalDataWindsTime[mostCurrentWindsTimeIndex]))
+                # check to make sure we found any winds at the current time
+                if mostCurrentWindsTimeIndex > -1 :
+                    currentWindsU             =          optionalDataWindU[mostCurrentWindsTimeIndex]
+                    currentWindsV             =          optionalDataWindV[mostCurrentWindsTimeIndex]
+                    
+                    maskingFactor = options.subdivideFactor if options.subdivideFactor > 0 else DEFAULT_WINDS_SUBDIVIDE_FACTOR
+                    LOG.debug ("Using winds subdivide factor: " + str(maskingFactor))
+                    maskTemp = np.zeros(currentWindsV.shape, dtype=np.bool)
+                    if maskingFactor > 1 :
+                        maskTemp1 = np.ones(currentWindsV.shape, dtype=np.bool)
+                        maskTemp2 = np.ones(currentWindsV.shape, dtype=np.bool)
+                        numbers1  =              np.repeat([range(currentWindsV.shape[1])], currentWindsV.shape[0], axis=0)
+                        numbers2  = np.transpose(np.repeat([range(currentWindsV.shape[0])], currentWindsV.shape[1], axis=0))
+                        maskTemp1 [ numbers1 % maskingFactor == 0 ] = False
+                        maskTemp2 [ numbers2 % maskingFactor == 0 ] = False
+                        maskTemp  = maskTemp1 | maskTemp2
+                    currentWindsU = np.ma.array(currentWindsU, mask=maskTemp)
+                    currentWindsV = np.ma.array(currentWindsV, mask=maskTemp)
+            
+            # build up the background data sets we want to plot
+            backgroundData = { }
+            zCounter = 1
+            
+            # if we're doing cloud effective emissivity, add those to the background list
+            if doOptionalCloudEffectiveEmiss :
+                tempLevels = _make_range_with_masked_arrays(listOfCloudEffectiveEmissivityPasses.values(), LEVELS_FOR_BACKGROUND_PLOTS)
+                for emissName in sorted(listOfCloudEffectiveEmissivityPasses.keys()) :
+                    emissSetNumber = emissName.split('_')[-1] # get the number off the end of the name
+                    # if the numbering is at all different between the variables, this will fail
+                    backgroundData[zCounter] = [listOfCloudEffectiveEmissivityPasses[emissName],
+                                                    listOfOptionalLat[defaultValues['optLatBase'] + emissSetNumber],
+                                                    listOfOptionalLon[defaultValues['optLonBase'] + emissSetNumber],
+                                                    matplotlib.cm.gray, tempLevels]
+                    zCounter = zCounter + 1
+            
+            # if we're doing the optical depth land and ocean, add those to the background list too
+            if doOptionalDepthLandAndOcean :
+                tempLevels = _make_range_with_masked_arrays(listOfOpticalDepthLandAndOcean.values(), LEVELS_FOR_BACKGROUND_PLOTS)
+                for aodName in sorted(listOfOpticalDepthLandAndOcean.keys()) :
+                    aodNumber = aodName.split('_')[-1] # get the number off the end of the name
+                    # if the numbering is at all different between the variables, this will fail
+                    backgroundData[zCounter] = [listOfOpticalDepthLandAndOcean[aodName],
+                                                    listOfOptionalLat[defaultValues['optLatBase'] + aodNumber],
+                                                    listOfOptionalLon[defaultValues['optLonBase'] + aodNumber],
+                                                    matplotlib.cm.jet, tempLevels]
+                    zCounter = zCounter + 1
+            
             # make the plot
             LOG.info("Creating trajectory plot for time " + str(float(currentTime)) + ".")
             tempFigure = _create_imapp_figure (initAODFlat,                     initLonData,                          initLatData,
                                                pressureData=thisFramePressures, pressLongitudeData=thisFramePressLon, pressLatitudeData=thisFramePressLat,
-                                               baseMapInstance=basemapObject, latRange=latRange, lonRange=lonRange)
+                                               baseMapInstance=basemapObject, latRange=latRange, lonRange=lonRange,
+                                               windsDataU=currentWindsU, windsDataV=currentWindsV,
+                                               windsDataLon=optionalDataWindsLongitude, windsDataLat=optionalDataWindsLatitude,
+                                               figureTitle="MODIS AOD & AOD Trajectories on " + str(currentTime) + "Z",
+                                               backgroundDataSets=backgroundData)
+                                               # TODO, the figure title needs to have the dates in it and the day may roll over, so current time can't be put in directly
             
             # save the plot to disk
             LOG.info("Saving plot to disk.")