Changeset 1715 for TI03-DataExtractor


Ignore:
Timestamp:
18/11/06 23:01:07 (13 years ago)
Author:
astephen
Message:

Merged with titania version.

Location:
TI03-DataExtractor/trunk
Files:
52 added
1 deleted
39 edited

Legend:

Unmodified
Added
Removed
  • TI03-DataExtractor/trunk/MANIFEST

    r1184 r1715  
    99pydxc/WSCaller.py 
    1010pydxc/__init__.py 
    11 pydxc/clientConfig.py 
    1211pydxc/common.py 
    1312pydxc/jsFunctions.py 
  • TI03-DataExtractor/trunk/cgi/dxui

    r1244 r1715  
    3131from pydxc import * 
    3232 
     33# Update local pythonpath for local imports  
     34for path in LOCAL_PYTHONPATH: 
     35    sys.path.insert(0, path) 
     36 
     37# Get local security 
     38if SECURITY_MODEL=="BADC": 
     39    from BADCSecurityViaCGI import * 
     40elif SECURITY_MODEL=="NDG": 
     41    from NDGSecurityViaCGI import * 
     42 
    3343# Set up CGI error reporting if DEBUG is set to 1 in clientConfig.py module 
     44#DEBUG=1 
    3445if DEBUG==1: 
    3546    import cgitb  
     
    5768         
    5869        self.displayer=DisplayManager() 
     70 
     71        #self.displayer._displayHTTPHeader() 
    5972 
    6073        # Parse the arguments 
     
    87100        else: 
    88101            self.secureToken="undefined" 
     102 
     103        #print "Content-type: text/html\n\n" 
    89104             
    90105        # Call the dx Web Service with the arguments provided        
     
    202217             
    203218            self.args["axis_%s" % axisIndex]=iList 
    204          
     219 
     220        # Now cope with axes with only one value selected - we need a list 
     221        # Also deal with a list of strings that should be floats 
     222      
     223        for arg,value in self.args.items(): 
     224            try: 
     225                if value.find("[OPTIONAL]")>-1: 
     226                    del self.args[arg] 
     227                    continue 
     228            except: 
     229                pass 
     230 
     231            if arg[:4]=="axis": 
     232                if type(value) not in (type((1,2)), type([2,3])): 
     233                    try:  
     234                        if value.find(",")>-1: 
     235                            value=[i.strip() for i in value.split(",")] 
     236                            try: 
     237                                value=[float(i) for i in value] 
     238                            except: 
     239                                pass 
     240                            self.args[arg]=value 
     241                        else: 
     242                            raise "something" 
     243                    except: 
     244                        try: 
     245                            value=float(value) 
     246                        except: 
     247                            try: 
     248                                value=int(value) 
     249                            except: 
     250                                pass 
     251                        self.args[arg]=[value,value] 
     252                else: 
     253                    value=[i for i in value] 
     254                    try: 
     255                        value=[float(i) for i in value] 
     256                    except: 
     257                        pass 
     258                    self.args[arg]=value 
     259    
     260        # Quick fix for long list of floats where we want just the two extremes: 
     261        for arg,value in self.args.items(): 
     262            if type(value[0])==type(2.3) and len(value)>2: 
     263                value=[value[0], value[-1]] 
     264                self.args[arg]=value 
     265 
     266        # Finally, identify args coming in as "clonedomain_w.x.y.z" and clone axes 
     267        # for these. 
     268         
     269        cloneDomains=getDictSubsetMatching(self.args, "clonedomain", "regex") 
     270 
     271        for arg,value in cloneDomains.items(): 
     272            varIndex=arg.split("_")[-1] 
     273            axesToClone=getDictSubsetMatching(self.args, "axis_%s" % value, "regex") 
     274            for axkey,axvalue in axesToClone.items(): 
     275                axisIndex=axkey.split(".")[-1] 
     276                newKey="axis_%s.%s" % (varIndex, axisIndex) 
     277                self.args[newKey]=axvalue 
     278 
     279            outputFormatToClone=getDictSubsetMatching(self.args, "outputFormat", "regex") 
     280            ofkey,ofvalue=outputFormatToClone.items()[0] 
     281            newKey="outputFormat_%s" % varIndex 
     282            self.args[newKey]=ofvalue 
     283            # Delete this clonedomain item 
     284            del self.args[arg] 
     285 
    205286        #print "Content-Type: text/html\n\n" 
    206287        #print "<P>".join(["%s:%s" % (n,v) for (n,v) in self.args.items()]) 
     
    220301        call the local implementation of the security. 
    221302        """ 
    222         if SECURITY_MODEL=="basic": 
    223             secChecker=SecurityViaCGI(self.username, self.password, self.secureToken) 
     303        if SECURITY_MODEL=="basic" or SECURITY_MODEL=="badc": 
     304            if SECURITY_MODEL=="basic": 
     305                secClass=SecurityViaCGI 
     306            elif SECURITY_MODEL=="badc": 
     307                secClass=BADCSecurityViaCGI 
     308 
     309            secChecker=apply(secClass, [self.username, self.password, self.secureToken]) 
    224310         
    225311            # Deal with logout 
     
    228314                secChecker.logout() 
    229315                secCheck="You have been logged out." 
     316                self.username="undefined" 
     317                self.loginStatus="out" 
    230318            else: 
    231319                secCheck=secChecker.validate()       
     
    237325                self.loginStatus="in" 
    238326                self.loginMessage="" 
     327 
    239328                (self.secureToken, self.username, self.userRoles)=secCheck 
    240329                 
     
    264353        Web Service and calls it with the relevant arguments. 
    265354        """ 
    266         #print "Content-Type: text/html\n\n" 
     355        #print "Content-Type: text/html\n\n" ; print self.userRoles 
    267356        # Just print the login page if not logged in and login required 
    268357        if RESTRICTED_DATA==1 and self.loginStatus=="out": 
     
    272361            self.displayer._displayIntroduction() 
    273362            #print self.loginlist            
    274             if SECURITY_MODEL=="basic": 
     363            if SECURITY_MODEL in ("basic", "badc"): 
    275364                self.displayer._displayLoginBar(self.username, self.loginStatus, self.loginMessage) 
    276365            elif SECURITY_MODEL=="ndg": 
     
    344433        if not self.args.has_key("sessionID") or self.args["sessionID"] in (None, "None", "undefined"): 
    345434            # Start session if not known about 
     435            #print "Content-type: text/html\n\n", self.server.callServerMethod("startSession", [self.username, self.password, self.secureToken]) 
    346436            if zsiv>=2.0: 
    347437                self.sessionID, self.secureToken=self.server.callServerMethod("startSession", [self.username, self.password, self.secureToken])[0] 
     
    375465 
    376466                self.displayer._displayHTMLHeader() 
    377                 if RESTRICTED_DATA==1: self.displayer._displayLoginBar(self.username, loginStatus="in", loginMessage="with roles: "+str(self.userRoles)) 
     467                if RESTRICTED_DATA==1:  
     468                    roleString=",".join(self.userRoles) 
     469                    self.displayer._displayLoginBar(self.username, loginStatus="in", loginMessage="with roles: "+roleString) 
    378470                self.displayer._displayRequestSummaryTable(createSummaryDict(summaryString)) 
    379471                self.displayer._displayReturnLine(self.sessionID) 
    380472                return "Display footer then complete" 
    381                  
     473 
    382474            elif action=="saveRequest": 
    383475                x=self.server.callServerMethod("getDataSubsetSpecifier", 
     
    386478                #dataSubsetSpecifier, self.secureToken=x                                            
    387479                self.displayer._displayHTTPHeader()  
    388                 print x          
    389480                self.displayer._displayHTMLHeader()      
    390481                if RESTRICTED_DATA==1: self.displayer._displayLoginBar(self.username, loginStatus="in", loginMessage="with roles: "+str(self.userRoles))         
     
    405496                status, self.secureToken=self.server.callServerMethod("uploadRequest",  
    406497                                              [self.sessionID, xmlFileString, self.secureToken]) 
    407          
     498 
     499            elif action=="getStatus": 
     500                response=self.server.callServerMethod("getStatus", [self.sessionID, self.secureToken]) 
     501                if zsiv>=2.0: 
     502                    response=response[0] 
     503                 
     504                (status, errorString, outputFilePaths, self.secureToken)=response 
     505                status=status[0] 
     506                outputFilePaths=outputFilePaths[0] 
     507                 
     508                self.displayer._displayHTTPHeader() 
     509                #print outputFilePaths 
     510                self.displayer._displayHTMLHeader() 
     511                if RESTRICTED_DATA==1: self.displayer._displayLoginBar(self.username, loginStatus="in", loginMessage="with roles: "+str(self.userRoles)) 
     512                self.displayer._displayStatus(status, errorString, self.sessionID) 
     513                if status=="complete": 
     514                    self.displayer._displayOutputFileList(outputFilePaths) 
     515                return "Display footer then complete" 
     516         
     517 
     518 
    408519           
    409520    def _getLatestOptions(self): 
     
    424535        response=self.server.callServerMethod("selectOptions", [self.sessionID, self._packArgsAsList(self.args)]) 
    425536        #self.displayer._displayHTTPHeader() 
     537        #print response, type(response) 
    426538        (optionCategories, options, optionStrings, summaryString, secureToken)=self._translateResponse(response)         
    427539        #print (optionCategories, options, optionStrings, summaryString, secureToken)    
     
    460572            self.displayer._displayHTTPHeader() 
    461573            self.displayer._displayHTMLHeader()   
    462             print "<P><B>You do not have the credential to view any datasets - Sorry!</B><P>"    
     574            print "<P><B>You do not have the credentials to view any datasets - Sorry!</B><P>"   
    463575         
    464576        # Can display simple form for these categories   
     
    480592            if RESTRICTED_DATA==1: self.displayer._displayLoginBar(self.username, loginStatus="in", loginMessage="with roles: "+str(self.userRoles)) 
    481593            self.displayer._displayDatasetSummaryLine(summaryString, optionCategories[0], self.sessionID) 
    482             self.displayer._displayMainTableHeader(self.sessionID, onSubmit=""" onSubmit='return validateAllTimeSelections()'""") 
     594            self.displayer._displayMainTableHeader(self.sessionID, onSubmit=""" onSubmit='return validateAllTimeSelections("off")'""") 
    483595            self.displayer._displayDomainOptions(summaryDict, optionCategories, options, optionStrings, self.sessionID) 
    484596            self.displayer._displayMainTableFooter() 
     
    493605                self.displayer._displayDatasetSummaryLine(summaryString, optionCategories, self.sessionID)           
    494606                self.displayer._displayMainTableHeader(self.sessionID)    
    495                 print '<INPUT NAME="action" TYPE="hidden" VALUE="requestCosts">'  
     607 
     608                # Get request costs here... 
     609                response=self.server.callServerMethod("getExtractionCosts", [self.sessionID, self.secureToken]) 
     610                if zsiv>=2.0: 
     611                    response=response[0] 
     612                (estimatedDuration, estimatedVolume)=response[0:2] 
     613                summaryDict["globals"]["estimatedDuration"]=estimatedDuration 
     614                summaryDict["globals"]["estimatedVolume"]=estimatedVolume 
     615                #print '<INPUT NAME="action" TYPE="hidden" VALUE="requestCosts">'  
    496616                self.displayer._displayConfirmationSection(summaryDict) 
    497617                 
     
    516636                self.displayer._displayOutputFileList(pathList)  
    517637 
     638            elif self.args.has_key("action") and self.args["action"]=="getOutput": 
     639                self.displayer._displayHTTPHeader() 
     640                self.displayer._displayHTMLHeader() 
     641                if RESTRICTED_DATA==1: self.displayer._displayLoginBar(self.username, loginStatus="in", loginMessage="with roles: "+str(self.userRoles)) 
     642                estimatedDuration=float(summaryDict["globals"]["estimatedDuration"]) 
     643                estimatedVolume=float(summaryDict["globals"]["estimatedVolume"]) 
     644                self.displayer._displayProcessingSection(estimatedDuration, estimatedVolume, self.sessionID) 
     645                response=self.server.callServerMethod("createOutput", [self.sessionID, self.secureToken])  #[0] 
     646 
     647                if zsiv>=2.0: 
     648                    response=response[0] 
     649                pathList, self.secureToken=response 
     650                #print "<P>", pathList, len(pathList) 
     651                #self.displayer._displayOutputFileList(pathList) 
     652 
     653 
    518654 
    519655    def _packArgsAsList(self, args): 
  • TI03-DataExtractor/trunk/dxc/configs/clientConfig.py

    r1244 r1715  
    187187CONFIRMATION_PAGE=1 
    188188 
     189# MAP_APPLET_TEMPLATE_LOCAL_DIR: 
     190# Local path to directory holding map applet template. 
     191# Needs to be writeable from web user. 
     192MAP_APPLET_TEMPLATE_LOCAL_DIR=os.path.join(WEB_EXTRAS_LOCAL_PATH, "maps") 
     193 
    189194# MAP_APPLET_TEMPLATE_URL_PATH: 
    190195# URL of map applet HTML template page 
    191 MAP_APPLET_TEMPLATE_URL_PATH=os.path.join(WEB_EXTRAS_URL_PATH, "maps/map_template.html") 
     196MAP_APPLET_TEMPLATE_URL_PATH=os.path.join(WEB_EXTRAS_URL_PATH, "maps", "map_template.html") 
    192197 
    193198# MAP_APPLET_TEMPLATE_LOCAL_PATH: 
    194199# Local path to map applet HTML template page 
    195 MAP_APPLET_TEMPLATE_LOCAL_PATH=os.path.join(WEB_EXTRAS_LOCAL_PATH, "maps/map_template.html") 
     200MAP_APPLET_TEMPLATE_LOCAL_PATH=os.path.join(MAP_APPLET_TEMPLATE_LOCAL_DIR, "map_template.html") 
     201 
     202# LOCAL_PYTHONPATH: 
     203# Local paths needed for imports 
     204LOCAL_PYTHONPATH=[] 
  • TI03-DataExtractor/trunk/dxs/bin/DXWSInterface.py

    r1244 r1715  
    4444sys.path.insert(0, configPath) 
    4545exec ("from %s import *" % configFilename[:-3]) 
     46 
     47# Path for virtual variables 
     48extraPath=os.path.split(configPath)[0] 
     49sys.path.insert(0, extraPath) 
    4650 
    4751from ZSI import dispatch 
     
    8791 
    8892 
     93def getStatus(sessionID, secureToken="undefined"): 
     94    """ 
     95    Returns the status of a request. 
     96    """ 
     97    print "\nMethod called: getStatus\n" 
     98    args={"sessionID":sessionID, "secureToken":secureToken, "action":"getStatus"} 
     99 
     100    try: 
     101        controller=DXController(args) 
     102    except Exception, error: 
     103        return str(error) 
     104 
     105    if hasattr(controller, "fork") and controller.fork==1: 
     106         print "CLEAN EXIT?" 
     107         os._exit() 
     108 
     109    status=controller.status 
     110    errorString=getattr(controller, "errorString", "") 
     111    print controller.__dict__ 
     112    outputFilePaths=controller.bag["outputFilePaths"] 
     113 
     114    secureToken=controller.secureToken 
     115    return [[status], [errorString], [outputFilePaths], [secureToken]] 
     116 
    89117 
    90118def startSession(username="undefined", password="undefined", secureToken="undefined"): 
     
    101129        controller=DXController(args) 
    102130    except Exception, error: 
     131        print "QQQQQQQQQQQQQQQQQQQQQQQQQ" 
    103132        return str(error)            
    104133         
     
    180209        controller=DXController(args) 
    181210    except Exception, error: 
     211        try: 
     212            e0=error[0] 
     213            if type(e0)==type("jljl") and len(e0)>1: 
     214                error=e0 
     215        except: 
     216            pass 
    182217        return str(error) 
    183218     
     
    229264    except Exception, error: 
    230265        return str(error) 
     266 
     267    if hasattr(controller, "fork") and controller.fork==1: 
     268         print "CLEAN EXIT?" 
     269         os._exit() 
    231270     
    232271    secureToken=controller.secureToken 
     
    302341            summaryString=summaryString+("%s:\t%s\n" % (key, req[key]))""" 
    303342 
     343    print "\n"*10, summaryString 
    304344    secureToken=controller.secureToken   
    305345    return [[summaryString], [secureToken]] 
     
    372412        controller=DXController(args) 
    373413    except Exception, error: 
     414        print "STOPPED HERE..." 
    374415        return str(error)    
    375              
    376     secureToken=controller.secureToken 
    377     print "ESTIMATED COSTS:", (controller.estimatedDuration, controller.estimatedVolume)  
    378     (estimatedDuration, estimatedVolume)=(controller.estimatedDuration, controller.estimatedVolume) 
     416 
     417    print "TESTTEST"         
     418    secureToken=controller.secureToken 
     419    (estimatedDuration, estimatedVolume)=(controller.bag["estimatedDuration"], controller.bag["estimatedVolume"]) 
    379420    print "Returning...", [estimatedDuration, estimatedVolume, secureToken] 
    380421 
  • TI03-DataExtractor/trunk/dxs/configs/serverConfig.py

    r1244 r1715  
    3939# version is "basic". NERC DataGrid is "ndg". 
    4040SECURITY_MODEL="basic" 
     41 
     42# ENABLE_CSML: 
     43# Switch that is set to 1 if you are running the DX with 
     44# CSML files (and therefore you have installed the CSML 
     45# library). 
     46ENABLE_CSML=0 
    4147 
    4248# PACKAGE_NAME: 
     
    233239# the ingestion of datasets. 0=OFF, 1=ON. 
    234240FILE_NAME_TEMPLATING=1 
     241 
     242# RUNNING_DIR: 
     243# Where forked processes are noted by the server. 
     244RUNNING_DIR=os.path.join(BASEDIR, "running") 
     245 
  • TI03-DataExtractor/trunk/dxs/dxvv/VVDict.py

    r1244 r1715  
    2323 
    2424# Import package modules 
    25 from DXDMLHandler import * 
     25from pydxs.DXDMLHandler import * 
    2626 
    2727class VVDict: 
     
    3434        Creates the dictionary. 
    3535        """ 
    36         self.vvDict={("twotimespqn", "file:/usr/local/test/dxs/testdata/testdata1.xml"):"VVDoubler"} 
     36        self.vvDict={("twotimespqn", "file:/usr/local/test/dxs/testdata/testdata1.xml"):"VVDoubler", 
     37                 ("any", "ensembles_hadgem"):"VVHadleyHadGEM1"} 
    3738                                 
    3839                                 
     
    4546        if not datasetURI: 
    4647            datasetURI=DXDMLHandler().getDatasetURI(datasetGroup, dataset) 
     48 
     49        if datasetURI.find("ensembles-hadgem1")>-1: 
     50            return "VVHadleyHadGEM1" 
    4751             
    4852        if variableID[-5:]=="_dxvv": 
     
    5357         
    5458        return self.vvDict[(variableID, datasetURI)] 
     59 
     60 
     61if __name__=="__main__": 
     62    x=VVDict() 
     63    print x.getProcessingClass("any", "ensembles-hadgem1-ldsjfdlsjfs") 
  • TI03-DataExtractor/trunk/dxs/dxvv/VVDoubler.py

    r1244 r1715  
    1111another variable. 
    1212 
     13The intention is that you can incorporate any code you like here as long as it  
     14provides a way of holding the output data in memory in a CDMS-like array/variable. 
     15 
     16The underlying algorithm can include as much complexity and old code as you wish. 
     17 
     18The varDict dictionary is key to providing metadata. 
     19 
    1320""" 
    1421 
     
    1623import os 
    1724 
    18  
    1925# Import package modules 
    2026import cdms 
     27from pydxs.CDMSDataHandler import * 
     28 
    2129 
    2230class VVDoubler: 
     
    2533    """ 
    2634     
    27     def __init__(self, variableID, datasetURI): 
     35    def __init__(self, variableID, datasetURI, axisSelectionDict, timeStep=None): 
    2836        """ 
    29         Hmmm 
     37        Takes in the variable ID of the virtual variable along with the CDML 
     38        that describes it. An axis selection dictionary is also provided and 
     39        possibly a time step. Using the varDict dictionary the code works out  
     40        the algorithm to derive the virtual variable from one or more existing 
     41        variables. varDict also provides a dictionary of potential attributes 
     42        that will be added to the output variable. Note that these are identified 
     43        by the name beginning with "vv_". This will be removed in the actual  
     44        attribute set in the file. 
    3045        """ 
     46        if variableID[-5:]=="_dxvv": variableID=variableID[:-5] 
    3147        varDict={("twotimespqn", "file:/usr/local/test/dxs/testdata/testdata1.xml"): 
    32                 ["pqn", "file:/usr/local/test/dxs/testdata/testdata1.xml"]} 
    33         (inputVar, fileURI)=varDict[(variableID, datasetURI)] 
     48                {"inputVarList":[["pqn","file:/usr/local/test/dxs/testdata/testdata1.xml"]], 
     49                 "vv_long_name":"Doubled marvellous quantity", "vv_units":"K", "vv_comment":"I'm a comment", "vv_name":""}} 
     50                  
     51        varDetails=varDict[(variableID, datasetURI)] 
     52        inputVarList=varDetails["inputVarList"] 
     53        #inputVarID=varDetails["inputVarID"] 
     54        #inputURI=varDetails["inputURI"] 
    3455         
    35         # open file 
    36         infile=cdms.open(fileURI) 
    37         invar=infile(inputVar) 
     56        #(inputVar, fileURI)=varDict[(variableID, datasetURI)] 
    3857         
    39         outvar=2*invar 
     58        # Call code to generate virtual variable 
     59        self.var=self._generateVirtualVar(inputVarList, axisSelectionDict, timeStep) 
     60 
     61        #infile=cdms.open(fileURI) 
     62        #invar=infile(inputVar) 
     63         
     64        # Set some basic attributes 
     65        self.var.id=variableID 
     66         
     67        for key in varDetails.keys(): 
     68            if key[:3]=="vv_": 
     69                name=key[3:] 
     70                value=varDetails[key] 
     71                setattr(self.var, name, value) 
     72         
     73 
     74    def _generateVirtualVar(self, inputVarList, axisSelectionDict, timeStep): 
     75        """ 
     76        Reads in input variables and derives a virtual variable from them. 
     77        """ 
     78        dataFileHandler=CDMSDataHandler() 
     79        (inputVarID, inputURI)=inputVarList[0] 
     80        invar=dataFileHandler.readVariableSubsetIntoMemory(inputURI, inputVarID, axisSelectionDict, timeStep) 
     81        newvar=2*invar 
    4082        # What about all the output metadata??? 
    41         self.var=outvar  
     83        self._cloneAttributes(invar, newvar)     
     84        return newvar 
     85         
     86 
     87    def _cloneAttributes(self, invar, outvar): 
     88        """ 
     89        Adds attributes from input variable to output variable 
     90        """ 
     91        return 
     92         
     93 
     94if __name__=="__main__": 
     95    x=VVDoubler("twotimespqn",  "file:/usr/local/test/dxs/testdata/testdata1.xml", {}).var 
     96    print x, x.shape, type(x), x.attributes 
  • TI03-DataExtractor/trunk/dxs/dxvv/__init__.py

    r1244 r1715  
    1111from VVDoubler import * 
    1212 
     13# VVHadleyHadGEM1 is a class that creates virtual varaibles for all HadGEM1 data 
     14from VVHadleyHadGEM1 import * 
  • TI03-DataExtractor/trunk/dxs/manuals/ingest.html

    r794 r1715  
    44        <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8"> 
    55        <TITLE>Home Page</TITLE> 
    6         <META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.1  (Linux)"> 
     6        <META NAME="GENERATOR" CONTENT="OpenOffice.org 2.0  (Linux)"> 
    77        <META NAME="CREATED" CONTENT="20060317;12440700"> 
    8         <META NAME="CHANGED" CONTENT="20060406;9145300"> 
     8        <META NAME="CHANGED" CONTENT="20060628;8092900"> 
    99        <META NAME="ProgId" CONTENT="FrontPage.Editor.Document"> 
    1010</HEAD> 
    1111<BODY LANG="en-US" DIR="LTR"> 
    12 <H1>The Data Extractor (DX) Ingestion Guide</H1> 
    13 <H2>Introduction</H2> 
    14 <P>This document is one of a series of documents describing how to 
    15 set up and use the Data Extractor (DX). Further information is, or 
    16 soon will be, available in the following guides:</P> 
    17 <UL> 
    18         <LI><P STYLE="margin-bottom: 0cm"><B>DX Overview</B></P> 
    19         <LI><P STYLE="margin-bottom: 0cm"><B>DX Installation Guide</B>  
    20         </P> 
    21         <LI><P STYLE="margin-bottom: 0cm"><B>DX Administrator's Guide</B>  
    22         </P> 
    23         <LI><P STYLE="margin-bottom: 0cm"><B>DX User Guide</B>  
    24         </P> 
    25         <LI><P><B>Guide to Securing the DX</B>  
    26         </P> 
    27 </UL> 
    28 <H2>Data Ingestion Overview</H2> 
    29 <P>The DX-Server package needs to be told about your local data 
    30 archive so that it can generate a series of XML files to describe the 
    31 contents of the archive. These are typically CDML (Climate Data 
    32 Management Language) files which can describe NetCDF, GRIB and (with 
     12<H1 LANG="en-GB">The Data Extractor (DX) Ingestion Guide</H1> 
     13<H2 LANG="en-GB">Introduction</H2> 
     14<P LANG="en-GB">This document is one of a series of documents 
     15describing how to set up and use the Data Extractor (DX). Further 
     16information is, or soon will be, available in the following guides:</P> 
     17<UL> 
     18        <LI><P LANG="en-GB" STYLE="margin-bottom: 0cm"><B>DX Overview</B></P> 
     19        <LI><P LANG="en-GB" STYLE="margin-bottom: 0cm"><B>DX Installation 
     20        Guide</B>  
     21        </P> 
     22        <LI><P LANG="en-GB" STYLE="margin-bottom: 0cm"><B>DX Administrator's 
     23        Guide</B>  
     24        </P> 
     25        <LI><P LANG="en-GB" STYLE="margin-bottom: 0cm"><B>DX User Guide</B>  
     26        </P> 
     27        <LI><P LANG="en-GB"><B>Guide to Securing the DX</B>  
     28        </P> 
     29</UL> 
     30<H2 LANG="en-GB">Data Ingestion Overview</H2> 
     31<P LANG="en-GB">The DX-Server package needs to be told about your 
     32local data archive so that it can generate a series of XML files to 
     33describe the contents of the archive. These are typically CDML 
     34(Climate Data Management Language) or CSML (Climate Sciences 
     35Modelling Language) files which can describe NetCDF, GRIB and (with 
    3336limited scope) PP-format data files. The purpose of these XML files 
    3437is to provide a dataset-wide view of your archive rather than lists 
     
    3841subsetting requests that can span 1000s of data files without needing 
    3942to know the format or names of any individual file.</P> 
    40 <P>There is also a top-level XML file that the DX-Server interrogates 
    41 to find out what your dataset groups are and which datasets make they 
    42 include. The CDML files map one-to-one to datasets in the DX-Server.</P> 
    43 <P>The following diagram shows how the DX-Server, Dataset Group XML 
    44 file, Dataset XML files and Administrator interact to manage these 
    45 files.</P> 
    46 <P><IMG SRC="images/dx_arch.gif" NAME="Graphic1" ALIGN=BOTTOM WIDTH=767 HEIGHT=383 BORDER=0></P> 
    47 <H2>Dataset Metadata and the DX Hierarchy</H2> 
    48 <P>The DX understands the concept of a &quot;Dataset&quot; as a 
    49 collection of one or more data files containing variables with a 
     43<P LANG="en-GB">There is also a top-level XML file that the DX-Server 
     44interrogates to find out what your dataset groups are and which 
     45datasets make they include. The CDML/CSML files map one-to-one to 
     46datasets in the DX-Server.</P> 
     47<P LANG="en-GB">The following diagram shows how the DX-Server, 
     48Dataset Group XML file, Dataset XML files and Administrator interact 
     49to manage these files.</P> 
     50<P LANG="en-GB"><IMG SRC="images/dx_arch.gif" NAME="Graphic1" ALIGN=BOTTOM WIDTH=767 HEIGHT=383 BORDER=0></P> 
     51<H2 LANG="en-GB">Dataset Metadata and the DX Hierarchy</H2> 
     52<P LANG="en-GB">The DX understands the concept of a &quot;Dataset&quot; 
     53as a collection of one or more data files containing variables with a 
    5054repeated structure. Typically these are 2D or 3D model fields with 
    5155one time step per file.</P> 
    52 <P>The DX also has the concept of a &quot;Dataset Group&quot;. This 
    53 is a logical collection of &quot;Datasets&quot;. For example:</P> 
     56<P LANG="en-GB">The DX also has the concept of a &quot;Dataset 
     57Group&quot;. This is a logical collection of &quot;Datasets&quot;. 
     58For example:</P> 
    5459<TABLE WIDTH=100% BORDER=1 CELLPADDING=2 CELLSPACING=3> 
    5560        <COL WIDTH=84*> 
     
    5863        <TR> 
    5964                <TD WIDTH=33%> 
    60                         <P><B>Dataset Group</B></P> 
    61                 </TD> 
    62                 <TD WIDTH=33%> 
    63                         <P>VFGS Model Output</P> 
     65                        <P LANG="en-GB"><B>Dataset Group</B></P> 
     66                </TD> 
     67                <TD WIDTH=33%> 
     68                        <P LANG="en-GB">VFGS Model Output</P> 
    6469                </TD> 
    6570                <TD WIDTH=34%> 
    66                         <P>VFGS Model Output</P> 
     71                        <P LANG="en-GB">VFGS Model Output</P> 
    6772                </TD> 
    6873        </TR> 
    6974        <TR> 
    7075                <TD WIDTH=33%> 
    71                         <P><B>Datasets</B></P> 
    72                 </TD> 
    73                 <TD WIDTH=33%> 
    74                         <P>VFGS Ocean Model Output</P> 
     76                        <P LANG="en-GB"><B>Datasets</B></P> 
     77                </TD> 
     78                <TD WIDTH=33%> 
     79                        <P LANG="en-GB">VFGS Ocean Model Output</P> 
    7580                </TD> 
    7681                <TD WIDTH=34%> 
    77                         <P>VFGS Atmospheric Model Output</P> 
     82                        <P LANG="en-GB">VFGS Atmospheric Model Output</P> 
    7883                </TD> 
    7984        </TR> 
    8085        <TR> 
    8186                <TD WIDTH=33%> 
    82                         <P><B>Variables</B></P> 
    83                 </TD> 
    84                 <TD WIDTH=33%> 
    85                         <P>Salinity, SST...</P> 
     87                        <P LANG="en-GB"><B>Variables</B></P> 
     88                </TD> 
     89                <TD WIDTH=33%> 
     90                        <P LANG="en-GB">Salinity, SST...</P> 
    8691                </TD> 
    8792                <TD WIDTH=34%> 
    88                         <P>u-wind, v-wind...</P> 
     93                        <P LANG="en-GB">u-wind, v-wind...</P> 
    8994                </TD> 
    9095        </TR> 
    9196</TABLE> 
    92 <P><BR><BR> 
    93 </P> 
    94 <P>By default the DX requires the Administrator to ingest new 
    95 Datasets into the DX-Server before they can be accessed by users. The 
    96 Administrator can also create new Dataset Groups to put Datasets 
    97 under.</P> 
    98 <P>When interacting with the DX (via the Browser Client or Command 
    99 Line Client) the user will select make selections in the following 
    100 order:</P> 
     97<P LANG="en-GB"><BR><BR> 
     98</P> 
     99<P LANG="en-GB">By default the DX requires the Administrator to 
     100ingest new Datasets into the DX-Server before they can be accessed by 
     101users. The Administrator can also create new Dataset Groups to put 
     102Datasets under.</P> 
     103<P LANG="en-GB">When interacting with the DX (via the Browser Client 
     104or Command Line Client) the user will select make selections in the 
     105following order:</P> 
    101106<OL> 
    102         <LI><P STYLE="margin-bottom: 0cm">Dataset Group  
    103         </P> 
    104         <LI><P STYLE="margin-bottom: 0cm">Dataset  
    105         </P> 
    106         <LI><P STYLE="margin-bottom: 0cm">Variable  
    107         </P> 
    108         <LI><P STYLE="margin-bottom: 0cm">Spatial (Horizontal and Vertical) 
    109         axes  
    110         </P> 
    111         <LI><P STYLE="margin-bottom: 0cm">Temporal axes  
    112         </P> 
    113         <LI><P>Output file format  
     107        <LI><P LANG="en-GB" STYLE="margin-bottom: 0cm">Dataset Group  
     108        </P> 
     109        <LI><P LANG="en-GB" STYLE="margin-bottom: 0cm">Dataset  
     110        </P> 
     111        <LI><P LANG="en-GB" STYLE="margin-bottom: 0cm">Variable  
     112        </P> 
     113        <LI><P LANG="en-GB" STYLE="margin-bottom: 0cm">Spatial (Horizontal 
     114        and Vertical) axes  
     115        </P> 
     116        <LI><P LANG="en-GB" STYLE="margin-bottom: 0cm">Temporal axes  
     117        </P> 
     118        <LI><P LANG="en-GB">Output file format  
    114119        </P> 
    115120</OL> 
    116 <P>If the user selects 2 variables the DX will try and subtract 
    117 variable 2 from variable 1 by interpolating variable 2 to the grid of 
    118 variable 1.</P> 
    119 <H2>Generating Metadata Files</H2> 
    120 <H3>Adding a new Dataset Group</H3> 
    121 <P STYLE="margin-bottom: 0cm"><SPAN STYLE="background: transparent">The 
     121<P LANG="en-GB">If the user selects 2 variables the DX will try and 
     122subtract variable 2 from variable 1 by interpolating variable 2 to 
     123the grid of variable 1.</P> 
     124<H2 LANG="en-GB">Generating Metadata Files</H2> 
     125<H3 LANG="en-GB">Adding a new Dataset Group</H3> 
     126<P LANG="en-GB" STYLE="margin-bottom: 0cm"><SPAN STYLE="background: transparent">The 
    122127top-level metadata file used by the DX-Server is typically called 
    123128<I>inpu</I></SPAN>t<I>Datasets.xml</I> and is located within the 
     
    127132versions to backup files in the same directory (just in case!).  
    128133</P> 
    129 <P STYLE="margin-bottom: 0cm"><BR> 
    130 </P> 
    131 <P STYLE="margin-bottom: 0cm; font-style: normal">To add a new 
    132 Dataset Group you use the <I>addDatasetGroup.py</I> script in the 
    133 scripts/ sub-directory. It has the following syntax:</P> 
    134 <P STYLE="margin-bottom: 0cm"><BR> 
    135 </P> 
    136 <P STYLE="margin-bottom: 0cm; font-style: normal">addDatasetGroups.py</P> 
    137 <P STYLE="margin-bottom: 0cm; font-style: normal">===================</P> 
    138 <P STYLE="margin-bottom: 0cm"><BR> 
    139 </P> 
    140 <P STYLE="margin-bottom: 0cm; font-style: normal">Script for adding a 
    141 new dataset group to the DX.</P> 
    142 <P STYLE="margin-bottom: 0cm"><BR> 
    143 </P> 
    144 <P STYLE="margin-bottom: 0cm; font-style: normal">Usage:</P> 
    145 <P STYLE="margin-bottom: 0cm; font-style: normal">======</P> 
    146 <P STYLE="margin-bottom: 0cm"><BR> 
    147 </P> 
    148 <P STYLE="margin-bottom: 0cm; font-style: normal">addDatasetGroup.py 
     134<P LANG="en-GB" STYLE="margin-bottom: 0cm"><BR> 
     135</P> 
     136<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">To add 
     137a new Dataset Group you use the <I>addDatasetGroup.py</I> script in 
     138the scripts/ sub-directory. It has the following syntax:</P> 
     139<P LANG="en-GB" STYLE="margin-bottom: 0cm"><BR> 
     140</P> 
     141<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">addDatasetGroups.py</P> 
     142<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">===================</P> 
     143<P LANG="en-GB" STYLE="margin-bottom: 0cm"><BR> 
     144</P> 
     145<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">Script 
     146for adding a new dataset group to the DX.</P> 
     147<P LANG="en-GB" STYLE="margin-bottom: 0cm"><BR> 
     148</P> 
     149<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">Usage:</P> 
     150<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">======</P> 
     151<P LANG="en-GB" STYLE="margin-bottom: 0cm"><BR> 
     152</P> 
     153<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">addDatasetGroup.py 
    149154-s &lt;shortName&gt; -l &lt;longName&gt; [-p &lt;fileNamePrefix&gt;]</P> 
    150 <P STYLE="margin-bottom: 0cm; font-style: normal">[-r 
     155<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">[-r 
    151156&lt;permittedRoles&gt;] [-u &lt;permittedUsers&gt;] [-b 
    152157&lt;detailedMetadataLink&gt;]</P> 
    153 <P STYLE="margin-bottom: 0cm; font-style: normal">[-d 
     158<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">[-d 
    154159&lt;discoveryMetadataLink&gt;] [-a &lt;usageMetadataLink&gt;] [-w 
    155160&lt;documentationLink&gt;]</P> 
    156 <P STYLE="margin-bottom: 0cm; font-style: normal">[-h] 
     161<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">[-h] 
    157162&lt;outputFilePath&gt;</P> 
    158 <P STYLE="margin-bottom: 0cm"><BR> 
    159 </P> 
    160 <P STYLE="margin-bottom: 0cm"><BR> 
    161 </P> 
    162 <P STYLE="margin-bottom: 0cm; font-style: normal">Where:</P> 
    163 <P STYLE="margin-bottom: 0cm; font-style: normal">======</P> 
    164 <P STYLE="margin-bottom: 0cm; font-style: normal">&lt;shortName&gt; 
     163<P LANG="en-GB" STYLE="margin-bottom: 0cm"><BR> 
     164</P> 
     165<P LANG="en-GB" STYLE="margin-bottom: 0cm"><BR> 
     166</P> 
     167<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">Where:</P> 
     168<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">======</P> 
     169<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">&lt;shortName&gt; 
    165170is the short name of the item to add (mandatory).</P> 
    166 <P STYLE="margin-bottom: 0cm; font-style: normal">&lt;longName&gt; is 
    167 the long name of the item to add (mandatory).</P> 
    168 <P STYLE="margin-bottom: 0cm; font-style: normal">&lt;fileNamePrefix&gt; 
     171<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">&lt;longName&gt; 
     172is the long name of the item to add (mandatory).</P> 
     173<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">&lt;fileNamePrefix&gt; 
    169174is the file name prefix for the DX to use (optional).</P> 
    170 <P STYLE="margin-bottom: 0cm; font-style: normal">&lt;permittedRoles&gt; 
     175<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">&lt;permittedRoles&gt; 
    171176is the list of roles allowed to access the data (default=&quot;all&quot;).</P> 
    172 <P STYLE="margin-bottom: 0cm; font-style: normal">&lt;permittedUsers&gt; 
     177<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">&lt;permittedUsers&gt; 
    173178is the list of users allowed to access the data (default=&quot;all&quot;).</P> 
    174 <P STYLE="margin-bottom: 0cm; font-style: normal">&lt;detailedMetadataLink&gt; 
     179<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">&lt;detailedMetadataLink&gt; 
    175180is the URI to the detailed (&quot;B&quot;) metadata (optional).</P> 
    176 <P STYLE="margin-bottom: 0cm; font-style: normal">&lt;discoveryMetadataLink&gt; 
     181<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">&lt;discoveryMetadataLink&gt; 
    177182is the URI to the discovery (&quot;D&quot;) metadata record 
    178183(optional).</P> 
    179 <P STYLE="margin-bottom: 0cm; font-style: normal">&lt;usageMetadataLink&gt; 
     184<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">&lt;usageMetadataLink&gt; 
    180185is the URI to the usage (&quot;A&quot;) metadata (optional).</P> 
    181 <P STYLE="margin-bottom: 0cm; font-style: normal">&lt;documentationLink&gt; 
     186<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">&lt;documentationLink&gt; 
    182187is the URI to documentation (optional).</P> 
    183 <P STYLE="margin-bottom: 0cm; font-style: normal">-h prints this help 
    184 message.</P> 
    185 <P STYLE="margin-bottom: 0cm; font-style: normal">&lt;outputFilePath&gt; 
     188<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">-h 
     189prints this help message.</P> 
     190<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">&lt;outputFilePath&gt; 
    186191is an alternative output file to write to (optional).</P> 
    187 <P STYLE="margin-bottom: 0cm"><BR> 
    188 </P> 
    189 <H3>Adding an Existing Dataset  
     192<P LANG="en-GB" STYLE="margin-bottom: 0cm"><BR> 
     193</P> 
     194<H3 LANG="en-GB">Adding an Existing Dataset  
    190195</H3> 
    191 <P STYLE="margin-bottom: 0cm"><SPAN STYLE="background: transparent">An 
     196<P LANG="en-GB" STYLE="margin-bottom: 0cm"><SPAN STYLE="background: transparent">An 
    192197existing dataset is defined as a dataset that already has a CDML file 
    193198describing it. If you have a CDML file you can send this as one of 
    194199the command-line arguments to the <I>addDataset.py</I> script in 
    195200scripts/ sub-directory. It has the following syntax:</SPAN></P> 
    196 <P STYLE="margin-bottom: 0cm"><BR> 
    197 </P> 
    198 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">addDataset.py</SPAN></P> 
    199 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">=============</SPAN></P> 
    200 <P STYLE="margin-bottom: 0cm"><BR> 
    201 </P> 
    202 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">Script 
     201<P LANG="en-GB" STYLE="margin-bottom: 0cm"><BR> 
     202</P> 
     203<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">addDataset.py</SPAN></P> 
     204<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">=============</SPAN></P> 
     205<P LANG="en-GB" STYLE="margin-bottom: 0cm"><BR> 
     206</P> 
     207<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">Script 
    203208for adding a new dataset to the DX.</SPAN></P> 
    204 <P STYLE="margin-bottom: 0cm"><BR> 
    205 </P> 
    206 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">Usage:</SPAN></P> 
    207 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">======</SPAN></P> 
    208 <P STYLE="margin-bottom: 0cm"><BR> 
    209 </P> 
    210 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">addDataset.py 
     209<P LANG="en-GB" STYLE="margin-bottom: 0cm"><BR> 
     210</P> 
     211<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">Usage:</SPAN></P> 
     212<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">======</SPAN></P> 
     213<P LANG="en-GB" STYLE="margin-bottom: 0cm"><BR> 
     214</P> 
     215<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">addDataset.py 
    211216-s &lt;shortName&gt; -l &lt;longName&gt; -g &lt;datasetGroup&gt; [-n 
    212217&lt;fileNameSection&gt;]</SPAN></P> 
    213 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">[-r 
     218<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">[-r 
    214219&lt;permittedRoles&gt;] [-u &lt;permittedUsers&gt;] [-b 
    215220&lt;detailedMetadataLink&gt;]</SPAN></P> 
    216 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">[-d 
     221<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">[-d 
    217222&lt;discoveryMetadataLink&gt;] [-a &lt;usageMetadataLink&gt;] [-w 
    218223&lt;documentationLink&gt;]</SPAN></P> 
    219 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">[-h] 
     224<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">[-h] 
    220225&lt;outputFilePath&gt;</SPAN></P> 
    221 <P STYLE="margin-bottom: 0cm"><BR> 
    222 </P> 
    223 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">Where:</SPAN></P> 
    224 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">======</SPAN></P> 
    225 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;shortName&gt; 
     226<P LANG="en-GB" STYLE="margin-bottom: 0cm"><BR> 
     227</P> 
     228<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">Where:</SPAN></P> 
     229<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">======</SPAN></P> 
     230<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;shortName&gt; 
    226231is the short name of the item to add (mandatory).</SPAN></P> 
    227 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;longName&gt; 
     232<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;longName&gt; 
    228233is the long name of the item to add (mandatory).</SPAN></P> 
    229 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;datasetGroup&gt; 
     234<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;datasetGroup&gt; 
    230235is the short name of the parent dataset group that the datasets sits 
    231236under (mandatory).</SPAN></P> 
    232 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;fileNameSection&gt; 
     237<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;fileNameSection&gt; 
    233238is the file name section for the DX to use (optional).</SPAN></P> 
    234 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;permittedRoles&gt; 
     239<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;permittedRoles&gt; 
    235240is the comma-separated list of roles allowed to access the data 
    236241(default=&quot;all&quot;).</SPAN></P> 
    237 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;permittedUsers&gt; 
     242<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;permittedUsers&gt; 
    238243is the comma-separated list of users allowed to access the data 
    239244(default=&quot;all&quot;).</SPAN></P> 
    240 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;detailedMetadataLink&gt; 
     245<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;detailedMetadataLink&gt; 
    241246is the URI to the detailed (&quot;B&quot;) metadata (optional).</SPAN></P> 
    242 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;discoveryMetadataLink&gt; 
     247<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;discoveryMetadataLink&gt; 
    243248is the URI to the discovery (&quot;D&quot;) metadata record 
    244249(optional).</SPAN></P> 
    245 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;usageMetadataLink&gt; 
    246 is the URI to the usage (&quot;A&quot;) metadata (optional).</SPAN></P> 
    247 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;documentationLink&gt; 
     250<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;usageMetadataLink&gt; 
     251is the URI to the usage (&quot;A&quot;) metadata. In the case of 
     252datasets the &lt;usageMetadataLink&gt; provides the URI of the 
     253CDML/CSML file used by the DX to query the metadata. This argument is 
     254therefore mandatory.</SPAN></P> 
     255<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;documentationLink&gt; 
    248256is the URI to documentation (optional).</SPAN></P> 
    249 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">-h 
     257<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">-h 
    250258prints this help message. </SPAN> 
    251259</P> 
    252 <P STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;outputFilePath&gt; 
     260<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><SPAN STYLE="background: transparent">&lt;outputFilePath&gt; 
    253261is an alternative output file to write to (optional). </SPAN> 
    254262</P> 
    255 <H3>Removing and Modifying Existing Datasets and Dataset Groups</H3> 
    256 <P>There is currently no automatic method of removing or modifying 
    257 existing Datasets and Dataset Groups in the top-level 
     263<H3 LANG="en-GB">Removing and Modifying Existing Datasets and Dataset 
     264Groups</H3> 
     265<P LANG="en-GB">There is currently no automatic method of removing or 
     266modifying existing Datasets and Dataset Groups in the top-level 
    258267<I>inputDatasets.xml </I>file. The recommended course of action is to 
    259268roll-back to a previous backup (see contents of datasets/ 
     
    261270<I>addDatasetGroup.py </I>and <I>addDataset.py</I> as required. You 
    262271can, of course, hand edit the XML file if you are brave enough!</P> 
    263 <H3>Generating a new Dataset XML File (CDML)</H3> 
    264 <P STYLE="margin-bottom: 0cm">The generation of a new CDML file 
    265 requires the use of CDAT's <I>cdscan</I> utility which is not 
    266 described here in detail. The simplest usage of cdscan is as follows:</P> 
    267 <P STYLE="margin-bottom: 0cm"><BR> 
    268 </P> 
    269 <P STYLE="margin-left: 2cm; margin-bottom: 0cm; font-style: normal">cdscan 
    270 -x &lt;cdmlFile&gt; &lt;inputDataFileList&gt;</P> 
    271 <P STYLE="margin-left: 2cm; margin-bottom: 0cm"><BR> 
    272 </P> 
    273 <P STYLE="margin-bottom: 0cm; font-style: normal">For example:</P> 
    274 <P STYLE="margin-left: 2cm; margin-bottom: 0cm; font-style: normal">cdscan 
    275 -x myCDMLFile.xml 2000*_*.nc</P> 
    276 <P STYLE="margin-left: 2cm; margin-bottom: 0cm"><BR> 
    277 </P> 
    278 <P STYLE="margin-bottom: 0cm; font-style: normal">This would scan all 
    279 files matching the glob pattern “2000*_*.nc” in the local 
    280 directory and write the output file to “ myCDMLFile.xml”.  
    281 </P> 
    282 <P STYLE="margin-bottom: 0cm"><BR> 
    283 </P> 
    284 <P STYLE="margin-bottom: 0cm; font-style: normal">You can get a full 
    285 listing cdscan's functionality by typing:</P> 
    286 <P STYLE="margin-bottom: 0cm"><BR> 
    287 </P> 
    288 <P STYLE="margin-left: 2cm; margin-bottom: 0cm; font-style: normal">cdscan 
    289 -h</P> 
    290 <P STYLE="margin-bottom: 0cm"><BR> 
    291 </P> 
    292 <P STYLE="margin-bottom: 0cm; font-style: normal">There are many 
    293 quirks to using cdscan. If it doesn't work for you please consult the 
    294 Trouble Shooting section below.</P> 
    295 <P STYLE="margin-bottom: 0cm"><BR> 
    296 </P> 
    297 <P STYLE="margin-bottom: 0cm; font-style: normal"><B>Note on using 
    298 file name templates in cdscan</B></P> 
    299 <P STYLE="margin-bottom: 0cm"><BR> 
    300 </P> 
    301 <P STYLE="margin-bottom: 0cm; font-style: normal; font-weight: medium"> 
     272<P LANG="en-GB">To clean out all Dataset Groups and Datasets from the 
     273<I>inputDatasets.xml</I><SPAN STYLE="font-style: normal"> file you 
     274can use the </SPAN><I>cleanOutdatasetXMLFile.py</I><SPAN STYLE="font-style: normal"> 
     275script which just removes all ingested items. When you first install 
     276the DX you may wish to do this in order to remove the test datasets 
     277provided with the standard installation bundle.</SPAN></P> 
     278<H3 LANG="en-GB">Generating a new Dataset XML File: 1. CDML</H3> 
     279<P LANG="en-GB" STYLE="margin-bottom: 0cm">The generation of a new 
     280CDML file requires the use of CDAT's <I>cdscan</I> utility which is 
     281not described here in detail. The simplest usage of cdscan is as 
     282follows:</P> 
     283<P LANG="en-GB" STYLE="margin-bottom: 0cm"><BR> 
     284</P> 
     285<P LANG="en-GB" STYLE="margin-left: 2cm; margin-bottom: 0cm; font-style: normal"> 
     286cdscan -x &lt;cdmlFile&gt; &lt;inputDataFileList&gt;</P> 
     287<P LANG="en-GB" STYLE="margin-left: 2cm; margin-bottom: 0cm"><BR> 
     288</P> 
     289<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">For 
     290example:</P> 
     291<P LANG="en-GB" STYLE="margin-left: 2cm; margin-bottom: 0cm; font-style: normal"> 
     292cdscan -x myCDMLFile.xml 2000*_*.nc</P> 
     293<P LANG="en-GB" STYLE="margin-left: 2cm; margin-bottom: 0cm"><BR> 
     294</P> 
     295<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">This 
     296would scan all files matching the glob pattern “2000*_*.nc” in 
     297the local directory and write the output file to “ myCDMLFile.xml”. 
     298</P> 
     299<P LANG="en-GB" STYLE="margin-bottom: 0cm"><BR> 
     300</P> 
     301<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">You 
     302can get a full listing cdscan's functionality by typing:</P> 
     303<P LANG="en-GB" STYLE="margin-bottom: 0cm"><BR> 
     304</P> 
     305<P LANG="en-GB" STYLE="margin-left: 2cm; margin-bottom: 0cm; font-style: normal"> 
     306cdscan -h</P> 
     307<P LANG="en-GB" STYLE="margin-bottom: 0cm"><BR> 
     308</P> 
     309<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal">There 
     310are many quirks to using cdscan. If it doesn't work for you please 
     311consult the Trouble Shooting section below.</P> 
     312<P LANG="en-GB" STYLE="margin-bottom: 0cm"><BR> 
     313</P> 
     314<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal"><B>Note 
     315on using file name templates in cdscan</B></P> 
     316<P LANG="en-GB" STYLE="margin-bottom: 0cm"><BR> 
     317</P> 
     318<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal; font-weight: medium"> 
    302319By default cdscan writes the name of every single file into a large 
    303320list within the CDML file. This can bloat the XML file greatly when 
     
    305322useful to utilise the file name templating option to overcome this 
    306323problem.</P> 
    307 <P STYLE="margin-bottom: 0cm"><BR> 
    308 </P> 
    309 <P STYLE="margin-bottom: 0cm; font-style: normal; font-weight: medium"> 
     324<P LANG="en-GB" STYLE="margin-bottom: 0cm"><BR> 
     325</P> 
     326<P LANG="en-GB" STYLE="margin-bottom: 0cm; font-style: normal; font-weight: medium"> 
    310327some stuff here....automate removal of cdms_filemap with some 
    311328argument!</P> 
    312 <H3>Treating Individual Data Files as Datasets</H3> 
    313 <P>The DX allows you to describe an individual data file as a dataset 
    314 if you prefer not to use the CDML files. You can just supply your 
    315 data file as the dataset argument in the <I>addDataset.py</I> script 
    316 and it will work the same as if it had ingested a CDML file. The only 
    317 limitation is that a data file will only be able to describe a few GB 
    318 of data whereas a CDML file can easily describe TBs of data.</P> 
    319 <H3>Trouble Shooting</H3> 
    320 <P>This section provides a list of possible problems and hopefully 
    321 some useful solutions.</P> 
    322 <UL> 
    323         <LI><P><B>Problem:</B></P> 
    324         <P><B>cdscan gives error: </B> 
    325         </P> 
    326 </UL> 
    327 <P STYLE="margin-bottom: 0cm"><B>Setting reference time units to days 
    328 since 2006-01-01 00:00:00</B></P> 
    329 <P><B>Traceback (most recent call last):</B></P> 
    330 <P>  <B>File &quot;/usr/local/cdat/bin/cdscan&quot;, line 1343, in ?</B></P> 
    331 <P>    <B>main(sys.argv)</B></P> 
    332 <P>  <B>File &quot;/usr/local/cdat/bin/cdscan&quot;, line 990, in 
    333 main</B></P> 
    334 <P>    <B>starttime = vartime[0]</B></P> 
    335 <P>  <B>File 
     329<H3 LANG="en-GB">Generating a new Dataset XML File: 2. CSML</H3> 
     330<P LANG="en-GB">To generate a CSML file you will need to import the 
     331CSML package from the NERC DataGrid software bundle. At the time of 
     332writing the interface to this is not finalised so please consult the 
     333CSML documentation for more details.</P> 
     334<H3 LANG="en-GB">Treating Individual Data Files as Datasets</H3> 
     335<P LANG="en-GB">The DX allows you to describe an individual data file 
     336as a dataset if you prefer not to use the CDML files. You can just 
     337supply your data file as the dataset argument in the <I>addDataset.py</I> 
     338script and it will work the same as if it had ingested a CDML file. 
     339The only limitation is that a data file will only be able to describe 
     340a few GB of data whereas a CDML file can easily describe TBs of data.</P> 
     341<H3 LANG="en-GB">Trouble Shooting</H3> 
     342<P LANG="en-GB">This section provides a list of possible problems and 
     343hopefully some useful solutions.</P> 
     344<UL> 
     345        <LI><P LANG="en-GB"><B>Problem:</B></P> 
     346        <P LANG="en-GB"><B>cdscan gives error: </B> 
     347        </P> 
     348</UL> 
     349<P LANG="en-GB" STYLE="margin-bottom: 0cm"><B>Setting reference time 
     350units to days since 2006-01-01 00:00:00</B></P> 
     351<P LANG="en-GB"><B>Traceback (most recent call last):</B></P> 
     352<P LANG="en-GB"><B>File &quot;/usr/local/cdat/bin/cdscan&quot;, line 
     3531343, in ?</B></P> 
     354<P LANG="en-GB"><B>main(sys.argv)</B></P> 
     355<P LANG="en-GB"><B>File &quot;/usr/local/cdat/bin/cdscan&quot;, line 
     356990, in main</B></P> 
     357<P LANG="en-GB"><B>starttime = vartime[0]</B></P> 
     358<P LANG="en-GB"><B>File 
    336359&quot;/disks/linux1/cdat_installations/cdat_latest/lib/python2.4/site-packages/cdms/axis.py&quot;, 
    337360line 1714, in __getitem__</B></P> 
    338 <P>    <B>raise IndexError, 'index out of bounds'</B></P> 
    339 <UL> 
    340         <P><B>IndexError: index out of bounds</B></P> 
    341 </UL> 
    342 <P><B>Solution:</B></P> 
    343 <P><B>Do your data files have a dimension set as UNLIMITED? This can 
    344 cause problems for cdscan so it is wise to reformat the data setting 
    345 the exact dimension value instead of setting as unlimited. This 
    346 should solve the problem.</B></P> 
    347 <P><B>Other cdscan problems are:</B></P> 
    348 <UL> 
    349         <LI><P><B>second/minute timestep</B></P> 
    350         <LI><P><B>repeat vars but differing on cellmethods – I have a 
    351         patch</B></P> 
    352         <LI><P><B>delete the cdmsfilemap</B></P> 
    353         <LI><P><B>template values – are they all listed in cdimport -h or 
    354         only in cdmsobj.py</B></P> 
    355         <LI><P><B>massive linear dimension or partition</B></P> 
    356         <LI><P><B>missing value stuff – we have a patch for simple time 
    357         cases.</B></P> 
    358         <LI><P><B>non-linear time dim – might need to do -j option </B> 
    359         </P> 
    360         <LI><P></P> 
    361 </UL> 
    362 <UL> 
    363         <LI><P><B>Problem:</B></P> 
     361<P LANG="en-GB"><B>raise IndexError, 'index out of bounds'</B></P> 
     362<UL> 
     363        <P LANG="en-GB"><B>IndexError: index out of bounds</B></P> 
     364</UL> 
     365<P LANG="en-GB"><B>Solution:</B></P> 
     366<P LANG="en-GB"><B>Do your data files have a dimension set as 
     367UNLIMITED? This can cause problems for cdscan so it is wise to 
     368reformat the data setting the exact dimension value instead of 
     369setting as unlimited. This should solve the problem.</B></P> 
     370<P LANG="en-GB"><B>Other cdscan problems are:</B></P> 
     371<UL> 
     372        <LI><P LANG="en-GB"><B>second/minute timestep</B></P> 
     373        <LI><P LANG="en-GB"><B>repeat vars but differing on cellmethods – 
     374        I have a patch</B></P> 
     375        <LI><P LANG="en-GB"><B>delete the cdmsfilemap</B></P> 
     376        <LI><P LANG="en-GB"><B>template values – are they all listed in 
     377        cdimport -h or only in cdmsobj.py</B></P> 
     378        <LI><P LANG="en-GB"><B>massive linear dimension or partition</B></P> 
     379        <LI><P LANG="en-GB"><B>missing value stuff – we have a patch for 
     380        simple time cases.</B></P> 
     381        <LI><P LANG="en-GB"><B>non-linear time dim – might need to do -j 
     382        option </B> 
     383        </P> 
     384        <LI><P LANG="en-GB"></P> 
     385</UL> 
     386<UL> 
     387        <LI><P LANG="en-GB"><B>Problem:</B></P> 
    364388        <UL> 
    365                 <LI><P><B>Solution:</B></P> 
     389                <LI><P LANG="en-GB"><B>Solution:</B></P> 
    366390        </UL> 
    367         <LI><P><B>Problem:</B></P> 
     391        <LI><P LANG="en-GB"><B>Problem:</B></P> 
    368392        <UL> 
    369                 <LI><P><B>Solution:</B></P> 
     393                <LI><P LANG="en-GB"><B>Solution:</B></P> 
    370394        </UL> 
    371395</UL> 
  • TI03-DataExtractor/trunk/dxs/scripts/addDataset.py

    r1138 r1715  
    1717                       [-r <permittedRoles>] [-u <permittedUsers>] [-b <detailedMetadataLink>] 
    1818                       [-d <discoveryMetadataLink>] [-a <usageMetadataLink>] [-w <documentationLink>] 
    19                        [-h] <outputFilePath> 
     19                       [-h] [<outputFilePath>] 
    2020                        
    2121 
  • TI03-DataExtractor/trunk/dxs/scripts/addDatasetGroup.py

    r794 r1715  
    1717                       [-r <permittedRoles>] [-u <permittedUsers>] [-b <detailedMetadataLink>] 
    1818                       [-d <discoveryMetadataLink>] [-a <usageMetadataLink>] [-w <documentationLink>] 
    19                        [-h] <outputFilePath> 
     19                       [-h] [<outputFilePath>] 
    2020                        
    2121 
  • TI03-DataExtractor/trunk/dxs/scripts/cleanOutDatasetXMLFile.py

    r794 r1715  
    2525 
    2626# Import standard library modules 
    27 import sys, getopt, time 
     27import sys, getopt, time, os 
    2828sys.path=sys.path+["..", "."] 
    2929 
     30# Sort location of config stuff 
     31confdir=None 
     32confdir=os.path.join(os.path.split(os.path.realpath(__file__))[0], "..", "configs") 
     33if not os.path.isdir(confdir): 
     34    if os.environ.has_key("DXS_CONFIG"): 
     35        confdir=os.path.split(os.environ["DXS_CONFIG"])[0] 
     36 
     37if not confdir: 
     38    x=raw_input("Please type the full path to the directory containing the 'serverConfig.py' file: ") 
     39    confdir=x.strip() 
     40 
     41sys.path.append(confdir) 
     42 
    3043# Import local modules 
    31 from pydxs.serverConfig import * 
     44from serverConfig import * 
    3245 
    3346 
  • TI03-DataExtractor/trunk/dxs/scripts/removeDataset.py

    r794 r1715  
    3636 
    3737# Import local modules 
    38 from InputDatasetManager import * 
     38from pydxs.InputDatasetManager import * 
    3939 
    4040def removeDataset(args): 
     
    4242    Sends command-line arguments to the InputDatasetManager class. 
    4343    """ 
    44     """outputFilePath=None 
    45     (argList, outputFilePath)=getopt.getopt(args, "s:l:g:n:r:u:b:d:a:hw:") 
     44    outputFilePath=None 
     45    (argList, outputFilePath)=getopt.getopt(args, "s:g:h") 
    4646     
    4747    if argList==[]:  
     
    5050         
    5151    if outputFilePath: outputFilePath=outputFilePath[0] 
    52      
    53     keyMap={"-s": "dxDatasetShortName", "-l": "dxDatasetLongName", "-g":"DXDatasetGroup",  
    54             "-n": "dxDatasetFileNameSection", "-r": "permittedRoles", "-u": "permittedUsers",  
    55             "-b": "detailedMetadataLink", "-d": "discoveryMetadataLink", "-a": "usageMetadataLink",  
    56             "-w": "documentationLink"} 
    57          
    58     argDict={} 
     52         
     53    datasetID=None 
    5954    datasetGroup=None 
     55 
    6056    for (key, value) in argList: 
    6157        if key=="-h": 
     
    6460        elif key=="-g": 
    6561            datasetGroup=value 
    66         elif key in ("-r", "-u"): 
    67             argDict[keyMap[key]]=value.replace(",", " ")             
    68         else: 
    69             argDict[keyMap[key]]=value 
     62        elif key=="-s": 
     63            datasetID=value 
    7064 
    7165    if datasetGroup==None: 
    7266        raise "Must provide parent dataset group to add dataset to with argument flag -g." 
    73     elif not argDict.has_key("usageMetadataLink"): 
    74         raise "Must provide the usage metadata link ('A' metadata) with argument flag -a." 
     67    if datasetID==None: 
     68        raise "Must provide dataset ID (short name) with flag -s." 
    7569         
    7670    ingestor=InputDatasetManager()   
    77     ingestor.addDataset(datasetGroup, argDict) 
    78     ingestor.writeXMLFile(outputFilePath)""" 
     71    ingestor.removeDataset(datasetGroup, datasetID) 
     72    ingestor.writeXMLFile(outputFilePath) 
    7973     
     74 
    8075 
    8176 
  • TI03-DataExtractor/trunk/install.conf

    r1109 r1715  
    117117# URL of map applet HTML page 
    118118MAP_APPLET_URL_PATH=os.path.join(WEB_EXTRAS_URL_PATH, "LiveMap_30/extractorMap.html") 
     119 
     120# LOGO_DIR: 
     121# Location of logos for the header section, this should be a 
     122# full or relative URL and NOT a directory path on your machine. 
     123LOGO_DIR=os.path.join(WEB_EXTRAS_URL_PATH, "logos") 
     124 
     125# MAP_APPLET_TEMPLATE_LOCAL_DIR: 
     126# Local path to directory holding map applet template. 
     127# Needs to be writeable from web user. 
     128MAP_APPLET_TEMPLATE_LOCAL_DIR=os.path.join(WEB_EXTRAS_LOCAL_PATH, "maps") 
     129 
     130# MAP_APPLET_TEMPLATE_URL_PATH: 
     131# URL of map applet HTML template page 
     132MAP_APPLET_TEMPLATE_URL_PATH=os.path.join(WEB_EXTRAS_URL_PATH, "maps", "map_template.html") 
     133 
     134# MAP_APPLET_TEMPLATE_LOCAL_PATH: 
     135# Local path to map applet HTML template page 
     136MAP_APPLET_TEMPLATE_LOCAL_PATH=os.path.join(MAP_APPLET_TEMPLATE_LOCAL_DIR, "map_template.html") 
     137 
  • TI03-DataExtractor/trunk/install.sh

    r1225 r1715  
    1 v="0.3.0" 
     1v="0.3.1" 
    22rm -rR *tar *gz README.txt *conf dx? pydx? pydx?-?.? pydx?-?-?.? cgi web_extras 
    33 
  • TI03-DataExtractor/trunk/pydxc/DateTimeManager.py

    r794 r1715  
    7373    return dt.getTimeBins(timelist) 
    7474 
     75 
     76def convertToSeconds(interval, unit): 
     77    """ 
     78    Returns the number of seconds in the interval. 
     79    Note: year and month are approx values. 
     80    """ 
     81    unit=unit.lower() 
     82    if unit[-1]=="s": unit=unit[:-1] 
     83    if unit=="year":  
     84        secs=365*24*60*60*interval 
     85    elif unit=="month": 
     86        secs=30*24*60*60*interval 
     87    elif unit=="day": 
     88        secs=24*60*60*interval 
     89    elif unit=="hour": 
     90        secs=60*60*interval 
     91    elif unit=="minute": 
     92        secs=60*interval 
     93    elif unit=="second": 
     94        pass 
     95    else: 
     96        raise "Unit not recognised: %s" % unit 
     97    return secs 
     98 
     99 
     100def getAppropriateUnitAndInterval(value, unit): 
     101    """ 
     102    Returns the appropriate time unit nearest to an integer for 
     103    time values that are fractions. 
     104    """ 
     105    if value>=1: 
     106        return (unit, int(value)) 
     107    nsecs=convertToSeconds(value, unit) 
     108    nsecs=int(nsecs) 
     109     
     110    if nsecs<=1: 
     111        (u,i)=("second", 1) 
     112    elif nsecs<=60: 
     113        (u,i)=("second", nsecs) 
     114    elif nsecs<=(60*60): 
     115        (u,i)=("minute", nsecs/60) 
     116    elif nsecs<=(60*60*24): 
     117        (u,i)=("hour", nsecs/60/60) 
     118    elif nsecs<=(60*60*24*30): 
     119        (u,i)=("day", nsecs/60/60/24) 
     120    elif nsecs<=(60*60*24*365): 
     121        (u,i)=("month", nsecs/60/60/24/30) 
     122    else: 
     123        (u,i)=("year", nsecs/60/60/24/365) 
     124    return (u,i) 
     125 
     126 
     127def formatYear(fstring, dateTimeObj): 
     128    """ 
     129    Copes with year outside Unix time epoch. 
     130    """ 
     131    return fstring.replace("%Y", "%.4d" % dateTimeObj[0]) 
    75132 
    76133 
     
    263320        else: 
    264321            monthmap=(None, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 
    265             return monthmap[month] 
     322            return monthmap[int(month)] 
    266323             
    267324             
     
    290347        #    count=count+1           
    291348        #checkCount=0 
    292         formatstring=time.strftime(formatstring, tuple(list((itime))+[0,1,0])) 
     349        formatstring=formatYear(formatstring, itime) 
     350        # Note the year has been got now so the rest uses a fake year to avoid error outside unix time 
     351        formatstring=time.strftime(formatstring, tuple([2000]+list((itime[1:]))+[0,1,0])) 
    293352        #while formatstring.find("%")>-1:  # Keep in while loop just in case more than one occurrence of a field required 
    294353        #    checkCount=checkCount+1 
  • TI03-DataExtractor/trunk/pydxc/DisplayManager.py

    r1244 r1715  
    7373        print "<P><B>Selected so far:" 
    7474        for item in selectionList: 
    75             print " -> %s" % item 
     75            print " >:> %s" % item 
    7676 
    7777 
     
    8484            print "<P><B>Login status: </B>%s&nbsp;&nbsp;&nbsp;&nbsp;" % statusMap[loginStatus] 
    8585            if len(loginMessage)>0: 
     86                if loginMessage.find("with roles")>-1: 
     87                    loginMessage=loginMessage.replace("[","").replace("]","").replace("'","") 
    8688                print '<FONT COLOR="red">&nbsp;&nbsp;&nbsp;&nbsp;[ %s ]</FONT>' % loginMessage 
    8789            if loginStatus=="out": 
     
    118120</form> 
    119121""" % (CGI_SCRIPT_URL_PATH, uriArgString) 
    120 #           statusMap={"out":"not logged in", "in":"logged in as %s" % username} 
    121 #           print "<P><B>Login status: </B>%s&nbsp;&nbsp;&nbsp;&nbsp;" % statusMap[loginStatus] 
    122 #           if len(loginMessage)>0: 
    123 #               print '<FONT COLOR="red">&nbsp;&nbsp;&nbsp;&nbsp;[ %s ]</FONT>' % loginMessage 
    124 #           if loginStatus=="out": 
    125 #               # Display a login form 
    126 #               print """<FORM NAME="loginForm" method="POST" action="%s">  
    127 #                     Username: <INPUT TYPE="text" SIZE="20" NAME="yousirnaim" VALUE=""> 
    128 #                     Password: <INPUT TYPE="password" SIZE="10" NAME="parcewerd" VALUE=""> 
    129 #                      <INPUT TYPE="submit" NAME="login" VALUE="Login"></FORM>""" % CGI_SCRIPT_URL_PATH 
    130 #           elif loginStatus=="in": 
    131 #               # Display a logout form 
    132 #               print """<FORM NAME="loginForm" method="POST" action="%s">  
    133 #                      <INPUT TYPE="submit" NAME="logout" VALUE="Logout"></FORM>""" % CGI_SCRIPT_URL_PATH        
    134                           
     122             
    135123         
    136124    def _displayHTMLFooter(self): 
     
    170158        print '<TABLE WIDTH="100%"><TR>' 
    171159                 
    172         print '<TABLE WIDTH="100%"><TR class="tablerow"><TD>FURTHER SELECTION</TD></TR></TABLE>' 
     160        print '<TABLE WIDTH="100%"><TR class="tablerow"><TD>SELECTIONS</TD></TR></TABLE>' 
    173161        # Begin form in HTML output 
    174162        print """<FORM NAME="extract_info" method="POST" action="%s"%s>""" % (CGI_SCRIPT_URL_PATH, onSubmit) 
     
    197185        itemMap={"datasetGroup":"Dataset Group", "dataset":"Dataset", 
    198186                 "variable":"Variable"}  
    199          
     187 
     188        print """<TD CLASS="tablestyle">"""      
    200189        if len(options)==0: 
    201190            print """<BR><B>You do not have permission to view any of the available options.</B> 
     
    206195            return 
    207196             
    208         # Now loop through getting the appropriate list of values to show        
    209         """ 
    210         for dsetNumber in range(1, self.numberOfDatasets+1): 
    211             selectedFlag=None 
    212             tableWidth=100/(self.numberOfDatasets) 
    213             print '<TD WIDTH="%s%%" class="tablestyle" VALIGN="top">' % tableWidth 
    214  
    215             #print '<P>%s<P>' % options 
    216             itemTitle=itemMap[optionCategories[0].split("_")[0]]+(" %s" % dsetNumber) 
    217             print "<P><B>PLEASE SELECT: %s</B><P>" % itemTitle 
    218              
    219             # Otherwise, write out the list of options. 
    220             radioName=optionCategories[dsetNumber-1] 
    221             if sessionObj.has_key(radioName):     
    222                 selectedFlag=sessionObj[radioName] 
    223                  
    224             if itemTitle.find("Dataset Group")>-1: 
    225                 # Need to wade through metadata links to deal with this one... 
    226                 datasetGroups=[] 
    227                 detailedMetadataLinks=[] 
    228                 discoveryMetadataLinks=[] 
    229                  
    230                 for option in options[dsetNumber-1]: 
    231                     datasetGroups.append(option[0]) 
    232                     detailedMetadataLinks.append(option[1][0]) 
    233                     discoveryMetadataLinks.append(option[1][1]) 
    234                 if selectedFlag==None or selectedFlag not in datasetGroups: 
    235                     selectedFlag=datasetGroups[0] 
    236                      
    237                 for option in datasetGroups: 
    238                     counter=datasetGroups.index(option) 
    239                     optionString=optionStrings[dsetNumber-1][counter] 
    240                      
    241                     if option==selectedFlag: 
    242                         print '<BR><INPUT TYPE="radio" NAME="%s" VALUE="%s" CHECKED>%s</INPUT>' % (radioName, option, optionString)                      
    243                     else: 
    244                         print '<BR><INPUT TYPE="radio" NAME="%s" VALUE="%s">%s</INPUT>' % (radioName, option, optionString)                          
    245                     if detailedMetadataLinks[counter].lower()!="none": 
    246                         print '&nbsp;<A HREF="%s">[ Detailed Metadata ]</A>' % detailedMetadataLinks[counter] 
    247                     if discoveryMetadataLinks[counter].lower()!="none": 
    248                         print '&nbsp;<A HREF="%s">[ Discovery Metadata ]</A>' % discoveryMetadataLinks[counter] 
    249                                              
    250             else: 
    251                 if selectedFlag==None or selectedFlag not in options[dsetNumber-1]: 
    252                     selectedFlag=options[dsetNumber-1][0] 
    253  
    254                 for option in options[dsetNumber-1]: 
    255                     optionString=optionStrings[dsetNumber-1][options[dsetNumber-1].index(option)] 
    256                      
    257                     if option==selectedFlag: 
    258                         print '<BR><INPUT TYPE="radio" NAME="%s" VALUE="%s" CHECKED>%s</INPUT>' % (radioName, option, optionString) 
    259                     else: 
    260                         print '<BR><INPUT TYPE="radio" NAME="%s" VALUE="%s">%s</INPUT>' % (radioName, option, optionString)      
    261                           
    262         print "</TD>" """ 
    263          
     197        # Now loop through getting the appropriate list of values to show                
    264198        itemTitle=itemMap[optionCategories[0].split("_")[0]] 
    265         print '<P><B>PLEASE SELECT: %s</B> (<A NAME="selectAll" onclick="selectAllCheckBoxes()">  select all </A> / <A NAME="deSelectAll" onclick="deSelectAllCheckBoxes()"> deselect all </A> )<P>' % itemTitle  
     199        print """<P><FONT COLOR="black"><B>PLEASE SELECT: %s</B> (<A NAME="selectAll"  
     200onclick="selectAllCheckBoxes()">  select all </A> / <A NAME="deSelectAll"  
     201onclick="deSelectAllCheckBoxes()"> deselect all </A> )</FONT><P>""" % itemTitle  
    266202         
    267203        # Insert useful select all javascript function for checkboxes 
     
    312248                    datasetGroup=summaryDict["datasetGroups"][dsgKey] 
    313249                    if datasetGroup!=lastDatasetGroup: 
    314                         print """<BR><B>%s -&gt; Dataset selection:</B>""" % datasetGroup            
     250                        print """<BR><B>%s &gt;&gt;&gt; Dataset selection:</B>""" % datasetGroup             
    315251 
    316252                    if not selectedFlag: 
     
    352288                    dataset=summaryDict["datasets"]["%s.%s" % (dsgKey, dsKey)] 
    353289                    if dataset!=lastDataset or lastDatasetGroup!=datasetGroup: 
    354                         print """<BR><B>%s -&gt; %s -&gt; Variable selection:</B>""" % (datasetGroup, dataset) 
     290                        print """<P><B>%s &gt;&gt;&gt; %s &gt;&gt;&gt; Variable  
     291selection:</B>""" % (datasetGroup, dataset) 
    355292 
    356293                    if not selectedFlag: 
     
    361298                    lastDataset=dataset  
    362299                    lastDatasetGroup=datasetGroup 
     300        print "</TD>" 
    363301                     
    364302             
    365303    def _displayDomainOptions(self, summaryDict, optionCategories, options, optionStrings, sessionID): 
    366304        """ 
    367         Displays the domain options for each variable. 
     305        Displays the domain options for each variable. Includes lots of code to  
     306        generate dictionaries and lists that are used later on to create an  
     307        appropriate user interface. 
    368308        """      
     309        # Define a bucket to store axis info in for later 
    369310        axisBucket=[[],[],[]] 
    370311        formatDict={} 
     
    379320            counter=counter+1 
    380321         
    381         """sameBucket=getIdenticalDomains(axisBucket) 
    382         if len(sameBucket)>0: 
    383             print "<P>Found the same: " 
    384             for sameVars in sameBucket: 
    385                 print "<BR>", (" ".join(sameVars)) 
    386             print "<P>"         """ 
     322        # define which variables have the same axes 
     323        sameBucket=getIdenticalDomains(axisBucket) 
    387324         
    388325        (optionCategories, options, optionStrings)=axisBucket 
    389         #print "<P>", formatDict, "<P>", optionCategories 
    390         print "<P><B>PLEASE SELECT: Domain options</B><P>"       
    391         print "<TABLE>" 
    392         print """<TR CLASS="tablestyle"> 
    393                         <TD><B>AXIS NAME</B></TD> 
    394                         <TD><B>RECOGNISED AS</B></TD> 
    395                         <TD><B>UNITS</B></TD> 
    396                         <TD COLSPAN="3"><B>SELECTION</B></TD> 
    397                         <TD><B>INFORMATION</B></TD></TR>""" 
    398326         
    399327        # Predefine what we need for the axis selection in terms of interfaces... 
    400328        knownAxisDict={}                 
    401                  
    402         # Loop through keys to get the number of variables 
    403329        axisDict={} 
    404330         
     
    407333        minValues=[] 
    408334        maxValues=[]     
    409          
     335 
     336        # Loop through keys to get varIndices in order   
    410337        for i in range(len(optionCategories)): 
    411338            optionName=optionCategories[i] 
     
    430357        axisDictKeys=axisDict.keys() 
    431358        axisDictKeys.sort() 
    432         #print axisDictKeys 
    433359         
    434360        # Now print javascript time functions if needed 
     
    439365            print jsFunctions.js_timeValidationFunctions % (minNames, minValues, maxValues) 
    440366         
     367        # Print options stuff    
     368        print "<P><B>PLEASE SELECT: Domain options</B><P>"       
     369 
     370        print """<A NAME="groupDomainsSelector" onClick="toggleDomainGrouping('on')">Group all similar domains</a> |&nbsp; 
     371        <A NAME="ungroupDomainSelector" onClick="toggleDomainGrouping('off')"> Keep  similar domains separate.</a></P>""" 
     372        # Set up the DIV tag that will allow javascript re-rendering of the selection 
     373        # interface. 
     374        print """<DIV ID="domainSelection">"""   
     375 
     376        # Define massive string that will hold all html to show ALL var domains  
     377        print1="" 
     378        print1=print1+ """<TABLE ID="domainTable">\n""" 
     379        print1=print1+ """<TR CLASS="tablestyle"> 
     380                        <TD><B>AXIS NAME</B></TD> 
     381                        <TD><B>RECOGNISED AS</B></TD> 
     382                        <TD><B>UNITS</B></TD> 
     383                        <TD COLSPAN="3"><B>SELECTION</B></TD> 
     384                        <TD><B>INFORMATION</B></TD></TR>\n"""    
     385         
     386        # loop through axis dictionary contents and render each axis 
     387        # according to what we have learnt about it 
    441388        for key in axisDictKeys: 
    442389 
     390            # summaryDict is used to get string info about datasetgroup/dataset/var 
    443391            varID=summaryDict["variables"][key] 
    444392            dsgKey, dsKey=re.match("(\d+)\.(\d+)", key).groups() 
    445393            datasetGroup=summaryDict["datasetGroups"][dsgKey] 
    446394            dataset=summaryDict["datasets"]["%s.%s" % (dsgKey, dsKey)] 
    447             print """<TR><TD COLSPAN="7">&nbsp;</TD></TR>"""     
    448             print """<TR CLASS="tablestyle"><TD COLSPAN="7"><B>%s -&gt; %s -&gt; %s</TD></TR>""" % (datasetGroup, dataset, varID)            
    449          
     395            print1=print1+ """<TR><TD COLSPAN="7">&nbsp;</TD></TR>\n"""  
     396            print1=print1+ """<TR CLASS="tablestyle"><TD COLSPAN="7"><B>%s &gt;&gt;&gt; %s &gt;&gt;&gt; %s</TD></TR>\n""" % (datasetGroup, dataset, varID)           
     397         
     398            # get sub-dictionary for this variable 
    450399            d=axisDict[key] 
     400 
     401            # get axis list 
    451402            axes=d["axes"] 
    452403             
     404            # create a dictionary of known axes that have been found 
     405            # that require particular rendering 
    453406            found={} 
    454407            # Check time, lat and lon 
     
    457410                    found[ax]=d[ax] 
    458411             
     412            # loop through all the axes and render them appropriately 
    459413            for axis in axes: 
    460414                (optionName, items)=axis 
    461415                varIndex=".".join(optionName.split(".")[:-1])[5:] 
    462416                axisIndex=int(optionName.split(".")[-1]) 
    463                 #items=options[i] 
    464417                [knownAxis, id, longName, units, listType, unused]=items[:6] 
    465418 
     419                # if latitude or longitude then render both in one code block 
    466420                if (found.has_key("latitude") and found.has_key("longitude")) and \ 
    467421                        axisIndex in (found["latitude"], found["longitude"]): 
     
    500454                    #print '<B>Horizontal Domain</B><P>' 
    501455                      
    502                     print """<TR><TD WIDTH="20%%"><B>%s</B></TD> 
     456                    print1=print1+ """<TR><TD WIDTH="20%%"><B>%s</B></TD> 
    503457                     <TD>%s</TD> 
    504458                     <TD>%s</TD> 
     
    508462                     <TD WIDTH="30%%"><FONT SIZE="-2"><B>NOTE ABOUT THE JAVA MAP APPLET:</B>  
    509463<BR>1. The map will not work if you do not have Java enabled on your browser.</FONT></TD> 
    510                      </TR>""" % (latLongName, latKnownAxis, latUnits,  
     464                     </TR>\n""" % (latLongName, latKnownAxis, latUnits,  
    511465                                   latOptionName+"_high", northernExtent)   
    512466                                                                              
     
    515469                    mapHTMLFile=self._checkMapAppletHTMLPage(lonOptionName, latOptionName) 
    516470                     
    517                     print """<TR><TD WIDTH="20%%"><B>%s</B></TD> 
     471                    print1=print1+ """<TR><TD WIDTH="20%%"><B>%s</B></TD> 
    518472                     <TD>%s</TD> 
    519473                     <TD>%s</TD>                      
     
    523477                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD> 
    524478                     <TD><BR><FONT SIZE="-2">2. This applet is known not to work on certain browsers: Mozilla, Konqueror.</FONT></TD> 
    525                      </TR>""" % (lonLongName, lonKnownAxis, lonUnits,  
     479                     </TR>\n""" % (lonLongName, lonKnownAxis, lonUnits,  
    526480                                   lonOptionName+"_low", westernExtent, mapHTMLFile, lonOptionName+"_high", 
    527481                                   easternExtent)   
    528482                                                     
    529                     print """<TR><TD WIDTH="20%%"><B>%s</B></TD> 
     483                    print1=print1+ """<TR><TD WIDTH="20%%"><B>%s</B></TD> 
    530484                     <TD>%s</TD> 
    531485                     <TD>%s</TD>                      
     
    535489                     <TD><FONT SIZE="-2"> 
    536490<BR>3. On some browsers you may have to select your subset twice before it registers.</FONT></TD> 
    537                      </TR>""" % ("","","",  
     491                     </TR>\n""" % ("","","",  
    538492                                   latOptionName+"_low", southernExtent)                     
    539493 
     494                # if time then render that in a particular way 
    540495                elif found.has_key("time") and axisIndex==found["time"]: 
    541                     (start,end,intervalValue)=items[6:9] 
     496                    (calendar, start,end,intervalValue)=items[5:9] 
    542497                     
    543498                     
    544                     print """<TR><TD WIDTH="20%%"><B>%s</B></TD> 
     499                    print1=print1+ """<TR><TD WIDTH="20%%"><B>%s</B></TD> 
    545500                     <TD>%s</TD> 
    546                      <TD>%s</TD>""" % (longName, knownAxis, units) 
    547  
    548                     self._displayTemporalDomainMenus(start, end, intervalValue, units, optionName) 
    549                     print """<TD><INPUT TYPE="button" NAME="validateTime" VALUE="Validate time selections" onClick='validateTimeSelections("%s")'/></TD></TR>""" % optionName 
     501                     <TD>%s</TD>\n""" % (longName, knownAxis, units) 
     502 
     503                    print1=print1+self._displayTemporalDomainMenus(start, end, intervalValue, units, calendar,optionName) 
     504                    print1=print1+ """<TD><INPUT TYPE="button" NAME="validateTime" VALUE="Validate time selections" onClick='validateTimeSelections("%s")'/></TD></TR>\n""" % optionName 
    550505                              
    551506                            
     
    554509                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD> 
    555510                     </TR>""" #% (optionName+"_low", start, optionName+"_high", end)    
    556                            
     511                 
     512                # else deal with other axis types, noting that these also vary             
    557513                else: 
    558                     start,end=items[6:8] 
    559                     print """<TR><TD WIDTH="20%%"><B>%s</B></TD> 
     514                    listType=items[4] 
     515                    if len(unused)>0:  
     516                        comment=unused 
     517                    else: 
     518                        comment="" 
     519 
     520                    # render axis according to the type of list sent 
     521                    # "full list" is all the numbers 
     522                    # "comma-separated ..." is a text box for user to input text into 
     523                    # all others are rendered as two input boxes, one low and one high 
     524                    if listType=="full list": 
     525                        fullList=items[6:] 
     526                        uniqueList=[] 
     527                        for i in fullList:  
     528                            if i not in uniqueList: 
     529                                uniqueList.append(i) 
     530                        optionsAsString="\n".join(["<OPTION>%s</OPTION>" % i for i in uniqueList]) 
     531                        hght=5 
     532                        if len(uniqueList)<5:  
     533                            hght=len(uniqueList) 
     534                        print1=print1+ """<TR><TD WIDTH="20%%"><B>%s</B></TD> 
     535                           <TD>%s</TD> 
     536                           <TD>%s</TD> 
     537                           <TD COLSPAN="3"><CENTER> 
     538                           <SELECT NAME="%s" SIZE="%s" MULTIPLE="multiple"> 
     539                             %s 
     540                           </SELECT> 
     541                           </TD> 
     542                           <TD><FONT SIZE="-2"><B>NOTE ABOUT THIS SELECTION CATEGORY:</B><BR>%s</FONT></TD> 
     543                           </TR>\n""" % (longName, knownAxis, units, optionName, hght, optionsAsString, comment) 
     544 
     545                    # or deal with comma-separated input in text box 
     546                    elif listType.split()[0]=="comma-separated": 
     547                        # Render a textarea with option to insert text 
     548                        cs,lts=listType.split() 
     549                        if lts.find("integer")>-1: 
     550                            ntype="Integer" 
     551                            nlength=lts[7:] 
     552                        elif lts.find("float")>-1: 
     553                            ntype="Float" 
     554                            nlength=lts[5:] 
     555 
     556                        taString="[OPTIONAL] You can insert values here following the format: \n%s %ss of length %s." % (cs.title(), ntype.lower(), nlength) 
     557 
     558                        fullList=items[6:] 
     559                        optionsAsString="\n".join(["<OPTION>%s</OPTION>" % i for i in fullList]) 
     560                        print1=print1+ """<TR><TD WIDTH="20%%"><B>%s</B></TD> 
     561                           <TD>%s</TD> 
     562                           <TD>%s</TD> 
     563                           <TD COLSPAN="3"><CENTER> 
     564                           <TEXTAREA NAME="%s" ROWS="5" COLS="50">%s</TEXTAREA> 
     565                           </TD> 
     566                           <TD><FONT SIZE="-2"><B>NOTE ABOUT THIS SELECTION CATEGORY:</B><BR>%s</FONT></TD> 
     567                           </TR>\n""" % (longName, knownAxis, units, optionName, taString, comment) 
     568 
     569                    # or deal with (low, high) range  
     570                    else: 
     571                        start,end=items[6:8] 
     572                        print1=print1+ """<TR><TD WIDTH="20%%"><B>%s</B></TD> 
    560573                     <TD>%s</TD> 
    561574                     <TD>%s</TD>                      
     
    563576                     <TD><TABLE BORDER="0"><TR><TD ALIGN="LEFT">&lt;&nbsp;<B>Low</B></TD><TD ALIGN="RIGHT"><B>High</B>&nbsp;&gt;</TD></TR></TABLE></TD>               
    564577                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD> 
    565                      </TR>""" % (longName, knownAxis, units,  
     578                     </TR>\n""" % (longName, knownAxis, units,  
    566579                     optionName+"_low", start, optionName+"_high", end)    
    567580 
    568             # Fudge output format for now 
    569             print """<TR><TD WIDTH="20%%"><B>OUTPUT FORMAT</B></TD>""" 
    570             print """<TD COLSPAN="3">Note that you should choose NetCDF format if you wish to visualise data.</TD>"""                 
    571             print '<TD COLSPAN="3"><SELECT NAME="outputFormat_%s">' % key 
    572             for format in formatDict["outputFormat_%s" % varIndex]:#("NetCDF", "NASA Ames"): 
    573                 print "<OPTION>%s</OPTION>" % format 
    574             print "</SELECT></TD>" 
     581            # Display output format  
     582            print1=print1+ """<TR><TD WIDTH="20%%"><B>OUTPUT FORMAT</B></TD>\n""" 
     583            print1=print1+ """<TD COLSPAN="3">Note that you should choose NetCDF format if you wish to visualise data.</TD>\n"""                      
     584            print1=print1+ '<TD COLSPAN="3"><SELECT NAME="outputFormat_%s">\n' % key 
     585            for format in formatDict["outputFormat_%s" % varIndex]: 
     586                print1=print1+ "<OPTION>%s</OPTION>\n" % format 
     587            print1=print1+ "</SELECT></TD>\n" 
     588             
     589        # Now create a string holding all the html for grouping domains for similar variables 
     590        print2="" 
     591        print2=print2+ """<TABLE ID="domainTable">\n""" 
     592        print2=print2+ """<TR CLASS="tablestyle"> 
     593                        <TD><B>AXIS NAME</B></TD> 
     594                        <TD><B>RECOGNISED AS</B></TD> 
     595                        <TD><B>UNITS</B></TD> 
     596                        <TD COLSPAN="3"><B>SELECTION</B></TD> 
     597                        <TD><B>INFORMATION</B></TD></TR>\n"""    
     598         
     599        # Now do the grouped bucket 
     600        varsAlreadyGrouped=[] 
     601        for key in axisDictKeys: 
     602 
     603            varIndices=re.match("(\d+\.\d+\.\d+)", key).groups()[0] 
     604             
     605            if varIndices in varsAlreadyGrouped: continue 
     606             
     607            varsToLoop=[key] 
     608            for sameVars in sameBucket: 
     609                if ("variable_"+varIndices) in sameVars: 
     610                    varsToLoop=[i.split("_")[-1] for i in sameVars] 
     611                    varsAlreadyGrouped=varsAlreadyGrouped+varsToLoop 
     612                    break 
     613             
     614            if len(varsToLoop)>1: 
     615                domainFlag="SAME DOMAIN: " 
     616            else: 
     617                domainFlag="" 
     618                 
     619            print2=print2+ """<TR><TD COLSPAN="7">&nbsp;</TD></TR>\n""" 
     620             
     621            for vkey in varsToLoop: 
     622                varID=summaryDict["variables"][vkey] 
     623                (dsgKey, dsKey, varKey)=re.match("(\d+)\.(\d+)\.(\d+)", key).groups()        
     624                datasetGroup=summaryDict["datasetGroups"][dsgKey] 
     625                dataset=summaryDict["datasets"]["%s.%s" % (dsgKey, dsKey)]       
     626                print2=print2+ """<TR CLASS="tablestyle"><TD COLSPAN="7"><B>%s%s &gt;&gt;&gt; %s &gt;&gt;&gt; %s</TD></TR>\n""" % (domainFlag, datasetGroup, dataset, varID) 
     627                # Create hidden field for cloning domain 
     628                if vkey!=varsToLoop[0]: 
     629                    print2=print2+ ("""<INPUT TYPE="hidden" NAME="clonedomain_%s" VALUE="%s"/>""" % (vkey, varsToLoop[0])) 
     630         
     631            d=axisDict[key] 
     632            axes=d["axes"] 
     633             
     634            found={} 
     635            # Check time, lat and lon 
     636            for ax in ("time", "latitude", "longitude"): 
     637                if d.has_key(ax): 
     638                    found[ax]=d[ax] 
     639 
     640            # loop through all the axes and render them appropriately        
     641            for axis in axes: 
     642                (optionName, items)=axis 
     643                varIndex=".".join(optionName.split(".")[:-1])[5:] 
     644                axisIndex=int(optionName.split(".")[-1]) 
     645                [knownAxis, id, longName, units, listType, unused]=items[:6] 
     646 
     647                # if latitude or longitude then render both in one code block 
     648                if (found.has_key("latitude") and found.has_key("longitude")) and \ 
     649                        axisIndex in (found["latitude"], found["longitude"]): 
     650                 
     651                    if found.has_key("used lat lon"):  continue 
     652                 
     653                    if axisIndex==found["latitude"]: 
     654                        # The current axis is latitude so need to get longitude 
     655                        latItems=items           
     656                        latOptionName=optionName         
     657                        lonIndex=found["longitude"] 
     658                         
     659                        for x in axes: 
     660                            if int(x[0].split(".")[-1])==lonIndex: 
     661                                # Found longitude axis in list 
     662                                (lonOptionName, lonItems)=x                      
     663                         
     664                    elif axisIndex==found["longitude"]: 
     665                        # The current axis is longitude so need to get latitude 
     666                        lonItems=items 
     667                        lonOptionName=optionName                         
     668                        latIndex=found["latitude"] 
     669                         
     670                        for x in axes: 
     671                            if int(x[0].split(".")[-1])==latIndex: 
     672                                # Found latitude axis in list 
     673                                (latOptionName, latItems)=x              
     674                                                                 
     675                    [latKnownAxis, latId, latLongName, latUnits, latListType, latUnused]=latItems[:6] 
     676                    northernExtent, southernExtent=latItems[6:8] 
     677                    [lonKnownAxis, lonId, lonLongName, lonUnits, lonListType, lonUnused]=lonItems[:6] 
     678                    westernExtent, easternExtent=lonItems[6:8] 
     679     
     680                    found["used lat lon"]=1 
    575681                      
    576         print "</TABLE>" 
     682                    #print '<B>Horizontal Domain</B><P>' 
     683                      
     684                    print2=print2+ """<TR><TD WIDTH="20%%"><B>%s</B></TD> 
     685                     <TD>%s</TD> 
     686                     <TD>%s</TD> 
     687                     <TD></TD>                                
     688                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/><BR></TD> 
     689                     <TD><B></B></TD> 
     690                     <TD WIDTH="30%%"><FONT SIZE="-2"><B>NOTE ABOUT THE JAVA MAP APPLET:</B>  
     691<BR>1. The map will not work if you do not have Java enabled on your browser.</FONT></TD> 
     692                     </TR>\n""" % (latLongName, latKnownAxis, latUnits,  
     693                                   latOptionName+"_high", northernExtent)   
     694                                                                              
     695                                                                              
     696                    # Check existence of map applet page for this axis ID, otherwise make it 
     697                    mapHTMLFile=self._checkMapAppletHTMLPage(lonOptionName, latOptionName) 
     698                     
     699                    print2=print2+ """<TR><TD WIDTH="20%%"><B>%s</B></TD> 
     700                     <TD>%s</TD> 
     701                     <TD>%s</TD>                      
     702                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD> 
     703                     <TD><TABLE BORDER="0"><TR><TD ALIGN="LEFT">&nbsp;<B></B></TD><TD><CENTER><B><input type="button" value="Select from map" 
     704    onClick="newWindow('%s','window2',550,400);"></CENTER></TD></TR></TABLE></TD>                     
     705                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD> 
     706                     <TD><BR><FONT SIZE="-2">2. This applet is known not to work on certain browsers: Mozilla, Konqueror.</FONT></TD> 
     707                     </TR>\n""" % (lonLongName, lonKnownAxis, lonUnits,  
     708                                   lonOptionName+"_low", westernExtent, mapHTMLFile, lonOptionName+"_high", 
     709                                   easternExtent)   
     710                                                     
     711                    print2=print2+ """<TR><TD WIDTH="20%%"><B>%s</B></TD> 
     712                     <TD>%s</TD> 
     713                     <TD>%s</TD>                      
     714                     <TD></TD>                                
     715                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD> 
     716                     <TD><B>&nbsp;</B></TD> 
     717                     <TD><FONT SIZE="-2"> 
     718<BR>3. On some browsers you may have to select your subset twice before it registers.</FONT></TD> 
     719                     </TR>\n""" % ("","","",  
     720                                   latOptionName+"_low", southernExtent)                     
     721 
     722                # if time then render that in a particular way 
     723                elif found.has_key("time") and axisIndex==found["time"]: 
     724                    (calendar, start,end,intervalValue)=items[5:9] 
     725                     
     726                     
     727                    print2=print2+ """<TR><TD WIDTH="20%%"><B>%s</B></TD> 
     728                     <TD>%s</TD> 
     729                     <TD>%s</TD>\n""" % (longName, knownAxis, units) 
     730 
     731                    print2=print2+self._displayTemporalDomainMenus(start, end, intervalValue, units, calendar,optionName) 
     732                    print2=print2+ """<TD><INPUT TYPE="button" NAME="validateTime" VALUE="Validate time selections" onClick='validateTimeSelections("%s")'/></TD></TR>\n""" % optionName 
     733                              
     734                            
     735                    """<TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD> 
     736                     <TD><TABLE BORDER="0"><TR><TD ALIGN="LEFT">&nbsp;<B>Low</B></TD><TD ALIGN="RIGHT"><B>High</B>&nbsp;</TD></TR></TABLE></TD>                       
     737                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD> 
     738                     </TR>""" #% (optionName+"_low", start, optionName+"_high", end)    
     739                 
     740                # else deal with other axis types, noting that these also vary             
     741                else: 
     742                    listType=items[4] 
     743                    if len(unused)>0:  
     744                        comment=unused 
     745                    else: 
     746                        comment="" 
     747 
     748                    # render axis according to the type of list sent 
     749                    # "full list" is all the numbers 
     750                    # "comma-separated ..." is a text box for user to input text into 
     751                    # all others are rendered as two input boxes, one low and one high 
     752                    if listType=="full list": 
     753                        fullList=items[6:] 
     754                        uniqueList=[] 
     755                        for i in fullList:  
     756                            if i not in uniqueList: 
     757                                uniqueList.append(i) 
     758                        optionsAsString="\n".join(["<OPTION>%s</OPTION>" % i for i in uniqueList]) 
     759                        hght=5 
     760                        if len(uniqueList)<5:  
     761                            hght=len(uniqueList) 
     762                        print2=print2+ """<TR><TD WIDTH="20%%"><B>%s</B></TD> 
     763                           <TD>%s</TD> 
     764                           <TD>%s</TD> 
     765                           <TD COLSPAN="3"><CENTER> 
     766                           <SELECT NAME="%s" SIZE="%s" MULTIPLE="multiple"> 
     767                             %s 
     768                           </SELECT> 
     769                           </TD> 
     770                           <TD><FONT SIZE="-2"><B>NOTE ABOUT THIS SELECTION CATEGORY:</B><BR>%s</FONT></TD> 
     771                           </TR>\n""" % (longName, knownAxis, units, optionName, hght, optionsAsString, comment) 
     772 
     773                    # or deal with comma-separated input in text box 
     774                    elif listType.split()[0]=="comma-separated": 
     775                        # Render a textarea with option to insert text 
     776                        cs,lts=listType.split() 
     777                        if lts.find("integer")>-1: 
     778                            ntype="Integer" 
     779                            nlength=lts[7:] 
     780                        elif lts.find("float")>-1: 
     781                            ntype="Float" 
     782                            nlength=lts[5:] 
     783 
     784                        taString="[OPTIONAL] You can insert values here following the format: \n%s %ss of length %s." % (cs.title(), ntype.lower(), nlength) 
     785 
     786                        fullList=items[6:] 
     787                        optionsAsString="\n".join(["<OPTION>%s</OPTION>" % i for i in fullList]) 
     788                        print2=print2+ """<TR><TD WIDTH="20%%"><B>%s</B></TD> 
     789                           <TD>%s</TD> 
     790                           <TD>%s</TD> 
     791                           <TD COLSPAN="3"><CENTER> 
     792                           <TEXTAREA NAME="%s" ROWS="5" COLS="50">%s</TEXTAREA> 
     793                           </TD> 
     794                           <TD><FONT SIZE="-2"><B>NOTE ABOUT THIS SELECTION CATEGORY:</B><BR>%s</FONT></TD> 
     795                           </TR>\n""" % (longName, knownAxis, units, optionName, taString, comment) 
     796 
     797                    # or deal with (low, high) range  
     798                    else: 
     799                        start,end=items[6:8] 
     800                        print2=print2+ """<TR><TD WIDTH="20%%"><B>%s</B></TD> 
     801                     <TD>%s</TD> 
     802                     <TD>%s</TD>                      
     803                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD> 
     804                     <TD><TABLE BORDER="0"><TR><TD ALIGN="LEFT">&lt;&nbsp;<B>Low</B></TD><TD ALIGN="RIGHT"><B>High</B>&nbsp;&gt;</TD></TR></TABLE></TD>               
     805                     <TD><INPUT TYPE="text" NAME="%s" VALUE="%s"/></TD> 
     806                     </TR>\n""" % (longName, knownAxis, units,  
     807                     optionName+"_low", start, optionName+"_high", end)    
     808 
     809            # Display output format  
     810            print2=print2+ """<TR><TD WIDTH="20%%"><B>OUTPUT FORMAT</B></TD>\n""" 
     811            print2=print2+ """<TD COLSPAN="3">Note that you should choose NetCDF format if you wish to visualise data.</TD>\n"""                      
     812            print2=print2+ '<TD COLSPAN="3"><SELECT NAME="outputFormat_%s">\n' % key 
     813            for format in formatDict["outputFormat_%s" % varIndex]: 
     814                print2=print2+ "<OPTION>%s</OPTION>\n" % format 
     815            print2=print2+ "</SELECT></TD>\n" 
     816 
     817        print1=print1+ """</TABLE>\n"""     
     818        print2=print2+ """</TABLE>\n""" 
     819        #print print1 
     820        print "</DIV>" 
     821 
     822        escapedprint1=print1.replace("\"", "\\\"") 
     823        escapedprint2=print2.replace("\"", "\\\"") 
     824 
     825        print """<SCRIPT language="javascript"> 
     826        function toggleDomainGrouping(grouper) { 
     827            var domainElement=document.getElementById("domainSelection"); 
     828            var ungrouped="";  
     829            var grouped=""; """ 
     830        for line in escapedprint1.split("\n"): 
     831            print """            ungrouped+="%s"; """ % line         
     832             
     833        for line in escapedprint2.split("\n"): 
     834            print """            grouped+="%s"; """ % line 
     835                 
     836        print """            if (grouper=="off") {      
     837                 domainElement.innerHTML=ungrouped;  
     838            } else { 
     839                 domainElement.innerHTML=grouped; 
     840            } 
     841            validateAllTimeSelections("off"); 
     842        } 
     843        toggleDomainGrouping("off"); 
     844 
     845            </SCRIPT> """ 
    577846 
    578847        print """<P><INPUT TYPE="checkbox" NAME="multipleFileOutput"> 
    579848               &nbsp;Use multiple output files [ this is the default large files as limited by the server ].""" 
     849 
     850        #print """<SCRIPT language="Javascript">validateAllTimeSelections("off");</SCRIPT>""" 
    580851                
    581852 
     
    8051076 
    8061077 
    807     def _displayTemporalDomainMenus(self, startTime, endTime, intervalValue, intervalUnits, axisIndex): 
     1078    def _displayTemporalDomainMenus(self, startTime, endTime, intervalValue, intervalUnits, calendar, axisIndex): 
    8081079        """ 
    8091080        Displays a set of menus for entering the date and time limits for this axis. 
     
    8151086         
    8161087        # Get the bin list for all times 
    817         timeList=DateTimeManager.createList(startTime, endTime, (intervalValue, intervalUnits), listtype="tuple") 
    818         timeBins=DateTimeManager.getTimeBins(timeList) 
     1088        if calendar=="360_day" and (intervalValue==30 and intervalUnits=="day"): 
     1089            intervalValue=1 
     1090            intervalUnits="month" 
     1091 
     1092        # This includes a little trick to avoid looping through masses of years 
     1093        startYear=startTime[0] 
     1094        endYear=endTime[0] 
     1095        ydiff=endYear-startYear 
     1096 
     1097        if intervalUnits.find("year")<0 and ydiff>6: 
     1098                # interval not years so assume that we can cut down years 
     1099                startPlus2=tuple([startYear+2]+list(startTime[1:])) 
     1100                l1=DateTimeManager.createList(startTime, startPlus2, (intervalValue, 
     1101                             intervalUnits), listtype="tuple") 
     1102                endMinus2=tuple([endYear-2]+list(endTime[1:])) 
     1103                l2=DateTimeManager.createList(endMinus2, endTime, (intervalValue, 
     1104                             intervalUnits), listtype="tuple") 
     1105                timeList=tuple(list(l1)+list(l2)) 
     1106                timeBins=DateTimeManager.getTimeBins(timeList) 
     1107                allYears=range(startYear, endYear+1) 
     1108                timeBins[0]=allYears 
     1109 
     1110 
     1111        else: 
     1112            (intervalUnits, intervalValue)=DateTimeManager.getAppropriateUnitAndInterval(intervalValue, intervalUnits) 
     1113 
     1114            timeList=DateTimeManager.createList(startTime, endTime,  
     1115                     (intervalValue, intervalUnits), listtype="tuple") 
     1116            timeBins=DateTimeManager.getTimeBins(timeList) 
    8191117         
    8201118        for i in range(len(startTime)): 
     
    8321130        #print '<TD WIDTH="50%">' 
    8331131        #print '<TABLE BORDER="1"><TR>' 
    834    
    835         print '<TD COLSPAN="3"><CENTER><TABLE BORDER="1">' 
     1132        print1="" 
     1133        print1=print1+ '<TD COLSPAN="3"><CENTER><TABLE BORDER="1">\n' 
    8361134         
    8371135        partMap={"low":"Start time", "high":"End time"} 
     
    8391137             
    8401138            if part=="gap": 
    841                 print '<TR><TD COLSPAN="6">&nbsp;</TD></TR>' 
     1139                print1=print1+ '<TR><TD COLSPAN="6">&nbsp;</TD></TR>\n' 
    8421140            else: 
    843                 print '<TR>' 
     1141                print1=print1+ '<TR>\n' 
    8441142                fieldFlag="" 
    8451143                count=0 
    8461144                for key in TIME_KEYS: 
    8471145                    if part=="text": 
    848                         print "<TD>%s</TD>" % key 
     1146                        print1=print1+ "<TD>%s</TD>\n" % key 
    8491147                    elif part in ("low", "high"): 
    850                         print """<TD><SELECT NAME="%s_%s.time.%s" %s>""" % (axisIndex,  
     1148                        print1=print1+ """<TD><SELECT NAME="%s_%s.time.%s"%s>\n""" % (axisIndex,  
    8511149                                   part, key.lower(), fieldFlag) 
    8521150                        if key=="year": 
     
    8571155                        for item in timeBins[count]: 
    8581156                            timeItem=timeFormat % item 
    859                             print """<OPTION VALUE="%s">%s</OPTION>""" % (timeItem, timeItem) 
     1157                            print1=print1+ """<OPTION VALUE="%s">%s</OPTION>\n""" % (timeItem, timeItem) 
    8601158                 
    861                         print "</SELECT></TD>" 
     1159                        print1=print1+ "</SELECT></TD>\n" 
    8621160                        count=count+1 
    8631161 
    864                 print "</TR>" 
    865         print "</CENTER></TABLE></TD>" 
    866  
     1162                print1=print1+ "</TR>\n" 
     1163        print1=print1+ "</CENTER></TABLE></TD>\n" 
     1164 
     1165        return print1 
    8671166        #print "</TR></TABLE><P>" 
    8681167        # Call the javascript to update the date field at start 
     
    9961295         
    9971296        # Link to view request summary 
    998         print '&nbsp;| <A HREF="%s?action=viewRequestSummary%s">View Current Request Summary</A>' % (CGI_SCRIPT_URL_PATH, sidString) 
     1297        #print '&nbsp;| <A HREF="%s?action=viewRequestSummary%s">View Current Request Summary</A>' % (CGI_SCRIPT_URL_PATH, sidString) 
    9991298         
    10001299        # Allow save of request (XML format) 
     
    10961395        else: 
    10971396            return pathList[:10]+["..."]+pathList[-10:] 
    1098              
     1397 
     1398 
     1399    def _displayStatus(self, status, errorString, sessionID): 
     1400        """ 
     1401        Displays the status of your request. 
     1402        """ 
     1403        # Show return to start link 
     1404        print '<P><A HREF="%s?action=clearRequest">Return to Start</A></P>' % CGI_SCRIPT_URL_PATH 
     1405 
     1406        print "<P><B>" 
     1407        if status=="complete": 
     1408            print "Your request has completed." 
     1409        elif status=="queued": 
     1410            print "Your current request is queued." 
     1411        else: 
     1412            if status=="failed": 
     1413                print "Your current request has %s with the following message:" % status 
     1414                print "</B><P>%s</P>" % errorString 
     1415                print """<P>We apologise for this problem.</P> 
     1416<P>Please report the above error to the administrator along with your session ID: <B>%s</B></P>""" % sessionID 
     1417            else: 
     1418                print "Your current request is %s." % status 
     1419        print "</B></P>" 
     1420         
     1421        if status not in ("complete", "failed"): 
     1422            print """<P>Click the button below to update this page&nbsp; 
     1423                 <FORM NAME="extract_info" method="POST" action="%s"> 
     1424                 <INPUT NAME="sessionID" TYPE="hidden" VALUE="%s"/> 
     1425                 <INPUT TYPE="hidden" NAME="action" VALUE="getStatus"/> 
     1426                 <INPUT TYPE="submit" NAME="statusGetter" VALUE="Check Status"/> 
     1427                 </FORM></P>""" % (CGI_SCRIPT_URL_PATH, sessionID) 
     1428                     
    10991429 
    11001430    def _displayOutputFileList(self, pathList): 
     
    11021432        Prints links to all the files the user has requested. 
    11031433        """ 
    1104         print "<P><B>Your request has been processed.</B><HR><P>"        
    11051434        print "<H3>Output information:</H3>" 
    11061435         
     
    11231452            if localPath=="...": 
    11241453                print """<TR class="tablerow"><TD COLSPAN="3">...</TD>""" 
    1125             elif url[-3:]=="xml": # No visualise for XML 
     1454            elif url[-3:] in ("xml", "txt"): # No visualise for XML 
    11261455                print """<TR class="tablerow"> 
    11271456                         <TD><B>%s</B></TD> 
     
    11431472        Method to tell user that there job is underway with details of their selection. 
    11441473        """ 
    1145         print """<H3>Processing Information:</H3> 
    1146               <P>Your <B>job ID</B> is: %s 
    1147               <P>The estimated duration of your job is:  %s """ %  (sessionID, self._sensibleTimeString(estimatedDuration)) 
    1148         print "<P>The estimated volume of your job is: %.2f MB" % ((estimatedVolume/1000000)+0.01) 
    1149         print "<P>Your extraction job is running...</P>" 
    1150          
    1151         if estimatedDuration>60:  
     1474        # Show return to start link 
     1475        print '<P><A HREF="%s?action=clearRequest">Return to Start</A></P>' % CGI_SCRIPT_URL_PATH 
     1476 
     1477        print """<H3>Processing Information:</H3>""" 
     1478        print "<TABLE>" 
     1479        template='<TR class="tablerow"><TD><B>%s</B></TD><TD>%s</TD></TR>' 
     1480        print template % ("Job ID", sessionID) 
     1481        print template % ("Estimated duration of job", self._sensibleTimeString(estimatedDuration)) 
     1482        print template % ("Estimated volume of your job", "%.2f MB"%((estimatedVolume/1000000)+0.01)) 
     1483        print "</TABLE>" 
     1484         
     1485        print "<P>Thank you for using the %s." % PACKAGE_NAME 
     1486 
     1487        if RESTRICTED_DATA:  
    11521488            try: 
    1153                 mailAddr=getUserEmail()  
    1154                 print "<P>You will be emailed at %s when the job has finished and the output is ready." % mailAddr         
     1489                print " You will be emailed when the job has finished." 
    11551490            except: 
    11561491                pass 
    11571492                 
    1158         print "<P>Thank you for using the %s." % PACKAGE_NAME 
    1159         print "<P>If you remain on this page it should eventually produce your output but the server may time out if your request is large.<P>" 
    1160  
     1493        print """<P><B>Click here to check the status of your request: </B> 
     1494                 <FORM NAME="extract_info" method="POST" action="%s"> 
     1495                 <INPUT NAME="sessionID" TYPE="hidden" VALUE="%s"/> 
     1496                 <INPUT TYPE="hidden" NAME="action" VALUE="getStatus"/> 
     1497                 <INPUT TYPE="submit" NAME="statusGetter" VALUE="Check Status"/> 
     1498                 </FORM></P>""" % (CGI_SCRIPT_URL_PATH, sessionID) 
    11611499 
    11621500 
     
    12221560         
    12231561        for key in globalKeys: 
    1224             print template % (key, "", d["globals"][key]) 
     1562            if key=="outputFilePaths": 
     1563                value=d["globals"][key] 
     1564                vlist=[i[1:-1] for i in value[1:-1].split(",")] 
     1565                if len(vlist)>10: 
     1566                    value=str(vlist[:4]+["...", "..."]+vlist[-4:]) 
     1567            else: 
     1568                value=d["globals"][key] 
     1569                if key=="estimatedDuration": value="%s seconds" % value 
     1570                if key=="estimatedVolume": value="%.2f MB" % (value/(2**20)) 
     1571                if key=="userRoles": value=value[1:-1].replace("'","") 
     1572            print template % (key, "", value) 
    12251573         
    12261574        print "</TABLE>" 
     
    12341582         
    12351583        self._displayRequestSummaryTable(summary)   
    1236  
    1237         print """<P><INPUT TYPE="submit" NAME="confirm" VALUE="Confirm"> Click the "Confirm" button to fetch your request.  
    1238         <BR>If you wish to modify your request please press the <I>Back</I> button on your browser.<P>""" 
     1584        print """<P> 
     1585             <INPUT TYPE="hidden" NAME="action" VALUE="getOutput"> 
     1586             <INPUT TYPE="submit" NAME="confirm" VALUE="Confirm"> Click the "Confirm" button to fetch your  
     1587request.  
     1588             <BR>If you wish to modify your request please press the <I>Back</I> button on your browser.<P>""" 
    12391589        print "</FORM><P>" 
    12401590         
  • TI03-DataExtractor/trunk/pydxc/SecurityViaCGI.py

    r1225 r1715  
    4747        # First check if the user is valid via a cookie 
    4848        cookieCheck=self._checkCookie() 
    49         #o=open('/tmp/tmp/cook.txt','w'); o.write(str(cookieCheck)) ; o.close() 
    5049 
    5150        if type(cookieCheck)==type(""): 
     
    103102        # Set the cookie 
    104103        print cookieMaker 
    105         #o=open('/tmp/tmp/out.txt', 'w'); o.write("%s" % (cookieString+"\n"+TOKEN_DOMAIN)) ; o.close() 
    106104         
    107105        return cookieString 
     
    150148        if not os.environ.has_key("HTTP_COOKIE"): 
    151149            cookieString=None 
    152             #out=open("/tmp/tmp/iscookie.txt","w");out.write("%s" % cookieString); out.close() 
    153150        else: 
    154151            cookieReader.load(os.environ["HTTP_COOKIE"]) 
  • TI03-DataExtractor/trunk/pydxc/WSCaller.py

    r1225 r1715  
    3434        """ 
    3535        # Set up SOAP bindings 
    36         trace=open('/tmp/tracefile.txt','w') 
    37          
    3836        # Need to deal with different ZSI versions 
    3937         
     
    4745            self.server = Binding(url=SOAP_SERVER_URL) 
    4846         
    49         #self.server=Binding(url='', host=SOAP_SERVER_NAME, port=SOAP_SERVER_PORT, tracefile=trace)              
    50  
    5147 
    5248    def callServerMethod(self, methodName, args, packArgs=None): 
     
    9389        the object returned from the Web Service call. 
    9490        """ 
    95         if type(response) in (type(""), type(u'w')): 
     91        if (type(response) in (type(""), type(u'w'))): 
    9692            # String returns are errors 
    9793            self._displayErrorPage(response) 
     94        elif (type(response)==type([1,2]) and (type(response[0])==type("jlkjl") and len(response)==1)): 
     95            self._displayErrorPage(response[0]) 
    9896        else: 
    9997            return response 
  • TI03-DataExtractor/trunk/pydxc/common.py

    r1244 r1715  
    3030 
    3131# Set up common functions 
    32  
    33 def DEPRECATEDcreateTimeKeyList(): 
    34     """ 
    35     Returns all the separate date and time component arguments required as a list. 
    36     """ 
    37     allTimeKeys=[] 
    38     for ts in ["start", "end"]: 
    39         for i in range(1, MAX_NUM_DATASETS+1): 
    40             for key in TIME_KEYS: 
    41                 allTimeKeys.append("%s%s_%s" % (ts, key, i)) 
    42     return allTimeKeys 
    43   
    4432 
    4533def getDateTimeComponents(dateTimeString): 
  • TI03-DataExtractor/trunk/pydxc/jsFunctions.py

    r1160 r1715  
    9999         
    100100        for (var x=0; x<item.length ; x++) { 
    101             if (parseInt(item[x].text)==valueToSelect) { 
     101            if (parseInt(item[x].text, 10)==valueToSelect) { 
    102102                item[x].selected=true; 
    103103            } 
     
    119119         
    120120        for (var i=0; i<timeComps.length; i++) { 
    121             lowTime[i]=parseInt(mainForm[axisLow+timeComps[i]].value); 
    122             highTime[i]=parseInt(mainForm[axisHigh+timeComps[i]].value); 
     121            lowTime[i]=parseInt(mainForm[axisLow+timeComps[i]].value,10); 
     122            highTime[i]=parseInt(mainForm[axisHigh+timeComps[i]].value,10); 
    123123        } 
    124124 
     
    139139} 
    140140 
    141 function validateAllTimeSelections() { 
     141function validateAllTimeSelections(alertSwitch) { 
    142142    // validates all time selections 
    143143    var mainForm=document.forms["extract_info"]; 
    144144    var axisNames=minNames; 
     145    var changed=0; 
    145146    for (var i=0; i<axisNames.length; i++) { 
    146147        axName=axisNames[i]; 
    147148        if (validateTimeSelections(axName)==false) { 
    148             alert("Axis '"+axName+"' held an invalid entry and has been modified. Please check and re-submit."); 
    149             return false; 
     149            if (alertSwitch!="off") { 
     150                alert("Axis '"+axName+"' held an invalid entry and has been modified. Please check and re-submit."); 
     151            } 
     152            changed=1; 
    150153        } 
    151154    }  
     155    if (changed==1) { 
     156        alert("Note that some invalid time selections have been brought into range.") 
     157        return false; 
     158    } 
    152159    return true; 
    153160} 
  • TI03-DataExtractor/trunk/pydxc/version.py

    r1225 r1715  
    1111""" 
    1212 
    13 version="0.3.0" 
     13version="0.3.4" 
  • TI03-DataExtractor/trunk/pydxs/CDMSDataHandler.py

    r1138 r1715  
    9191        else: 
    9292            name=v.standard_name 
     93 
     94        if hasattr(v, "cell_methods"): 
     95            name="%s [%s]" % (name, v.cell_methods) 
     96 
    9397        return name 
    9498 
     
    148152            #axisIndexString="axis%s.%s" % ("77777", axcount) #(varIndex+1, axcount) 
    149153            units=None 
     154            axisSpecificInfo="" 
     155 
    150156            if axis.isTime(): 
    151157                knownAxis="time" 
    152158                (start, end, (intervalValue, intervalUnits))=self.getTemporalDomain(datasetGroup, dataset, variable, datasetURI) 
    153159                arrayValues=[start, end, intervalValue] 
     160                if hasattr(axis, "calendar") and axis.calendar=="360_day": 
     161                    axisSpecificInfo=axis.calendar 
    154162                listType="start end interval" 
    155163                units=intervalUnits 
     
    182190            longName=self._getBestName(axis).title() 
    183191            if not units:  units=getattr(axis, "units", "") 
    184              
    185             unused="" 
    186             rtlist.append([knownAxis, id, longName, units, listType, unused]+arrayValues) 
     192 
     193            if type(arrayValues)!=type([2,3]): 
     194                arrayValues=list(arrayValues) 
     195 
     196            # Need two values minimum so re-use if only one but really don't want to send at all 
     197            if len(arrayValues)==1:   
     198                arrayValues=[arrayValues[0]]*2 
     199            
     200            rtlist.append([knownAxis, id, longName, units, listType, axisSpecificInfo]+arrayValues) 
    187201            axcount=axcount+1 
    188202             
     
    238252            start_time.append(getattr(start_time_components, key)) 
    239253            end_time.append(getattr(end_time_components, key))"""  
     254 
    240255        time_units=time_axis.units.split()[0] 
    241256        if time_units[-1]=="s":  time_units=time_units[:-1] 
     
    328343        lonLength=None 
    329344        size=1 
     345 
     346        seenAxes=[] 
    330347        for key in axisSelectionDict.keys(): 
    331348            #print key, axisSelectionDict[key] 
     
    335352            axis=var.getAxis(axisIndex) 
    336353             
     354            axisID=axis.id 
     355            if axisID in seenAxes:   
     356                continue 
     357            else: 
     358                seenAxes.append(axisID) 
     359 
    337360            if axisIndex==timeAxisIndex: 
    338361                axlen=len(self.getSelectedTimeSteps(datasetURI, variable, {key:(low, high)}))            
     
    354377                         
    355378            size=size*axlen 
     379            print "Axlen and size:", axlen, size 
    356380            axesCounted.append(axisIndex) 
    357381            axLens.append(axlen) 
     
    363387        arrayShape=[] 
    364388        for axis in var.getAxisList(): 
     389            print "Sizing:", size 
    365390            if axcount not in axesCounted: 
    366391                size=size*len(axis) 
     
    388413            size=size 
    389414 
     415        print "SUPERSIZE:", size 
     416 
     417        
    390418        return (tuple(arrayShape), gridShape, size) 
    391419 
     
    407435        self._openDataFile(datasetURI=datasetURI) 
    408436        var=self._getVariable(variable) 
    409          
     437 
    410438        axisList=var.getAxisList() 
    411439             
     
    433461                    (low, high, nudgeMessage)=nudgeSingleValuesToAxisValues(low, axis[:], "Latitude")     
    434462                    if loworig!=low:   print "Nudged latitudes to nearest points..." 
    435                 selectionStrings.append('%s=(%s, %s)' % (axis.id, low, high))            
     463                selectionStrings.append('%s=(%s, %s)' % (axis.id, low, high))    
    436464            elif axis.isLongitude(): 
    437465                (low, high)=axisSelectionDict[key][:2] 
     
    443471            else: 
    444472                selector=axisSelectionDict[key][:2] 
    445                 selectionStrings.append('%s=%s' % (axis.id, str(selector))) 
     473                s=str(selector) 
     474                if s[0]=="[" and s[-1]=="]": 
     475                    s="("+s[1:-1]+")" 
     476                selectionStrings.append('%s=%s' % (axis.id, s)) 
    446477         
    447478        fullSelectionString=", ".join(selectionStrings) 
     
    469500if __name__=="__main__":         
    470501    a=CDMSDataHandler() 
     502    print a.getDomain(variable="vo", datasetURI="file:/badc/ecmwf-e40/metadata/e40-1.0-am-195709-200208.xml") 
    471503    print a.getVariables(datasetGroup='Test Data Group 1', dataset='Test Dataset 1') 
    472504    print a.getVariables(datasetGroup='Test Data Group 3', datasetURI='file:/usr/local/test/dxs/testdata/testdata3.xml')     
  • TI03-DataExtractor/trunk/pydxs/CDMSOutputHandler.py

    r794 r1715  
    1616# Import package modules including global variables 
    1717from DXErrors import * 
     18from common import * 
    1819 
    1920 
     
    2425        Opens the output NetCDF file using CDMS. 
    2526        """ 
     27        self.outputFileName=outputFileName 
    2628        self.outputFile=cdms.open(outputFileName, "w") 
    2729         
     
    4042        for att in attDict: 
    4143            self.outputFile.__setattr__(att, attDict[att]) 
     44        self.outputFile.Conventions="CF-1.0" 
    4245             
    4346 
     
    5659        """ 
    5760        self.outputFile.close() 
     61        fixFilePermissions(self.outputFileName) 
  • TI03-DataExtractor/trunk/pydxs/CSMLDataHandler.py

    r1244 r1715  
    1818import os  
    1919import sys  
    20 sys.path.append("/disks/glue1/astephens")  
    21 sys.path.append("/disks/glue1/astephens/csml/parser")  
    22 sys.path.append("/disks/glue1/astephens/csml/Scanner")  
    23 #import API # csml's api class  
    2420import re  
    2521import cdms  
    2622  
    27 # Import global variables  
     23# Import package modules  
     24# Set dummy variable for local import that will be overwritten if  
     25# serverConfig is imported. 
     26ENABLE_CSML=0 
    2827from serverConfig import *  
    2928from common import *  
     
    3130from DXDMLHandler import DXDMLHandler  
    3231from DXErrors import *  
     32  
     33# Import external modules 
     34if ENABLE_CSML==1: 
     35    # Import CSML's API package 
     36    import API 
    3337  
    3438# Set up global variables  
  • TI03-DataExtractor/trunk/pydxs/DXController.py

    r1225 r1715  
    1313# Import required modules  
    1414import sys 
    15 import os  
    16 import time  
     15import os, shelve  
     16import time, getopt 
    1717 
    1818# Bring package into local scope 
    19 from serverConfig import BASEDIR 
     19from serverConfig import BASEDIR, RUNNING_DIR 
    2020sys.path.insert(0, os.path.split(BASEDIR)[0]) 
    2121sys.path.insert(0, "..") 
    2222from pydxs import * 
    2323 
    24   
    25 # Add any other locally required directories in which you have modules. 
     24# Update local pythonpath for local imports  
    2625for path in LOCAL_PYTHONPATH: 
    27    sys.path.insert(0, path)   
     26    sys.path.insert(0, path) 
     27 
     28# Get local security 
     29if SECURITY_MODEL=="BADC": 
     30    from BADCServerSecurity import * 
     31elif SECURITY_MODEL=="NDG": 
     32    from NDGSecurityManager import * 
    2833 
    2934 
     
    4651        self.username=None  
    4752        self.password=None 
     53        self.userEmail=None 
    4854        self.userRoles=[] 
    4955        self.sessionID=None 
     
    5258        self.secureToken="undefined" 
    5359        self.error=None 
    54      
     60        self.fork=None 
     61        self.status="undefined" 
     62 
    5563        # Parse the arguments 
    5664        try: 
     
    7785                raise DXSessionObjectError, error    
    7886 
     87        try: 
     88            self.statusFile=os.path.join(RUNNING_DIR, self.bag["sessionID"]) 
     89        except Exception, error: 
     90            raise DXSessionObjectError, error 
     91 
     92        # Check status if already running 
     93        if self.error==None: 
     94            try: 
     95                if self.bag.has_key("action") and self.bag["action"]=="getStatus": 
     96                    self._getStatus() # sets value of self.status 
     97                    print "\n\nSTATUS:",self.status,"\n",self.statusFile 
     98            except: 
     99                pass 
     100 
     101 
    79102        # Generate the options object 
    80         if self.error==None:     
     103        if self.error==None and not (self.bag.has_key("action") and self.bag["action"]=="getStatus"):    
    81104            try:    
    82105                self._generateOptions()   
     
    84107                raise DXOptionHandlingError, error 
    85108 
    86  
    87109        # Write request to a file if it has some content 
    88110        if self.error==None: 
    89             if overlap(["datasetGroup_1", "datasetURI_1", "sessionID", "numberOfDatasets"],  
     111            if overlap(["datasetGroup_1", "datasetURI_1", "sessionID"],  
    90112                      self.bag.keys()):          
    91113                try:       
     
    100122                except Exception, error: 
    101123                    raise DXValidationError, error""" 
    102              
     124 
    103125        # Estimate the cost of the extraction 
    104126        creditChecked=None 
     
    111133                except Exception, error: 
    112134                    raise DXCreditError, error 
    113                      
     135             
    114136 
    115137        # Estimate the cost of the extraction 
     
    119141                try: 
    120142                    (self.estimatedDuration, self.estimatedVolume)=self._createOutput(costOnly=1) 
     143                    self.bag["estimatedDuration"]=self.estimatedDuration 
     144                    self.bag["estimatedVolume"]=self.estimatedVolume 
    121145                    sizeLimitInBytes=REQUEST_SIZE_LIMIT*2L**20 
    122146                    # If size is over limit then send a tidy error to the user 
     
    127151                        err="""Your request of %.1f MB is over the current %s MB size limit.     
    128152The Data Extractor cannot yet deal with such large requests. 
    129 Consider mailing <A HREF="mailto:%s">%s</A> for advice or submit multiple smaller requests.""" % (sizeInMB,  
    130                                REQUEST_SIZE_LIMIT, ADMIN_MAIL_ADDRESS, ADMIN_MAIL_ADDRESS)       
     153Consider mailing the Adminstrator (%s) for advice or submit multiple  
     154smaller requests.""" % \ 
     155         (sizeInMB, REQUEST_SIZE_LIMIT, ADMIN_MAIL_ADDRESS, ADMIN_MAIL_ADDRESS)  
    131156                        raise DXSizeLimitError, err 
    132157                except Exception, error: 
     
    143168                             
    144169                try:         
    145                     self._createOutput()   
    146                     self.logger=LogManager(self.bag)         
    147                     self.bag["status"]="complete"        
    148                     self.logger.logCompletedRequest(self.bag["outputFilePaths"])                 
     170                    rtvalue=self._createOutput()  
     171                    if rtvalue==None: # Parent process 
     172                        self.bag["status"]="running" 
     173                        self.status=self.bag["status"]  
     174                    elif rtvalue==1: # Child process - request complete 
     175                        self.logger=LogManager(self.bag)             
     176                        self.bag["status"]="complete" 
     177                        self.status=self.bag["status"]   
     178                        self.logger.logCompletedRequest(self.bag["outputFilePaths"])             
     179                        self.fork=1                  
     180                        # Mail user to say it completed... 
     181                        if RESTRICTED_DATA==1: 
     182                            self._sendCompletionMessage()                             
     183 
    149184                except Exception, error: 
    150                     raise DXProcessingError, error 
     185                    self.bag["status"]="failed" 
     186                    self.status=self.bag["status"] 
     187                    statusFile=open(self.statusFile, "a") 
     188                    errorString=str(error).replace("\n", "  ") 
     189                    if len(errorString)>0: 
     190                        sout="%s: ERROR_STRING %s." % (self.status, errorString) 
     191                    else: 
     192                        sout=self.status 
     193                    self.errorString=errorString 
     194                    statusFile.write(sout+"\n") 
     195                    statusFile.close() 
     196                    raise Exception, error 
    151197         
    152198        if self.error==None: 
     
    154200            if self.bag.has_key("action") and self.bag["action"]=="clearRequest": 
    155201                del self.bag["action"] 
     202            for key in ["proceed", "getOutput", "confirm", "action"]: 
     203                if self.bag.has_key(key): 
     204                    del self.bag[key] 
    156205            self.sessionObjectManager.writeSessionObject(self.bag) 
    157206        else: 
     
    159208            self.logger.logError(self.error) 
    160209          
     210        if self.fork==1: pass # os._exit() 
     211 
    161212             
    162213    def _parseArgs(self, args): 
     
    194245        allowed groups from whatever implementation you have put in place. 
    195246        """ 
    196         if SECURITY_MODEL=="basic": 
     247        secClassMap={"basic":"SecurityManager", "badc":"BADCServerSecurity", 
     248                     "ndg":"NDGSecurityManager"} 
     249        try: 
     250            secClass=secClassMap[SECURITY_MODEL] 
     251        except: 
     252            raise DXSecurityError, "Security model '%s' not supported." % SECURITY_MODEL 
     253 
     254        secChecker=eval("%s(self.username, self.password, self.secureToken)" % secClass) 
     255  
     256        """if SECURITY_MODEL=="basic": 
    197257            secChecker=SecurityManager(self.username, self.password, self.secureToken) 
     258        elif SECURITY_MODEL=="badc": 
     259            secChecker=BADCServerSecurity(self.username, self.password, self.secureToken) 
    198260        elif SECURITY_MODEL=="ndg": 
    199261            secChecker=NDGSecurityManager(self.username, self.password, self.secureToken)  
    200262        else: 
    201             raise DXSecurityError, "Security model '%s' not supported." % SECURITY_MODEL 
     263            raise DXSecurityError, "Security model '%s' not supported." % SECURITY_MODEL""" 
    202264           
    203265        # Do something about logout here as well 
     
    205267        secCheck=secChecker.validateUser()  
    206268        self.username=secChecker.username 
     269        self.userEmail=secChecker.getUserEmail(self.username)[-1] 
    207270 
    208271        if type(secCheck)==type(""): 
     
    240303 
    241304        # Say it is under construction at present 
    242         self.bag["status"]="constructing" 
     305        #self.bag["status"]="constructing" 
     306        #self.status=self.bag["status"] 
    243307         
    244308        # Add the rest of the arguments to the session object 
     
    274338                                   "%.4d-%.2d-%.2dT%.2d:%.2d:%f" % tuple(value[1])) 
    275339 
     340    def _getStatus(self): 
     341        """ 
     342        Returns a status string for the job that is running (having forked). 
     343        """ 
     344        try: 
     345            line=open(self.statusFile).readlines()[-1] 
     346            self.status=line.strip() 
     347        except: 
     348            self.status="No status information available about your request." 
     349 
     350        if self.status.find("ERROR_STRING")>-1: 
     351            self.errorString=self.status.split("ERROR_STRING")[-1] 
     352            self.status="failed" 
     353        self.bag["status"]=self.status 
     354 
    276355 
    277356    def _generateOptions(self): 
     
    286365         
    287366         
    288     def DEPRECATED_validate(self): 
    289         """ 
    290         Validates the selections made by the user. Returns 1 if successful 
    291         and a string if failure. 
    292         """ 
    293         try: 
    294             ValidateSelection(self.bag) 
    295         except Exception, error: 
    296             raise DXValidationError, error 
    297              
    298       
    299367    def _checkCredit(self): 
    300368        """ 
     
    313381        """    
    314382        outputManager=OutputManager(self.bag) 
     383         
    315384        pathDict=outputManager.getOutputFilePathDict() 
    316385        sizeDict=outputManager.getOutputSizes() 
     
    323392            return (duration, outputSize) 
    324393         
    325         print """Should really fork this process at this point so that we can return  
    326               something if likely to be large job.""" 
    327         outputManager.createOutputs() 
    328         pathDict=outputManager.getOutputFilePathDict() 
    329         sizeDict=outputManager.getOutputSizes() 
    330         durationDict=outputManager.getOutputDurationEstimates() 
    331          
    332         (outputFilePaths, outputSize, duration)=constructOutputInformation(pathDict, sizeDict, durationDict) 
    333         self.bag["outputFilePaths"]=outputFilePaths 
    334          
     394        print "\n"*5 
     395        print os.getpid(),"\n\n" 
     396        print """FORKING HERE...""" 
     397 
     398        if duration<0: 
     399            # No need to fork quick process 
     400            outputManager.createOutputs() 
     401        else: 
     402            forkedProcess=os.fork() 
     403 
     404            if forkedProcess==0: 
     405                self.bag["status"]="processing" 
     406                self.status=self.bag["status"] 
     407                statusFile=open(self.statusFile, "a") 
     408                statusFile.write(self.status+"\n") 
     409                statusFile.close() 
     410                outputManager.createOutputs() 
     411                self.bag["status"]="complete" 
     412                self.status=self.bag["status"] 
     413                statusFile=open(self.statusFile, "a") 
     414                statusFile.write(self.status+"\n") 
     415                statusFile.close() 
     416 
     417                return 1 
     418            else: 
     419                return 
     420 
     421    def _sendCompletionMessage(self): 
     422        """ 
     423        Mails user to inform her that job has completed and where files are. 
     424        """ 
     425        subject="BADC Data Extractor: Job %s complete" % self.bag["sessionID"] 
     426        fileList=[translateURI(uri) for uri in self.bag["outputFilePaths"]] 
     427        pathString="" 
     428        length=len(fileList) 
     429        if length==1: 
     430            plural1="file has" 
     431            plural2="is" 
     432        else: 
     433            plural1="files have" 
     434            plural2="are" 
     435 
     436        if length>50: 
     437            lm50=length-50 
     438            midString=""" 
     439   *** and %s more files following the same file-naming convention... *** 
     440""" % lm50 
     441            fileList=fileList[:25]+[midString]+fileList[-25:] 
     442        for f in fileList: 
     443            pathString+="""%s 
     444""" % f 
     445          
     446        msg="""Dear BADC User, 
     447 
     448Your Data Extractor job has successfully completed. 
     449 
     450%s output %s been produced and %s accessible via: 
     451 
     452%s  
     453 
     454====================================== 
     455 
     456Thank you for using the Data Extractor.  
     457 
     458If you have any comments please contact the Administrator at: %s 
     459 
     460""" % (length, plural1, plural2, pathString, ADMIN_MAIL_ADDRESS) 
     461        sendMail([self.userEmail], subject, msg, autoline="off") 
     462 
    335463 
    336464 
    337465if __name__=="__main__": 
    338     x=DXController({}).bag 
    339     sessionID=x["sessionID"] 
    340     DXController({"sessionID":sessionID, "secureToken":None}) 
    341     DXController({"sessionID":sessionID, "secureToken":None, "datasetGroup_1":"Test Data Group 1"}) 
    342     DXController({"sessionID":sessionID, "secureToken":None, "dataset_1.1":"Test Dataset 1"})     
    343     DXController({"sessionID":sessionID, "secureToken":None, "variable_1.1.1":"pqn"}) 
    344     DXController({"sessionID":sessionID, "secureToken":None, "axis_1.1.1.2":(-30,30)})  
    345     DXController({"sessionID":sessionID, "secureToken":None, "axis_1.1.1.1":("1999-01-01T00:00:00", "1999-01-01T06:00:00")}) 
    346     DXController({"sessionID":sessionID, "secureToken":None, "outputFormat_1.1.1":"NetCDF"})   
    347     DXController({"sessionID":sessionID, "secureToken":None, "outputFormat_1.1.1":"NetCDF", "action":"requestCosts"})            
    348     DXController({"sessionID":sessionID, "secureToken":None, "getOutput":"getOutput"})     
    349      
     466    # Test if called at command-line 
     467    args=sys.argv[1:] 
     468    if len(args)>0: 
     469        sessionFile=None 
     470        configFile=None 
     471        (argList, dummy)=getopt.getopt(args, "s:c:")         
     472        for arg,value in argList: 
     473            if arg=="-s": 
     474                sessionFile=value 
     475            elif arg=="-c": 
     476                configFile=value 
     477 
     478        if not sessionFile or not configFile: 
     479            print "Cannot run from command line without -c and -s arguments used correctly." 
     480            sys.exit() 
     481         
     482        # get correct config path set up 
     483        sys.path.insert(0, os.path.split(configFile)[0]) 
     484        dict=shelve.open(sessionFile) 
     485        sessDict={} 
     486        for key,value in dict.items(): 
     487            sessDict[key]=value 
     488 
     489        DXController(sessDict) 
     490                 
     491 
     492    else: 
     493        # OLD TESTS 
     494        x=DXController({}).bag 
     495        sessionID=x["sessionID"] 
     496        DXController({"sessionID":sessionID, "secureToken":None}) 
     497        DXController({"sessionID":sessionID, "secureToken":None, "datasetGroup_1":"Test Data Group 1"}) 
     498        DXController({"sessionID":sessionID, "secureToken":None, "dataset_1.1":"Test Dataset 1"})     
     499        DXController({"sessionID":sessionID, "secureToken":None, "variable_1.1.1":"pqn"}) 
     500        DXController({"sessionID":sessionID, "secureToken":None, "axis_1.1.1.2":(-30,30)})  
     501        DXController({"sessionID":sessionID, "secureToken":None, "axis_1.1.1.1":("1999-01-01T00:00:00", "1999-01-01T06:00:00")}) 
     502        DXController({"sessionID":sessionID, "secureToken":None, "outputFormat_1.1.1":"NetCDF"})   
     503        DXController({"sessionID":sessionID, "secureToken":None, "outputFormat_1.1.1":"NetCDF", "action":"requestCosts"})            
     504        DXController({"sessionID":sessionID, "secureToken":None, "getOutput":"getOutput"})     
     505 
  • TI03-DataExtractor/trunk/pydxs/DXDMLHandler.py

    r1244 r1715  
    2020# Import local modules 
    2121from serverConfig import INPUT_DATASETS_FILE 
    22 from common import deUnicodeObject 
     22from common import deUnicodeObject,sortUnique 
    2323from DXErrors import * 
    2424 
     
    4343        for dsg in dsgNodes: 
    4444            dsgNames.append(dsg.getElementsByTagName("dxGroupLongName")[0].childNodes[0].nodeValue.strip()) 
    45         dsgNames.sort() 
     45        dsgNames=sortUnique(dsgNames) 
    4646        return dsgNames 
    4747 
     
    6161        if dsNames==[]: 
    6262            raise DXOptionHandlingError, "Cannot match any datasets to dataset group: '%s'" % datasetGroup 
    63         dsNames.sort() 
     63        dsNames=sortUnique(dsNames) 
     64         
    6465        return dsNames     
    6566 
     
    8384        if rtlist==[]: 
    8485            raise DXOptionHandlingError, "Cannot match any datasets to dataset group: '%s'" % datasetGroup 
    85         rtlist.sort() 
     86        rtlist=sortUnique(rtlist) 
    8687        return rtlist                    
    8788 
     
    105106                    dsURIs.append([dsURI, dsName, dsgName]) 
    106107 
    107         dsURIs.sort() 
     108        dsURIs=sortUnique(dsURIs) 
    108109        return dsURIs     
    109110 
     
    147148        URI_list=self.getDatasetURIList() 
    148149        for i in URI_list: 
    149             print i 
    150150            if i[0]==datasetURI or i[0]==("file:"+datasetURI): 
    151151                return (i[2], i[1]) 
    152         raise DXOptionHandlingError, "Cannot match any dataset group and dataset to the datasetURI: '%s'" % datasetURI 
     152                     
     153        raise DXOptionHandlingError, ("Cannot match any dataset group and dataset to the datasetURI: '%s'" % datasetURI) 
    153154 
    154155 
  • TI03-DataExtractor/trunk/pydxs/DatasetFormatDecider.py

    r1138 r1715  
    2121from CDMSDataHandler import * 
    2222from CSMLDataHandler import * 
     23from MIDASDataHandler import * 
     24from ECMWFGRIB1NoSubsetDataHandler import * 
    2325 
    2426 
     
    4042        self.datasetFormat=None 
    4143 
    42         #print "INPUTS ot DatasetFormatDecider:", datasetGroup, dataset, datasetURI 
     44        #print "INPUTS to DatasetFormatDecider:", datasetGroup, dataset, datasetURI 
    4345 
    4446        if not datasetURI: 
     
    4951         
    5052        if datasetURI==None: 
     53            print "HELP HELP HELP\n\n\n", datasetGroup, dataset, "\n\n" 
    5154            raise DXError, "Cannot determine the datasetURI." 
    5255             
     
    5558        if not os.path.isfile(datasetURI): 
    5659            # check if it is a class 
    57             parts=datasetURI.split("/") 
    58             raise DXError, "Checking for class not yet implemented." 
     60            if datasetURI.find("MIDAS")>-1: 
     61                self.datasetFormat=MIDASDataHandler() 
     62            else: 
     63                parts=datasetURI.split("/") 
     64                raise DXError, "Checking for class not yet implemented." 
    5965        else: 
    6066            header=open(datasetURI).read(1000) 
    61             if header.lower().find("cdms")>-1: 
     67            if header.find("GRIBNoSubset")>-1: 
     68                self.datasetFormat=ECMWFGRIB1NoSubsetDataHandler() 
     69            elif header.lower().find("cdms")>-1: 
    6270                self.datasetFormat=CDMSDataHandler() 
    6371            elif header.lower().find("csml")>-1: 
     
    6977 
    7078if __name__=="__main__": 
     79    print  DatasetFormatDecider("ECMWF ERA-40 Re-analyses","6-hourly Analyses on Model Levels (T159 Spectral)").datasetFormat 
    7180    print "CDMS file..." 
    7281    print DatasetFormatDecider("Test Data Group 3", "Test Dataset 3").datasetFormat 
  • TI03-DataExtractor/trunk/pydxs/DateTimeManager.py

    r794 r1715  
    7373    return dt.getTimeBins(timelist) 
    7474 
     75 
     76def convertToSeconds(interval, unit): 
     77    """ 
     78    Returns the number of seconds in the interval. 
     79    Note: year and month are approx values. 
     80    """ 
     81    unit=unit.lower() 
     82    if unit[-1]=="s": unit=unit[:-1] 
     83    if unit=="year":  
     84        secs=365*24*60*60*interval 
     85    elif unit=="month": 
     86        secs=30*24*60*60*interval 
     87    elif unit=="day": 
     88        secs=24*60*60*interval 
     89    elif unit=="hour": 
     90        secs=60*60*interval 
     91    elif unit=="minute": 
     92        secs=60*interval 
     93    elif unit=="second": 
     94        pass 
     95    else: 
     96        raise "Unit not recognised: %s" % unit 
     97    return secs 
     98 
     99 
     100def getAppropriateUnitAndInterval(value, unit): 
     101    """ 
     102    Returns the appropriate time unit nearest to an integer for 
     103    time values that are fractions. 
     104    """ 
     105    if value>=1: 
     106        return (unit, int(value)) 
     107    nsecs=convertToSeconds(value, unit) 
     108    nsecs=int(nsecs) 
     109     
     110    if nsecs<=1: 
     111        (u,i)=("second", 1) 
     112    elif nsecs<=60: 
     113        (u,i)=("second", nsecs) 
     114    elif nsecs<=(60*60): 
     115        (u,i)=("minute", nsecs/60) 
     116    elif nsecs<=(60*60*24): 
     117        (u,i)=("hour", nsecs/60/60) 
     118    elif nsecs<=(60*60*24*30): 
     119        (u,i)=("day", nsecs/60/60/24) 
     120    elif nsecs<=(60*60*24*365): 
     121        (u,i)=("month", nsecs/60/60/24/30) 
     122    else: 
     123        (u,i)=("year", nsecs/60/60/24/365) 
     124    return (u,i) 
     125 
     126 
     127def formatYear(fstring, dateTimeObj): 
     128    """ 
     129    Copes with year outside Unix time epoch. 
     130    """ 
     131    return fstring.replace("%Y", "%.4d" % dateTimeObj[0]) 
    75132 
    76133 
     
    263320        else: 
    264321            monthmap=(None, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 
    265             return monthmap[month] 
     322            return monthmap[int(month)] 
    266323             
    267324             
     
    290347        #    count=count+1           
    291348        #checkCount=0 
    292         formatstring=time.strftime(formatstring, tuple(list((itime))+[0,1,0])) 
     349        formatstring=formatYear(formatstring, itime) 
     350        # Note the year has been got now so the rest uses a fake year to avoid error outside unix time 
     351        formatstring=time.strftime(formatstring, tuple([2000]+list((itime[1:]))+[0,1,0])) 
    293352        #while formatstring.find("%")>-1:  # Keep in while loop just in case more than one occurrence of a field required 
    294353        #    checkCount=checkCount+1 
  • TI03-DataExtractor/trunk/pydxs/FileNames.py

    r1153 r1715  
    6363        if basedir: 
    6464            self.template=os.path.join(basedir, self.template) 
    65   
     65 
    6666  
    6767    def getFileNameTemplate(self): 
     
    8484            (temp1, temp2)=self.template.split("<date_time_here>")  
    8585            fileNames=[]  
    86          
    87             for timeStep in self.timeSteps:  
    88                 fileName=createList(timeStep, timeStep, formatstring=(temp1+"%Y%m%d%H"+temp2))[0]  
    89                 fileNames.append(fileName)  
    90            
     86            if len(self.timeSteps)==1: 
     87                ts=self.timeSteps[0] 
     88                try:  
     89                    ts="%.4d%.2d%.2d%.2d" % tuple(getDateTimeComponents(ts)[:4]) 
     90                except: 
     91                    pass 
     92                #print temp1, ts, temp2 
     93                fname=(temp1+ts+temp2).replace(" ","") 
     94                fileNames=[fname] 
     95 
     96            else: 
     97                #print self.timeSteps, "\n", len(self.timeSteps) 
     98                for timeStep in self.timeSteps:  
     99                    fileName=createList(timeStep, timeStep, formatstring=(temp1+"%Y%m%d%H"+temp2))[0]  
     100                    fileNames.append(fileName)  
     101 
    91102        fileNames=[self._tidyFileNameObject(fn) for fn in fileNames]     
    92103        return fileNames  
     
    194205            fnobj=fnobj.replace("_-", "_")  
    195206            fnobj=fnobj.replace("_.", ".") 
     207            fnobj=fnobj.replace(" ","") 
    196208            end=fnobj  
    197209            if start==end: found=None  
    198          
     210 
     211        fnobj=fnobj.replace(" ","")         
    199212        fnobj=fnobj.replace("_undefined_", "_") 
    200213        fnobj=fnobj.lower()  
  • TI03-DataExtractor/trunk/pydxs/InputDatasetManager.py

    r1138 r1715  
    2222from common import * 
    2323from DXErrors import * 
     24 
     25 
     26def deleteExcessWhiteSpace(xmlString): 
     27    """ 
     28    Removes excess white space in the xml string. 
     29    """ 
     30    xmlString=xmlString.replace("  ","") 
     31    xmlString=xmlString.replace("  ","") 
     32    return xmlString 
     33 
    2434 
    2535class InputDatasetManager: 
     
    5464                 ["dxGroupLongName","REQUIRED"], 
    5565                 ["dxGroupFileNamePrefix","undefined"], 
    56                  ["dxGroupAccessRestrictions",[["permittedRoles","all"], ["permittedUsers","all"]]], 
     66                 ["dxGroupAccessRestrictions",[["permittedRoles",""], ["permittedUsers","none"]]], 
    5767                 ["MetadataLinks",[["detailedMetadataLink", "undefined"],  
    5868                                   ["discoveryMetadataLink", "undefined"], 
     
    100110                 ["dxDatasetLongName","REQUIRED"], 
    101111                 ["dxDatasetFileNameSection","undefined"], 
    102                  ["dxDatasetAccessRestrictions",[["permittedRoles","all"], ["permittedUsers","all"]]], 
     112                 ["dxDatasetAccessRestrictions",[["permittedRoles",""], ["permittedUsers","none"]]], 
    103113                 ["MetadataLinks",[["detailedMetadataLink", "undefined"],  
    104114                                   ["discoveryMetadataLink", "undefined"], 
     
    157167        self.doc.writexml(outputFile, indent="", addindent="    ", newl="\n") 
    158168        outputFile.close() 
     169        time.sleep(1) 
     170        f=open(outputFilePath) 
     171        data=f.read() 
     172        f.close() 
     173        data=deleteExcessWhiteSpace(data) 
     174        f=open(outputFilePath, "w") 
     175        f.write(data) 
     176        f.close() 
    159177        print "New input dataset XML file written to: %s" % outputFilePath 
    160178         
    161179         
    162 """      
    163     def (self):          
    164     def (self):  
    165     def (self):  
    166     def (self):  
    167     def (self):  
    168     def (self):  
    169     def (self):  
    170     def (self):  
    171     def (self):  
    172     def (self):  
    173     def (self):  
    174     def (self):  
    175     def (self):  
    176 """ 
    177180 
    178181  
  • TI03-DataExtractor/trunk/pydxs/MailManager.py

    r794 r1715  
    2020from common import * 
    2121 
    22 def sendMail(recipients, subject, msg): 
     22def sendMail(recipients, subject, msg, autoline="on"): 
    2323    """ 
    2424    Wrapper for MailManager class. 
    2525    """ 
    2626    x=MailManager() 
    27     x.sendMail(recipients, subject, msg) 
     27    x.sendMail(recipients, subject, msg, autoline) 
    2828    print "Sent mail." 
    2929 
     
    4343         
    4444         
    45     def sendMail(self, recipients, subject, msg): 
     45    def sendMail(self, recipients, subject, msg, autoline="on"): 
    4646        """ 
    4747        Sends out the message provided. 
    4848        """  
    49         sender=ADMIN_MAIL_ADDRESS 
    50          
     49        sender=MAIL_SENDER 
     50        if autoline=="on": 
     51            autoline="This message has been automatically generated by the %s\n" %  PACKAGE_NAME 
     52        else: 
     53            autoline="" 
     54             
    5155        # mail to each separately 
    5256        for recipient in recipients:             
     
    5458From: %s 
    5559Subject: %s 
    56 This message has been automatically generated by the %s\n 
    57 %s""" % (recipient, sender, subject, PACKAGE_NAME, msg) 
     60%s%s""" % (recipient, sender, subject, autoline, msg) 
    5861            self.mailserver.sendmail(sender, recipient, content) 
    5962 
  • TI03-DataExtractor/trunk/pydxs/OptionHandler.py

    r1244 r1715  
    2222from CDMSDataHandler import * 
    2323from CSMLDataHandler import * 
     24from ECMWFGRIB1NoSubsetDataHandler import * 
     25from MIDASDataHandler import * 
    2426from DXErrors import * 
    2527from DatasetFormatDecider import * 
     
    228230            elif isinstance(dataHandler, CSMLDataHandler): 
    229231                outputFormatList=["CSML/NetCDF"] 
     232            elif isinstance(dataHandler, MIDASDataHandler): 
     233                outputFormatList=["ASCII Text"] 
     234            elif isinstance(dataHandler, ECMWFGRIB1NoSubsetDataHandler): 
     235                outputFormatList=["GRIB"] 
    230236                 
    231237            choices.append(("outputFormat_%s.%s.%s" % (dsgCode, dsCode, varCode), outputFormatList)) 
  • TI03-DataExtractor/trunk/pydxs/OutputManager.py

    r1160 r1715  
    3030from CSMLDataHandler import * 
    3131from CSMLOutputHandler import * 
     32from ECMWFGRIB1NoSubsetDataHandler import * 
     33from ECMWFGRIB1NoSubsetOutputHandler import * 
     34from MIDASDataHandler import * 
     35from MIDASOutputHandler import * 
    3236from DatasetFormatDecider import * 
    3337from FileNames import * 
    3438from DXErrors import * 
     39import dxvv 
    3540 
    3641# Make sure CDMS automatic bounds generation is set to OFF 
     
    106111            varID=dct[key][1] 
    107112            paths=dct[key][4] 
    108             pathdict[varID]=paths 
     113            pathdict["%s-%s"%(varID,key)]=paths 
    109114        return pathdict 
    110115 
     
    119124            varID=dct[key][1] 
    120125            size=dct[key][2] 
    121             sizedict[varID]=size 
     126            sizedict["%s-%s"%(varID,key)]=size 
    122127        return sizedict 
    123128         
     
    137142            if format=="NASA Ames": 
    138143                multiplier=3 
    139             durationdict[varID]=size*TIMING_SCALE_FACTOR*multiplier 
     144 
     145            if format=="ASCII text": 
     146                multiplier=multiplier*5 
     147 
     148            dur=size*TIMING_SCALE_FACTOR*multiplier 
     149            if dur<5: dur=3 
     150            durationdict["%s-%s"%(varID,key)]=dur 
    140151        return durationdict 
    141152 
     
    169180 
    170181        varCount=0 
     182 
     183        # Check number of datasets is not over limit 
     184        if len(varKeys)>MAX_NUM_DATASETS: 
     185            raise Exception, "You have requested more variables than the current DX limit (%s). Please go back and reduce the size of your request." % MAX_NUM_DATASETS 
     186 
     187        # Loop through all variables 
    171188        for varKey in varKeys: 
    172189            varCodes=varKey.split("_")[-1] 
     
    186203            sizeOfRequest=self._adjustFileSizeByFormat(sizeOfRequest, outputFormat) 
    187204             
    188                      
     205            if sizeOfRequest>(REQUEST_SIZE_LIMIT*(2**20)): 
     206                raise Exception, "Your request is above the current size limit for the DX (of %s MB), please submit smaller requests." % REQUEST_SIZE_LIMIT 
     207 
     208            print "\n"*10, sizeOfRequest, REQUEST_SIZE_LIMIT*(2**20)         
     209             
     210            # Now split depending on single or multiple output 
    189211            if sizeOfRequest>(MAX_FILE_SIZE*(2**20)) or ONE_FILE_PER_TIMESTEP==1: 
    190212                     
    191                 print "\n\n\n", (MAX_FILE_SIZE*(2**20)), sizeOfRequest, ONE_FILE_PER_TIMESTEP 
     213                print "\n\n\n", MAX_FILE_SIZE, (MAX_FILE_SIZE*(2**20)), sizeOfRequest, ONE_FILE_PER_TIMESTEP 
    192214                 
     215                # If only need to generate file names - multiple files 
    193216                if mode=="file names": 
    194217                    fileNamer=FileNames(datasetGroup=datasetGroup, dataset=dataset, timeSteps=timeStepStringList,  
    195218                                    fileFormat=outputFormat, variables=[varID], 
    196219                                    basedir=self.outputDir) 
     220 
    197221                    outputFilePathList=fileNamer.createFileNameList() 
    198                      
     222 
    199223                    if isinstance(dataFileHandler, CSMLDataHandler): 
    200224                        # CSML special case, just make first file the xml with copy of first .nc name 
     
    202226                        csmlPath=os.path.splitext(ncPath)[0]+".xml" 
    203227                        outputFilePathList.insert(0, csmlPath) 
    204                  
     228 
     229                # Otherwise create the outputs - multiple files 
     230                # CSML not supported via this route yet 
     231                # MIDAS not supported via this route yet 
    205232                elif mode=="create outputs": 
    206233                    # Now get the real data 
     
    216243                        outputFilePathList.append(outputFilePath) 
    217244                                                 
    218                         data=dataFileHandler.readVariableSubsetIntoMemory(datasetURI, varID, axisSelectionDict, timeStep) 
     245                        if varID[-5:]=="_dxvv": 
     246                            # Check if virtual variable being used 
     247                            vvd=dxvv.VVDict() 
     248                            procClass=vvd.getProcessingClass(varID, datasetURI) 
     249                            exec "vvHandler=dxvv.%s" % procClass 
     250                            data=vvHandler(varID, datasetURI, axisSelectionDict, timeStep).var 
     251                            print data 
     252                        else:  
     253                            data=dataFileHandler.readVariableSubsetIntoMemory(datasetURI, varID, axisSelectionDict, timeStep) 
    219254                         
    220255                        outputFileHandler=outputHandler(outputFilePath) 
     
    223258                        outputFileHandler.closeFile() 
    224259                        print "\nWrote variable '%s' to output file: %s" % (varID, outputFilePath)               
    225                          
     260                        fixFilePermissions(outputFilePath) #added as fix?                
     261 
     262            # Else if only producing one output file 
     263            # or NetCDF and CSML in the case of CSML     
    226264            else: 
    227265                if len(timeStepStringList)==0: 
     
    230268                    timeStepStringList=timeStepStringList 
    231269                else: 
    232                     timeStepStringList=["%s-%s" % (timeStepStringList[0], timeStepStringList[-1])] 
     270                    ts0="%.4d%.2d%.2d%.2d" % tuple(getDateTimeComponents(timeStepStringList[0])[:4]) 
     271                    ts1="%.4d%.2d%.2d%.2d" % tuple(getDateTimeComponents(timeStepStringList[-1])[:4]) 
     272                    timeStepStringList=["%s-%s" % (ts0,ts1)] 
    233273                             
     274                # File names are created here as well - should really cache this 
    234275                print "Work out file name as only one file..." 
    235276                fileNamer=FileNames(datasetGroup=datasetGroup, dataset=dataset, timeSteps=timeStepStringList,  
    236277                                    fileFormat=outputFormat, variables=[varID], 
    237278                                    basedir=self.outputDir) 
     279              
    238280                outputFilePathList=fileNamer.createFileNameList() 
    239                          
     281                #print outputFilePathList                
     282 
     283                # If CSML - single output file - for creating file names 
    240284                if isinstance(dataFileHandler, CSMLDataHandler): 
    241285                    ncPath=outputFilePathList[0] 
     
    243287                    outputFilePathList.insert(0, csmlPath) 
    244288                                 
     289                # If creating outputs - single output file 
     290                # or CSML/NetCDF supporting CSML 
    245291                if mode=="create outputs": 
    246292                    # Now get the real data 
     
    248294                    outputFilePath=outputFilePathList[0] 
    249295                     
     296 
     297                    # CSML route 
    250298                    if isinstance(dataFileHandler, CSMLDataHandler): 
    251299                        # CSML needs subsetting in one go 
    252                         #ncPath=outputFilePath 
    253                         #csmlPath=os.path.splitext(ncPath)[0]+".xml" 
    254                         #outputFilePathList.insert(0, csmlPath) 
    255300                        dataFileHandler.subsetVariableToCSMLNC(datasetURI, varID, axisSelectionDict, csmlPath, ncPath) 
     301                        fixFilePermissions(csmlPath) 
     302                        fixFilePermissions(ncPath) 
    256303                        print "\nWrote variable '%s' to output files: %s, %s" % (varID, csmlPath, ncPath) 
     304 
     305                    # MIDAS handler here 
     306                    elif isinstance(dataFileHandler, MIDASDataHandler): 
     307                        # MIDAS does subsetting in one go 
     308                        dataFileHandler.subsetMIDASToASCIIFile(datasetURI, axisSelectionDict, outputFilePath, region=None) 
     309                        fixFilePermissions(outputFilePath)  
     310                        print "\nWrote MIDAS subset to output file: %s" % outputFilePath 
     311 
     312                    # CDMS route - including virtual variables 
    257313                    else: 
    258                         data=dataFileHandler.readVariableSubsetIntoMemory(datasetURI, varID, axisSelectionDict) 
     314                        if varID[-5:]=="_dxvv": 
     315                            # Check if virtual variable being used 
     316                            vvd=dxvv.VVDict() 
     317                            procClass=vvd.getProcessingClass(varID, datasetURI) 
     318                            exec "vvHandler=dxvv.%s" % procClass 
     319                            data=vvHandler(varID, datasetURI, axisSelectionDict).var 
     320                            print data 
     321                        else: 
     322                            data=dataFileHandler.readVariableSubsetIntoMemory(datasetURI, varID, axisSelectionDict) 
    259323                         
    260324                        outputFileHandler=outputHandler(outputFilePath) 
     
    263327                        outputFileHandler.closeFile() 
    264328                        print "\nWrote variable '%s' to output file: %s" % (varID, outputFilePath)                   
     329                        fixFilePermissions(outputFilePath)  
    265330                     
    266331     
     
    268333            print "\n\n", outputFilePathList, "\n\n" 
    269334            varCount=varCount+1 
     335            print "\n\nHERE IS THE VARDICT...\n\n", self.varDict 
    270336 
    271337 
     
    274340        Get output handler. 
    275341        """ 
    276         if outputFormat not in OUTPUT_FORMATS: 
    277             raise DXOptionHandlingError, "Output format '%s' is not supported." % outputFormat 
     342        #if outputFormat not in OUTPUT_FORMATS: 
     343        #    raise DXOptionHandlingError, "Output format '%s' is not supported." % outputFormat 
    278344             
    279345        if isinstance(dataHandler, CDMSDataHandler): 
     
    284350        elif isinstance(dataHandler, CSMLDataHandler): 
    285351            outputHandler=CSMLOutputHandler 
     352        elif isinstance(dataHandler, MIDASDataHandler): 
     353            outputHandler=MIDASOutputHandler 
    286354             
    287355        return outputHandler 
     
    380448            outputFileHandler.writeVariableAndGlobalAttributes(data, {}) 
    381449            outputFileHandler.closeFile() 
    382              
    383             print "\nWrote variable '%s' to output file: %s" % (data.id, outputFilePath)                     
    384              
    385  
     450            print "\nWrote variable '%s' to output file: %s" % (data.id, outputFilePath) 
    386451        outputVarID=opMethod 
    387452        self.varDict[0]=(datasetURI, outputVarID, outputSize, outputFormat, outputFilePathList[:]) 
     
    394459if __name__=="__main__": 
    395460    #print "Setting ONE_FILE_PER_TIMESTEP=1" 
    396    
     461    x=OutputManager({"username":"jane", "datasetGroup_1":"Test Data Group 1", 
     462                     "dataset_1.3":"Test Dataset 1", "variable_1.3.1":"twotimespqn_dxvv", 
     463                     "axis_1.3.1.1":("1999-01-01T00:00:00", "1999-01-01T06:00:00"), 
     464                     "outputFormat_1.3.1":"NetCDF", 
     465                     "datasetGroup_2":"Test Data Group 2", 
     466                     "dataset_2.1":"Test Dataset 2", "variable_2.1.1":"var2", 
     467                     "axis_2.1.1.1":("2004-01-01T12:00:00", "2004-01-01T12:00:00"), 
     468                     "outputFormat_2.1.1":"NetCDF"})  
     469    print x.getOutputFilePathDict()    
     470    print x.createOutputs() 
     471    sys.exit() 
    397472    #ONE_FILE_PER_TIMESTEP=1 
    398473    x=OutputManager({"username":"jane", "datasetGroup_1":"Test Data Group 1", 
  • TI03-DataExtractor/trunk/pydxs/SecurityManager.py

    r794 r1715  
    119119                return "Your log in has expired. Please log in again." 
    120120    
     121 
     122    def getUserEmail(self, username): 
     123        """ 
     124        Returns e-mail address of user. 
     125        """ 
     126        return (username, "completely.RANDOM.email.address@non-existent.server.org") 
  • TI03-DataExtractor/trunk/pydxs/__init__.py

    r1225 r1715  
    5252from CSMLOutputHandler import CSMLOutputHandler 
    5353 
     54# MIDASDataHandler is the class that allows a MIDAS dataset to be interrogated. 
     55from MIDASDataHandler import MIDASDataHandler 
     56 
     57# MIDASOutputHandler is a dummy class. 
     58# Note: It might not actually be needed! 
     59from MIDASOutputHandler import MIDASOutputHandler 
     60 
    5461# OutputManager is the class used to match the request to the dataset and 
    5562# actually extract data. 
  • TI03-DataExtractor/trunk/pydxs/common.py

    r1244 r1715  
    3232CF_METADATA_GLOBAL_ATTRIBUTE_KEYS="Conventions title source institution history references comment".split() 
    3333 
     34dateTimePattern=re.compile(r"^(\d{4}).(\d{1,2}).(\d{1,2})(\s+|T)(\d+):(\d+):(\d+\.?.*)$") 
     35 
     36 
    3437# Set up common functions 
    3538 
     39def getDateTimeComponents(dateTimeString): 
     40    """ 
     41    Takes in a time string in standard DateTime format and returns the items in it. 
     42    """ 
     43    match=dateTimePattern.match(dateTimeString) 
     44    if not match: 
     45        raise "Cannot match date time string: %s" % dateTimeString 
     46 
     47    items=match.groups() 
     48    (year, month, day, hour, minute)=[int(i) for i in items[:3]+items[4:6]] 
     49    second=float(items[6]) 
     50    return (year, month, day, hour, minute, second) 
     51 
     52 
    3653def mapFileFormatToExtension(format): 
    3754    """ 
    3855    Returns a suitable file extension for a known file format. 
    3956    """ 
    40     extMap={"CSML/NetCDF":"nc", "NetCDF":"nc", "NASA Ames":"na"} 
     57    extMap={"CSML/NetCDF":"nc", "NetCDF":"nc", "NASA Ames":"na", "ASCII Text":"txt"} 
    4158    return extMap[format] 
    4259     
     
    156173    duration=0 
    157174         
     175    print "\n\nKEYS OH KEYS", pathDict.keys(), sizeDict.keys(), durationDict.keys() 
     176 
    158177    for key in pathDict.keys(): 
     178         
    159179        outputSize=outputSize+sizeDict[key] 
    160180        duration=duration+durationDict[key] 
     
    225245    return newpath 
    226246 
     247 
     248def sortUnique(list1): 
     249    """ 
     250    Returns sorted list that removes any duplicates. 
     251    """ 
     252    rtlist=[] 
     253    list1.sort() 
     254    for i in list1: 
     255        if i not in rtlist: rtlist.append(i) 
     256    return rtlist 
    227257 
    228258 
     
    365395    to write the output and if not it creates it. 
    366396    """  
     397    if SECURITY_MODEL=="badc": 
     398        reqDirScript="/home/badc/software/infrastructure/make_user_request_dir" 
     399        os.system("%s %s > /dev/null" % (reqDirScript, user)) 
     400    else:  
     401        makeDirsAndPerms(OUTPUT_DIR, user, OUTPUT_DIR_PERMISSION, "%s.%s" % 
     402                                               (OUTPUT_FILE_USER, OUTPUT_FILE_GROUP)) 
     403                                                
    367404    if user==None or user=="None":   user="anonymous" 
    368405    outputDir=os.path.join(OUTPUT_DIR, user, "dx_output") 
     
    370407        makeDirsAndPerms(OUTPUT_DIR, (user, "dx_output"), OUTPUT_DIR_PERMISSION, "%s.%s" % 
    371408                                           (OUTPUT_FILE_USER, OUTPUT_FILE_GROUP)) 
    372     # Local rule follows 
    373     if LOCAL_RULES==1:  makeAccessControlFile(user)      
    374409    return outputDir 
    375410 
  • TI03-DataExtractor/trunk/pydxs/version.py

    r1225 r1715  
    1111""" 
    1212 
    13 version="0.3.0" 
     13version="0.3.4" 
  • TI03-DataExtractor/trunk/setup.py

    r1244 r1715  
    3838import sys, os, shutil, time, re 
    3939from ConfigParser import ConfigParser 
    40 version="0.3.0" 
     40version="0.3.4" 
    4141overwrite="OFF" 
    4242 
     
    276276        configFile.close() 
    277277        print "Re-written config file: %s\n" % (configFileName) 
    278  
    279          
    280         if "MAP_APPLET_TEMPLATE_LOCAL_PATH" in confFileVarDict.keys(): 
     278             
     279        if "MAP_APPLET_TEMPLATE_LOCAL_DIR" in confFileVarDict.keys():            
    281280            print "\nChanging permissions on maps/ directory..." 
    282             os.chmod(os.path.split(MAP_APPLET_TEMPLATE_LOCAL_PATH)[0], 0777) 
     281            os.chmod(MAP_APPLET_TEMPLATE_LOCAL_DIR, 0777) 
    283282 
    284283        # Need my cleaning old python installations code here... 
     
    309308    if "dxs" in packages: 
    310309        print """You can start the server Web Service by typing: 
    311     python %s/bin/DXWSInterface.py 
    312     """ % dxsBasedir 
     310    python %s/bin/DXWSInterface.py %s/configs/serverConfig.py 
     311    """ % (dxsBasedir, dxsBasedir) 
    313312 
    314313    if "dxc" in packages: 
     
    343342    try: 
    344343        import ZSI 
     344 
    345345        print "OK!" 
    346346    except: 
     
    369369        makeDirAndPerm(dirname, permissions=permissions, owner=owner, group=group) 
    370370    print "Directory is ready: ", dirname         
     371 
    371372 
    372373 
Note: See TracChangeset for help on using the changeset viewer.