source: TI03-DataExtractor/trunk/pydxs/CSMLDataHandler.py @ 1715

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI03-DataExtractor/trunk/pydxs/CSMLDataHandler.py@1715
Revision 1715, 21.7 KB checked in by astephen, 13 years ago (diff)

Merged with titania version.

Line 
1#   Copyright (C) 2004 CCLRC & NERC( Natural Environment Research Council ).
2#   This software may be distributed under the terms of the
3#   Q Public License, version 1.0 or later. http://ndg.nerc.ac.uk/public_docs/QPublic_license.txt
4 
5"""
6CSMLDataHandler.py
7==================
8 
9CSMLDataHandler module for the dx package.
10 
11This module holds the CSMLDataHandler class that is used
12to hold and access information about datasets held in CSML-type
13formats visible to the dx package.
14 
15""" 
16 
17# Import required modules
18import os 
19import sys 
20import re 
21import cdms 
22 
23# Import package modules
24# Set dummy variable for local import that will be overwritten if
25# serverConfig is imported.
26ENABLE_CSML=0
27from serverConfig import * 
28from common import * 
29from DateTimeManager import * 
30from DXDMLHandler import DXDMLHandler
31from DXErrors import * 
32 
33# Import external modules
34if ENABLE_CSML==1:
35    # Import CSML's API package
36    import API
37 
38# Set up global variables
39dateTimePattern=re.compile(r"^(\d{4}).(\d{1,2}).(\d{1,2})(\s+|T)(\d+):(\d+):(\d+)\.?(\d+)?") 
40         
41         
42class CSMLDataHandler: 
43    """
44    A group of methods to connect to a dataset group or
45    dataset to extract information about the contents.
46    """ 
47   
48    def __init__(self, datasetURI=None): 
49        """
50        Set up instance variables.
51        """ 
52        self.DXDML=DXDMLHandler() 
53        self.file=datasetURI
54        if self.file: self._openDataFile(datasetURI=self.file) 
55   
56   
57    def _openDataFile(self, datasetGroup=None, dataset=None, datasetURI=None): 
58        """
59        Opens a file and allocates to file handle called: self.file.
60        """ 
61        if datasetURI: 
62            csmlfile=datasetURI
63        else: 
64            for item in self.DXDML.getDatasetsAndDatasetURIs(datasetGroup): 
65                if item[0]==dataset: 
66                    csmlfile=item[1] 
67         
68        # Check if path starts with "file:"
69        if csmlfile[:5]=="file:": 
70            csmlfile=csmlfile[5:] 
71         
72        try: 
73            self.file=API.Parser.Dataset() 
74            self.file.parse(csmlfile) 
75        except IOError, error: 
76            raise DXDataIOError, error
77 
78 
79    def _getVariable(self, varname): 
80        """
81        Gets variable metadata object from a data file.
82        """ 
83        try: 
84            rtvalue=self.file.getFeature(varname) 
85        except: 
86            raise DXOptionHandlingError, "Cannot find variable %s in file %s" % (varname, self.file.id) 
87        return rtvalue
88         
89 
90    def _getBestName(self, v, vcount=0): 
91        """
92        Returns the best name for a cdms variable.
93        """ 
94        if not hasattr(v, "standard_name"): 
95            if not hasattr(v, "long_name"): 
96                if not hasattr(v, "title"): 
97                    if not hasattr(v, "name"): 
98                        if hasattr(v, "id"): 
99                            name=v.id 
100                        else: 
101                            vcount=vcount+1 
102                            name="unnamed_var_%s" % vcount
103                    else: 
104                       name=v.name
105                else: 
106                    name=v.title
107            else: 
108                name=v.long_name
109        else: 
110            name=v.standard_name
111        return name
112 
113 
114    def getVariables(self, datasetGroup=None, dataset=None, datasetURI=None): 
115        """
116        Returns a list of variables for the given dataset
117        group/dataset combination or datasetURI. The variable name used is selected
118        hierarchically depending on the available attributes. Each returned item in
119        the list includes a [<long_name>, <id>].
120        """ 
121        self._openDataFile(datasetGroup, dataset, datasetURI) 
122        features=self.file.getFeatureList() 
123        rtvars=[] 
124        vcount=0 
125 
126        for ftid in features: 
127           v=self.file.getFeature(ftid) 
128           name=v.description
129               
130           # Fix name to remove leading asterisks and lower case surface start.
131           name=name.replace("_", " ") 
132           if name[:2]=="**": name=(name[2:]).strip() 
133           if name[:7]=="surface": name=(name[7:]).strip() 
134           # Remove variables they are actually bounds on axes or coefficients in formulae
135           if v.id not in ("bounds_longitude", "bounds_latitude", "bounds_level", "bounds_time", "p0"): 
136               rtvars.append([name, v.id]) 
137           
138        return rtvars
139 
140    def fuzzyMatch(self, item, matcher):
141        import re
142        match=re.match(r"(%s)(_\d+)?" % matcher, item)
143        if match:  return match.groups()[0]
144        return None
145 
146    def getDomain(self, datasetGroup=None, dataset=None, variable=None, datasetURI=None): 
147        """
148        Returns the full domain listing for a variable returning:
149         
150        [knownAxisString, id, longName, units, listType, unusedItem, 
151        listValue-1, listValue-2, ..., listValue-n]
152         
153        For example:
154         
155        ["time", "time", "Time", "hours since 1999-09-09 00:00:00", "start end interval",
156        "", 0, 3, 6]
157         
158        This listType represents 6-hourly time steps of 0,1,2,3 past the base time.
159         
160        listType can also take the value "full list" where all values in the list are provided,
161        or "start end" where only the first and last value are given.
162        """ 
163        self._openDataFile(datasetGroup, dataset, datasetURI) 
164        var=self._getVariable(variable) 
165        varList=self.file.getFeatureList() 
166        varList.sort() 
167         
168        varIndex=varList.index(var.id) 
169        rtlist=[] 
170         
171        axcount=0 
172         
173        axisList=self._getOrderedAxisList(var) 
174                 
175        for axis in axisList: 
176            #axisIndexString="axis%s.%s" % ("77777", axcount) #(varIndex+1, axcount)
177            (name, values)=axis
178            units=None 
179            if name=="t": 
180                knownAxis="time" 
181                (start, end, (intervalValue, intervalUnits))=self.getTemporalDomain(datasetGroup, dataset, variable, datasetURI) 
182                arrayValues=[start, end, intervalValue] 
183                listType="start end interval" 
184                units=intervalUnits
185            elif self.fuzzyMatch(name,"level"): 
186                knownAxis="level" 
187                arrayValues=values[:] 
188                listType="full list" 
189            elif self.fuzzyMatch(name,"latitude"): 
190                knownAxis="latitude" 
191                arrayValues=[values[0], values[-1]] 
192                arrayValues.sort() 
193                arrayValues.reverse() 
194                listType="start end" 
195            elif self.fuzzyMatch(name,"longitude"): 
196                knownAxis="longitude" 
197                arrayValues=[values[0], values[-1]] 
198                arrayValues.sort()       
199                listType="start end"                                     
200            else: 
201                # For any axis not known as above
202                knownAxis="" 
203                if len(values[:])>200: 
204                    arrayValues=[values[0], values[-1]] 
205                    listType="start end"                     
206                else: 
207                    arrayValues=values[:] 
208                    listType="full list" 
209             
210            id=name
211            longName=name.title() 
212            if not units:  units="" 
213             
214            unused=""
215            newList=[]
216            if type(arrayValues)!=type([]): 
217                for i in arrayValues:
218                    newList.append(i)
219                arrayValues=newList
220            rtlist.append([knownAxis, id, longName, units, listType, unused]+arrayValues) 
221            axcount=axcount+1 
222             
223        return rtlist
224         
225 
226    def getHorizontalDomain(self, datasetGroup=None, dataset=None, variable=None, datasetURI=None): 
227        """
228        Returns the horizontal domain as (northernExtent, westernExtent, southernExtent, easternExtent).
229        """ 
230        raise "getHorizontalDomain - has been deprecated!"       
231        self._openDataFile(datasetGroup, dataset, datasetURI) 
232        var=self._getVariable(variable) 
233        lat=list(var.getLatitude()[:]) 
234        if lat[-1]<lat[0]: lat.reverse() 
235        (southernExtent, northernExtent)=(lat[0], lat[-1]) 
236        lon=var.getLongitude()[:] 
237        (westernExtent, easternExtent)=(lon[0], lon[-1]) 
238        return (northernExtent, westernExtent, southernExtent, easternExtent) 
239 
240 
241    def getVerticalSpatialDomain(self, datasetGroup=None, dataset=None, variable=None, datasetURI=None): 
242        """
243        Returns the vertical domain as a tuple containing
244        a list of levels (or "Single level" string) and the units.
245        """ 
246        raise "getVerticalSpatialDomain - has been deprecated!" 
247        self._openDataFile(datasetGroup, dataset, datasetURI) 
248        var=self._getVariable(variable) 
249        try: 
250            levels=var.getLevel() 
251            vertical_units=levels.units
252            vertical_domain=tuple(map(lambda x: float(x), levels[:])) 
253     
254        except: 
255            vertical_domain=("Single level",) 
256            vertical_units=None 
257        return (vertical_domain, vertical_units) 
258 
259 
260    def getTemporalDomain(self, datasetGroup=None, dataset=None, variable=None, datasetURI=None): 
261        """
262        Returns the temporal domain as a tuple of (start time, end time, 
263        (interval value, interval units)).
264        """ 
265        self._openDataFile(datasetGroup, dataset, datasetURI) 
266        var=self._getVariable(variable) 
267        time_axis=var.getDomainReference()["t"].split() 
268        #time_keys=("year", "month", "day", "hour", "minute", "second")
269        start_time=str(time_axis[0]).replace(" ", "T") 
270        end_time=str(time_axis[-1]).replace(" ", "T") 
271 
272        time_units="months" 
273        if time_units[-1]=="s":  time_units=time_units[:-1] 
274         
275                 
276        """if len(time_axis)>1:
277            interval_value=abs(time_axis[1]-time_axis[0])""" 
278        if len(time_axis)>1: 
279                # convert array to relative times
280                #relTimes=[]
281                #relTimeAxis=cdms.createAxis([0])
282                #relTimeAxis.designateTime()
283                #relTimeAxis.units="%s since %s" % (time_units, start_time.replace("T", " "))
284                dtp=dateTimePattern
285                match=dtp.match(start_time) 
286                if not match: 
287                    raise "Cannot match date time pattern: %s" % start_time
288                matchlist=match.groups() 
289                timeItems=[int(i) for i in (matchlist[:3]+matchlist[4:7])] 
290                timeObj=apply(DateTimeManager, tuple(timeItems))#[float[i] for i in match.groups()]))
291                 
292                matchlist2=dtp.match(time_axis[1]).groups() 
293                secondTimeObj=apply(DateTimeManager, tuple([int(x) for x in matchlist2[:3]+matchlist2[4:7]])) 
294                secondTimeLong=long(secondTimeObj.formatTime("%Y%m%d%H%M%S")) 
295                # Step through times in order to get interval (only works for hours at present).
296                 
297                for i in range(1,6000000,1): 
298                    timeObj.add(1, time_units) 
299                    if long(timeObj.formatTime("%Y%m%d%H%M%S"))==secondTimeLong: 
300                        interval_value=i
301                        break 
302        else: 
303            interval_value=1  # To stop loops breaking later!"""
304        return (start_time, end_time, (interval_value, time_units)) 
305 
306 
307    def getSelectedTimeSteps(self, datasetURI, variable, axisSelectionDict): 
308        """
309        Returns a list of time step strings based on the selection.
310        """     
311        self._openDataFile(datasetURI=datasetURI) 
312        var=self._getVariable(variable) 
313         
314        timeAxis=None 
315        axcount=0 
316         
317        for axis in self._getOrderedAxisList(var): 
318            (name, values)=axis 
319            if name=="t": 
320                timeAxisIndex=axcount
321                timeAxis=axis
322            axcount=axcount+1 
323 
324        if timeAxis==None: 
325            return [] 
326         
327        startDateTime=None 
328        for key in axisSelectionDict.keys(): 
329            #print key, axisSelectionDict[key]
330            axisIndex=int(key.split(".")[-1])-1 
331            if axisIndex==timeAxisIndex: 
332                (startDateTime, endDateTime)=axisSelectionDict[key][:2] 
333         
334        # If no time selection specified just return the full list
335        if startDateTime==None: 
336            return timeAxis[1] 
337         
338        startDateTime=startDateTime.replace("T", " ") 
339        items=startDateTime.split(":") 
340        startDateTime=":".join(items[:-1])+":"+("%f" % float(items[-1])) 
341        endDateTime=endDateTime.replace("T", " ") 
342        items=endDateTime.split(":") 
343        endDateTime=":".join(items[:-1])+":"+("%f" % float(items[-1])) 
344         
345        timeSteps=timeAxis[1] 
346        selectedTimes=[] 
347 
348        for timeStep in timeSteps: 
349            #ts=timeStep
350            match=dateTimePattern.match(timeStep) 
351            matchlist=list(match.groups()[:3])+list(match.groups()[4:6]) 
352            matchlist=[int(i) for i in matchlist] 
353            matchlist=matchlist+[float("%s.%s" % match.groups()[6:8])] 
354            ts="%.4d-%.2d-%.2d %.2d:%.2d:%f" % tuple(matchlist) 
355            #print str(timeStep), startDateTime
356             
357            #ts=str(timeStep).replace("T", " ")
358            #print ts, startDateTime
359            if ts>endDateTime: 
360                break 
361            elif ts<startDateTime: 
362                continue 
363            else: 
364                selectedTimes.append(ts) 
365         
366        if selectedTimes==[]: 
367            raise DXOptionHandlingError, "All selected time steps for '%s' are out of range, please go back and re-select." % variable
368                 
369        return selectedTimes
370 
371 
372    def getSelectedVariableArrayDetails(self, datasetURI, variable, axisSelectionDict): 
373        """
374        Returns a tuple representing the (array shape, grid shape, size)
375        of the selected subset of a variable. Grid shape can be None if both latitude
376        and longitude axes are not present. 
377        """     
378        self._openDataFile(datasetURI=datasetURI) 
379        var=self._getVariable(variable) 
380        varType='d' # Hard-coded for CSML # var.typecode()
381                 
382        timeAxisIndex=None 
383        axcount=0 
384        axisList=self._getOrderedAxisList(var) 
385         
386        for axis in axisList: 
387            if axis[0]=="t": 
388                timeAxisIndex=axcount
389            axcount=axcount+1 
390           
391        startDateTime=None     
392         
393        axesCounted=[] 
394        axLens=[] 
395        latLength=None 
396        lonLength=None 
397        size=1 
398        for key in axisSelectionDict.keys(): 
399            #print key, axisSelectionDict[key]
400            # Set the axisIndex as value minus one because we index from 1 in the dx lists
401            axisIndex=int(key.split(".")[-1])-1 
402            (low, high)=axisSelectionDict[key][:2] 
403            axis=self._getAxisFromIndex(var, axisIndex) 
404            (name, values)=axis
405             
406            if axisIndex==timeAxisIndex: 
407                axlen=len(self.getSelectedTimeSteps(datasetURI, variable, {key:(low, high)}))           
408            elif low==high: 
409                axlen=1 
410            else: 
411                axlen=len(getValuesInRange(low, high, values[:])) 
412                if axlen==0: 
413                    if (self.fuzzyMatch(name,"longitude") or self.fuzzyMatch(name,"latitude")) and low==high: 
414                        print "Lat and lon can be axis length zero because we'll nudge to nearest if only one value given." 
415                        axlen=1 
416                    else: 
417                        raise DXOptionHandlingError, "All selected '%s' axis values for '%s' are out of range, please go back and re-select." % (name, variable) 
418         
419                if self.fuzzyMatch(name,"latitude"): 
420                    latLength=axlen
421                elif self.fuzzyMatch(name,"longitude"): 
422                    lonLength=axlen
423                         
424            size=size*axlen
425            axesCounted.append(axisIndex) 
426            axLens.append(axlen) 
427         
428        print axesCounted
429        print axLens
430         
431        axcount=0 
432        arrayShape=[] 
433        for axis in self._getOrderedAxisList(var): 
434            (name, values)=axis
435            if axcount not in axesCounted: 
436                size=size*len(values) 
437                arrayShape.append(len(values)) 
438            else: 
439                #print axcount
440                arrayShape.append(axLens[axesCounted.index(axcount)])     
441            if self.fuzzyMatch(name,"latitude") and latLength==None: 
442                latLength=len(axis) 
443            elif self.fuzzyMatch(name,"longitude") and lonLength==None: 
444                lonLength=len(axis)   
445            axcount=axcount+1 
446         
447        # Now work out gridShape if appropriate
448        if latLength and lonLength: 
449            gridShape=(latLength, lonLength) 
450        else: 
451            gridShape=None 
452         
453        if varType=="f": 
454            size=size*4. 
455        elif varType=="d": 
456            size=size*8 
457        elif varType=="i": 
458            size=size
459 
460        return (tuple(arrayShape), gridShape, size) 
461 
462 
463    def getSelectedVariableSubsetSize(self, datasetURI, varID, axisSelectionDict): 
464        """
465        Returns the size in bytes of the selected subset of a variable.
466        """ 
467        return self.getSelectedVariableArrayDetails(datasetURI, varID, axisSelectionDict)[2] 
468 
469         
470#    def readVariableSubsetIntoMemory(self, datasetURI, variable, axisSelectionDict, timeStep=None):
471    def subsetVariableToCSMLNC(self, datasetURI, variable, axisSelectionDict, csmlPath, ncPath, timeStep=None): 
472        """
473        Reads the variable with ID 'variable' into memory from file
474        'datasetURI' - sub-setting across all axes indicated in 'axisSelectionDict'.
475        If 'timeStep' is provided then override the time selection in 'axisSelectionDict'
476        with the 'timeStep' given.
477        """ 
478        self._openDataFile(datasetURI=datasetURI) 
479        var=self._getVariable(variable) 
480         
481        axisList=self._getOrderedAxisList(var) 
482             
483        selectionDict={} 
484        timeSelection=[] 
485        for key in axisSelectionDict.keys(): 
486            #print key, axisSelectionDict[key]
487            axisIndex=int(key.split(".")[-1])-1 
488            axis=axisList[axisIndex]   
489            (name, values)=axis
490            id=name
491             
492            # deal with time differently
493            if name=="t": 
494                if timeStep!=None:       
495                    timeStep=timeStep.replace(" ", "T")                 
496                    timeSelection=[self._fixTimeStringForCSML(timeStep)] 
497                else: 
498                    selector=axisSelectionDict[key][:2] 
499                    selector=(selector[0].replace(" ", "T"), selector[1].replace(" ", "T")) 
500                    selector=[self._fixTimeStringForCSML(ts) for ts in selector] 
501                    if selector[0]==selector[1]: selector=[selector[0]] 
502                    timeSelection=selector               
503            elif self.fuzzyMatch(name,"latitude"): 
504                (low, high)=axisSelectionDict[key][:2] 
505                if low==high: 
506                    loworig=low
507                    (low, high, nudgeMessage)=nudgeSingleValuesToAxisValues(low, values[:], "Latitude")   
508                    if loworig!=low:   print "Nudged latitudes to nearest points..." 
509                selectionDict[name]=(low, high) 
510            elif self.fuzzyMatch(name,"longitude"): 
511                (low, high)=axisSelectionDict[key][:2] 
512                if low==high: 
513                    loworig=low
514                    (low, high, nudgeMessage)=nudgeSingleValuesToAxisValues(low, values[:], "Longitude")         
515                    if loworig!=low:   print "Nudged latitudes to nearest points..."     
516                selectionDict[name]=(low, high)   
517            else: 
518                selector=axisSelectionDict[key][:2] 
519                selectionDict[name]=selector
520         
521        if timeSelection==[]: 
522            for axis in axisList: 
523                if axis[0]=="t": 
524                    selector=axis[1] 
525                    selector=[self._fixTimeStringForCSML(ts) for ts in selector] 
526                    timeSelection=selector               
527       
528        print "Generating axis list values for any axes not selected explicitly by user...[NOT IMPLEMENTED]"
529 
530        print "timeSelection:", timeSelection
531        print "selectionDict:", selectionDict
532         
533        (subsetCSML, subsetNetCDF, arraySize)=var.subsetToGridSeries(timeSelection, csmlPath, ncPath, **selectionDict) 
534        #variableData=eval("self.file('%s', %s)" % (variable, fullSelectionString))
535        return #variableData         
536         
537 
538    def getCFGlobalAttributes(self, datafile): 
539        """
540        Gets any CF metadta global attributes that are available
541        from the source  _getOrderedAxisList(self, var)dataset/file.
542        """ 
543        # Make sure data file is open
544        if self.file==None: self._openDataFile(datasetURI=datafile) 
545        gatts={} 
546 
547        for gatt in CF_METADATA_GLOBAL_ATTRIBUTE_KEYS: 
548            if hasattr(self.file, gatt): 
549                gatts[gatt]=self.file.__getattr__(gatt) 
550         
551        return gatts 
552 
553 
554    def _getOrderedAxisList(self, var): 
555        """
556        For CSML API - returns ordered list of axes.
557        """ 
558        axisList=[] 
559        dr=var.getDomainReference() 
560        drkey=dr.keys()[0] 
561        axisList.append([drkey, dr[drkey].split()]) 
562         
563        dc=var.getDomainComplement() 
564        for key in ("level", "latitude", "longitude"):
565          for dckey in dc.keys():
566             
567            if self.fuzzyMatch(dckey, key):# in dc.keys():
568                axisList.append([dckey, dc[dckey]])
569        print "Returning from _getOrderedAxisList()" 
570        return axisList
571 
572 
573    def _getAxisFromIndex(self, var, axindex): 
574        """
575        For CSML API - returns axis for var given index.
576        """ 
577        return self._getOrderedAxisList(var)[axindex] 
578     
579 
580    def _fixTimeStringForCSML(self, timeString): 
581        """
582        Removes zero padding from time string.
583        """ 
584        matchlist=list(dateTimePattern.match(timeString).groups()) 
585        if matchlist[-1]==None: matchlist[-1]=0 
586        timeItems=[int(i) for i in (matchlist[:3]+matchlist[4:8])] 
587        newString="%s-%s-%sT%s:%s:%s.%s" % tuple(timeItems) 
588        return newString
589     
590         
591if __name__=="__main__":         
592    a=CSMLDataHandler() 
593    """print a.getVariables(datasetGroup='CSML test dataset group', dataset='CSML test dataset great test')
594     
595    print a.getVariables(datasetGroup='CSML test dataset group', datasetURI='file:/usr/local/test/dxs/testdata/csml1.xml')     
596     
597    print a.getDomain('CSML test dataset group', 'CSML test dataset great test', "var2")
598 
599    #print a.getHorizontalDomain('CSML test dataset group', 'CSML test dataset great test', "var2")
600    # These have been deprecated!
601    #print a.getVerticalSpatialDomain('CSML test dataset group', 'CSML test dataset great test', "var2")
602 
603    print a.getTemporalDomain('CSML test dataset group', 'CSML test dataset great test', "var2")
604 
605    print a.getCFGlobalAttributes("file:/usr/local/test/dxs/testdata/csml1.xml")
606 
607 
608    print a.getSelectedVariableArrayDetails('file:/usr/local/test/dxs/testdata/csml1.xml', "var2", 
609                     {"axis_1.1.1.1":("2006-05-15T12:00:00", "2006-06-15T12:00:00"),
610                     "axis_1.1.1.2":(10,20), "axis_1.1.1.3":(0,90)})
611 
612    print "Array Details..."
613    x=a.getSelectedVariableArrayDetails('file:/usr/local/test/dxs/testdata/csml1.xml', "var2", 
614                     {"axis_1.1.1.1":("2006-05-15T12:00:00", "2006-06-15T12:00:00"),
615                     "axis_1.1.1.3":(30,-30)})
616 
617    print x
618     
619    print "Size..."
620    print x[2]
621     
622    print "\n\n\nREALLY SUBSET"
623    print a.subsetVariableToCSMLNC("file:/usr/local/test/dxs/testdata/csml1.xml", "var2",
624                     {'axis_1.1.1.1':('2006-05-15T12:00:0.000000', '2006-06-15T12:00:0.000000'),   
625                      'axis_1.1.1.3': [0.0, 35.0], 'axis_1.1.1.2': [40.0, 90.0]}, "/tmp/a.csml", "/tmp/a.nc")
626                       
627    print "\nTry another..."           
628    print a.subsetVariableToCSMLNC("file:/usr/local/test/dxs/testdata/csml1.xml", "var2",
629                  ge   {'axis_1.1.1.3': [0.0, 75.0], 'axis_1.1.1.2': [20.0, 90.0],
630                      'axis_1.1.1.1':("2006-05-15T12:00:00", "2006-06-15T12:00:00")}, "/tmp/a.csml", "/tmp/a.nc")"""
631                       
632    print a.subsetVariableToCSMLNC("file:/disks/glue1/astephens/coapec_metadata/COAPEC_500YrRun_wholerun_monthly_atmos.xml",
633                     "gproduct", {"axis_1.1.1.1":["2790-01-16T00:00:00", "2790-02-16T00:00:00"], 
634                              "axis_1.1.1.2":[0.0, 75.0], "axis_1.1.1.3":[0.0, 75.0]}, "/tmp/a.csml", "/tmp/a.nc")
635
636    print a.getDomain(variable="gproduct", datasetURI="file:/disks/glue1/astephens/coapec_metadata/COAPEC_500YrRun_wholerun_monthly_atmos.xml") 
637 
Note: See TracBrowser for help on using the repository browser.