#!/usr/bin/env python # encoding: utf-8 """ plot_viirs_RGB_crefl.py The purpose of this script is to create an RGB image from several VIIRS bands, which have been atmospherically corrected by crefl. ########### True-color ########### >>>>>>>>>>> Long Answer >>>>>>>>>>> True-color imagery uses MODIS Bands 1, 4, and 3, respectively corresponding to the red, green, and blue range of the light spectrum, are assigned to the red, green, and blue channels of a digital image. These images are called true-color or natural color because this combination of wavelengths is similar to what the human eye would see. >>>>>>>>>>>> Short Answer >>>>>>>>>>>> >>> Modis Bands: 1,4,3 (670 nm: 565 nm: 479 nm) >>> Viirs Bands: M05,M04,M03 (672 nm, 555 nm ,488 nm) >>> Colors: Fire detection=red outlines >>> Advantages: Natural-looking images of land surface, oceanic and atmospheric features. ###################### Band 3,6,7 Combination ###################### >>>>>>>>>>> Long Answer >>>>>>>>>>> The 3-6-7 composite assigns Bands 3, 6, and 7 to the red, green, and blue components of a digital image. This combination is good for revealing snow and ice because they are very reflective in the visible part of the spectrum, and very absorbent in Bands 6 and 7, which are a part of the spectrum called the short-wave infrared, or SWIR. >>> Snow and Ice Since the only visible light used in these images (Band 3) is assigned to red, snow and ice appear bright red. The more ice, the stronger the absorption in the SWIR bands, and the more red the color. Thick ice and snow appear vivid red (or red-orange), while small ice crystals in high-level clouds will appear reddish-orange or peach. >>> Vegetation Vegetation is absorbent in Band 3 and Band 7, but reflective in Band 6, and so will appear greenish in this band combination. Bare soil will appear bright cyan in the image since it much more reflective in Band 6 and Band 7 than Band 3. >>> Water Liquid water on the ground will be very dark since it absorbs in the red and the SWIR, but small liquid water drops in clouds scatter light equally in both the visible and the SWIR, and will therefore appear white. Sediments in water appear dark red. >>>>>>>>>>>> Short Answer >>>>>>>>>>>> >>> Modis Bands: 3,6,7 (479 nm, 1652 nm, 2155 nm) >>> Viirs Bands: M03, M10, M11 (488 nm, 1610 nm, 2250 nm) >>> Colors: Vegetation=Green Ice or snow=Red Liquid water on the ground=Black or dark red Liquid water clouds=White Ice clouds=Peach Desert=Light blue-green >>> Advantages: Distinguishing liquid water from frozen water, for example, clouds over snow, ice cloud versus water cloud; or floods from dense vegetation. ###################### Band 7-2-1 Combination ###################### >>>>>>>>>>> Long Answer >>>>>>>>>>> In this composite, MODIS Bands 7, 2, and 1, are assigned to the red, green, and blue portions of the digital image. This combination is most useful for identifying burn scars. >>> Vegetation and bare ground Vegetation is very reflective in the near infrared (Band 2), and absorbent in Band 1 and Band 7. Assigning that band to green means even the smallest hint of vegetation will appear bright green in the image. Naturally bare soil, like a desert, is reflective in all bands used in this image, but more so in the SWIR (Band 7, red) and so soils will often have a pinkish tinge. >>> Burned areas If vegetation burns, bare soil in the area will become exposed. Band 1 slightly increases usually, but that may be offset by the presence of black carbon residue. The near infrared (Band 2) will become darker, and Band 7 becomes more reflective. When assigned to red in the image, Band 7 will show burn scars as deep or bright red, depending on the type of vegetation burned, the amount of residue, or the completeness of the burn. >>> Water As with the 3-6-7 composite, water will appear black. Sediments in water appear dark blue. >>>>>>>>>>>> Short Answer >>>>>>>>>>>> >>> Modis Bands: 7,2,1 (2155 nm, 876 nm, 670 nm) >>> Viirs Bands: M11, M07, M05 (2250 nm, 865 nm, 672 nm) >>> Colors: Vegetation=Green Water=Black or dark blue Desert/Naturally bare soil=Sandy pink Burn scar=Red to reddish-brown, depending on the nature of the pre-fire vegetation and the severity of the burn. >>> Advantages Distinguishing burn scars from naturally low vegetation or bare soil. Enhancing floods. Minimum commandline... python plot_viirs_RGB_crefl.py --geo_file=geofile.h5 --red_file=redfile.h5 --green_file=greenfile.h5 --blue_file=bluefile.h5 OR python plot_viirs_RGB_crefl.py --geo_file=geofile.h5 --crefl_file=creflFile.h5 Created by Geoff Cureton on 2012-10-03. Copyright (c) 2012 University of Wisconsin SSEC. All rights reserved. """ file_Date = '$Date$' file_Revision = '$Revision$' file_Author = '$Author$' file_HeadURL = '$HeadURL$' file_Id = '$Id$' __author__ = 'G.P. Cureton <geoff.cureton@ssec.wisc.edu>' __version__ = '$Id$' __docformat__ = 'Epytext' import os, sys, logging, traceback from os import path,uname,environ import string import re import uuid import shlex, subprocess from subprocess import CalledProcessError, call from shutil import rmtree from glob import glob import optparse as optparse from time import time from datetime import datetime,timedelta import numpy as np from numpy import ma as ma import scipy as scipy import matplotlib import matplotlib.cm as cm from matplotlib.colors import ListedColormap from matplotlib.figure import Figure matplotlib.use('Agg') from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas #matplotlib.use('WXAgg') #from matplotlib.backends.backend_wxagg import FigureCanvasAgg as FigureCanvas # This must come *after* the backend is specified. import matplotlib.pyplot as ppl from mpl_toolkits.basemap import Basemap import Image as Image import VIIRS as VIIRS import tables as pytables from tables import exceptions as pyEx from pyhdf.SD import SD,SDC,SDim import pyhdf.HDF as pyHDF # every module should have a LOG object sourcename= file_Id.split(" ") LOG = logging.getLogger(sourcename[1]) ################################################### # Global Data # ################################################### #global someGlobalVar #def someFunction(someParameter) : #global someGlobalVar #someVar = someGlobalVar + someParemeter ################################### # Get File Lists # ################################### def granuleFiles(geoGlob,prodGlob): ''' Returns sorted lists of the geolocation and product files. ''' geoDir = path.dirname(path.abspath(path.expanduser(geoGlob))) prodDir = path.dirname(path.abspath(path.expanduser(prodGlob))) print "Initial geoGlob = ",geoGlob print "Initial prodGlob = ",prodGlob geoGlob = path.basename(path.abspath(path.expanduser(geoGlob))) prodGlob = path.basename(path.abspath(path.expanduser(prodGlob))) geoPrefix = string.split(geoGlob,'_')[0] print "geoDir = ",geoDir print "prodDir = ",prodDir print "geoGlob = ",geoGlob print "prodGlob = ",prodGlob print "geoPrefix = ",geoPrefix geoList_in = glob("%s/%s" % (geoDir,geoGlob)) prodList_in = glob("%s/%s" % (prodDir,prodGlob)) geoList_in.sort() prodList_in.sort() #print "prodList_in..." #for prodFile in prodList_in: #print prodFile geoList = [] prodList = [] #prodList = prodList_in for files in prodList_in : prod_arr = string.split(path.basename(files),"_") #print "prod_arr = ",prod_arr dateStamp = prod_arr[2] timeStamp = prod_arr[3] geoFileGlob="%s/%s*%s_%s*.h5" % (geoDir,geoPrefix,dateStamp,timeStamp) #print "dateStamp = ",dateStamp #print "timeStamp = ",timeStamp #print "geoFileGlob = ",geoFileGlob geoFile = glob("%s/%s*%s_%s*.h5" % (geoDir,geoPrefix,dateStamp,timeStamp)) if (np.shape(geoFile)[0] != 0) : geoList.append(geoFile[0]) prodList.append(files) else : #geoList.append(files) print " ... no match found for %s, appending %s" % ( geoFile, files) pass #for geoFile,prodFile in zip(geoList,prodList): #print geoFile,prodFile return geoList,prodList ################################################### # Granulation Functions # ################################################### def _run_crefl(crefl_exe, geoFile, redFile, greenFile, blueFile, outFile): currDir = path.abspath('.') crefl_exe = path.abspath(path.expanduser(crefl_exe)) crefl_dir = path.dirname(crefl_exe) geoFile = path.abspath(path.expanduser(geoFile)) blueFile = path.abspath(path.expanduser(blueFile)) greenFile = path.abspath(path.expanduser(greenFile)) redFile = path.abspath(path.expanduser(redFile)) outFile = path.abspath(path.expanduser(outFile)) LOG.info('outfile = %s' % (outFile)) os.chdir(crefl_dir) try : LOG.info('Computing corrected reflectances.') cmdStr = '%s viirs --verbose --of=%s %s %s %s %s' % (crefl_exe, outFile, geoFile, blueFile, greenFile, redFile) LOG.debug('\t%s' % (cmdStr)) args = shlex.split(cmdStr) LOG.debug('\t%s' % (repr(args))) procRetVal = 0 procObj = subprocess.Popen(args,bufsize=0, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) procObj.wait() procRetVal = procObj.returncode procOutput = procObj.stdout.read() LOG.debug("%s" % (procOutput)) if not (procRetVal == 0) : LOG.error('Computing corrected reflectances failed for crefl command...\n%s.' % (cmdStr)) sys.exit(procRetVal) except Exception, err: LOG.warn( "%s" % (str(err))) os.chdir(currDir) def gran_Sdr(geoFile,redFile,greenFile,blueFile,isRadiance=False): ''' Returns the granulated SDR dataset ''' try : reload(VIIRS.viirsSDR) reload(VIIRS.ViirsData) del(viirsSdrObj) del(latArr) del(lonArr) del(redArr) del(greenArr) del(blueArr) except : pass LOG.info("Creating viirsSdrObj...") reload(VIIRS.viirsSDR) viirsSdrObj = VIIRS.viirsSDR.viirsSDR() LOG.info("done") # Determine the correct fillValue trimObj = VIIRS.ViirsData.ViirsTrimTable() eps = 1.e-6 rgbKeys = ['lat','lon','lat_0','lon_0','red','green','blue','redName','greenName','blueName'] RGBfiles = {'red':redFile,'green':greenFile,'blue':blueFile} RGBdict = {} for chans,chanFileName in zip(['red','green','blue'],['redName','greenName','blueName']): LOG.info("Ingesting %s channel ..." % (chans)) retArr = viirsSdrObj.ingest(geoFile,RGBfiles[chans],isRadiance,1) LOG.info("done\n") try : latArr = viirsSdrObj.Lat[:,:] lonArr = viirsSdrObj.Lon[:,:] ModeGran = viirsSdrObj.ModeGran lat_0 = latArr[np.shape(latArr)[0]/2,np.shape(latArr)[1]/2] lon_0 = lonArr[np.shape(lonArr)[0]/2,np.shape(lonArr)[1]/2] RGBdict['lat_0'] = lat_0 RGBdict['lon_0'] = lon_0 badGeo = False if not (-90. <= lat_0 <= 90.) : LOG.error("Latitude of granule midpoint (%f) does not satisfy (-90. <= lat_0 <= 90.)\nfor file %s\n\taborting..." % (lat_0,geoFile)) badGeo = True if not (-180. <= lat_0 <= 180.) : LOG.error("Longitude of granule midpoint (%f) does not satisfy (-180. <= lon_0 <= 180.)\nfor file %s\n\taborting..." % (lon_0,geoFile)) badGeo = True if badGeo : sys.exit(1) RGBdict['lat'] = latArr[:,:] RGBdict['lon'] = lonArr[:,:] RGBdict['ModeGran'] = ModeGran RGBdict[chans] = viirsSdrObj.ViirsSDR[:,:] RGBdict[chanFileName] = RGBfiles[chans] except : LOG.error("There was an exception...") sys.exit(1) return RGBdict def gran_Sdr2(geoFile,redFile,greenFile,blueFile,isRadiance=False): ''' Returns the granulated SDR dataset ''' try : reload(VIIRS.viirsSDR) reload(VIIRS.ViirsData) del(viirsSdrObj) del(latArr) del(lonArr) del(redArr) del(greenArr) del(blueArr) except : pass LOG.info("Creating viirsSdrObj...") reload(VIIRS.viirsSDR) viirsSdrObj = VIIRS.viirsSDR.viirsSDR() LOG.info("done") # Determine the correct fillValue trimObj = VIIRS.ViirsData.ViirsTrimTable() eps = 1.e-6 rgbKeys = ['lat','lon','lat_0','lon_0','red','green','blue','redName','greenName','blueName'] RGBfiles = {'red':redFile,'green':greenFile,'blue':blueFile} RGBdict = {} # Ingest the VIIRS geolocation LOG.info("Ingesting geolocation...") retArr = viirsSdrObj.ingest(geoFile,None,isRadiance,1) latArr = viirsSdrObj.Lat[:,:] lonArr = viirsSdrObj.Lon[:,:] ModeGran = viirsSdrObj.ModeGran lat_0 = latArr[np.shape(latArr)[0]/2,np.shape(latArr)[1]/2] lon_0 = lonArr[np.shape(lonArr)[0]/2,np.shape(lonArr)[1]/2] RGBdict['lat_0'] = lat_0 RGBdict['lon_0'] = lon_0 badGeo = False if not (-90. <= lat_0 <= 90.) : LOG.error("Latitude of granule midpoint (%f) does not satisfy (-90. <= lat_0 <= 90.)\nfor file %s\n\taborting..." % (lat_0,geoFile)) badGeo = True if not (-180. <= lat_0 <= 180.) : LOG.error("Longitude of granule midpoint (%f) does not satisfy (-180. <= lon_0 <= 180.)\nfor file %s\n\taborting..." % (lon_0,geoFile)) badGeo = True if badGeo : return 1 RGBdict['lat'] = latArr[:,:] RGBdict['lon'] = lonArr[:,:] RGBdict['ModeGran'] = ModeGran # Ingest the VIIRS red, green and blue channels for chans,chanFileName in zip(['red','green','blue'],['redName','greenName','blueName']): LOG.info("Ingesting %s channel ..." % (chans)) retArr = viirsSdrObj.ingest(None,RGBfiles[chans],isRadiance,1) LOG.info("done\n") try : RGBdict[chans] = viirsSdrObj.ViirsSDR[:,:] RGBdict[chanFileName] = RGBfiles[chans] except : LOG.error("There was an exception...") return 1 return RGBdict def gran_crefl(creflList,geoList): ''' Returns the granulated corrected reflectance ''' try : reload(VIIRS.viirsSDR) reload(VIIRS.ViirsData) del(viirsSdrObj) del(latArr) del(lonArr) del(redArr) del(greenArr) del(blueArr) except : pass # Determine the correct fillValue trimObj = VIIRS.ViirsData.ViirsTrimTable() trimMask = trimObj.createModTrimArray(nscans=48,trimType=bool) eps = 1.e-6 rgbKeys = ['lat','lon','lat_0','lon_0','red','green','blue','redName','greenName','blueName'] creflChanNames = {'red':'CorrRefl_05', 'green':'CorrRefl_04', 'blue':'CorrRefl_03'} LOG.info("Creating viirsSdrObj...") reload(VIIRS.viirsSDR) viirsSdrObj = VIIRS.viirsSDR.viirsSDR() #print creflList RGBdict = {} #for grans in np.arange(len(creflList)): for grans in np.arange(2): creflFile = creflList[grans] LOG.info("Opening VIIRS crefl file %s..."%(creflFile)) try : creflFileObj = SD( creflFile, SDC.READ ) LOG.info("Successfully opened crefl file") except pyHDF.HDF4Error: LOG.error("Could not open crefl file: %s" % (creflFile)) sys.exit(1) # Attempt to read geolocation from crefl file. If this fails, # fall back to reading from VIIRS geolocation file #LOG.info("Ingesting VIIRS geolocation from crefl file %s..." % (creflFile)) try : latArr = np.vstack((latArr, creflFileObj.select('Latitude').get() )) lonArr = np.vstack((lonArr, creflFileObj.select('Longitude').get() )) ModeGran = 1 except NameError : latArr = creflFileObj.select('Latitude').get() lonArr = creflFileObj.select('Longitude').get() ModeGran = 1 LOG.info("Intermediate latArr.shape = %s" % (str(latArr.shape))) LOG.info("Intermediate lonArr.shape = %s" % (str(lonArr.shape))) for chans in ['red','green','blue']: colourArr = '%sArr'%(chans) LOG.info("Processing %s..." % (colourArr)) try : chanArr = creflFileObj.select(creflChanNames[chans]).get() LOG.info("%s chanArr shape is %s" % (chans,str(chanArr.shape))) vars()[colourArr] = np.vstack((vars()[colourArr],chanArr)) LOG.info("Finished reading VIIRS corrected reflectance %s from %s" % (chans,creflFile)) except KeyError: LOG.info("Reading first VIIRS corrected reflectance %s from %s..." % (creflChanNames[chans],creflFile)) vars()[colourArr] = creflFileObj.select(creflChanNames[chans]).get() LOG.info("Finished reading first VIIRS corrected reflectance %s from %s" % (chans,creflFile)) #LOG.info("Intermediate %sArr.shape = %s" % (chans,str(vars()[chans+'Arr'].shape))) #try : #except Exception, err: #creflFileObj.end() #LOG.error( "%s" % (str(err))) #LOG.error( "Unable to read VIIRS corrected reflectance %s from %s, aborting..." % (chans,creflFile)) #sys.exit(1) # Close crefl file creflFileObj.end() print "" print redArr #except Exception, err: #LOG.error( "%s" % (str(err))) lat_0 = latArr[np.shape(latArr)[0]/2,np.shape(latArr)[1]/2] lon_0 = lonArr[np.shape(lonArr)[0]/2,np.shape(lonArr)[1]/2] RGBdict['lat_0'] = lat_0 RGBdict['lon_0'] = lon_0 RGBdict['lat'] = latArr[:,:] RGBdict['lon'] = lonArr[:,:] RGBdict['ModeGran'] = ModeGran RGBdict['redName'] = 'SVM05_npp_d20120705_t2028301_e2029543_b03568_c20120706035000918229_noaa_ops.h5' RGBdict['greenName'] = 'SVM04_npp_d20120705_t2028301_e2029543_b03568_c20120706034958022764_noaa_ops.h5' RGBdict['blueName'] = 'SVM03_npp_d20120705_t2028301_e2029543_b03568_c20120706035000894469_noaa_ops.h5' # TODO : Impose proper bow-tie deletion on crefl output. return RGBdict def _create_map_image_RGB(RGBdict,pointSize=1.,scale=1.3,mapRes='c',stride=1,\ sdrKey='M15',isRadiance=False,prodFileName='',outFileName='out.png',dpi=300,titleStr='VIIRS RGB'): ''' Plots the VIIRS Scientific Data Record (SDR)on an orthographic projection ''' gridLat = RGBdict['lat'] gridLon = RGBdict['lon'] lat_0 = RGBdict['lat_0'] lon_0 = RGBdict['lon_0'] ModeGran = RGBdict['ModeGran'] # Setup plotting data reload(VIIRS.ViirsData) # If we have a zero size array, make a dummy dataset # to span the allowed data range, which will be plotted with # vanishing pointsize if (np.shape(gridLon)[0]==0) : print "We have no valid data, synthesising dummy data..." gridLat = np.array([lat_0,lat_0]) gridLon = np.array([lon_0,lon_0]) gridData = np.array([vmin,vmax]) pointSize = 0.001 figWidth = 5. # inches figHeight = 4. # inches # Create figure with default size, and create canvas to draw on fig = Figure(figsize=((figWidth,figHeight))) canvas = FigureCanvas(fig) # Create main axes instance, leaving room for colorbar at bottom, # and also get the Bbox of the axes instance ax_rect = [0.05, 0.18, 0.9, 0.75 ] # [left,bottom,width,height] ax = fig.add_axes(ax_rect) # Granule axis title ax_title = ppl.setp(ax,title=prodFileName) ppl.setp(ax_title,fontsize=6) ppl.setp(ax_title,family="monospace") # Create Basemap instance # set 'ax' keyword so pylab won't be imported. #m = Basemap(projection='ortho',lon_0=lon_0,lat_0=lat_0,ax=ax,fix_aspect=True,resolution='c') print "scale = ",scale m = Basemap(projection='ortho',lon_0=lon_0,lat_0=lat_0,\ ax=ax,fix_aspect=True,resolution=mapRes,\ llcrnrx = -1. * scale * 3200. * 750./2.,\ llcrnry = -1. * scale * 3200. * 750./2.,\ urcrnrx = scale * 3200. * 750./2.,\ urcrnry = scale * 3200. * 750./2.) x,y=m(np.array(gridLon),np.array(gridLat)) # Some map style configuration stufff #m.drawlsmask(ax=ax,land_color='gray',ocean_color='black',lakes=True) m.drawmapboundary(ax=ax,linewidth=0.01,fill_color='grey') m.drawcoastlines(ax=ax,linewidth=0.3,color='white') #m.fillcontinents(ax=ax,color='gray',lake_color='black',zorder=0) #m.drawparallels(np.arange(-90.,120.,30.),color='white') #m.drawmeridians(np.arange(0.,420.,60.),color='white') if (ModeGran == 0) : fig.text(0.5, 0.555, 'NIGHT',fontsize=30, color='white',ha='center',va='center',alpha=0.6) else : # Convert the scaledImg array to something that can be displayed using scatter... scaledImg = RGBdict['scaledImg'] trimObj = VIIRS.ViirsData.ViirsTrimTable() trimMask = trimObj.createModTrimArray(nscans=48,trimType=bool) raveldTrimMask = np.ravel(trimMask) onboard_pt_value = trimObj.sdrTypeFill['ONBOARD_PT_FILL'][scaledImg.dtype.name] # Mask the geolocation x = ma.array(np.ravel(x),mask=raveldTrimMask) y = ma.array(np.ravel(y),mask=raveldTrimMask) # Scale channels to be 0..1 R = scaledImg[:,:,0].astype('float')/255. G = scaledImg[:,:,1].astype('float')/255. B = scaledImg[:,:,2].astype('float')/255. # Ravel the channel arrays R = np.ravel(R) G = np.ravel(G) B = np.ravel(B) # Mask the RGB arrays R = ma.array(R,mask=raveldTrimMask) G = ma.array(G,mask=raveldTrimMask) B = ma.array(B,mask=raveldTrimMask) # Compress the geolocation and RGB arrays x = x.compressed() y = y.compressed() R = R.compressed() G = G.compressed() B = B.compressed() # Shrink the geolocation and RGB arrays print "Stride = ",stride print "dpi = ",dpi x = x[::stride] y = y[::stride] R = R[::stride] G = G[::stride] B = B[::stride] # Construct the data array gridData = np.transpose(np.array([R,G,B])) print x.shape print y.shape print gridData.shape # Plot the granule data # TODO: Use pcolormesh instead. cs = m.scatter(x,y,s=pointSize,c=gridData,axes=ax,edgecolors='none',vmin=0.,vmax=1.) # RGB information at the bottom of the plot. timeString = 'Creation date: %s' %(datetime.strftime(datetime.utcnow(),"%Y-%m-%d %H:%M:%S Z")) fig.text(0.98, 0.01, timeString,fontsize=5, color='gray',ha='right',va='bottom',alpha=0.9) channelDict = {'red':string.split(path.basename(RGBdict['redName']),'_')[0][2:],\ 'green':string.split(path.basename(RGBdict['greenName']),'_')[0][2:],\ 'blue':string.split(path.basename(RGBdict['blueName']),'_')[0][2:]} RGBstring = "R : %s (%s $\mu\mathrm{m}$); G : %s (%s $\mu\mathrm{m}$); B : %s (%s $\mu\mathrm{m}$)" % \ (channelDict['red'],\ str(VIIRS.ViirsData.ViirsBandCenter[channelDict['red']]),\ channelDict['green'],\ str(VIIRS.ViirsData.ViirsBandCenter[channelDict['green']]),\ channelDict['blue'],\ str(VIIRS.ViirsData.ViirsBandCenter[channelDict['blue']]) ) fig.text(0.5, 0.07, RGBstring,fontsize=10, color='black',ha='center',va='bottom',alpha=1.0) # # Add a small globe with the swath indicated on it # # # Create main axes instance, leaving room for colorbar at bottom, # and also get the Bbox of the axes instance glax_rect = [0.81, 0.75, 0.18, 0.20 ] # [left,bottom,width,height] glax = fig.add_axes(glax_rect) m_globe = Basemap(lat_0=0.,lon_0=0.,\ ax=glax,resolution='c',area_thresh=10000.,projection='robin') # If we previously had a zero size data array, increase the pointSize # so the data points are visible on the global plot pointSize = 0.2 if (np.shape(gridLon)[0]==2) : print "We have no valid data, synthesising dummy data..." pointSize = 5. x,y = m_globe(np.array(gridLon),np.array(gridLat)) swath = np.zeros(np.shape(x),dtype=int) m_globe.drawcoastlines(ax=glax,linewidth=0.1) m_globe.fillcontinents(ax=glax,color='gray',zorder=0) m_globe.drawmapboundary(linewidth=0.1) p_globe = m_globe.scatter(x,y,s=pointSize,c="red",axes=glax,edgecolors='none') # Globe axis title glax_xlabel = ppl.setp(glax,xlabel=titleStr) ppl.setp(glax_xlabel,fontsize=6) # Redraw the figure canvas.draw() # save image print "Writing file to ",outFileName canvas.print_figure(outFileName,dpi=dpi) def _create_map_image_RGB_noravel(RGBdict,pointSize=1.,scale=1.3,mapRes='c',stride=1,\ sdrKey='M15',isRadiance=False,prodFileName='',outFileName='out.png',dpi=300,titleStr='VIIRS RGB'): ''' Plots the VIIRS Scientific Data Record (SDR)on an orthographic projection ''' gridLat = RGBdict['lat'] gridLon = RGBdict['lon'] lat_0 = RGBdict['lat_0'] lon_0 = RGBdict['lon_0'] ModeGran = RGBdict['ModeGran'] # Setup plotting data reload(VIIRS.ViirsData) # If we have a zero size array, make a dummy dataset # to span the allowed data range, which will be plotted with # vanishing pointsize if (np.shape(gridLon)[0]==0) : print "We have no valid data, synthesising dummy data..." gridLat = np.array([lat_0,lat_0]) gridLon = np.array([lon_0,lon_0]) gridData = np.array([vmin,vmax]) pointSize = 0.001 figWidth = 5. # inches figHeight = 4. # inches # Create figure with default size, and create canvas to draw on fig = Figure(figsize=((figWidth,figHeight))) canvas = FigureCanvas(fig) # Create main axes instance, leaving room for colorbar at bottom, # and also get the Bbox of the axes instance ax_rect = [0.05, 0.18, 0.9, 0.75 ] # [left,bottom,width,height] ax = fig.add_axes(ax_rect) # Granule axis title ax_title = ppl.setp(ax,title=prodFileName) ppl.setp(ax_title,fontsize=6) ppl.setp(ax_title,family="monospace") # Create Basemap instance # set 'ax' keyword so pylab won't be imported. #m = Basemap(projection='ortho',lon_0=lon_0,lat_0=lat_0,ax=ax,fix_aspect=True,resolution='c') print "scale = ",scale m = Basemap(projection='ortho',lon_0=lon_0,lat_0=lat_0,\ ax=ax,fix_aspect=True,resolution=mapRes,\ llcrnrx = -1. * scale * 3200. * 750./2.,\ llcrnry = -1. * scale * 3200. * 750./2.,\ urcrnrx = scale * 3200. * 750./2.,\ urcrnry = scale * 3200. * 750./2.) x,y=m(np.array(gridLon),np.array(gridLat)) # Some map style configuration stufff #m.drawlsmask(ax=ax,land_color='gray',ocean_color='black',lakes=True) m.drawmapboundary(ax=ax,linewidth=0.01,fill_color='grey') m.drawcoastlines(ax=ax,linewidth=0.3,color='white') #m.fillcontinents(ax=ax,color='gray',lake_color='black',zorder=0) #m.drawparallels(np.arange(-90.,120.,30.),color='white') #m.drawmeridians(np.arange(0.,420.,60.),color='white') if (ModeGran == 0) : fig.text(0.5, 0.555, 'NIGHT',fontsize=30, color='white',ha='center',va='center',alpha=0.6) else : # Convert the scaledImg array to something that can be displayed using scatter... scaledImg = RGBdict['scaledImg'] trimObj = VIIRS.ViirsData.ViirsTrimTable() trimMask = trimObj.createModTrimArray(nscans=48,trimType=bool) raveldTrimMask = np.ravel(trimMask) onboard_pt_value = trimObj.sdrTypeFill['ONBOARD_PT_FILL'][scaledImg.dtype.name] # Mask the geolocation x = ma.array(np.ravel(x),mask=raveldTrimMask) y = ma.array(np.ravel(y),mask=raveldTrimMask) # Scale channels to be 0..1 R = scaledImg[:,:,0].astype('float')/255. G = scaledImg[:,:,1].astype('float')/255. B = scaledImg[:,:,2].astype('float')/255. # Ravel the channel arrays R = np.ravel(R) G = np.ravel(G) B = np.ravel(B) # Mask the RGB arrays R = ma.array(R,mask=raveldTrimMask) G = ma.array(G,mask=raveldTrimMask) B = ma.array(B,mask=raveldTrimMask) # Compress the geolocation and RGB arrays x = x.compressed() y = y.compressed() R = R.compressed() G = G.compressed() B = B.compressed() # Shrink the geolocation and RGB arrays print "Stride = ",stride print "dpi = ",dpi x = x[::stride] y = y[::stride] R = R[::stride] G = G[::stride] B = B[::stride] # Construct the data array gridData = np.transpose(np.array([R,G,B])) print x.shape print y.shape print gridData.shape # Plot the granule data # TODO: Use pcolormesh instead. cs = m.scatter(x,y,s=pointSize,c=gridData,axes=ax,edgecolors='none',vmin=0.,vmax=1.) # RGB information at the bottom of the plot. timeString = 'Creation date: %s' %(datetime.strftime(datetime.utcnow(),"%Y-%m-%d %H:%M:%S Z")) fig.text(0.98, 0.01, timeString,fontsize=5, color='gray',ha='right',va='bottom',alpha=0.9) channelDict = {'red':string.split(path.basename(RGBdict['redName']),'_')[0][2:],\ 'green':string.split(path.basename(RGBdict['greenName']),'_')[0][2:],\ 'blue':string.split(path.basename(RGBdict['blueName']),'_')[0][2:]} RGBstring = "R : %s (%s $\mu\mathrm{m}$); G : %s (%s $\mu\mathrm{m}$); B : %s (%s $\mu\mathrm{m}$)" % \ (channelDict['red'],\ str(VIIRS.ViirsData.ViirsBandCenter[channelDict['red']]),\ channelDict['green'],\ str(VIIRS.ViirsData.ViirsBandCenter[channelDict['green']]),\ channelDict['blue'],\ str(VIIRS.ViirsData.ViirsBandCenter[channelDict['blue']]) ) fig.text(0.5, 0.07, RGBstring,fontsize=10, color='black',ha='center',va='bottom',alpha=1.0) # # Add a small globe with the swath indicated on it # # # Create main axes instance, leaving room for colorbar at bottom, # and also get the Bbox of the axes instance glax_rect = [0.81, 0.75, 0.18, 0.20 ] # [left,bottom,width,height] glax = fig.add_axes(glax_rect) m_globe = Basemap(lat_0=0.,lon_0=0.,\ ax=glax,resolution='c',area_thresh=10000.,projection='robin') # If we previously had a zero size data array, increase the pointSize # so the data points are visible on the global plot pointSize = 0.2 if (np.shape(gridLon)[0]==2) : print "We have no valid data, synthesising dummy data..." pointSize = 5. x,y = m_globe(np.array(gridLon),np.array(gridLat)) swath = np.zeros(np.shape(x),dtype=int) m_globe.drawcoastlines(ax=glax,linewidth=0.1) m_globe.fillcontinents(ax=glax,color='gray',zorder=0) m_globe.drawmapboundary(linewidth=0.1) p_globe = m_globe.scatter(x,y,s=pointSize,c="red",axes=glax,edgecolors='none') # Globe axis title glax_xlabel = ppl.setp(glax,xlabel=titleStr) ppl.setp(glax_xlabel,fontsize=6) # Redraw the figure canvas.draw() # save image print "Writing file to ",outFileName canvas.print_figure(outFileName,dpi=dpi) class BandData(): def __init__(self,geoGlob): geoFile = path.abspath(glob(geoGlob)[0]) dateStamp = string.split(path.basename(geoFile),'_')[2] timeStamp = string.split(path.basename(geoFile),'_')[3] print geoFile print dateStamp print timeStamp bands = ['03','04','05','10','11'] bandFiles = {} for band in bands: bandGlob = string.replace(geoGlob,'GMODO','SVM'+band) bandFiles['SVM'+band] = path.abspath(glob(bandGlob)[0]) print bandFiles['SVM'+band] def viirs_rgb(imgType,RGBdict,swathImg,swathName=None): print 'lat_0 = %f' % (RGBdict['lat_0']) print 'lon_0 = %f' % (RGBdict['lon_0']) print 'lat.shape = %s' % (repr(RGBdict['lat'].shape)) print 'lon.shape = %s' % (repr(RGBdict['lon'].shape)) print 'red.shape = %s' % (repr(RGBdict['red'].shape)) print 'green.shape = %s' % (repr(RGBdict['green'].shape)) print 'blue.shape = %s' % (repr(RGBdict['blue'].shape)) # Construct the Bow-tie deletion mask trimObj = VIIRS.ViirsData.ViirsTrimTable() trimMask = trimObj.createModTrimArray(nscans=48,trimType=bool) R = ma.masked_less(RGBdict['red'],-1.5) G = ma.masked_less(RGBdict['green'],-1.5) B = ma.masked_less(RGBdict['blue'],-1.5) print "min RGBdict['red'] = %f" % (np.min(R)) print "min RGBdict['green'] = %f" % (np.min(G)) print "min RGBdict['blue'] = %f" % (np.min(B)) print "max RGBdict['red'] = %f" % (np.max(R)) print "max RGBdict['green'] = %f" % (np.max(G)) print "max RGBdict['blue'] = %f" % (np.max(B)) bandMin = max(np.min(R),np.min(G),np.min(B)) bandMax = max(np.max(R),np.max(G),np.max(B)) band_R_scaled = 255. * (R - np.min(R)) / np.max(R - np.min(R)) band_G_scaled = 255. * (G - np.min(G)) / np.max(G - np.min(G)) band_B_scaled = 255. * (B - np.min(B)) / np.max(B - np.min(B)) newimg = np.zeros((768,3200,3),dtype=np.float32) newimg[:,:,0] = band_R_scaled[:,:] newimg[:,:,1] = band_G_scaled[:,:] newimg[:,:,2] = band_B_scaled[:,:] # Make an image object from a numpy array im = Image.fromarray(newimg.astype(np.uint8)) # Limits for differential scaling if imgType == 'TrueColor' or imgType == 'Vegetation' : # True Colour input = np.array([0, 30, 60, 120, 190, 255],dtype=np.float32) #output = np.array([0, 110, 160, 210, 240, 255],dtype=np.float32) # Original scaling output = np.array([0, 180, 200, 220, 240, 255],dtype=np.float32) # New scaling elif imgType == 'SnowIce' : # Snow/Ice input = np.array([0, 25, 55, 100, 255],dtype=np.float32) output = np.array([0, 90, 140, 175, 255],dtype=np.float32) elif imgType == 'CloudPhase' : newimg[:,:,1] = 255. - band_B_scaled input = np.array([0, 30, 60, 120, 190, 255],dtype=np.float32) output = np.array([0, 30, 60, 120, 190, 255],dtype=np.float32) # New scaling else : print "error: invalid band combination. Try 'TrueColor','SnowIce','Vegetation'" return 1 inputRange = input[1 :]-input[:-1] outputRange = output[1 :]-output[:-1] inputMin,inputMax = input[:-1], input[1 :] outputMin,outputMax = output[:-1], output[1 :] slope = (outputMax-outputMin)/(inputMax-inputMin) intercept = outputMax - (slope*inputMax) scaledImg = np.zeros((768,3200,3),dtype=np.float32) print "Scaling red channel..." for pair in np.arange(np.size(inputRange)): inputIdx = np.where((newimg[:,:,0]>=inputMin[pair])*(newimg[:,:,0]<inputMax[pair])) rows,cols = inputIdx[0],inputIdx[1] print "min,max of unscaled red channel:",np.min(newimg[rows,cols,0]),np.max(newimg[rows,cols,0]) scaledImg[rows,cols,0] = slope[pair] * newimg[rows,cols,0] + intercept[pair] print "min,max of scaled red channel:",np.min(newimg[rows,cols,0]),np.max(newimg[rows,cols,0]) print "\nScaling green channel..." for pair in np.arange(np.size(inputRange)): inputIdx = np.where((newimg[:,:,1]>=inputMin[pair])*(newimg[:,:,1]<inputMax[pair])) rows,cols = inputIdx[0],inputIdx[1] print "min,max of unscaled green channel:",np.min(newimg[rows,cols,1]),np.max(newimg[rows,cols,1]) scaledImg[rows,cols,1] = slope[pair] * newimg[rows,cols,1] + intercept[pair] print "min,max of scaled green channel:",np.min(newimg[rows,cols,1]),np.max(newimg[rows,cols,1]) print "\nScaling blue channel..." for pair in np.arange(np.size(inputRange)): inputIdx = np.where((newimg[:,:,2]>=inputMin[pair])*(newimg[:,:,2]<inputMax[pair])) rows,cols = inputIdx[0],inputIdx[1] print "min,max of unscaled blue channel:",np.min(newimg[rows,cols,2]),np.max(newimg[rows,cols,2]) scaledImg[rows,cols,2] = slope[pair] * newimg[rows,cols,2] + intercept[pair] print "min,max of scaled blue channel:",np.min(newimg[rows,cols,2]),np.max(newimg[rows,cols,2]) scaledImg = scaledImg.astype('uint8') RGB_trimMask = np.zeros((768,3200,3),dtype=np.bool) RGB_trimMask[:,:,0] = trimMask[:,:] RGB_trimMask[:,:,1] = trimMask[:,:] RGB_trimMask[:,:,2] = trimMask[:,:] onboard_pt_value = trimObj.sdrTypeFill['ONBOARD_PT_FILL']['uint8'] scaledImg_masked = np.zeros((768,3200,3),dtype=np.uint8) scaledImg_masked = ma.array(scaledImg,mask=RGB_trimMask,fill_value=onboard_pt_value) # Make some pixels red... afires_mask = np.zeros((768,3200,3),dtype=np.uint8) afires_mask[:,:,0] = 255 * np.ones((768,3200),dtype=np.uint8) scaledImg_masked[380:390,1600:1610,:] = afires_mask[380:390,1600:1610,:] scaledImg_masked[8,2264,:] = afires_mask[8,2264,:] scaledImg_masked[9,2491,:] = afires_mask[9,2491,:] if swathImg : im = Image.fromarray(scaledImg_masked[::-1,::-1,:]) LOG.info("Initial swathName = %r" % (swathName)) if swathName == None : swathName = 'Viirs_swath_truecolor.png' else : swathName = string.replace(swathName,'.png','_swath.png') LOG.info("Final swathName = %r" % (swathName)) im.save(swathName) scaledImg = scaledImg_masked.filled() RGBdict['scaledImg'] = scaledImg return RGBdict def crefl_rgb(imgType,RGBdict,swathImg,swathName=None): print 'lat_0 = %f' % (RGBdict['lat_0']) print 'lon_0 = %f' % (RGBdict['lon_0']) print 'lat.shape = %s' % (repr(RGBdict['lat'].shape)) print 'lon.shape = %s' % (repr(RGBdict['lon'].shape)) print 'red.shape = %s' % (repr(RGBdict['red'].shape)) print 'green.shape = %s' % (repr(RGBdict['green'].shape)) print 'blue.shape = %s' % (repr(RGBdict['blue'].shape)) # Construct the Bow-tie deletion mask trimObj = VIIRS.ViirsData.ViirsTrimTable() trimMask = trimObj.createModTrimArray(nscans=48,trimType=bool) R = ma.masked_equal(RGBdict['red'],32767) G = ma.masked_equal(RGBdict['green'],32767) B = ma.masked_equal(RGBdict['blue'],32767) print "min RGBdict['red'] = %f" % (np.min(R)) print "min RGBdict['green'] = %f" % (np.min(G)) print "min RGBdict['blue'] = %f" % (np.min(B)) print "max RGBdict['red'] = %f" % (np.max(R)) print "max RGBdict['green'] = %f" % (np.max(G)) print "max RGBdict['blue'] = %f" % (np.max(B)) bandMin = max(np.min(R),np.min(G),np.min(B)) bandMax = max(np.max(R),np.max(G),np.max(B)) band_R_scaled = 255. * (R - np.min(R)) / np.max(R - np.min(R)) band_G_scaled = 255. * (G - np.min(G)) / np.max(G - np.min(G)) band_B_scaled = 255. * (B - np.min(B)) / np.max(B - np.min(B)) newimg = np.zeros((768,3200,3),dtype=np.float32) newimg[:,:,0] = band_R_scaled[:,:] newimg[:,:,1] = band_G_scaled[:,:] newimg[:,:,2] = band_B_scaled[:,:] # Make an image object from a numpy array im = Image.fromarray(newimg.astype(np.uint8)) # Limits for differential scaling if imgType == 'TrueColor' or imgType == 'Vegetation' : # True Colour input = np.array([0, 30, 60, 120, 190, 255],dtype=np.float32) #output = np.array([0, 110, 160, 210, 240, 255],dtype=np.float32) # Original scaling output = np.array([0, 180, 200, 220, 240, 255],dtype=np.float32) # New scaling elif imgType == 'SnowIce' : # Snow/Ice input = np.array([0, 25, 55, 100, 255],dtype=np.float32) output = np.array([0, 90, 140, 175, 255],dtype=np.float32) elif imgType == 'CloudPhase' : newimg[:,:,1] = 255. - band_B_scaled input = np.array([0, 30, 60, 120, 190, 255],dtype=np.float32) output = np.array([0, 30, 60, 120, 190, 255],dtype=np.float32) # New scaling else : print "error: invalid band combination. Try 'TrueColor','SnowIce','Vegetation'" return 1 inputRange = input[1 :]-input[:-1] outputRange = output[1 :]-output[:-1] inputMin,inputMax = input[:-1], input[1 :] outputMin,outputMax = output[:-1], output[1 :] slope = (outputMax-outputMin)/(inputMax-inputMin) intercept = outputMax - (slope*inputMax) scaledImg = np.zeros((768,3200,3),dtype=np.float32) print "Scaling red channel..." for pair in np.arange(np.size(inputRange)): inputIdx = np.where((newimg[:,:,0]>=inputMin[pair])*(newimg[:,:,0]<inputMax[pair])) rows,cols = inputIdx[0],inputIdx[1] print "min,max of unscaled red channel:",np.min(newimg[rows,cols,0]),np.max(newimg[rows,cols,0]) scaledImg[rows,cols,0] = slope[pair] * newimg[rows,cols,0] + intercept[pair] print "min,max of scaled red channel:",np.min(newimg[rows,cols,0]),np.max(newimg[rows,cols,0]) print "\nScaling green channel..." for pair in np.arange(np.size(inputRange)): inputIdx = np.where((newimg[:,:,1]>=inputMin[pair])*(newimg[:,:,1]<inputMax[pair])) rows,cols = inputIdx[0],inputIdx[1] print "min,max of unscaled green channel:",np.min(newimg[rows,cols,1]),np.max(newimg[rows,cols,1]) scaledImg[rows,cols,1] = slope[pair] * newimg[rows,cols,1] + intercept[pair] print "min,max of scaled green channel:",np.min(newimg[rows,cols,1]),np.max(newimg[rows,cols,1]) print "\nScaling blue channel..." for pair in np.arange(np.size(inputRange)): inputIdx = np.where((newimg[:,:,2]>=inputMin[pair])*(newimg[:,:,2]<inputMax[pair])) rows,cols = inputIdx[0],inputIdx[1] print "min,max of unscaled blue channel:",np.min(newimg[rows,cols,2]),np.max(newimg[rows,cols,2]) scaledImg[rows,cols,2] = slope[pair] * newimg[rows,cols,2] + intercept[pair] print "min,max of scaled blue channel:",np.min(newimg[rows,cols,2]),np.max(newimg[rows,cols,2]) scaledImg = scaledImg.astype('uint8') # TODO : Actually apply the mask to the arrays. RGB_trimMask = np.zeros((768,3200,3),dtype=np.bool) RGB_trimMask[:,:,0] = trimMask[:,:] RGB_trimMask[:,:,1] = trimMask[:,:] RGB_trimMask[:,:,2] = trimMask[:,:] onboard_pt_value = trimObj.sdrTypeFill['ONBOARD_PT_FILL']['uint8'] scaledImg_masked = np.zeros((768,3200,3),dtype=np.uint8) scaledImg_masked = ma.array(scaledImg,mask=RGB_trimMask,fill_value=onboard_pt_value) if swathImg : im = Image.fromarray(scaledImg_masked) LOG.info("Initial swathName = %r" % (swathName)) if swathName == None : swathName = 'Viirs_swath_truecolor_crefl.png' else : swathName = string.replace(swathName,'.png','_swath.png') LOG.info("Final swathName = %r" % (swathName)) im.save(swathName) scaledImg = scaledImg_masked.filled() RGBdict['scaledImg'] = scaledImg return RGBdict ###################################################### ###################################################### ###################################################### def basemap_rgb(RGBdict): # it looks like the reload(VIIRS.ViirsData) figWidth = 5. # inches figHeight = 4. # inches # Create figure with default size, and create canvas to draw on fig = Figure(figsize=((figWidth,figHeight))) canvas = FigureCanvas(fig) # Create main axes instance, leaving room for colorbar at bottom, # and also get the Bbox of the axes instance ax_rect = [0.05, 0.18, 0.9, 0.75 ] # [left,bottom,width,height] ax = fig.add_axes(ax_rect) # Granule axis title ax_title = ppl.setp(ax,title="VIIRS RGB") ppl.setp(ax_title,fontsize=6) ppl.setp(ax_title,family="monospace") # Create Basemap instance # set 'ax' keyword so pylab won't be imported. #m = Basemap(projection='ortho',lon_0=lon_0,lat_0=lat_0,ax=ax,fix_aspect=True,resolution='c') scale = 1.3 lat_0 = RGBdict['lat_0'] lon_0 = RGBdict['lon_0'] m = Basemap(projection='ortho',lon_0=lon_0,lat_0=lat_0,\ ax=ax,fix_aspect=True,resolution='l',\ llcrnrx = -1. * scale * 3200. * 750./2.,\ llcrnry = -1. * scale * 3200. * 750./2.,\ urcrnrx = scale * 3200. * 750./2.,\ urcrnry = scale * 3200. * 750./2.) x,y=m(np.array(RGBdict['lon']),np.array(RGBdict['lat'])) # Some map style configuration stufff m.drawmapboundary(ax=ax,linewidth=0.01,fill_color='grey') m.drawcoastlines(ax=ax,linewidth=0.3,color='white') #m.fillcontinents(ax=ax,color='gray',lake_color='black',zorder=0) #m.drawparallels(np.arange(-90.,120.,30.),color='white') #m.drawmeridians(np.arange(0.,420.,60.),color='white') # Convert the scaledImg array to something that can be displayed using scatter... scaledImg = RGBdict['scaledImg'] #shrink = 1 shrink = 13 trimObj = VIIRS.ViirsData.ViirsTrimTable() trimMask = trimObj.createModTrimArray(nscans=48,trimType=bool) raveldTrimMask = np.ravel(trimMask) onboard_pt_value = trimObj.sdrTypeFill['ONBOARD_PT_FILL'][scaledImg.dtype.name] # Mask the geolocation x = ma.array(np.ravel(x),mask=raveldTrimMask) y = ma.array(np.ravel(y),mask=raveldTrimMask) # Scale channels to be 0..1 R = scaledImg[:,:,0].astype('float')/255. G = scaledImg[:,:,1].astype('float')/255. B = scaledImg[:,:,2].astype('float')/255. # Ravel the channel arrays R = np.ravel(R) G = np.ravel(G) B = np.ravel(B) # Mask the RGB arrays R = ma.array(R,mask=raveldTrimMask) G = ma.array(G,mask=raveldTrimMask) B = ma.array(B,mask=raveldTrimMask) # Compress the geolocation and RGB arrays x = x.compressed() y = y.compressed() R = R.compressed() G = G.compressed() B = B.compressed() # Shrink the geolocation and RGB arrays x = x[::shrink] y = y[::shrink] R = R[::shrink] G = G[::shrink] B = B[::shrink] # Construct the data array data = np.transpose(np.array([R,G,B])) print x.shape print y.shape print data.shape pointSize=0.2 # Plot the granule data cs = m.scatter(x,y,s=pointSize,c=data,axes=ax,faceted=False,vmin=0.,vmax=1.) # Redraw the figure canvas.draw() # save image canvas.print_figure("test.png",dpi=300) ################################################### # Main Function # ################################################### def main(): prodChoices=['TrueColor','SnowIce','CloudPhase','Vegetation'] mapRes = ['c','l','i'] description = \ ''' This is a brief description of %prog ''' usage = "usage: %prog [mandatory args] [options]" version = version="%prog PEATE" parser = optparse.OptionParser(description=description,usage=usage,version=version) # Mandatory arguments mandatoryGroup = optparse.OptionGroup(parser, "Mandatory Arguments", "At a minimum these arguments must be specified") parser.add_option_group(mandatoryGroup) # Optional arguments optionalGroup = optparse.OptionGroup(parser, "Extra Options", "These options may be used to customize plot characteristics.") optionalGroup.add_option('-g','--geo_file', action="store", dest="geoFile" , type="string", help="The full path of the VIIRS geolocation file") optionalGroup.add_option('--red_file', action="store", dest="redFile", type="string", help="The full path of the VIIRS SDR file corresponding to the red channel.") optionalGroup.add_option('--green_file', action="store", dest="greenFile", type="string", help="The full path of the VIIRS SDR file corresponding to the green channel.") optionalGroup.add_option('--blue_file', action="store", dest="blueFile", type="string", help="The full path of the VIIRS SDR file corresponding to the blue channel.") optionalGroup.add_option('-r','--svn_revision', action="store", dest="svnRevision", default=string.split(__version__," ")[2], type="string", help="The Subversion revision number/tag of this script") optionalGroup.add_option('-R','--svn_repo_path', action="store", dest="svnRepoPath", default="https://svn.ssec.wisc.edu/repos/geoffc/Python/VIIRS/"+path.basename(sys.argv[0]), type="string", help="The full Subversion repository path of this script [default is %default].") optionalGroup.add_option('-d','--dpi', action="store", dest="dpi", default='200.', type="float", help="The resolution in dots per inch of the output png file. [default: %default]") optionalGroup.add_option('-s','--scale', action="store", dest="scale", default='1.3', type="float", help="The extent of the plot viewport as a proportion of the VIIRS swath width (2400 km). [default: %default]") optionalGroup.add_option('-S','--stride', action="store", dest="stride", default='1', type="int", help="Sample every STRIDE pixels in the VIIRS IP/SDR product. [default: %default]") optionalGroup.add_option('-P','--point_size', action="store", dest="pointSize", default='0.1', type="float", help="Size of the plot point used to represent each pixel. [default: %default]") optionalGroup.add_option('-m','--map_res', action="store", dest="mapRes", default='c', type="choice", choices=mapRes, help="The map coastline resolution. Possible values are 'c' (coarse),'l' (low) and 'i' (intermediate). [default: %default]") optionalGroup.add_option('-a','--map_annotation', action="store", dest="mapAnn", #default='', type="string", help="The map legend describing the dataset being shown. [default: IPPROD]") optionalGroup.add_option('-o','--output_file', action="store", dest="outputFile", default="out.png", type="string", help="The full path of the output png file. [default: %default]") optionalGroup.add_option('--crefl_glob', action="store", dest="creflGlob", type="string", help="The full path of the VIIRS corrected relectance file output from crefl.") optionalGroup.add_option('--crefl_bin', action="store", dest="creflBin", type="string", help="The full path of the crefl binary executable.") optionalGroup.add_option('--crefl', action="store_true", dest="run_crefl", help="Compute the corrected reflectances from VIIRS visible channels.") optionalGroup.add_option('--swath_image', action="store_true", dest="createSwathImage", help="Produce an unprojected image file of the RGB scene.") optionalGroup.add_option('--no_map_image', action="store_true", dest="disableMapImage", help="Do not produce the map-projected RGB image.") optionalGroup.add_option('--afires_file', action="store", dest="afilesFile", type="string", help="The full path of the VIIRS Active Fires file.") optionalGroup.add_option('-p','--product', action="store", dest="rgbProd", type="choice", default="TrueColor", choices=prodChoices, help='''The VIIRS RGB product.\n\n Possible values are... %s ''' % (prodChoices.__str__()[1:-1])) optionalGroup.add_option('-v', '--verbose', dest='verbosity', action="count", default=0, help='each occurrence increases verbosity 1 level from ERROR: -v=WARNING -vv=INFO -vvv=DEBUG') parser.add_option_group(optionalGroup) # Parse the arguments from the command line (options, args) = parser.parse_args() # Set up the logging levels levels = [logging.ERROR, logging.WARN, logging.INFO, logging.DEBUG] output_logFile = "plot_viirs_RGB_crefl.py.log" try : logFormat = '(%(levelname)s): %(filename)s ; %(module)s::%(funcName)s ; line %(lineno)d -> %(message)s' #logging.basicConfig(format=logFormat, filename=output_logFile, filemode='w', level = levels[options.verbosity]) logging.basicConfig(format=logFormat, level = levels[options.verbosity]) except IndexError : print "ERROR : Invalid verbosity flag. Only -v, -vv, -vvv allowed, exiting..." sys.exit(1) verbosity = '-' for v in range(options.verbosity) : verbosity += 'v' # Check that the input files actually exist viirsGeo = False viirsRGB = False creflBin = False creflGlob = False if (options.geoFile is not None): if not path.exists(options.geoFile) : parser.error("Geolocation file \n\t%s\ndoes not exist, aborting..." % (options.geoFile)) viirsGeo = True if (options.redFile is not None and \ options.greenFile is not None and \ options.blueFile is not None): if not path.exists(options.redFile) : parser.error("Channel file \n\t%s\ndoes not exist, aborting..." % (options.redFile)) if not path.exists(options.greenFile) : parser.error("Channel file \n\t%s\ndoes not exist, aborting..." % (options.greenFile)) if not path.exists(options.blueFile) : parser.error("Channel file \n\t%s\ndoes not exist, aborting..." % (options.blueFile)) viirsRGB = True if (options.creflBin is not None): if not path.exists(str(options.creflBin)) : parser.error("crefl binary file \n\t%s\ndoes not exist, aborting..." % (options.creflBin)) creflBin = True if (options.creflGlob is not None): creflList = glob(options.creflGlob) if (creflList == []) : parser.error("crefl file \n\t%s\ndoes not exist, aborting..." % (options.creflGlob)) creflGlob = True # We have the VIIRS SDR files... if viirsRGB: LOG.info('VIIRS SDR files exist...') # Want to run crefl *and* have VIIRS geolocation... if options.run_crefl and creflBin and viirsGeo: if options.creflGlob is None : options.creflGlob = path.basename(options.geoFile) options.creflGlob = string.replace(string.replace(options.creflGlob,'GMTCO','CREFL'),'.h5','.hdf') options.creflGlob = path.join(path.curdir,options.creflGlob) LOG.info('Proposed output filename for crefl output: %s' % (options.creflGlob)) LOG.info('Generating corrected reflectances using crefl...') _run_crefl(options.creflBin, options.geoFile, options.redFile, options.greenFile, options.blueFile,options.creflGlob) LOG.info('Ingesting corrected reflectances generated using crefl...') RGBdict = gran_crefl(options.creflGlob,options.geoFile) LOG.info('Generating RGB map from corrected reflectances...') RGBdict = crefl_rgb(options.rgbProd,RGBdict,options.createSwathImage,swathName=options.outputFile) # Do *not* want to run crefl, *and* have VIIRS geolocation... elif not options.run_crefl and viirsGeo: LOG.info('Ingesting uncorrected reflectances...') #RGBdict = gran_Sdr(options.geoFile,options.redFile,options.greenFile,options.blueFile, \ #isRadiance=False) RGBdict = gran_Sdr2(options.geoFile,options.redFile,options.greenFile,options.blueFile, \ isRadiance=False) LOG.info('Generating RGB map from uncorrected reflectances...') LOG.info('Swathname = %s' %(options.outputFile)) #RGBdict = viirs_rgb(options.rgbProd,RGBdict,options.createSwathImage) RGBdict = viirs_rgb(options.rgbProd,RGBdict, \ options.createSwathImage,swathName=options.outputFile) elif creflGlob : LOG.info('options.geoFile = %s' % (options.geoFile)) creflList = glob(options.creflGlob) geoList = [] if options.geoFile is None else glob(options.geoFile) #LOG.info('creflList = %r' % (creflList)) LOG.info('Ingesting corrected reflectances from existing crefl file %s' % (options.creflGlob)) RGBdict = gran_crefl(creflList,geoList) sys.exit(0) LOG.info('Generating RGB map using corrected reflectances from existing crefl file %s' % (options.creflGlob)) LOG.info('Swathname = %s' %(options.outputFile)) RGBdict = crefl_rgb(options.rgbProd,RGBdict, \ options.createSwathImage,swathName=options.outputFile) else : parser.error('''Incomplete mandatory arguments, must provide either red|green|blue files|geo|creflBin files, or geo|creflOut files, aborting...''') # Scale the three VIIRS channels, construct and RGB array #print "RGBdict['ModeGran'] = ",RGBdict['ModeGran'] #if (RGBdict['ModeGran'] != 0): ##RGBdict = viirs_rgb(options.rgbProd,RGBdict) #RGBdict = crefl_rgb(options.rgbProd,RGBdict) #else : #pass #print "RGBdict.items() = ",RGBdict.items() # Make a plot if desired if not options.disableMapImage : prodFileName="" #'''%s\n%s REV:%s''' % (path.basename(options.geoFile),options.svnRepoPath,str(options.svnRevision)) dataSet = string.lower((options.rgbProd).lstrip()) mapRes = str(options.mapRes) # Copy the Channel name to the map annotation if options.mapAnn == None : options.mapAnn = options.rgbProd else : pass options.mapAnn = string.replace(options.mapAnn,'\\n','\n') _create_map_image_RGB(RGBdict,pointSize=options.pointSize,scale=options.scale,mapRes=mapRes,stride=options.stride,\ sdrKey='M15',isRadiance=False,prodFileName=prodFileName,\ outFileName=options.outputFile,dpi=options.dpi,titleStr=options.mapAnn) #orthoPlot_RGB_noravel(RGBdict,pointSize=options.pointSize,scale=options.scale,mapRes=mapRes,stride=options.stride,\ #sdrKey='M15',isRadiance=False,prodFileName=prodFileName,\ #outFileName=options.outputFile,dpi=options.dpi,titleStr=options.mapAnn) print "Exiting..." sys.exit(0) if __name__ == '__main__': main()