You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@climate.apache.org by jo...@apache.org on 2014/05/09 04:03:55 UTC

[46/51] [abbrv] [partial] Adding Jinwon's custom RCMET

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/cli/rcmet_ui.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/cli/rcmet_ui.py b/src/main/python/rcmes/cli/rcmet_ui.py
new file mode 100755
index 0000000..ddc11f6
--- /dev/null
+++ b/src/main/python/rcmes/cli/rcmet_ui.py
@@ -0,0 +1,91 @@
+#!/usr/local/bin/python
+""" 
+    Step by Step Wizard that demonstrates how the underlying RCMES code can
+    be used to generate climate dataset intercomparisons
+"""
+# Imports
+# Native Python Module Imports
+import sys
+
+# RCMES Imports
+from classes import Model, JobProperties, GridBox
+import storage.rcmed as rcmed
+import toolkit.metrics
+import toolkit.do_data_prep
+from utils import misc
+
+def rcmetUI():
+    """"
+    Command Line User interface for RCMET.
+    Collects user OPTIONS then runs RCMET to perform processing.
+    
+    Duplicates job of GUI.
+    """
+    print 'Regional Climate Model Evaluation System BETA'
+    print "Querying RCMED for available parameters..."
+
+    try:
+        parameters = rcmed.getParams()
+    except Exception:
+        raise
+        sys.exit()
+
+    # Section 0: Collect directories to store RCMET working files.
+    workDir, cacheDir = misc.getDirSettings()
+    temporalGrid = misc.getTemporalGrid()
+    spatialGrid = misc.getSpatialGrid()
+    jobProperties = JobProperties(workDir, cacheDir, spatialGrid, temporalGrid)
+    
+    # Section 1a: Enter model file/s
+    modelFiles = misc.getModelFiles()
+    # Create a list of model objects for use later
+    models = [Model(modelFile) for modelFile in modelFiles]
+
+    # Section 3b: Select 1 Parameter from list
+    for parameter in parameters:
+        """( 38 ) - CRU3.1 Daily-Mean Temperature : monthly"""
+        print "({:^2}) - {:<54} :: {:<10}".format(parameter['parameter_id'], parameter['longname'], parameter['timestep'])
+
+    obsDatasetList = []
+    validParamIds = [int(p['parameter_id']) for p in parameters]
+    while obsDatasetList == []:
+        print("Please select the available observation you would like to use from the list above:")
+        userChoice = int(raw_input(">>>"))
+        if userChoice in validParamIds:
+            for param in parameters:
+                if param['parameter_id'] == userChoice:
+                    obsDatasetList.append(param)
+                else:
+                    pass
+        else:
+            print("Your selection '%s' is invalid.  Please make another selection." % userChoice)
+    
+
+    # User must provide startTime and endTime if not defined
+    if jobProperties.startDate == None or jobProperties.endDate == None:
+        jobProperties.startDate, jobProperties.endDate = misc.userDefinedStartEndTimes(obsDatasetList, models)
+
+    try:
+        gridBox = GridBox(jobProperties.latMin, jobProperties.lonMin, jobProperties.latMax,
+                          jobProperties.lonMax, jobProperties.gridLonStep, jobProperties.gridLatStep)
+    except:
+        gridBox = None
+
+    numOBS, numMDL, nT, ngrdY, ngrdX, Times, lons, lats, obsData, mdlData, obsList, mdlName = toolkit.do_data_prep.prep_data(jobProperties, obsDatasetList, gridBox, models)
+  
+    counts = {'observations': numOBS,
+              'models'      : numMDL,
+              'times'       : nT}
+    subRegions = misc.getSubRegionsInteractively(counts, jobProperties.workDir)
+
+    # TODO: New function Call
+    fileOutputOption = jobProperties.writeOutFile
+    modelVarName = models[0].varName
+    toolkit.metrics.metrics_plots(modelVarName, numOBS, numMDL, nT, ngrdY, ngrdX, Times, lons, lats, obsData, mdlData, obsList, mdlName, workDir, subRegions, fileOutputOption)
+
+
+
+# Actually call the UI function.
+if __name__ == "__main__":
+    rcmetUI()
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/cli/rcmet_ui.pyc
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/cli/rcmet_ui.pyc b/src/main/python/rcmes/cli/rcmet_ui.pyc
new file mode 100644
index 0000000..bc5ed9f
Binary files /dev/null and b/src/main/python/rcmes/cli/rcmet_ui.pyc differ

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/rcmet.py
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/rcmet.py b/src/main/python/rcmes/rcmet.py
new file mode 100755
index 0000000..01799f9
--- /dev/null
+++ b/src/main/python/rcmes/rcmet.py
@@ -0,0 +1,305 @@
+#!/usr/local/python27
+""" DOCSTRING"""
+
+# Python Standard Lib Imports
+import argparse
+import ConfigParser
+import datetime
+import glob
+import os
+import sys
+import numpy as np
+import numpy.ma as ma
+
+
+# RCMES Imports
+import storage.rcmed as db
+from toolkit import do_data_prep, process, metrics
+from utils import misc
+from classes import JobProperties, Model, GridBox
+from cli import rcmet_ui as ui
+
+parser = argparse.ArgumentParser(description='Regional Climate Model Evaluation Toolkit.  Use -h for help and options')
+parser.add_argument('-c', '--config', dest='CONFIG', help='Path to an evaluation configuration file')
+args = parser.parse_args()
+
+def checkConfigSettings(config):
+    """ This function will check the SETTINGS block of the user supplied config file.
+    This will only check if the working and cache dirs are writable from this program.
+    Additional configuration parameters can be checked here later on.
+    
+    Input::
+        config - ConfigParser configuration object
+    
+    Output::
+        none - An exception will be raised if something goes wrong
+    """
+    settings = config.items('SETTINGS')
+    for key_val in settings:
+        # Check the user provided directories are valid
+        if key_val[0] == 'workDir' or key_val[0] == 'cacheDir':
+            _ =  misc.isDirGood(os.path.abspath(key_val[1]))
+
+        else:
+            pass    
+
+def setSettings(settings, config):
+    """
+    This function is used to set the values within the 'SETTINGS' dictionary when a user provides an external
+    configuration file.
+    
+    Input::
+        settings - Python Dictionary object that will collect the key : value pairs
+        config - A configparse object that contains the external config values
+    
+    Output::
+        None - The settings dictionary will be updated in place.
+    """
+    pass
+
+def generateModels(modelConfig):
+    """
+    This function will return a list of Model objects that can easily be used for 
+    metric computation and other processing tasks.
+    
+    Input::  
+        modelConfig - list of ('key', 'value') tuples.  Below is a list of valid keys
+            filenamepattern - string i.e. '/nas/run/model/output/MOD*precip*.nc'
+            latvariable - string i.e. 'latitude'
+            lonvariable - string i.e. 'longitude'
+            timevariable - string i.e. 't'
+            timestep - string 'monthly' | 'daily' | 'annual'
+            varname - string i.e. 'pr'
+
+    Output::
+        modelList - List of Model objects
+    """
+    # Setup the config Data Dictionary to make parsing easier later
+    configData = {}
+    for entry in modelConfig:
+        configData[entry[0]] = entry[1]
+
+    modelFileList = None
+    for keyValTuple in modelConfig:
+        if keyValTuple[0] == 'filenamePattern':
+            modelFileList = glob.glob(keyValTuple[1])
+            modelFileList.sort()
+
+    # Remove the filenamePattern from the dict since it is no longer used
+    configData.pop('filenamePattern')
+    
+    models = []
+    for modelFile in modelFileList:
+        # use getModelTimes(modelFile,timeVarName) to generate the modelTimeStep and time list
+        _ , configData['timeStep'] = process.getModelTimes(modelFile, configData['timeVariable'])
+        configData['filename'] = modelFile
+        model = Model(**configData)
+        models.append(model)
+    
+    return models
+
+def generateSettings(config):
+    """
+    Helper function to decouple the argument parsing from the Settings object creation
+    
+    Input::  
+        config - list of ('key', 'value') tuples.
+            workdir - string i.e. '/nas/run/rcmet/work/'
+            cachedir - string i.e. '/tmp/rcmet/cache/'
+    Output::
+        JobProperties - JobProperties Object
+    """
+    # Setup the config Data Dictionary to make parsing easier later
+    configData = {}
+    for entry in config:
+        configData[entry[0]] = entry[1]
+        
+    return JobProperties(**configData)
+
+def makeDatasetsDictionary(rcmedConfig):
+    """
+    Helper function to decouple the argument parsing from the RCMEDDataset object creation
+
+    Input::  
+        rcmedConfig - list of ('key', 'value') tuples.
+            obsDatasetId=3,10
+            obsParamId=36,32
+            obsTimeStep=monthly,monthly
+
+    Output::
+        datasetDict - Dictionary with dataset metadata
+    # Setup the config Data Dictionary to make parsing easier later
+    """
+    delimiter = ','
+    configData = {}
+    for entry in rcmedConfig:
+        if delimiter in entry[1]:
+            # print 'delim found - %s' % entry[1]
+            valueList = entry[1].split(delimiter)
+            configData[entry[0]] = valueList
+        else:
+            configData[entry[0]] = entry[1:]
+
+    return configData
+
+def tempGetYears():
+    startYear = int(raw_input('Enter start year YYYY \n'))
+    endYear = int(raw_input('Enter end year YYYY \n'))
+    # CGOODALE - Updating the Static endTime to be 31-DEC
+    startTime = datetime.datetime(startYear, 1, 1, 0, 0)
+    endTime = datetime.datetime(endYear, 12, 31, 0, 0)
+    return (startTime, endTime)
+
+
+def runUsingConfig(argsConfig):
+    """
+    This function is called when a user provides a configuration file to specify an evaluation job.
+
+    Input::
+        argsConfig - Path to a ConfigParser compliant file
+
+    Output::
+        Plots that visualize the evaluation job. These will be output to SETTINGS.workDir from the config file
+    """
+    
+    print 'Running using config file: %s' % argsConfig
+    # Parse the Config file
+    userConfig = ConfigParser.SafeConfigParser()
+    userConfig.optionxform = str # This is so the case is preserved on the items in the config file
+    userConfig.read(argsConfig)
+
+    try:
+        checkConfigSettings(userConfig)
+    except:
+        raise
+
+    jobProperties = generateSettings(userConfig.items('SETTINGS'))
+    workdir = jobProperties.workDir
+    
+    try:
+        gridBox = GridBox(jobProperties.latMin, jobProperties.lonMin, jobProperties.latMax,
+                          jobProperties.lonMax, jobProperties.gridLonStep, jobProperties.gridLatStep)
+    except:
+        gridBox = None
+
+    models = generateModels(userConfig.items('MODEL'))
+    
+    # 5/28/2013, JK: The RCMED block has been modified to accommodate ref data input from users' local disk
+
+    datasetDict = makeDatasetsDictionary(userConfig.items('RCMED'))
+
+
+    # Go get the parameter listing from the database
+    try:
+        params = db.get_parameters_metadata()
+    except:
+        raise
+
+    obsDatasetList = []
+    obsList = []
+    obsVarName = datasetDict['obsVarName'][0]
+    obsTimeName = datasetDict['obsTimeVar'][0]
+    obsLonName = datasetDict['obsLonVar'][0]
+    obsLatName = datasetDict['obsLatVar'][0]
+    obsTimestep = []
+    obsSource = int(datasetDict['obsSource'][0])
+    #print 'Obs datasetDict'
+    #print datasetDict
+
+    if obsSource < 0:                             # no obs data to be processed
+        obsVarName = []
+        obsTimeName = []
+        obsLonName = []
+        obsLatName = []
+    elif obsSource == 0:                          # input from RCMED
+        for param_id in datasetDict['obsParamId']:
+            for param in params:
+                if int(param['parameter_id']) == int(param_id):
+                    obsDatasetList.append(param)
+                else:
+                    pass
+    elif obsSource == 1:                        # input from local disk
+        for param in datasetDict['obsInputFile']:
+            obsDatasetList.append(param)
+        for param in datasetDict['obsFileName']:
+            obsList.append(param)
+        for param in datasetDict['obsDltaTime']:
+            obsTimestep.append(param)
+    #print obsSource,obsDatasetList,obsList,obsTimeName,obsTimestep
+
+    #TODO: Unhardcode this when we decided where this belongs in the Config File
+    jobProperties.maskOption = True
+    # User must provide startTime and endTime if not defined
+    if jobProperties.startDate == None or jobProperties.endDate == None:
+        jobProperties.startDate,jobProperties.endDate = misc.userDefinedStartEndTimes(obsSource,obsList,obsTimeName,obsDatasetList,models)
+
+    numOBS,numMDL,nT,ngrdY,ngrdX,Times,lons,lats,obsData,mdlData,obsName,mdlName,varType = do_data_prep.prep_data   \
+          (jobProperties,obsSource,obsDatasetList,obsList,obsVarName,obsLonName,obsLatName,obsTimeName,obsTimestep,gridBox,models)
+
+    # 6/3/2013: Combine the regridded reference and model datasets. The packing order is: 
+    #               First pack all ref (obs) data with the ref enseble in the end (if exists).
+    #               Then pack all model data with the model ensemble in the end (if exists)
+    #           Release 'obsData' and 'mdlData' after their values are transferred to 'allData'
+    print 'Input and regridding of both obs and model data are completed. Combine the obs and model data'
+    numDatasets = numOBS + numMDL
+    allData = ma.zeros((numDatasets, nT, ngrdY, ngrdX))
+    if (numOBS>0) & (numMDL>0):
+        dataName = obsName + mdlName
+        allData[0:numOBS, :, :, :] = obsData[0:numOBS, :, :, :]
+        allData[numOBS:numDatasets, :, :, :] = mdlData[0:numMDL, :, :, :]
+        obsData = 0.
+        mdlData = 0.
+    elif numOBS==0:
+        dataName = mdlName
+        allData = mdlData
+        mdlData = 0.
+    else:
+        dataName = obsName
+        allData = obsData
+        obsData = 0
+    print ''
+    print 'dataName: ',dataName,' shape of all data= ',allData.shape
+
+    ##################################################################################
+    # calculate metrics and make plots using the regridded reference and model data. #
+    ##################################################################################
+    print 'Data preparation is completed; now move to metrics calculations'
+    
+    try:
+        subRegionConfig = misc.configToDict(userConfig.items('SUB_REGION'))
+        subRegions = misc.parseSubRegions(subRegionConfig)
+        # REORDER SUBREGION OBJECTS until we standardize on Python 2.7
+        # TODO Remove once Python 2.7 support is finalized
+        if subRegions:
+            subRegions.sort(key=lambda x:x.name)
+        
+    except ConfigParser.NoSectionError:
+        
+        counts = {'observations': numOBS,
+                  'models'      : numMDL,
+                  'times'       : nT}
+        subRegions = misc.getSubRegionsInteractively(counts, workdir)
+        
+        if len(subRegions) == 0:
+            print 'Processing without SubRegion support'
+        
+
+    # TODO: New function Call
+    timeRegridOption = jobProperties.temporalGrid
+    fileOutputOption = jobProperties.writeOutFile
+    modelVarName = models[0].varName
+    metrics.metrics_plots(modelVarName, numOBS, numMDL, nT, ngrdY, ngrdX, Times, lons, lats, allData, dataName, workdir, subRegions, \
+                          timeRegridOption, fileOutputOption, varType)
+
+
+if __name__ == "__main__":
+    
+    if args.CONFIG:
+        
+        runUsingConfig(args.CONFIG)
+
+    else:
+        print 'Interactive mode has been enabled'
+        ui.rcmetUI()
+
+    #rcmet_cordexAF()

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/resources/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/resources/.svn/all-wcprops b/src/main/python/rcmes/resources/.svn/all-wcprops
new file mode 100755
index 0000000..b1b775d
--- /dev/null
+++ b/src/main/python/rcmes/resources/.svn/all-wcprops
@@ -0,0 +1,17 @@
+K 25
+svn:wc:ra_dav:version-url
+V 89
+/repos/asf/!svn/ver/1479720/incubator/climate/trunk/rcmet/src/main/python/rcmes/resources
+END
+cordexSubRegions.txt
+K 25
+svn:wc:ra_dav:version-url
+V 110
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/rcmes/resources/cordexSubRegions.txt
+END
+cordexAF.cfg
+K 25
+svn:wc:ra_dav:version-url
+V 102
+/repos/asf/!svn/ver/1479720/incubator/climate/trunk/rcmet/src/main/python/rcmes/resources/cordexAF.cfg
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/resources/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/resources/.svn/entries b/src/main/python/rcmes/resources/.svn/entries
new file mode 100755
index 0000000..71a5233
--- /dev/null
+++ b/src/main/python/rcmes/resources/.svn/entries
@@ -0,0 +1,99 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/python/rcmes/resources
+https://svn.apache.org/repos/asf
+
+
+
+2013-05-06T23:24:37.933090Z
+1479720
+huikyole
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+cordexSubRegions.txt
+file
+
+
+
+
+2013-05-24T10:13:50.000000Z
+b2e732c6fd18365a4a2ffdff8cde539c
+2013-01-25T19:56:01.681818Z
+1474794
+mjjoyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+928
+
+watersheds
+dir
+
+cordexAF.cfg
+file
+
+
+
+
+2013-05-24T10:13:50.000000Z
+914367b5c8e85cb405f1c5c548110445
+2013-05-06T23:24:37.933090Z
+1479720
+huikyole
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+956
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/resources/.svn/text-base/cordexAF.cfg.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/resources/.svn/text-base/cordexAF.cfg.svn-base b/src/main/python/rcmes/resources/.svn/text-base/cordexAF.cfg.svn-base
new file mode 100755
index 0000000..77ee0d5
--- /dev/null
+++ b/src/main/python/rcmes/resources/.svn/text-base/cordexAF.cfg.svn-base
@@ -0,0 +1,30 @@
+[SETTINGS]
+workDir=/home/huikyole/work/RCMES/cases/cordex-af
+cacheDir=/nas/share4-cf/huikyole/RCMES_cache
+# Choices: full, annual, monthly, daily
+temporalGrid=monthly
+# Choices, obs, model, user
+spatialGrid=model
+gridLonStep=0.44 ; only use with user spatialGrid
+gridLatStep=0.44 ; only use with user spatialGrid
+latMin=-45.76 ; only use with user spatialGrid
+latMax=42.24 ; only use with user spatialGrid
+lonMin=-24.64 ; only use with user spatialGrid
+lonMax=60.28 ; only use with user spatialGrid
+# Choices: False, NetCDF
+outputFile=NetCDF
+[MODEL]
+filenamePattern=/nas/share4-cf/jinwonki/data/cordex-af/*pr.nc
+latVariable=lat
+lonVariable=lon
+timeVariable=time
+varName=pr
+precipFlag=True ; This is just used to support an unknown UNITS in precip data
+
+[RCMED]
+obsParamId=36  ; pcp  and pr
+obsTimeStep=monthly ; WITH THE PARAMETER SERVICE THIS WILL GO AWAY
+
+[SUB_REGION]
+# Sub Region(s) Full File Path
+subRegionFile=../rcmes/resources/cordexSubRegions.txt

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/resources/.svn/text-base/cordexSubRegions.txt.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/resources/.svn/text-base/cordexSubRegions.txt.svn-base b/src/main/python/rcmes/resources/.svn/text-base/cordexSubRegions.txt.svn-base
new file mode 100755
index 0000000..c4dc220
--- /dev/null
+++ b/src/main/python/rcmes/resources/.svn/text-base/cordexSubRegions.txt.svn-base
@@ -0,0 +1,25 @@
+[REGIONS]
+# RegionXX:["region Label", north, south, east, west] >>> Region00:["Region Zero", 30.1, 10.54, 92.1332, -10.7 ]
+#TestRegion:["TEST", 27, 25, 15, 12]
+Region01:["R01", 36.5, 29, 0.0, -10]
+Region02:["R02", 37.5, 29, 10, 0]
+Region03:["R03", 32.5, 25, 20, 10]
+Region04:["R04", 32.5, 25, 33, 20]
+Region05:["R05", 20.0, 12, -10.2, -19.3]
+Region06:["R06", 25.0, 15.0, 30, 15]
+Region07:["R07", 15,   7.3, 10, -10]
+Region08:["R08", 7.3,  5.0, 10, -10]
+Region09:["R09", 15, 6.9, 40, 33.9]
+Region10:["R10", 11.8, 2.2, 51.8, 44.2]
+Region11:["R11", 10, 0, 25, 10]
+Region12:["R12", 0, -10, 25, 10]
+Region13:["R13", 0, -15, 40, 30]
+Region14:["R14", -21.4, -27.9, 20, 13.6]
+Region15:["R15", -27.9, -35, 20, 13.6]
+Region16:["R16", -21.4, -35, 35.7, 20]
+Region17:["R17", -11.7, -25.8, 50.3, 43.2]
+Region18:["R18", 35.0, 25, 40, 33]
+Region19:["R19", 35, 28, 50, 45]
+Region20:["R20", 20.0, 13, 50, 43]
+Region21:["R21", 27.5, 20, 58, 50]
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/resources/cordexAF.cfg
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/resources/cordexAF.cfg b/src/main/python/rcmes/resources/cordexAF.cfg
new file mode 100755
index 0000000..b26d279
--- /dev/null
+++ b/src/main/python/rcmes/resources/cordexAF.cfg
@@ -0,0 +1,55 @@
+# The configure file for the Indian subdomain of the CORDEX-Asia domain
+[SETTINGS]
+workDir=/Volumes/rcmes2t/rcmet/cases/cordex-af/work
+cacheDir=/Volumes/rcmes2t/rcmet/cases/cordex-af/cache
+# temporalGrid assigns the data time step to be temporally regridded: Choices = full (entire period), annual, monthly, daily
+temporalGrid=monthly
+# Choices, obs, model, user
+# gridLonStep, gridLatStep, latMin, latMax, lonMin, lonMax are used only with 'user' spatial grid option
+spatialGrid=user
+gridLonStep=0.44
+gridLatStep=0.44
+latMin=-45.76
+latMax=42.24
+lonMin=-24.64
+lonMax=60.28
+# Choices: False, NetCDF
+outputFile=False
+# variableType (reference units): 'precipitation' (mm/day); 'temperature' (K); 'cloudiness' (%), 'radiation' (W/m^2);
+#                                 'evaporation' (mm/day); 'runoff' (mm/day); 'SMC' (fraction)'; 'SWE' (mm); 'heatFlux' (W/m2)
+variableType=precipitation
+
+[MODEL]
+# The model data file(s) to be evaluated is(are) assinged here. Note that the current convention is for easy handling of
+#   multiple model datasets from coordinated experiments such as CORDEX that tend to assign a data file with a name that
+#   follows pre-determined convention (a combination of model name, institution, variable name, experiment name, etc.).
+#   In case only one model is evaluated, a user can specify the full file name for 'filenamePattern'
+#filenamePattern = none           # option currently not working; 2b added for obs-only processing
+filenamePattern=/Volumes/rcmes2t/rcmet/cases/cordex-af/mdlData/mon/*pr.nc
+latVariable=lat
+lonVariable=lon
+timeVariable=time
+varName=pr
+
+[RCMED]
+# obsParamId designates the reference data file. see http://rcmes.jpl.nasa.gov/rcmed/parameters
+# for multiple ref datasets, provide the id separated by ',' (e.g., 36,37 for TRMM and CRU3.1).
+# obsSource specifies the source of the reference data: 0 = RCMED, 1 = user's local disk, -9 = no obs data
+#   For obsSource == 1, obsInputFile, the file that provides the list of users' own reference data
+#                       also a user have to provide obsVarName, obsTimeVar, obsLonVar, and obsLatVar as specified in the data files
+obsSource = 0
+obsInputFile = /nas/share1-hp/jinwonki/data/rean/narr/day_narccap_domain/NARR_prec.nc,/nas/share1-hp/jinwonki/data/obs/cpc/netcdf/cpc_1979_present.nc
+obsVarName = pr,pr
+obsFileName = NARR,CPC
+obsDltaTime = daily,daily
+obsTimeVar = time,time
+obsLonVar = lon,longitude
+obsLatVar = lat,latitude
+# if obsSource = 0, the lines from 'obsSource' to 'obsLatVar' above are inactive
+# 36= TRMM monthly, 37= CRU3.1 monthly, 72= UDEL monthly; 74= GPCP2.2 monthly; 81=GPCC
+obsParamId=37,72,81,36,74
+obsTimeStep=monthly,monthly,monthly,monthly,monthly ; WITH THE PARAMETER SERVICE THIS WILL GO AWAY
+
+[SUB_REGION]
+# Sub Region(s) Full File Path
+subRegionFile=/Volumes/rcmes2t/rcmet/cases/cordex-af/work/inputs/subRgns.AF

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/resources/cordexIndia.cfg
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/resources/cordexIndia.cfg b/src/main/python/rcmes/resources/cordexIndia.cfg
new file mode 100755
index 0000000..d63beaf
--- /dev/null
+++ b/src/main/python/rcmes/resources/cordexIndia.cfg
@@ -0,0 +1,56 @@
+# The configure file for the Indian subdomain of the CORDEX-Asia domain
+[SETTINGS]
+workDir=/Volumes/rcmes2t/rcmet/cases/cordex-sa/work
+cacheDir=/Volumes/rcmes2t/rcmet/cases/cordex-sa/cache
+# temporalGrid assigns the data time step to be temporally regridded: Choices = full (entire period), annual, monthly, daily
+temporalGrid=monthly
+# Choices, obs, model, user
+# gridLonStep, gridLatStep, latMin, latMax, lonMin, lonMax are used only with 'user' spatial grid option
+spatialGrid=user
+gridLonStep=0.5
+gridLatStep=0.5
+latMin=5.
+latMax=40.
+lonMin=60.
+lonMax=100.
+# Choices: False, NetCDF
+outputFile=False
+# variableType (reference units): 'precipitation' (mm/day); 'temperature' (K); 'cloudiness' (%), 'radiation' (W/m^2);
+#                                 'evaporation' (mm/day); 'runoff' (mm/day); 'SMC' (fraction)'; 'SWE' (mm); 'heatFlux' (W/m2)
+variableType=precipitation
+
+[MODEL]
+# The model data file(s) to be evaluated is(are) assinged here. Note that the current convention is for easy handling of
+#   multiple model datasets from coordinated experiments such as CORDEX that tend to assign a data file with a name that
+#   follows pre-determined convention (a combination of model name, institution, variable name, experiment name, etc.).
+#   In case only one model is evaluated, a user can specify the full file name for 'filenamePattern'
+#filenamePattern = none           # option currently not working; 2b added for obs-only processing
+filenamePattern=/Volumes/rcmes2t/rcmet/cases/cordex-sa/mdlData/mon/pr*.nc
+latVariable=lat
+lonVariable=lon
+timeVariable=time
+varName=pr
+
+[RCMED]
+# obsParamId designates the reference data file. see http://rcmes.jpl.nasa.gov/rcmed/parameters
+# for multiple ref datasets, provide the id separated by ',' (e.g., 36,37 for TRMM and CRU3.1).
+# obsSource specifies the source of the reference data: 0 = RCMED, 1 = user's local disk, -9 = no obs data
+#   For obsSource == 1, obsInputFile, the file that provides the list of users' own reference data
+#                       also a user have to provide obsVarName, obsTimeVar, obsLonVar, and obsLatVar as specified in the data files
+obsSource = 0
+obsInputFile = /nas/share1-hp/jinwonki/data/rean/narr/day_narccap_domain/NARR_prec.nc,/nas/share1-hp/jinwonki/data/obs/cpc/netcdf/cpc_1979_present.nc
+obsVarName = pr,pr
+obsFileName = NARR,CPC
+obsDltaTime = daily,daily
+obsTimeVar = time,time
+obsLonVar = lon,longitude
+obsLatVar = lat,latitude
+# if obsSource = 0, the lines from 'obsSource' to 'obsLatVar' above are inactive
+# 36= TRMM monthly, 37= CRU3.1 monthly, 72= UDEL monthly; 74= GPCP2.2 monthly; 80= aphr1101
+obsParamId=37,80,81,36,74
+obsTimeStep=monthly,monthly,monthly,monthly ; WITH THE PARAMETER SERVICE THIS WILL GO AWAY
+
+[SUB_REGION]
+# Sub Region(s) Full File Path
+#subRegionFile=/nas/share3-wf/jinwonki/rcmet/cases/cordex-sa/work/inputs/subRgnsSA.India
+subRegionFile=/Volumes/rcmes2t/rcmet/cases/cordex-sa/work/inputs/subRgnsSA.India

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/resources/narccap.cfg
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/resources/narccap.cfg b/src/main/python/rcmes/resources/narccap.cfg
new file mode 100755
index 0000000..f0f3b50
--- /dev/null
+++ b/src/main/python/rcmes/resources/narccap.cfg
@@ -0,0 +1,55 @@
+[SETTINGS]
+workDir=/Volumes/rcmes2t/rcmet/cases/narccap/work
+cacheDir=/Volumes/rcmes2t/rcmet/cases/narccap/cache
+# temporalGrid assigns the data time step to be temporally regridded: Choices = full (entire period), annual, monthly, daily
+temporalGrid=monthly
+# Choices, obs, model, user
+# gridLonStep, gridLatStep, latMin, latMax, lonMin, lonMax are used only with 'user' spatial grid option
+spatialGrid=user
+gridLonStep=0.5
+gridLatStep=0.5
+latMin=23.75            ; for NARCCAP-ConterminousUS / WUS
+latMax=49.75            ; for NARCCAP-ConterminousUS / WUS
+lonMin=-125.75          ; for NARCCAP-ConterminousUS / WUS
+lonMax=-66.75           ; for NARCCAP-Conterminous US
+#lonMax=-100.75          ; for NARCCAP-WUS.
+# Choices: False, NetCDF
+outputFile=NetCDF
+# variableType (reference units): 'precipitation' (mm/day); 'temperature' (K); 'cloudiness' (%), 'radiation' (W/m^2);
+#                                 'evaporation' (mm/day); 'runoff' (mm/day); 'SMC' (fraction)'; 'SWE' (mm); 'heatFlux' (W/m2)
+variableType=precipitation
+
+[MODEL]
+# The model data file(s) to be evaluated is(are) assinged here. Note that the current convention is for easy handling of
+#   multiple model datasets from coordinated experiments such as CORDEX that tend to assign a data file with a name that
+#   follows pre-determined convention (a combination of model name, institution, variable name, experiment name, etc.).
+#   In case only one model is evaluated, a user can specify the full file name for 'filenamePattern'
+#filenamePattern = none           # option currently not working; 2b added for obs-only processing
+filenamePattern=/Volumes/rcmes2t/rcmet/cases/narccap/mdlData/mon/prec*.nc
+latVariable=lat
+lonVariable=lon
+timeVariable=time
+varName=prec
+#variableType=precipitation
+
+[RCMED]
+# obsParamId designates the reference data file. see http://rcmes.jpl.nasa.gov/rcmed/parameters
+# for multiple ref datasets, provide the id separated by ',' (e.g., 36,37 for TRMM and CRU3.1).
+# obsSource specifies the source of the reference data: 0 = RCMED, 1 = user's local disk, -9 = no obs data
+#   For obsSource == 1, obsInputFile, the file that provides the list of users' own reference data
+obsSource = 0
+obsInputFile = /nas/share1-hp/jinwonki/data/rean/narr/day_narccap_domain/NARR_prec.nc,/nas/share1-hp/jinwonki/data/obs/cpc/netcdf/cpc_1979_present.nc
+obsVarName = pr,pr
+obsFileName = NARR,CPC
+obsDltaTime = daily,daily
+obsTimeVar = time,time
+obsLonVar = lon,longitude
+obsLatVar = lat,latitude
+# if obsSource = 0, the lines from 'obsSource' to 'obsLatVar' above are inactive
+#obsParamId=37,72,81,36,74
+obsParamId=37,36
+obsTimeStep=monthly,monthly,monthly,monthly,monthly ; WITH THE PARAMETER SERVICE THIS WILL GO AWAY
+
+[SUB_REGION]
+# Sub Region(s) Full File Path
+subRegionFile=/Volumes/rcmes2t/rcmet/cases/narccap/work/inputs/subRgnsNARCCAP.US

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/all-wcprops
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/all-wcprops b/src/main/python/rcmes/services/.svn/all-wcprops
new file mode 100755
index 0000000..3cd9eb6
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/all-wcprops
@@ -0,0 +1,71 @@
+K 25
+svn:wc:ra_dav:version-url
+V 88
+/repos/asf/!svn/ver/1482547/incubator/climate/trunk/rcmet/src/main/python/rcmes/services
+END
+run_rcmes_processing.py
+K 25
+svn:wc:ra_dav:version-url
+V 112
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/run_rcmes_processing.py
+END
+list_vars_in_file.py
+K 25
+svn:wc:ra_dav:version-url
+V 109
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/list_vars_in_file.py
+END
+main_ws.py
+K 25
+svn:wc:ra_dav:version-url
+V 99
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/main_ws.py
+END
+__init__.py
+K 25
+svn:wc:ra_dav:version-url
+V 100
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/__init__.py
+END
+bottlemet.py
+K 25
+svn:wc:ra_dav:version-url
+V 101
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/bottlemet.py
+END
+find_latlon_var.py
+K 25
+svn:wc:ra_dav:version-url
+V 107
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/find_latlon_var.py
+END
+README.txt
+K 25
+svn:wc:ra_dav:version-url
+V 99
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/README.txt
+END
+decode_model_times.py
+K 25
+svn:wc:ra_dav:version-url
+V 110
+/repos/asf/!svn/ver/1476460/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/decode_model_times.py
+END
+directory_helpers.py
+K 25
+svn:wc:ra_dav:version-url
+V 109
+/repos/asf/!svn/ver/1482547/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/directory_helpers.py
+END
+find_time_var.py
+K 25
+svn:wc:ra_dav:version-url
+V 105
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/find_time_var.py
+END
+dataset_helpers.py
+K 25
+svn:wc:ra_dav:version-url
+V 107
+/repos/asf/!svn/ver/1480068/incubator/climate/trunk/rcmet/src/main/python/rcmes/services/dataset_helpers.py
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/entries
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/entries b/src/main/python/rcmes/services/.svn/entries
new file mode 100755
index 0000000..b34041c
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/entries
@@ -0,0 +1,402 @@
+10
+
+dir
+1485921
+https://svn.apache.org/repos/asf/incubator/climate/trunk/rcmet/src/main/python/rcmes/services
+https://svn.apache.org/repos/asf
+
+
+
+2013-05-14T20:07:57.184268Z
+1482547
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13f79535-47bb-0310-9956-ffa450edef68
+
+run_rcmes_processing.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+b72b173d9a8423c2ecc3ff915009717f
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4914
+
+list_vars_in_file.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+2a2cd6269710cf6136c3b026713a63fb
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1548
+
+main_ws.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+f6aaf93ae28329a6a6c75d074ce69bf5
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+889
+
+__init__.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+5c7b875cde03a6b682cc84a7858fd5dc
+2012-08-16T14:19:38.500472Z
+1473885
+cgoodale
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+132
+
+bottlemet.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+6f5737a819d82d8c0cd574d6195acdbf
+2013-02-20T17:07:53.256865Z
+1474978
+cgoodale
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+21280
+
+find_latlon_var.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+aa30bfb54cacbfb99ac263ae42ab32da
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4154
+
+README.txt
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+dcf5694caba89c7989ff1e86fd9ea14b
+2012-08-14T20:33:03.986567Z
+1473860
+pramirez
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1854
+
+decode_model_times.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+52b776bfd8845a4830659cb09779af9b
+2013-03-05T16:19:20.432667Z
+1475039
+mjjoyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4817
+
+directory_helpers.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+22a41a483c4a806e3ef7dd8c17364e2e
+2013-05-14T20:07:57.184268Z
+1482547
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1260
+
+find_time_var.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+addf1ca2427854ece4e5cbdaf1920e3b
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2882
+
+dataset_helpers.py
+file
+
+
+
+
+2013-05-24T10:13:49.000000Z
+69f9dd2f04b3b8e171e9b5593c076203
+2013-05-07T20:50:17.582309Z
+1480068
+joyce
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+834
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/prop-base/__init__.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/prop-base/__init__.py.svn-base b/src/main/python/rcmes/services/.svn/prop-base/__init__.py.svn-base
new file mode 100755
index 0000000..614166f
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/prop-base/__init__.py.svn-base
@@ -0,0 +1,5 @@
+K 12
+svn:keywords
+V 11
+Id Revision
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/prop-base/decode_model_times.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/prop-base/decode_model_times.py.svn-base b/src/main/python/rcmes/services/.svn/prop-base/decode_model_times.py.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/prop-base/decode_model_times.py.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/prop-base/find_latlon_var.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/prop-base/find_latlon_var.py.svn-base b/src/main/python/rcmes/services/.svn/prop-base/find_latlon_var.py.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/prop-base/find_latlon_var.py.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/prop-base/find_time_var.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/prop-base/find_time_var.py.svn-base b/src/main/python/rcmes/services/.svn/prop-base/find_time_var.py.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/prop-base/find_time_var.py.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/prop-base/list_vars_in_file.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/prop-base/list_vars_in_file.py.svn-base b/src/main/python/rcmes/services/.svn/prop-base/list_vars_in_file.py.svn-base
new file mode 100755
index 0000000..869ac71
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/prop-base/list_vars_in_file.py.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/README.txt.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/README.txt.svn-base b/src/main/python/rcmes/services/.svn/text-base/README.txt.svn-base
new file mode 100755
index 0000000..27622ab
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/README.txt.svn-base
@@ -0,0 +1,68 @@
+RCMET Client API Web Service README
+===========================================================
+
+Prerequisites:
+
+ * Python 2.6+ with easy_install
+ * Bottle (http://bottlepy.org) Web Framework 
+
+Usage:
+
+ ./python main_ws.py
+
+
+Hints:
+
+  Changing the port Bottle runs on
+  --------------------------------
+  The port Bottle starts up on can be changed by editing
+  the last line in the ./main_ws.py file as follows:
+
+  if __name__ == "__main__":
+    run(host='localhost', port=*NEWPORT*)
+
+
+API Documentation:
+=================================================================
+
+Extract Model File Variables
+--------------------------------
+http://<webserviceUrl>/list/vars/"<PATH>"
+
+  INPUTS: 
+    PATH: the fully qualified path to the model file to use. Note 
+          that the path must be enclosed in double quotes.
+
+  RETURN:
+    SUCCESS: {"variables": ["tas", "level", "lon", "time", "lat"]}
+    FAILURE: []   <-- should probably be {}
+
+
+Extract Model Latitude and Longitude Variables and Bounds
+---------------------------------------------------------
+http://<webserviceUrl>/list/latlon/"<PATH>"
+
+  INPUTS: 
+    PATH: the fully qualified path to the model file to use. Note 
+    	  that the path must be enclosed in double quotes.
+
+  RETURN:
+    SUCCESS: {"latMax": "42.24", "success": 1, "latname": "lat", 
+              "lonMax": "60.28", "lonMin": "-24.64", 
+	      "lonname": "lon", "latMin": "-45.76"}
+    FAILURE: ?
+
+
+Extract Model Time Variable and Bounds
+--------------------------------------
+http://<webserviceUrl>/list/time/"<PATH>"
+
+  INPUTS: 
+    PATH: the fully qualified path to the model file to use. Note 
+          that the path must be enclosed in double quotes.
+
+  RETURN:
+    SUCCESS:  {"start_time": "1989-01-15 00:00:00", 
+    	       "timename": "time", "success": 1, 
+	       "end_time": "2008-12-15 00:00:00"}
+    FAILURE: ?

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/__init__.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/__init__.py.svn-base b/src/main/python/rcmes/services/.svn/text-base/__init__.py.svn-base
new file mode 100755
index 0000000..9a00597
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/__init__.py.svn-base
@@ -0,0 +1,2 @@
+"""The Services Package is a collection of RESTful Web Service modules that can
+be used to create custom User Interfaces to RCMES"""
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/bottlemet.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/bottlemet.py.svn-base b/src/main/python/rcmes/services/.svn/text-base/bottlemet.py.svn-base
new file mode 100755
index 0000000..0bcefb8
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/bottlemet.py.svn-base
@@ -0,0 +1,599 @@
+'''
+ Module to create a web service for RCMET statistical metrics
+'''
+
+
+
+
+##########################################################################################
+#setting up bottle and importing metrics
+##########################################################################################
+
+#sets up bottle and necessary methods.
+from bottle import route, run, post, request, redirect, debug 
+
+#temporary quick-fix to track errors, not for publication 
+debug(True)
+
+#imports pickle
+import pickle
+
+#imports metrics from RCMET
+import rcmes.metrics as mtx
+
+
+
+
+##########################################################################################
+#error-catching dictionaries 
+##########################################################################################
+
+#dictionary of MetricNames and their number of variables. Useful later on
+HowManyVariables={
+	"calc_stdev" :1,
+	"calc_annual_cycle_means" : 2,
+	"calc_annual_cycle_std" : 2,
+	"calc_annual_cycle_domain_means" : 2,
+	"calc_annual_cycle_domain_std" : 2,
+	"calc_bias" : 2,
+	"calc_bias_dom" : 2,
+	"calc_difference" : 2,
+	"calc_mae" : 2,
+	"calc_mae_dom" :2,
+	"calc_rms" : 2,
+	"calc_rms_dom" : 2,
+	"calc_temporal_pat_cor" : 2,
+	"calc_pat_cor" : 2,
+	"calc_nash_sutcliff" : 2,
+	"calc_pdf" : 2,
+	"calc_anom_corn" : 3
+}		
+	
+#dictionary of metric names and the names of their variables.
+NameOfVariables={
+	"calc_stdev":['t1'],
+	"calc_annual_cycle_means" :['data','time'],
+	"calc_annual_cycle_std" :['data','time'],
+	"calc_annual_cycle_domain_means" :['data','time'],
+	"calc_annual_cycle_domain_std" :['data','time'],
+	"calc_bias" :['t1','t2'],
+	"calc_bias_dom" :['t1','t2'],
+	"calc_difference" :['t1','t2'], 
+	"calc_mae" :['t1','t2'],
+	"calc_mae_dom" : ['t1','t2'],
+	"calc_rms" :['t1','t2'],
+	"calc_rms_dom" :['t1','t2'],
+	"calc_temporal_pat_cor" :['t1','t2'],
+	"calc_pat_cor" :['t1','t2'],
+	"calc_nash_sutcliff" :['t1','t2'],
+	"calc_pdf" :['t1','t2'],
+	"calc_anom_corn" :['t1','t2','t4']
+}				
+
+#two lists that will help with user explanation later
+
+ArrayNames=[]	   
+
+ListOfArrays=[]
+	
+	
+	
+##########################################################################################
+
+#Running the metrics through interactive web pages
+
+##########################################################################################
+
+
+
+##########################################################################################
+#First parts: introduction and identification of user's needs
+##########################################################################################
+
+#basic first page. Explanation could be more comprehensive
+@route('/rcmet/metrics/online')	
+def ShowPossibleMetrics():
+	'''
+	Returns a page in html that allows the user to select a metric through links
+	'''
+	return '''<html>
+		<head> RCMET Metrics through Bottle </head>
+		<body>
+		<p>Please select the metric you will use.</p>
+		
+		<p> Metrics with one variable: 
+		<a href='/rcmet/metrics/online/calc_stdev'>"calc_stdev" to return standard deviation</a>
+		</p>
+	
+		<p> Metrics with two variables: 
+		<a href='/rcmet/metrics/online/calc_annual_cycle_means'>"calc_annual_cycle_means" to return monthly means</a>
+		<a href='/rcmet/metrics/online/calc_annual_cycle_std'>""calc_annual_cycle_std" to return monthly standard deviation</a>  
+		<a href='/rcmet/metrics/online/calc_annual_cycle_domain_means'>"calc_annual_cycle_domain_ means" to return monthly 
+		domain means</a>   
+		<a href='/rcmet/metrics/online/calc_annual_cycle_domain_std'>"calc_annual_cycle_domain_std" to return monthly standard 
+		deviation</a>	
+		<a href='/rcmet/metrics/online/calc_bias'>"calc_bias" to return mean difference</a>	
+		<a href='/rcmet/metrics/online/calc_bias_dom'>"calc_bias_dom" to return domain mean difference</a>	 
+		<a href='/rcmet/metrics/online/calc_difference'>"calc_difference" to return difference</a>
+		<a href='/rcmet/metrics/online/calc_mae'>"calc_mae" to return mean absolute error</a>	
+		<a href='/rcmet/metrics/online/calc_mae_dom'>"calc_mae_dom" to return domain mean difference over time</a>
+		<a href='/rcmet/metrics/online/calc_rms'>"calc_rms" to return root mean square error
+		</a>	
+		<a href='/rcmet/metrics/online/calc_rms_dom'>"calc_rms_dom" to return domain root mean square error</a>	
+		<a href='/rcmet/metrics/online/calc_temporal_pat_cor'>"calc_temporal_pat_cor" to return temporal pattern correlation</a>
+		<a href='/rcmet/metrics/online/calc_pat_cor'>"calc_pat_cor" to return pattern correlation</a>
+		<a href='/rcmet/metrics/online/calc_nash_sutcliff'>"calc_nash_sutcliff" to return Nash-Sutcliff coefficient of 
+		efficiency</a>
+		<a href='/rcmet/metrics/online/calc_pdf'>"calc_pdf" to return probability distribution function</a>
+		
+		<p> Metrics with three variables:
+		<a href='/rcmet/metrics/online/calc_anom_corn'>"calc_anom_corn" to return anomaly correlation</a> </p>
+		</body>
+		<html>'''
+
+#creates introductory page to explain how to use bottle
+@route('/rcmet/metrics/online/<MetricNameHere>')
+def VariableSubmission(MetricNameHere):
+	'''
+	Returns a page in html that allows the user to choose between submitting variables on the command line or searching 
+	RCMED
+	'''	  
+	
+	global MetricName
+	
+	MetricName=MetricNameHere
+	
+	if MetricName in HowManyVariables:
+		return "For metric %s , you need %d variable(s), which will represent: %s" %(MetricName, 
+			HowManyVariables[MetricName], NameOfVariables[MetricName][:]), '''<html>
+			<body>
+			<p>Will you enter variables (which are arrays) through the command line or 
+			will you search the RCMES Database?</p>
+			<a href="/rcmet/metrics/online/commandline">command line</a>
+			<a href="/rcmet/metrics/online/rcmed">RCMED</a>
+			</body>
+			</html>''',
+			'''<a href='/rcmet/metrics/online/methods'>Run Methods</a>'''
+	
+	else:
+		return "The metric you entered doesn't exist."
+
+
+##########################################################################################
+#getting arrays through the command line
+##########################################################################################
+
+#Tells the user how to send variables from the command line
+@route('/rcmet/metrics/online/commandline')
+def ArraysFromCommandLine():
+	'''
+	Explains to the user how to submit a variable through POST on the command line
+	'''
+	if HowManyVariables[MetricName]-count<=0:
+		print "You have already submitted all the needed variables for this metric."
+		redirect('/rcmet/metrics/online/calculate')
+	else:
+		return "Please use your command line to POST a form with the array. Send either a pickled file or serialized ",
+		"string. Name the form: array. Include also, a form that describes/names the array. Call this form: name. A ",
+		"sample would be array=array_here and name=array_name_here. Send the form to: ",
+		"http://.../rcmet/metrics/<metric_name>/commandline. Once the computer receives all variables, you may ", 
+		"move on to the metrics portion of the website. Currently, you have submitted %d variable(s) and need %d ",
+		"more. The next variable you submit will represent the variable %s in %s" %(count, 
+		(HowManyVariables[MetricName]-count),NameOfVariables[MetricName][count], MetricName)
+	
+#this function	gets the array from the command line
+@route('/rcmet/metrics/online/commandline', method='POST') 
+def ReceivingArrays():
+	'''
+	Uses the POST method to retrieve any arrays sent by the user, and proceed to deserialize them. Also adds each
+	variable to the appropriate list, and proceeds to offer the user the option to add more variables or else move
+	on to calculating the value of the metric;
+	'''
+		
+	try:
+		BottleMetrics.GetVariablesFromCommandLine()
+			
+		return "Variable received as %s. Will represent %s" % (ArrayNames[count-1], 
+		NameOfVariables[MetricName][count-1]), "Submit more variables?",
+		'''<a href='/rcmet/metrics/online/rcmed'>Online</a>''',
+		'''<a href='/rcmet/metrics/online/commandline'>Command Line</a>''',
+		'''<a href='/rcmet/metrics/online/calculate'>No More Variables</a>''',
+		'''<a href='/rcmet/metrics/online/methods'>Run Methods</a>'''
+	
+	except pickle.UnpicklingError:
+		return "This object cannot be unpickled. Send only a file or serialized string.",
+		'''<a href='/rcmet/metrics/online/commandline'>Re-submit Variable</a>''',
+		'''<a href='/rcmet/metrics/online/methods'>Run Methods</a>'''
+		
+
+##########################################################################################
+#getting variables through RCMED
+##########################################################################################
+
+#explains how to enter information into a dynamic link
+@route('/rcmet/metrics/online/rcmed')
+def QueryRcmed():
+	'''
+	Returns a page in html that explains to the user how to search RCMED for the desired arrays, and offers the
+	user multiple forms in which to enter search parameters
+	'''
+	
+	#I was unclear what type the dataset ID and paramID were supposed to be. This may need to change
+	
+	return "Currently, you have submitted %d variable(s) and need %d more. The next"\
+	" variable you submit will represent the variable %s in %s" %(count, 
+	(HowManyVariables[MetricName]-count),NameOfVariables[MetricName][count], MetricName),'''<html>
+	<head> Query RCMED for Array Data </head>
+	<body>
+	<p>Enter the parameters into the appropriate boxes.</p>
+	<form method="POST">
+		<p>Dataset ID</p>
+		<input name="datasetID"	 type="string" />
+		<p>Parameter ID</p>
+		<input name="paramID"	 type="string" />
+		<p>latMin, float</p>
+		<input name="latMin"	 type="float" />
+		<p>latMax, float</p>
+		<input name="latMax"	 type="float" />
+		<p>lonMin, float</p>
+		<input name="lonMin"	 type="float" />
+		<p>lonMax, float</p>
+		<input name="lonMax"	 type="float" />
+		<p>startTime, datetime object</p>
+		<input name="startTime"	 type="datetime" />
+		<p>endTime, datetime object</p>
+		<input name="endTime"	 type="datetime" />
+		<p>cachedir, string</p>
+		<input name="cachedir"	 type="string" />
+		<p>Array Name, string</p>
+		<input name="ArrayName"	 type="string" />
+		<input type="Submit" /> </form>
+	</body>
+	</html>''' 
+	
+	
+@route('/rcmet/metrics/online/rcmed', method='POST')
+def GetVariablesFromDatabase():
+	'''
+	Gets data from forms, searches the database, processes the variables, and prompts the user to submit more.
+	'''
+	BottleMetrics.GetVariablesFromRcmed()	 
+
+
+	return "Submit more variables?",'''<a href='/rcmet/metrics/online/rcmed'>Online</a>''',
+	'''<a href='/rcmet/metrics/online/commandline'>Command Line</a>''',
+	'''<a href='/rcmet/metrics/online/calculate'>No More Variables</a>''',
+	'''<a href='/rcmet/metrics/online/methods'>Run Methods</a>'''
+
+
+##########################################################################################
+#running the metrics online
+##########################################################################################
+
+#this function actually runs the metrics
+@route('/rcmet/metrics/online/calculate')
+def Calculate(MetricName):
+	'''
+	Uses variables from the lists to return the answer for the metric. Also returns a brief description of the metric performed. 
+	'''
+		
+	if HowManyVariables[MetricName]<count:
+		return "You have too few variables to run this metric.",'''<a href='/rcmet/metrics/online/commandline'>Command Line</a>,
+		<a href='/rcmet/metrics/online/rcmed'>Online</a>''','''<a href='/rcmet/metrics/online/methods'>Run Methods</a>'''
+	
+	else:
+		return BottleMetrics.ExplainMetric(), str(result), '''<a href='/rcmet/metrics/online/methods'>Run Methods</a>''',
+		'''<a href='/rcmet/metrics/online'>Start Over</a>'''
+			
+	
+	'''<a href='/rcmet/metrics/online/methods'>Run Methods</a>'''
+	
+@route('/rcmet/metrics/online/methods')
+def ChooseMethodOnline():
+	'''
+	Allows an online user to access any method in the class
+	'''
+	
+	return "Which method?", '''<html>
+	<a href='/rcmet/metrics/online/methods/Status'>Status</a>
+	<a href='/rcmet/metrics/online/methods/ExplainMetric'>ExplainMetric</a>
+	<a href='/rcmet/metrics/online/methods/VariableCount'>VariableCount</a>
+	<a href='/rcmet/metrics/online/methods/ReturnResult'>ReturnResult</a>
+	<a href='/rcmet/metrics/online/methods/CleanUp'>CleanUp</a>'''
+	
+@route('/rcmet/metrics/online/methods/<MethodName>)
+def RunMethodOnline(MethodName):
+	'''
+	Runs any method in class MetricWebService() chosen by an online user
+	'''
+		
+	MetricWebServiceMethod=getattr(BottleMetrics, MethodName)
+	
+	return BottleMetrics.MetricWebServiceMethod(), '''<a href='/rcmet/metrics/online'>Back to Beginning</a>'''
+	
+
+##########################################################################################	
+##########################################################################################
+
+#creating a class for the Web Service 
+
+##########################################################################################
+##########################################################################################
+
+class MetricWebService(object):
+	'''
+	Class containing all of the necessary functions to find, process, and use the variables to run metrics. Also allows
+	the user to see the state of the metric, i.e. how many variables have been entered. 
+	'''
+		
+	def __init__(self):
+
+		global count
+		count=0
+
+##########################################################################################
+
+	def Status(self):
+		'''
+		Provides a standardized system for showing how many variables are submitted, allowing the user to 
+		check their progress 
+		'''
+		print "For metric %s , you need %d variable(s): %s. Currently, you have submitted "\
+		"%d variable(s) and need %d more. The values you have submitted, %s, will represent %s respectively." 
+		%(MetricName, HowManyVariables[MetricName], NameOfVariables[MetricName][:], count, 
+		(HowManyVariables[MetricName]-count),ArrayNames[:],NameOfVariables[MetricName][:])
+		
+		return "For metric %s , you need %d variable(s): %s. Currently, you have submitted "\
+		"%d variable(s) and need %d more. The values you have submitted, %s, will represent %s respectively." 
+		%(MetricName, HowManyVariables[MetricName], NameOfVariables[MetricName][:], count, 
+		(HowManyVariables[MetricName]-count),ArrayNames[:],NameOfVariables[MetricName][:])
+		
+##########################################################################################
+
+	def ExplainMetric(self):
+		'''
+		Provides a standardized means of returning a metric's docstring and thus describing the metric
+		'''
+		method=getattr(mt, MetricName)
+
+		print method.__doc__
+
+		return method.__doc__
+##########################################################################################
+
+	def VariableCount(self):
+		'''
+		Determines how many variables have been submitted, and if the right number has, this function runs the RunMetrics() method
+		'''
+			
+		if HowManyVariables[MetricName]-count>0:
+		
+			print "Please add more variables"
+			
+			return "Please add more variables"
+					
+		if HowManyVariables[MetricName]-count<0:
+			print "You have added too many variables"
+			
+			return "Please add more variabels"
+			
+		else:
+			print "You have added all necessary metrics. The program will now run your metric."
+			
+			self.RunMetrics()
+			
+
+##########################################################################################
+	
+	def ProcessVariables(self, array, ArrayName):	
+		'''
+		adds the variables posted by the user to the appropriate lists, raises count to indicate this addition, and
+		starts VariableCount()
+		'''			
+		ListOfArrays.append(array)
+		ArrayNames.append(ArrayName)
+			
+		global count
+		count=count+1
+			
+		print "Variable received as %s. Will represent %s" % (ArrayName, 
+		NameOfVariables[MetricName][count-1])
+			
+		self.VariableCount()
+		
+##########################################################################################
+
+	def GetVariablesFromCommandLine(self):	
+		'''
+		Gets array and array name from forms, deserializes them with unpickle, and runs ProcessVariables()
+		'''	
+		
+		if HowManyVariables[MetricName]-count>0:
+			array=request.forms.get('array')
+			ArrayName=request.forms.get('name')
+			
+			if type(array)==str:
+				array=pickle.loads(array)	   
+			
+			else:
+				array=pickle.load(array)
+		
+			self.ProcessVariables(array, ArrayName)
+		
+		else:
+			self.VariableCount()
+	
+##########################################################################################
+	
+	def GetVariablesFromRcmed(self):	
+		'''
+		Gets search parameters from forms, runs a search of RCMED, and returns the array mdata
+		'''
+		
+		if HowManyVariables[MetricName]-count>0:
+		
+			import rcmes.db as db
+	
+			datasetID=request.forms.get('datasetID')
+			paramID=request.forms.get('paramID')
+			latMin=request.forms.get('latMin')
+			latMax=request.forms.get('latMax')
+			lonMin=request.forms.get('lonMin')
+			lonMax=request.forms.get('lonMax')
+			startTime=request.forms.get('startTime')
+			endTime=request.forms.get('endTime')
+			cachedir=request.forms.get('cachedir')
+	
+			ArrayName=request.forms.get('name')				
+					
+			try:
+			
+				db.extract_data_from_db(datasetID, paramID, latMin, latMax, lonMin, lonMax, startTime, endTime, cachedir)
+				
+				#I don't think this will work
+				array=mdata
+				
+				self.ProcessVariables(array,ArrayName)
+										
+			except TypeError:
+				print "One of your variables was not entered in the correct format or was not entered at all"
+			
+		else:
+			self.VariableCount()	
+			
+##########################################################################################
+	
+	def GetVariables(self):
+		'''
+		Runs two links that connect with functions meant to handle the variables posted to the links
+		'''
+####################
+		
+		@route('/rcmet/metrics/get/variables/commandline', method='POST') 
+		def VariablesPostedToCommandline():
+			'''
+			runs the method GetVariablesFromCommandLine() at the URL, allowing the user to post their forms to this url and have
+			them handled by GetVariablesFromCommandLine().
+			'''
+			
+			try:
+				self.GetVariablesFromCommandLine()
+					
+			except pickle.UnpicklingError:
+				print "This object cannot be unpickled. Send only a file or serialized string."
+	
+
+####################
+
+		@route('/rcmet/metrics/get/variables/rcmed', method='POST')
+		def GetVariablesFromRCMED(self):
+			'''
+			runs the method GetVariablesFromRcmed() at the URL, allowing the user to post their forms to this url and have
+			them handled by GetVariablesFromRcmed().
+			'''
+			
+			self.GetVariablesFromRcmed()	 
+				
+##########################################################################################
+				
+	def RunMetrics(self):
+		'''
+		Calls to metrics.py and runs the desired metric using variables submitted by the user. Returns a string of the 
+		value returned by the metric
+		'''
+		
+		print "Running metric"	
+		  
+		method=getattr(mtx, MetricName)
+	
+		global result
+	
+		if HowManyVariables[MetricName]==1:
+			result=method(ListOfArrays[0])
+			
+		if HowManyVariables[MetricName]==2:
+			result=method(ListOfArrays[0], ListOfArrays[1])
+				
+		if HowManyVariables[MetricName]==3:
+			result=method(ListOfArrays[0], ListOfArrays[1], ListOfArrays[2])
+		
+##########################################################################################
+		
+	@route('/rcmet/metrics/commandline/return/result')
+	def ReturnResult():
+		'''
+		links the result to a uri from which the user can easily fetch it. Note, the result is returned as a string
+		'''	
+	#If the result of the metrics is an array, I would recommend including a provision in 
+	#ReturnResult() that pickles or somehow serializes the result, and then, upon getting 
+	#the pickled string from the URL, the user could unpickle it and use it as an array. 	
+	
+		return str(result)
+		
+##########################################################################################
+
+	def CleanUp(self, name):
+		'''
+		resets the lists, the count, and the variable MetricName back to zero, enabling a user to in effect start over, without
+		re-creating the instance of the class. 
+		'''
+		
+		global ArrayNames
+		ArrayNames=[]
+		
+		global ListOfArrays
+		ListOfArrays=[]
+		
+		global count
+		count=0	
+		
+		global MetricName
+		name=MetricName
+
+##########################################################################################
+#final commands to tie everything together 
+##########################################################################################
+
+#allows the command line user to remotely create an instance of the class
+@route('/rcmet/metrics/commandline', method='POST')
+def CreateAnInstance():
+	'''
+	Sets up a POST page that creates an instance of the class for a user on the command line. The user does not need
+	to open this page for it to function; they need only post the name of the metric they want. 
+	'''
+	
+	NameOfMetric=request.forms.get('NameOfMetric')
+	
+	global MetricName
+	
+	MetricName=NameOfMetric
+
+	if name in HowManyVariables:
+		BottleMetrics.GetVariables()
+	
+	else:
+		print "The metric you entered, %s, does not exist" %name	
+
+
+
+@route('/rcmet/metrics/commandline/methods', method='POST')
+def RunAMethod():
+	'''
+	Allows a command line user to access any method in class MetricWebService() by sending a form
+	'''
+	MethodName=request.forms.get('MethodName')
+	
+	MetricWebServiceMethod=getattr(BottleMetrics, MethodName)
+	
+	BottleMetrics.MetricWebServiceMethod()
+	 
+
+BottleMetrics=MetricWebService()
+
+#final function starts up bottle at http://localhost:8080
+#note: localhost:8080 may need to be changed eventually 
+run(host='localhost', port=8080)
+
+
+
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/dataset_helpers.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/dataset_helpers.py.svn-base b/src/main/python/rcmes/services/.svn/text-base/dataset_helpers.py.svn-base
new file mode 100755
index 0000000..2031caf
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/dataset_helpers.py.svn-base
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+"""
+    Provides Bottle services for interacting with RCMED
+"""
+
+from bottle import request, route
+
+import requests
+import Nio
+
+@route('/getObsDatasets')
+def getObservationDatasetData():
+    r = requests.get('http://rcmes.jpl.nasa.gov/query-api/datasets.php')
+
+    # Handle JSONP requests
+    if (request.query.callback):
+        return "%s(%s)" % (request.query.callback, r.text)
+    # Otherwise, just return JSON
+    else:
+        return r.text
+
+@route('/getDatasetParam')
+def getDatasetParameters():
+    url = 'http://rcmes.jpl.nasa.gov/query-api/parameters.php?dataset=' + request.query.dataset
+    r = requests.get(url)
+
+    # Handle JSONP requests
+    if (request.query.callback):
+        return "%s(%s)" % (request.query.callback, r.text)
+    # Otherwise, just return JSON
+    else:
+        return r.text

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/decode_model_times.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/decode_model_times.py.svn-base b/src/main/python/rcmes/services/.svn/text-base/decode_model_times.py.svn-base
new file mode 100755
index 0000000..ae7974d
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/decode_model_times.py.svn-base
@@ -0,0 +1,185 @@
+#!/usr/local/bin/python
+"""Module to simplify handling of model times """
+def decodeTimeFromString(time_string):
+    '''
+    # Decodes string into a python datetime object
+    # Method: tries a bunch of different time format possibilities and hopefully one of them will hit.
+    # 
+    #   Input:  time_string - a string that represents a date/time
+    #   Output: mytime - a python datetime object
+    #
+    #   Peter Lean   February 2011
+    '''
+    import time
+    import datetime
+
+    try:
+        mytime = time.strptime(time_string, '%Y-%m-%d %H:%M:%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y/%m/%d %H:%M:%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y%m%d %H:%M:%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y:%m:%d %H:%M:%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y%m%d%H%M%S')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+    try:
+        mytime = time.strptime(time_string, '%Y-%m-%d %H:%M')
+        mytime = datetime.datetime(*mytime[0:6])
+        return mytime
+
+    except ValueError:
+        pass
+
+
+    print 'Error decoding time string: string does not match a predefined time format'
+    return 0
+
+
+
+def decode_model_times(filelist,timeVarName):
+   '''
+   #  Routine to convert from model times ('hours since 1900...', 'days since ...') 
+   #  into a python datetime structure
+   #
+   #  Input:
+   #      filelist - list of model files
+   #      timeVarName - name of the time variable in the model files
+   #
+   #  Output:
+   #      times  - list of python datetime objects describing model data times
+   #
+   #
+   #     Peter Lean February 2011
+   #
+   '''
+   import datetime
+   import re
+   import string
+   import math
+   import numpy
+   import Nio
+
+   f = Nio.open_file(filelist[0])
+   xtimes = f.variables[timeVarName]
+   timeFormat = xtimes.units
+
+   # search to check if 'since' appears in units
+   try:
+     sinceLoc = re.search('since',timeFormat).end()
+
+   except:
+     print 'Error decoding model times: time variable attributes do not contain "since"'
+     return 0
+
+   # search for 'seconds','minutes','hours', 'days', 'months', 'years' so know units
+   units = ''
+   try:
+     mysearch = re.search('minutes',timeFormat).end()
+     units = 'minutes'
+   except:
+     pass
+   try:
+     mysearch = re.search('hours',timeFormat).end()
+     units = 'hours'
+   except:
+     pass
+   try:
+     mysearch = re.search('days',timeFormat).end()
+     units = 'days'
+   except:
+     pass
+   try:
+     mysearch = re.search('months',timeFormat).end()
+     units = 'months'
+   except:
+     pass
+   try:
+     mysearch = re.search('years',timeFormat).end()
+     units = 'years'
+   except:
+     pass
+   
+   # cut out base time (the bit following 'since')
+   base_time_string = string.lstrip(timeFormat[sinceLoc:])
+
+   # decode base time
+   base_time = decodeTimeFromString(base_time_string)
+
+
+   times=[]
+   for xtime in xtimes[:]:
+      if(units=='minutes'):  
+         dt = datetime.timedelta(minutes=xtime)
+         new_time = base_time + dt
+
+      if(units=='hours'):  
+         dt = datetime.timedelta(hours=xtime)
+         new_time = base_time + dt
+
+      if(units=='days'):  
+         dt = datetime.timedelta(days=xtime)
+         new_time = base_time + dt
+
+      if(units=='months'):   # NB. adding months in python is complicated as month length varies and hence ambigous.
+         # Perform date arithmatic manually
+         #  Assumption: the base_date will usually be the first of the month
+         #              NB. this method will fail if the base time is on the 29th or higher day of month
+         #                      -as can't have, e.g. Feb 31st.
+         new_month = int(base_time.month + xtime % 12)
+         new_year = int(math.floor(base_time.year + xtime / 12.))
+         new_time = datetime.datetime(new_year,new_month,base_time.day,base_time.hour,base_time.second,0)
+
+      if(units=='years'):
+         dt = datetime.timedelta(years=xtime)
+         new_time = base_time + dt
+         
+      times.append(new_time)
+
+   return times
+
+
+''' NOT USED BY BOTTLE WS CALLS
+import sys
+import datetime 
+filename = [sys.argv[1]]
+time_var_name = sys.argv[2]
+
+print filename, type(filename)
+print time_var_name
+
+times = decode_model_times(filename,time_var_name)
+
+for time in times:
+  print time.strftime('%Y-%m-%d %H:%M:%S')
+'''

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/directory_helpers.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/directory_helpers.py.svn-base b/src/main/python/rcmes/services/.svn/text-base/directory_helpers.py.svn-base
new file mode 100755
index 0000000..70147c4
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/directory_helpers.py.svn-base
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+"""
+    Provides helpers for listing retrieving directory information from the server.
+"""
+
+from bottle import request, route
+import os
+import json
+
+PATH_LEADER = "/usr/local/rcmes"
+
+@route('/getDirInfo/<dirPath:path>')
+def getDirectoryInfo(dirPath):
+    dirPath = PATH_LEADER + dirPath
+    dirPath = dirPath.replace('/../', '/')
+    dirPath = dirPath.replace('/./', '/')
+
+    if os.path.isdir(dirPath):
+        listing = os.listdir(dirPath)
+        listingNoHidden = [f for f in listing if f[0] != '.']
+        joinedPaths = [os.path.join(dirPath, f) for f in listingNoHidden]
+        joinedPaths = [f + "/" if os.path.isdir(f) else f for f in joinedPaths]
+        finalPaths = [p.replace(PATH_LEADER, '') for p in joinedPaths]
+        sorted(finalPaths, key=lambda s: s.lower())
+        returnJSON = finalPaths
+    else:
+        returnJSON = []
+
+    returnJSON = json.dumps(returnJSON)
+    if request.query.callback:
+        return "%s(%s)" % (request.query.callback, returnJSON)
+    else:
+        return returnJSON
+
+@route('/getPathLeader/')
+def getPathLeader():
+    returnJSON = {"leader": PATH_LEADER}
+
+    if request.query.callback:
+        return "%s(%s)" % (request.query.callback, returnJSON)
+    else:
+        return returnJSON

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/find_latlon_var.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/find_latlon_var.py.svn-base b/src/main/python/rcmes/services/.svn/text-base/find_latlon_var.py.svn-base
new file mode 100755
index 0000000..f46e8d4
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/find_latlon_var.py.svn-base
@@ -0,0 +1,136 @@
+#!/usr/local/bin/python
+"""
+    Small command line utility to find what the latitude and longitude variables are called in a model file.
+
+    Background::  
+        Model output files tend not to follow any defined standard in terms of 
+        variable naming conventions.  One model may call the latitude "lat", 
+        another one may call it "Latitudes".  This script looks for the 
+        existence of any of a predefined list of synonyms for lat and long.
+
+    This script should be run from the command line (i.e. not called from 
+    within python)
+
+    Input::
+        -filename
+    
+    Output::
+        -success flag (1 or 0): were both latitude and longitude variable names found in the file?
+    
+    if successful::
+        -name of latitude variable
+        -name of longitude variable
+        -latMin -descriptions of lat/lon ranges in data files
+        -latMax
+        -lonMin
+        -lonMax
+    
+    if unsuccessful:
+        -list of variable names in file
+    
+    (NB. all printed to standar output)
+    
+"""
+
+import sys
+import Nio
+import bottle
+from bottle import request
+import json
+
+#filename = sys.argv[1]
+
+@bottle.route('/list/latlon/:filename#".*"#')
+def find_latlon(filename):
+  success = 0
+  filename = filename.strip('"')
+  f = Nio.open_file(filename)
+  var_name_list = f.variables.keys()
+
+  # convert all variable names into lower case
+  var_name_list_lower = [x.lower() for x in var_name_list]
+
+  # create a "set" from this list of names
+  varset = set(var_name_list_lower)
+
+  # Use "set" types for finding common variable name from in the file and from the list of possibilities
+  lat_possible_names = set(['latitude','lat','lats','latitudes'])
+  lon_possible_names = set(['longitude','lon','lons','longitudes'])
+
+  # Search for common latitude name variants:
+  # Find the intersection of two sets, i.e. find what latitude is called in this file.
+  
+  try:
+    print 'hello from inside try block'
+    lat_var_name = list(varset & lat_possible_names)[0]
+    successlat = 1
+    index = 0
+    for i in var_name_list_lower: 
+     if i==lat_var_name:
+          whlat = index
+     index += 1
+    latname = var_name_list[whlat]
+
+    lats = f.variables[latname][:]
+    latMin = lats.min()
+    latMax = lats.max()
+
+  except:
+    print 'exception happens'
+    latname = 'not_found'
+    successlat = 0
+
+  # Search for common longitude name variants:
+  # Find the intersection of two sets, i.e. find what longitude
+  # is called in this file.
+  try:
+    lon_var_name = list(varset & lon_possible_names)[0]
+    successlon = 1
+    index = 0
+    for i in var_name_list_lower:
+     if i==lon_var_name:
+          whlon = index
+     index += 1
+    lonname = var_name_list[whlon]
+
+    lons = f.variables[lonname][:]
+    #this will correct all lons to -180 , 180
+    lons[lons>180]=lons[lons>180]-360
+    
+    lonMin = lons.min()
+    lonMax = lons.max()
+
+  except:
+    lonname = 'not_found'
+    successlon = 0
+
+  
+  if(successlat & successlon): 
+     success = 1
+  
+  
+  if success:
+    print success, latname, lonname, latMin, latMax, lonMin, lonMax
+    val_types= [int,str,str,str,str,str,str]
+    success_values = [success, latname, lonname, latMin, latMax, lonMin, lonMax]
+    value_names = ['success','latname','lonname','latMin','latMax','lonMin','lonMax']
+    values = [vtypes(svalues) for vtypes,svalues in zip(val_types,success_values)]
+    print values
+    output = dict(zip(value_names,values))
+    #json_output = json.dumps({'success':success,'latname':latname, \
+    #                          'lonname':lonname,'latMin':latMin, \
+    #                           'latMax':latMax,'lonMin':lonMin, \
+    #                           'lonMax':lonMax }, sort_keys=True, indent=4)
+    if (request.query.callback):
+      return "%s(%s)" % (request.query.callback, output)
+    return output
+
+  if success==0:
+    json_output = json.dumps({'success':success,
+                                 'variables':var_name_list }, \
+                                sort_keys=True, indent=4)
+    if (request.query.callback):
+      return "%s(%s)" % (request.query.callback, json_output)
+    return json_output
+    #print success, var_name_list
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/find_time_var.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/find_time_var.py.svn-base b/src/main/python/rcmes/services/.svn/text-base/find_time_var.py.svn-base
new file mode 100755
index 0000000..b099553
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/find_time_var.py.svn-base
@@ -0,0 +1,87 @@
+#!/usr/local/bin/python
+"""
+    Small command line utility to find what the time variable is called in a model file.
+    
+    Background::  
+        Model output files tend not to follow any defined standard in terms of 
+        variable naming conventions.  One model may call the time "time", 
+        another one may call it "t".  This script looks for the existence of 
+        any of a predefined list of synonyms for time.
+    
+    This script should be run from the command line (i.e. not called from within python)
+    
+    Input::
+        -filename
+    
+    Output::
+        -success flag (1 or 0): were both latitude and longitude variable names found in the file?
+        
+        if successful:
+            -name of time variable
+            -(TODO) modelStartTime -descriptions of time ranges in data files
+            -(TODO) modelEndTime
+        if unsuccessful:
+            -list of variable names in file
+    
+    (NB. all printed to standar output)
+"""
+
+import sys
+import bottle
+from bottle import request
+import Nio
+import json
+import decode_model_times as dmt
+
+
+#filename = sys.argv[1]
+
+
+@bottle.route('/list/time/:filename#".*"#')
+def list_time(filename):
+    filename = filename.strip('"')
+    success = 0
+    f = Nio.open_file(filename)
+    var_name_list = f.variables.keys()
+    # convert all variable names into lower case
+    var_name_list_lower = [x.lower() for x in var_name_list]
+    # create a "set" from this list of names
+    varset = set(var_name_list_lower)
+    # Use "set" types for finding common variable name from in the file and from the list of possibilities
+    time_possible_names = set(['time','t','times','date','dates','julian'])
+    # Search for common latitude name variants:
+    # Find the intersection of two sets, i.e. find what latitude is called in this file.
+    try:
+      time_var_name = list(varset & time_possible_names)[0]
+      success = 1
+      index = 0
+      for i in var_name_list_lower:
+       if i==time_var_name:
+            wh = index
+       index += 1
+      timename = var_name_list[wh]
+      
+    except:
+      timename = 'not_found'
+      success = 0
+    
+    if success:
+        print 'timename is '+timename
+        times = dmt.decode_model_times([filename],timename)
+        start_time = str(min(times))
+        end_time = str(max(times))
+        time_var = json.dumps({'success':success,'timename':timename,
+                               'start_time':start_time,'end_time':end_time})
+        #return time_var
+        if (request.query.callback):
+            return "%s(%s)" % (request.query.callback, time_var)
+        return time_var
+        
+    if success==0:
+        json_output = json.dumps({'success':success,'variables':var_name_list })
+    if (request.query.callback):
+        return "%s(%s)" % (request.query.callback, json_output)
+    return json_output
+       
+    #print success, var_name_list
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/list_vars_in_file.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/list_vars_in_file.py.svn-base b/src/main/python/rcmes/services/.svn/text-base/list_vars_in_file.py.svn-base
new file mode 100755
index 0000000..43da7e6
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/list_vars_in_file.py.svn-base
@@ -0,0 +1,59 @@
+#!/usr/local/bin/python
+"""
+ Small command line utility to list the variables contained within a model file.
+
+  This script should be run from the command line (i.e. not called from within python)
+
+       Input: 
+               -filename
+
+       Output: 
+               -list of variable names in file
+
+       (NB. all printed to standar output)
+
+       Peter Lean   February 2011
+
+ WEBSERVICE PLAN
+
+    URL:  localhost:9999/list_vars/:filename    (full file path plus file name)
+    Example:  localhost:9999/list/vars/"/usr/local/wrm/modeldata/wrf.nc"
+
+    Return:  JSON Array of Variable Names
+    Example:  { "variables": [ "time_bnds", "tas", "level", "lon", "time", "lat" ] }
+"""
+
+import sys
+import Nio
+import bottle
+from bottle import request
+import json
+#filename = sys.argv[1]
+
+
+@bottle.route('/list/vars/:filename#".*"#')
+def list_vars(filename):
+    success = 0
+    filename = filename.strip('"')
+    print filename + ' is filename variable'
+    try:
+      f = Nio.open_file(filename)
+      success = 1
+    except:
+      print 'Error_reading_file '+filename
+    
+    if success:  #make some json
+      var_name_list = json.dumps({'variables':f.variables.keys() }, \
+                                 sort_keys=True, indent=2)
+      if (request.query.callback):
+          return "%s(%s)" % (request.query.callback, var_name_list)
+      return var_name_list
+  
+    else:
+      failRet = "{\"FAIL\": \""+filename+"\"}"
+      if (request.query.callback):
+          return "%s(%s)" % (request.query.callback, failRet)
+      return failRet
+  
+
+

http://git-wip-us.apache.org/repos/asf/climate/blob/a6aa1cd2/src/main/python/rcmes/services/.svn/text-base/main_ws.py.svn-base
----------------------------------------------------------------------
diff --git a/src/main/python/rcmes/services/.svn/text-base/main_ws.py.svn-base b/src/main/python/rcmes/services/.svn/text-base/main_ws.py.svn-base
new file mode 100755
index 0000000..4d78f4d
--- /dev/null
+++ b/src/main/python/rcmes/services/.svn/text-base/main_ws.py.svn-base
@@ -0,0 +1,36 @@
+"""Module that demonstrates how to initialize the RESTful web services that 
+power the RCMET GUI"""
+
+from bottle import route, response, run, static_file, hook
+import list_vars_in_file
+import find_latlon_var
+import find_time_var
+import decode_model_times as dmt
+import run_rcmes_processing
+import dataset_helpers
+import directory_helpers
+
+@route('/')
+@route('/index.html')
+def index():
+    return "<a href='/hello'>Go to Hello World page</a>"
+
+@route('/hello')
+def hello():
+    return "Hello World!"
+
+@route('/api/status')
+def api_status():
+    return {'status':'online', 'key':'value'}
+
+@route('/static/evalResults/<filename>')
+def get_eval_result_image(filename):
+    return static_file(filename, root="/tmp/rcmet")
+
+@hook('after_request')
+def enable_cors():
+    response.headers['Access-Control-Allow-Origin'] = '*'
+
+if __name__ == "__main__":
+    run(host='localhost', port=8082)
+