blob: 4089582ac15601cea322ddc118eca5c83bd02b1e [file] [log] [blame]
import calendar
import os
from datetime import datetime as datetime
import urllib
import storage.files as files
import toolkit.process as process
import utils.misc
class BoundingBox(object):
def __init__(self, latMin, lonMin, latMax, lonMax):
self.latMin = latMin
self.lonMin = lonMin
self.latMax = latMax
self.lonMax = lonMax
class SubRegion(BoundingBox):
def __init__(self, name, latMin, lonMin, latMax, lonMax):
BoundingBox.__init__(self, latMin, lonMin, latMax, lonMax)
self.name = name
class GridBox(BoundingBox):
def __init__(self, latMin, lonMin, latMax, lonMax, lonStep, latStep):
BoundingBox.__init__(self, latMin, lonMin, latMax, lonMax)
self.lonStep = lonStep
self.latStep = latStep
self.lonCount = int((self.lonMax - self.lonMin) / self.lonStep) + 1
self.latCount = int((self.latMax - self.latMin) / self.latStep) + 1
class JobProperties(object):
def __init__(self, workDir, cacheDir, spatialGrid, temporalGrid, gridLonStep=None, gridLatStep=None, outputFile='false',
latMin=None, latMax=None, lonMin=None, lonMax=None, startDate=None, endDate=None):
self.workDir = os.path.abspath(workDir)
self.cacheDir = os.path.abspath(cacheDir)
self.spatialGrid = spatialGrid
self.temporalGrid = temporalGrid
if gridLonStep and gridLatStep:
self.gridLonStep = float(gridLonStep)
self.gridLatStep = float(gridLatStep)
else:
self.gridLonStep = None
self.gridLatStep = None
# Support for both User provided Dates, and Interactive Date Collection
if startDate and endDate:
self.startDate = datetime.strptime(startDate, '%Y%m%d')
self.endDate = datetime.strptime(endDate, '%Y%m%d')
else:
self.startDate = None
self.endDate = None
if outputFile.lower() == 'false':
self.writeOutFile = 'no'
elif outputFile.lower() == 'netcdf':
self.writeOutFile = 'nc'
else:
self.writeOutFile = False
if self.spatialGrid.lower() == 'user':
self.latMin = float(latMin)
self.latMax = float(latMax)
self.lonMin = float(lonMin)
self.lonMax = float(lonMax)
def obsDatasetCount(self):
self.parameterList = self.obsParamId.split(',')
count = len(self.paramterList)
return count
class Model(object):
def __init__(self, *args, **kwargs):
"""
This Class can be instantiated with either a single filename or a dictionary of parameters.
If a single filename is used, then the class will use internal methods to parse the file
and set the needed attributes.
Input (single file)::
filename - Full path to a local model file
Input (keyword dictionary)::
filename - Full path to a local model file
latVariable - the name of the latitude variable within the file
lonVariable - the name of the longitude variable within the file
timeVariable - the name of the time variable within the file
timeStep - description of the time between readings ['hourly','daily','monthly','annual']
varName - name of the variable to analyze within the model
precipFlag - boolean telling if this is precipitation data
Output::
Model object
"""
if len(args) == 1:
self.filename = args[0]
self.name = os.path.basename(self.filename)
self.processModelFile()
self.precipFlag = False
if len(kwargs) == 7:
self.filename = kwargs['filename']
self.name = os.path.basename(self.filename)
self.latVariable = kwargs['latVariable']
self.lonVariable = kwargs['lonVariable']
self.timeVariable = kwargs['timeVariable']
self.timeStep = kwargs['timeStep']
self.varName = kwargs['varName']
self.times, _ = process.getModelTimes(self.filename, self.timeVariable)
self.minTime = min(self.times)
self.maxTime = max(self.times)
self.setLatitudeRange()
self.setLongitudeRange()
if kwargs['precipFlag'] == 'True':
self.precipFlag = True
else:
self.precipFlag = False
def setLatitudeRange(self):
self.latMin, self.latMax = files.getVariableRange(self.filename, self.latVariable)
def setLongitudeRange(self):
self.lonMin, self.lonMax = files.getVariableRange(self.filename, self.lonVariable)
def processModelFile(self):
""" This series of steps should be consolidated to merely pass around a PyNIO object
Until then we will be opening the same file repeatedly. And clearly wasting I/O
"""
self.latVariable, self.lonVariable, self.latMin, self.latMax, self.lonMin, self.lonMax = files.findLatLonVarFromFile(self.filename)
self.timeVariable, modelVariables = files.findTimeVariable(self.filename)
self.times, self.timeStep = process.getModelTimes(self.filename, self.timeVariable)
self.varName = utils.misc.askUserForVariableName(modelVariables, "analysis")
self.minTime = min(self.times)
self.maxTime = max(self.times)
class Parameter(object):
def __init__(self, param_id, shortName=None, description=None, endDate=None ):
pass
class RCMED(object):
def __init__(self):
pass
def retriveData(self, parameter, dataBounds, timeStep=None):
# Returns the data
pass
@classmethod
def isoDateString(self, pythonDate):
isoDate = pythonDate.strftime("%Y%m%dT%H%MZ")
return isoDate
@classmethod
def jplUrl(self, datasetID, paramID, latMin, latMax, lonMin, lonMax, startTime, endTime, cachedir, timestep):
""" This will create a valid RCMED Query URL used to contact the JPL RCMED Instance"""
JPL_RCMED_URL = 'http://rcmes.jpl.nasa.gov/query-api/query.php?'
"""This block will expand the Time Range based on the timestep to ensure complete temporal range coverage"""
expanded = False
if timestep.lower() == 'monthly':
if startTime.day != 1:
# Clean the startTime
startTimeString = startTime.strftime('%Y%m%d')
normalInputDatetimeString = startTimeString[:6] + '01'
startTime = datetime.strptime(normalInputDatetimeString, '%Y%m%d')
expanded = True
lastDayOfMonth = calendar.monthrange(endTime.year, endTime.month)[1]
if endTime.day != lastDayOfMonth:
# Clean the endTime
endTimeString = endTime.strftime('%Y%m%d')
endTimeString = endTimeString[:6] + str(lastDayOfMonth)
endTime = datetime.strptime(endTimeString, '%Y%m%d')
expanded = True
elif timestep.lower() == 'daily':
if startTime.hour != 0 or startTime.minute != 0 or startTime.second != 0:
datetimeString = startTime.strftime('%Y%m%d%H%M%S')
normalDatetimeString = datetimeString[:8] + '000000'
startTime = datetime.strptime(normalDatetimeString, '%Y%m%d%H%M%S')
expanded = True
endTimeString = endTime.strftime('%Y%m%d%H%M%S')
endTimeString = endTimeString[:8] + '235959'
endTime = datetime.strptime(endTimeString, '%Y%m%d%H%M%S')
if expanded:
print "Your date range selection has been expanded to ensure we return the largest number of available readings."
print "The new date Range is: %s through %s" % (startTime.strftime('%Y-%m-%d %H:%M:%S'), endTime.strftime('%Y-%m-%d %H:%M:%S'))
timeStart = self.isoDateString(startTime)
timeEnd = self.isoDateString(endTime)
query = [('datasetId',datasetID), ('parameterId',paramID), ('latMin',latMin), ('latMax',latMax),
('lonMin', lonMin), ('lonMax',lonMax), ('timeStart', timeStart), ('timeEnd', timeEnd)]
queryURL = urllib.urlencode(query)
urlRequest = JPL_RCMED_URL+queryURL
return urlRequest
class RCMEDDataset(object):
def __init__(self, obsDatasetId, obsParamId, obsTimeStep):
self.datasetId = obsDatasetId
self.parameterId = obsParamId
self.timeStep = obsTimeStep