source: TI02-CSML/trunk/parser/csmldoc.py @ 977

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI02-CSML/trunk/parser/csmldoc.py@977
Revision 977, 10.8 KB checked in by domlowe, 14 years ago (diff)

moved gridseries subsetting to new api structure

Line 
1'''csmldoc.py
2Contains Parser high level  api to enable reading of csml document/features etc
3Note - All class names are prefixed with 'CSML' to avoid conflict with Parser classes
4of similar names.
5'''
6
7from Parser import * #import parser into same namespace
8import parser_extra
9
10#import the DataInterface module from the Scanner, assumes it is in a sibling directory to the one containing csmlio.py
11#TODO - how best to organise modules...
12import os
13currentPath=os.getcwd()
14parentPath=os.sep.join(currentPath.split(os.sep)[:-1])
15parserPath=parentPath + '/Scanner/csmllibs'
16sys.path.append(parserPath) #append the parser path to sys.path
17try:
18    import csmldataiface
19except:
20    print 'Could not import CSML Data Interface module. Make sure the Parser code is in ../parser directory on the same level as ../Scanner directory.'
21    sys.exit()
22
23#global to hold top level dataset object - otherwise we will constantly be reparsing it.
24
25class CSMLDataset:
26    def __init__(self,csmlfile):
27        """must be provided with csmlfile
28        parses the csmlfile into self.dataset """
29        self.dataset=Dataset()
30        tree = ElementTree(file=csmlfile)
31        self.dataset.fromXML(tree.getroot())
32        self.dataset =parser_extra.ParserPostProcessor(self.dataset).resolveReferences()
33    def getFeatureList(self):
34        #returns a list of feature ids for the dataset
35        self.featureList = []
36        for member in self.dataset.featureCollection.members:
37             self.featureList.append(member.id)
38        return self.featureList
39
40    def getFeature(self, featureID):
41        """ returns a single feature object, which can be accessed by both the high-level api and the Parser API"""
42        for member in self.dataset.featureCollection.members:
43                if member.id == featureID:
44                    if  isinstance(member,PointFeature):
45                        return CSMLPointFeature(member,self.dataset)
46                    elif isinstance(member,PointSeriesFeature):
47                        return CSMLPointSeriesFeature(member,self.dataset)
48                    elif  isinstance(member,ProfileFeature):
49                        return CSMLProfileFeature(member,self.dataset)
50                    elif  isinstance(member,GridSeriesFeature):
51                        return CSMLGridSeriesFeature(member,self.dataset)
52                    #elif etc... for all feature types
53
54    def getFileExtract(self,extractID):
55        for extract in self.dataset.arrayDescriptors:
56            if  extract.id==extractID:
57                return CSMLAbstractFileExtract(extract) 
58
59    #other Dataset level methods go here:
60    ############
61    #def getArrayDescriptors
62    #etc...
63   
64class CSMLAnyFile:
65    def __init__(self,filename):
66        self.DI=csmldataiface.DataInterface()
67        self.DI=self.DI.getUnknownInterfaceType(filename)
68        self.DI.openFile(filename)
69    def getVariableData(self,variableName,**kwargs):
70        #kwargs can contain a subset definition
71        self.DI.setVariable(variableName)
72        if kwargs:
73            data = self.DI.getSubsetOfDataForVar(**kwargs)
74        else:
75            data = self.DI.getDataForVar()
76        return data
77
78class CSMLAbstractFileExtract:
79    def __init__(self,extract):
80        self.parsedExtract=extract
81        self.file=self.parsedExtract.fileName
82        self.variableName=self.parsedExtract.variableName
83        self.DI = csmldataiface.DataInterface()
84        self.DI=self.DI.getUnknownInterfaceType(self.file)
85        self.DI.openFile(self.file)
86    def getAxisData(self):
87        self.DI.setAxis(self.variableName)
88        fulldata = self.DI.getDataForAxis()
89        return fulldata
90    def getVariableData(self,**kwargs):
91        #kwargs can contain a subset definition
92        self.DI.setVariable(self.variableName)
93        if kwargs:
94            data = self.DI.getSubsetOfDataForVar(**kwargs)
95        else:
96            data = self.DI.getDataForVar()
97        return data
98    def close(self):
99        self.DI.closeFile()
100
101class CSMLAbstractFeature: 
102    """Contains methods applicable to any feature but methods can be overwritten by individual feature types
103        - see testMethod for example.
104    """
105    def __init__(self,feature,parentDataset):
106        self.parsedFeature=feature
107        self.parentDataset=parentDataset
108        '''sets self.parsedFeature to contain the lower level parsed feature'''
109    def getAllowedSubsettings(self):
110        return ['none']
111
112    def getFeatureType(self):
113        return str(self.parsedFeature)
114   
115    def testMethod(self):
116        #default "testMethod" for all features
117        print '/n Underlying feature type: ' + str(self.parsedFeature)
118        return 'abstract test method called and not overwritten'
119       
120    def getDomain(self):
121        #should return a list contianing the domain reference and compliment if any.
122        return []
123   
124    def getOutputOptions(self):
125        #return generic output options for abstract features - this may in fact be none... and will be always overwritten within specific feature types
126        pass
127   
128    def getSubset(self, **kwargs):
129        pass
130    def __writeNetCDF(self,var, timeSubset,fulldata,**kwargs):
131        """writes a NetCDF file containing feature data"""
132        pass
133
134    def __writeCSML(self, var, timeSubset,fulldata,**kwargs):
135        """writes a CSML document to descibe subsetted feature"""
136        pass
137
138class CSMLPointFeature(CSMLAbstractFeature):
139    def __init__(self,feature):
140        CSMLAbstractFeature.__init__(self,feature)
141    def getOutputOptions(self):
142            #return output options for Point feature... not implemented
143        pass
144    def testMethod(self):
145        """Over writes abstract testMethod"""
146        print 'underlying feature type:' + str(self.parsedFeature)
147        return 'abstract test method overwritten by CSMLPointFeature class'
148
149class CSMLPointSeriesFeature(CSMLAbstractFeature):
150    def __init__(self,feature):
151        CSMLAbstractFeature.__init__(self,feature)
152    def getOutputOptions(self):
153            #return output options for PointSeries feature... not implemented
154        pass
155    def testMethod(self):
156        """Over writes abstract testMethod"""
157        print 'underlying feature type:' + str(self.parsedFeature)
158        return 'abstract test method overwritten by CSMLPointSeriesFeature class'
159   
160   
161class CSMLProfileFeature(CSMLAbstractFeature):
162    def __init__(self,feature):
163        CSMLAbstractFeature.__init__(self,feature)
164    def getOutputOptions(self):
165            #return output options for ProfileSeries feature... not implemented
166        pass
167    '''NOTE:this feature does not have a "testMethod" so default abstract testMethod is used from CSMLAbstractFeature'''
168    #def testMethod(self):
169    #   pass
170   
171class CSMLGridSeriesFeature(CSMLAbstractFeature):
172    def __init__(self,feature, dataset):
173        CSMLAbstractFeature.__init__(self,feature,dataset)
174    def getAllowedSubsettings(self):
175        return ['subsetToGridSeries']
176    def getOutputOptions(self):
177            #return output options for GridSeries feature... not implemented
178        pass
179   
180    def __getDomainReference(self):
181        #Inspects a time position list for the domain reference.
182        #TODO, does not handle a file extract in place of a list.
183        if isinstance(self.parsedFeature.domain.domainReference,TimePositionList):         
184            time = {}
185            time['t'] = self.parsedFeature.domain.domainReference.timePositions
186            domainref  = time
187        self.domainReference=domainref
188        return domainref
189       
190    def __getDomainComplement(self):
191        #This will return a list containing one or more ordinates:
192        #currently in form [Name, values]
193        domaincomp ={}
194        dc = self.parsedFeature.domain.domainComplement
195        #dc should be a grid!
196        if isinstance(dc, Grid):
197            for ordinate in dc.ordinates:
198                fe=CSMLAbstractFileExtract(ordinate.axisValues)
199                domaincomp[ordinate.definesAxis]=fe.getAxisData()
200                fe.close()
201        self.domainComplement=domaincomp
202        return domaincomp
203           
204    def getDomain(self):
205        #returns both the domain reference axes and domain compliment axes in a single domain dictionary
206        #axes are in no particular order
207        domain = {}
208        dr=self.__getDomainReference()
209        dc=self.__getDomainComplement()
210        for key in dc.keys():
211            domain[key]=dc[key]
212        for key in dr.keys():
213            domain[key]=dr[key]
214        return domain
215
216    def subsetToGridSeries(self, timeSubset,  **kwargs):
217        domainref = self.__getDomainReference()
218        filelog=[]
219        self.times=timeSubset
220        self.files=[]
221        fulldata=None
222        for time in self.times:
223            listPosition=domainref['t'].split().index(time)
224            for comp in self.parsedFeature.rangeSet.aggregatedArray.component:
225                var = comp.variableName
226                f=CSMLAnyFile(comp.fileName.split()[listPosition])
227                data=f.getVariableData(var, **kwargs)
228                self.files.append(comp.fileName.split()[listPosition])
229                filelog.append(comp.fileName.split()[listPosition]) #needed?
230                if fulldata is None:
231                    fulldata = data.tolist()
232                else:
233                    for item in data.tolist():
234                        fulldata.append(item)
235        ###### create the csml document ###############
236        output_file='temp.xml'
237        dset = self.parentDataset
238        dset.featureCollection.members=[]# clear out all the existing features
239        dset.arrayDescriptors=[]
240        strTimes =''
241        for time in self.times:
242            strTimes= strTimes + ' ' + time
243        self.parsedFeature.domain.domainReference=TimePositionList(timePositions=strTimes)
244        strFiles=''
245        for file in self.files:
246            strFiles= strFiles + ' ' + file
247        #print dir(feat.rangeSet.aggregatedArray.component)
248        for comp in self.parsedFeature.rangeSet.aggregatedArray.component:
249            comp.fileName=strFiles
250        dset.featureCollection.members.append(self.parsedFeature)
251        csml = dset.toXML()   
252        #Tidy up and print the CSML document:
253        #strCSML= parseString(tostring(csml)).toprettyxml()
254        strCSML=parser_extra.PrettyPrint(csml)
255        strCSML=parser_extra.removeInlineNS(strCSML)
256        print strCSML
257        ################################
258       
259        ######create the netcdf file #############
260        ################################
261       
262        return output_file
263
264        #self.writeNetCDF(var, timeSubset,fulldata,**kwargs)
265        #self.writeCSML(var, timeSubset,fulldata,**kwargs)
266
267    def testMethod(self):
268        """Over writes abstract testMethod"""
269        print 'underlying feature type:' + str(self.parsedFeature)
270        return 'abstract test method overwritten by CSMLGridSeriesFeature class'
271   
272# etc.. do same for all features
Note: See TracBrowser for help on using the repository browser.