source: TI02-CSML/branches/CSML2/csmllibs/csmlfeaturetypes.py @ 1890

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI02-CSML/branches/CSML2/csmllibs/csmlfeaturetypes.py@1890
Revision 1890, 21.7 KB checked in by domlowe, 13 years ago (diff)

added addChildElem method to csElement class

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#!/usr/bin/env python
2#**************************************************************************************
3#csmlfeaturetypes.py
4#For creating CSML featuretypes
5#v0.5 split off 11th November 2005
6#Dominic Lowe, BADC
7#**************************************************************************************
8
9import csml.csmllibs
10import sys
11
12class featureBuilder(object):
13    def __init__(self, dataset_element, gml_FeatureCollection_element, ffmap,fileExtractDictionary, timedim, timestorage,spatialstorage,valuestorage):
14        self.ds_element=dataset_element
15        self.gml_FeatureCollection_element = gml_FeatureCollection_element
16        self.ffmap = ffmap
17        self.fileExtractDictionary = fileExtractDictionary
18        self.timedim = timedim
19        self.timestorage=timestorage
20        self.spatialstorage=spatialstorage
21        self.valuestorage=valuestorage
22               
23        #empty list to hold featureMembers
24        self.fms =[]
25               
26        #at the moment, only one featuretype per CSML Dataset is supported.
27        #get the featuretype of the first representative file in the ffmap object
28        self.featuretype=  self.ffmap.getRepresentativeFiles()[0].getFeatureType()
29       #and create the features
30        print 'determining feature type'
31        print self.featuretype
32        if self.featuretype == 'GridSeries':
33            self.createCSMLGridSeriesFeatures()
34        elif self.featuretype == 'PointSeries':       
35            self.createCSMLPointSeriesFeatures()
36       
37        #after the features have been generated append all featureMembers to the feature collection
38        self.gml_FeatureCollection_element.members=self.fms
39   
40       
41    #Some internal methods that are of use to all feature types:
42    def _getDescriptiveName(self,DI):
43        #given a data interface class with the variable or axis set, try to get a descriptive name
44        #eg. long name
45        try:
46            descName=DI.getVariableAttribute('long_name')
47            descName
48        except AttributeError:
49            descName = "missing name"
50        descName=descName.replace('&','&') #remove ampersands TODO- extend this
51        return descName
52   
53    def _populateListOfFiles(self,repfile):
54        #given a representative file, get list of files: one representative file + all related files
55        listOfFiles=[]
56        repfilename=repfile.getRepresentativeFileName()
57        listOfFiles.append(repfilename)
58        relfiles = repfile.getRelatedFiles()
59        for f in relfiles:
60            fname = f.getRelatedFileName()
61            listOfFiles.append(fname)
62        return repfilename,listOfFiles
63       
64    def _getFilesAndTimes(self):
65        #TODO try and speed up csmllibs.csmltime.getFileTimeList
66        OrderedFileTimeList,self.caltype,self.units = csml.csmllibs.csmltime.getFileTimeList(self.listOfFiles,self.timedim)
67        #build strings to hold times/filenames for current gridseriesfeature
68        self.timeString =''
69        self.filesinDir = ''
70        for j in range (0, len(OrderedFileTimeList)):
71            t= OrderedFileTimeList[j][0]
72            f = OrderedFileTimeList[j][1]
73            self.timeString = self.timeString + ' ' + str(t)
74            self.filesinDir = self.filesinDir + ' ' + f
75   
76    def _getCorrectExtractType(self):
77        #returns an empty parser file extract object of the correct type.
78        if self.extractType=='NetCDFExtract':
79            fe = csml.parser.NetCDFExtract()
80        if self.extractType=='NASAAmesExtract':
81            fe = csml.parser.NASAAmesExtract()
82        if self.extractType=='GRIBExtract':
83            fe = csml.parser.GRIBExtract()
84        if self.extractType=='PPExtract':
85            fe = csml.parser.PPExtract()
86        return fe
87       
88   
89    def createCSMLGridSeriesFeatures(self):
90        #This method assumes that the variables (features) are shared across identically structured files
91        #should be supplied with a featurefilemap object (see csmlfiles for FileMapMaker)
92        representativeFiles=self.ffmap.getRepresentativeFiles()
93        for repfile in representativeFiles:
94            self.repfilename,self.listOfFiles=self._populateListOfFiles(repfile)
95            self._getFilesAndTimes()
96            #Open representative file and create feature members:
97            DI = csml.csmllibs.csmldataiface.DataInterface()
98            DI=DI.getUnknownInterfaceType(self.repfilename)
99            DI.openFile(self.repfilename)
100            allVarNames=DI.getListofVariables()
101            numFeatures=len(allVarNames)
102            #Create a GridSeriesFeature for each variable:
103            for i in range(0, numFeatures):
104                DI.setVariable(allVarNames[i])
105                dimNames=DI.getVariableAxes()
106                if len(dimNames) <= 2:
107                    #it's an axis or bounds not a feature, try next variable
108                    continue
109                gsFeature=csml.parser.GridSeriesFeature()
110                gsFeature.id=str(allVarNames[i])
111                desc = self._getDescriptiveName(DI)
112                #GridSeriesFeature_element.description=csml.parser.Description(desc)
113                gsFeature.description=desc
114                #value (coverage)
115                gsCoverage=csml.parser.GridSeriesCoverage()
116                gsDomain=csml.parser.GridSeriesDomain()
117                gcT=csml.parser.GridCoordinatesTable()
118               
119               
120               
121                #add an axisName element(s) for  each spatial dimension.
122                # and an ordinate element
123                axes=[]
124                for i in range (1, len(dimNames)):
125                    #axisNames
126                    axisname ='dim'+str(i)
127                    axes.append(axisname)
128                   
129                    ordinates=[]
130                    for i in range (1, len(dimNames)):
131                        ord=csml.parser.GridOrdinateDescription()
132                        #ord.gridAxesSpanned='dim' + str(i)
133                        #ord.sequenceRule=csml.csmllibs.csmlextra.getSeqRule(len(dimNames))
134                        #dimName=dimNames[len(dimNames)-i]
135                        #ord.definesAxis=dimName
136                        ##look up file extract name in dictionary
137                        ##(axisid stored in dictionary = current filename + variable name)
138                        #axisid=self.repfilename+dimName
139                        #if self.spatialstorage=='fileextract':
140                            ##refer to extract
141                            #ord.axisValues='#'+self.fileExtractDictionary[axisid]
142                        #else:
143                            ##store inline
144                             #DI.setAxis(dimName)
145                             #ord.axisValues=csml.csmllibs.csmlextra.cleanString(str(DI.getDataForAxis()))
146                             
147                        #ordinates.append(ord)
148                        gcT.addChildElem('gridOrdinates',ord)                   
149                    #grid.axisNames=axes
150               
151                gsDomain.coordTransformTable=gcT
152                gsCoverage.gridSeriesDomain=gsDomain
153                gsFeature.value=gsCoverage
154                gsDomain=csml.parser.GridSeriesDomain()
155               
156                #DOMAIN REFERENCE
157                #tpl=csml.parser.TimePositionList()
158                #if self.timestorage =='inline':
159                    #tpl.timePositions=self.timeString
160                    #tpl.frame='%s:%s'%(self.caltype,self.units)
161                #else:
162                    ## do something to create a single extract for the times (from the representative file).
163                    #tpl.timePositions = csml.csmllibs.csmlfileextracts.createSingleExtract(self.extractType, repfilename, self.timedim, len(self.timeString.split()))
164                    #tpl.frame='%s:%s'%(self.caltype,self.units)
165                #gsDomain.domainReference=tpl
166                #grid=csml.parser.Grid()
167                ##COVERAGE FUNCTION
168                #mr =csml.parser.MappingRule(csml.csmllibs.csmlextra.getMappingRule(len(dimNames)))
169                #GridSeriesFeature_element.coverageFunction=mr
170                ##RANGESET
171                #arrSz = DI.getArraySizeOfVar()
172                #try:
173                    #strUom = DI.getVariableAttribute('units')
174                #except AttributeError:
175                    ## if units attribute doesn't exist:
176                    #strUom ="dimensionless or units not determined"
177                #rs=csml.parser.RangeSet()
178                #if self.valuestorage=='inline':
179                    ##TO DO, store the rangeset inline - use Datablock class???
180                    #pass
181                #else:
182                    ##store the rangeSet as an aggregatedArray
183                    #aa=csml.parser.AggregatedArray()
184                    #aa.arraySize=[]
185                    #aa.arraySize.append(arrSz)
186                    #aa.uom=strUom
187                    #aa.aggType='new' #can it be anything else?
188                    #aa.aggIndex='1'
189                    ##FileExtract (fe) element will be NetCDF/GRIB/PPExtract element (As defined earlier in ExtractType)
190                    #self.extractType= DI.extractType
191                    #fe = self._getCorrectExtractType()
192                    #varSize=DI.getShapeOfVar()
193                    #fe.arraySize=varSize
194                    #fe.fileName=self.filesinDir
195                    #fe.variableName=allVarNames[i]
196                    #aa.component=[fe]
197                    #rs.aggregatedArray=aa
198                #GridSeriesFeature_element.rangeSet=rs
199                ##DOMAIN COMPLEMENT
200                #grid.srsName='urn:EPSG:GeographicCRS:4326'
201                #numSpDims=len(varSize) -1
202                #grid.srsDimension=str(numSpDims)
203                #grid.dimension=str(numSpDims)
204                #ge =csml.parser.GridEnvelope(low=DI.getLowLimits(), high=DI.getHighLimits())
205                #grid.limits=ge
206                ##add an axisName element(s) for  each spatial dimension.
207                ## and an ordinate element
208                #axes=[]
209                #for i in range (1, len(dimNames)):
210                    ##axisNames
211                    #axisname ='dim'+str(i)
212                    #axes.append(axisname)
213                    ##ordinates
214                    #grid.ordinates=[]
215                    #for i in range (1, len(dimNames)):
216                        #ord=csml.parser.GridOrdinateDescription()
217                        #ord.gridAxesSpanned='dim' + str(i)
218                        #ord.sequenceRule=csml.csmllibs.csmlextra.getSeqRule(len(dimNames))
219                        #dimName=dimNames[len(dimNames)-i]
220                        #ord.definesAxis=dimName
221                        ##look up file extract name in dictionary
222                        ##(axisid stored in dictionary = current filename + variable name)
223                        #axisid=self.repfilename+dimName
224                        #if self.spatialstorage=='fileextract':
225                            ##refer to extract
226                            #ord.axisValues='#'+self.fileExtractDictionary[axisid]
227                        #else:
228                            ##store inline
229                             #DI.setAxis(dimName)
230                             #ord.axisValues=csml.csmllibs.csmlextra.cleanString(str(DI.getDataForAxis()))
231                        #grid.ordinates.append(ord)
232                    #grid.axisNames=axes
233                #gsDomain.domainComplement=grid
234                #GridSeriesFeature_element.domain=gsDomain
235                #GridSeriesFeature_element.parameter=csml.parser.Phenomenon(href='http://badc.rl.ac.uk/localparams#%s'%allVarNames[i])
236                self.fms.append(gsFeature)
237            DI.closeFile()
238    ###End of createCSMLGridSeriesFeatures###
239
240    def createCSMLPointSeriesFeatures(self): 
241        representativeFiles=self.ffmap.getRepresentativeFiles()
242        for repfile in representativeFiles:
243            self.repfilename,self.listOfFiles=self._populateListOfFiles(repfile)
244            self._getFilesAndTimes()
245            DI = csml.csmllibs.csmldataiface.DataInterface()
246            DI=DI.getUnknownInterfaceType(self.repfilename)
247            DI.openFile(self.repfilename)
248            allVarNames=DI.getListofVariables()
249            numFeatures=len(allVarNames)       
250            try:
251                DI.setAxis(self.timedim)
252                times=DI.getDataForAxis()
253            except:                     
254                times = DI.getTimes()
255            #Create features:
256            for i in range (0, numFeatures):
257                PointSeriesFeature_element=csml.parser.PointSeriesFeature()
258                if str(allVarNames[i]).upper() in ['ERROR FLAG', 'ERROR']: #might need to extend this list
259                    break
260                PointSeriesFeature_element.id=str(allVarNames[i])
261                desc=self._getDescriptiveName(DI)
262                PointSeriesFeature_element.description=csml.parser.Description(desc)
263                #DOMAIN
264                psDomain=csml.parser.PointSeriesDomain()
265                t=csml.parser.Trajectory()
266                t.srsName='urn:EPSG:geographicCRS:4326' #TO Do
267                t.locations =csml.parser.DirectPositionList(vals='1 1')
268               
269                if self.timestorage =='inline':
270                    tpl =csml.parser.TimePositionList()
271                    tpl.timePositions=self.timeString
272                    tpl.frame='%s:%s'%(self.caltype,self.units)
273                    t.times=tpl
274                else:
275                    # do something to create a single extract for the times (from the representative file).
276                    tpl.timePositions = csml.csmllibs.csmlfileextracts.createSingleExtract(self.extractType, repfilename, self.timedim, len(self.timeString.split())) 
277                    tpl.frame='%s:%s'%(self.caltype,self.units)
278               
279               
280#                 if self.timestorage =='inline':
281#                     t.times=csmllibs.Parser.TimePositionList('#RefSysX',str(times))
282#                 else:
283#                     #todo: depends on the file mapping???
284#                     t.times=csmllibs.Parser.TimePositionList('#RefSysX','blah') #blah = dummy times
285#                 print 'times: ' + str(allVarNames[i])
286#                 print len(times)
287#                 print len(listOfFiles)
288#                 arraySize=len(times) * len(listOfFiles)
289#                 fextract=csmllibs.csmlfileextracts.createSingleExtract(self.extractType,filenames,self.timedim,arraySize)
290#                 tplist = csmllibs.Parser.TimePositionList(timePositions=fextract)
291#                 t.times=tplist                                                                   
292                filenames=csml.csmllibs.csmlextra.cleanString(str(self.listOfFiles))
293                psDomain.domainReference=t
294                #RANGESET
295                DI.setVariable(allVarNames[i])
296                try:
297                    strUom = DI.getVariableAttribute('units')
298                except AttributeError:
299                    #if units attribute doesn't exist:
300                    strUom ="dimensionless or units not determined"
301                try:                   
302                    measuredvalues = DI.getDataForVar()
303                except:
304                    measuredvalues = ' could not get values '
305                rs=csml.parser.RangeSet()
306                if self.valuestorage=='inline':
307                    #encode inline
308                    rs.quantityList=csml.parser.MeasureOrNullList(uom=strUom, val=str(measuredvalues)[1:-1])                         
309                else:
310                    #create a file extract link
311                    arraySize=len(measuredvalues)*len(self.listOfFiles) 
312                    #TODO this needs to be able to handle inline, use VALUESTORAGE to determine which to use:
313                    self.extractType=DI.extractType
314                    fextract=csml.csmllibs.csmlfileextracts.createSingleExtract(self.extractType,filenames,allVarNames[i],arraySize)
315                    qlist = csml.parser.MeasureOrNullList(val=fextract)
316                    rs.quantityList=qlist
317                PointSeriesFeature_element.rangeSet=rs
318                #COVERAGEFUNCTION                           
319                #PARAMETER
320                #need to do parameter and coverageFunction elements
321                PointSeriesFeature_element.domain=psDomain
322                self.fms.append(PointSeriesFeature_element)
323            DI.closeFile()
324       
325
326#This function needs revising in light of a) csml parser and b) new profile feature types
327    def createCSMLProfileFeature(csmldoc, dataset_element, gml_FeatureCollection_element,  ffmap, timedim):
328            representativeFiles=ffmap.getRepresentativeFiles()
329            listOfFiles=[]
330            for repfile in representativeFiles:
331                    repfilename=repfile.getRepresentativeFileName()
332                    listOfFiles.append(repfilename)
333                    relfiles = repfile.getRelatedFiles()
334                    for f in relfiles:
335                            #hopefully there are no related files at the moment!
336                            fname = f.getRelatedFileName()
337                            listOfFiles.append(fname)
338                    #print listOfFiles
339                   
340            for file in listOfFiles:
341                    DI = csmllibs.csmldataiface.DataInterface()
342                    DI=DI.getUnknownInterfaceType(file)
343                    print'opening file'
344                    DI.openFile(file)
345                    print 'getting variables'
346                    allVarNames=DI.getListofVariables()
347                    print 'getting feature count'
348                    numFeatures=len(allVarNames)       
349                   
350                    print "FEATURES"
351                    print "***********"
352                    for i in range (0, len(allVarNames)):
353                            print allVarNames[i]
354                           
355                    for i in range (0, numFeatures):
356                            gml_featureMember_element=csmldoc.createElement("gml:featureMember")
357                            ProfileFeature_element=csmldoc.createElement("ProfileFeature")
358                            ProfileFeature_element.setAttribute('gml:id',str(allVarNames[i]))
359                            gml_description_element = csmldoc.createElement("gml:description")
360                            gml_featureMember_element.appendChild(ProfileFeature_element)
361                            #***********************************************************************
362                            #PointSeriesDomain:
363                            #***********************************************************************
364                            ProfileDomain_element=csmldoc.createElement("ProfileDomain")
365                           
366                           
367                            #***********************************************************************
368                            # domainReference element (and sub-elements)               
369                            #***********************************************************************
370                            domainReference_element=csmldoc.createElement("domainReference")
371                            #orientedPosition_element=csmldoc.createElement("OrientedPosition")
372                            #locations_element=csmldoc.createElement("locations")
373                            #times_element=csmldoc.createElement("times")
374                            #trajectory_element.appendChild(locations_element)
375                            #trajectory_element.appendChild(times_element)
376                            #domainReference_element.appendChild(orientedPosition_element)
377                           
378                            #gml_timePositionList_element = csmldoc.createElement("gml:TimePositionList")
379                            #gml_timePositionList_element.appendChild(csmldoc.createTextNode(self.timeString))
380                            #domainReference_element.appendChild(gml_timePositionList_element)
381                            ProfileDomain_element.appendChild(domainReference_element)
382                            #***********************************************************************
383                            domainComplement_element=csmldoc.createElement("domainComplement")
384                            ProfileDomain_element.appendChild(domainComplement_element)
385                           
386                            #***********************************************************************
387                            # gml:rangeSet_element
388                            #***********************************************************************
389                           
390                            gml_rangeSet_element=csmldoc.createElement("gml:rangeSet") 
391                           
392                            #***********************************************************************
393                            # gml:coverageFunction element (and sub-element MappingRule)               
394                            #***********************************************************************
395                            gml_coverageFunction_element=csmldoc.createElement("gml:coverageFunction")
396                            MappingRule_element=csmldoc.createElement("MappingRule")
397                            #MappingRule_element.setAttribute('scanOrder',csmllibs.csmlextra.getMappingRule(len(dimNames)))
398                            MappingRule_element.setAttribute('scanOrder','tba')
399                            gml_coverageFunction_element.appendChild(MappingRule_element)
400                           
401                           
402                            gml_featureMember_element.appendChild(ProfileDomain_element)
403                            gml_featureMember_element.appendChild(gml_rangeSet_element)
404                            gml_featureMember_element.appendChild(gml_coverageFunction_element)
405                            gml_FeatureCollection_element.appendChild(gml_featureMember_element)       
406                           
407            return 
408                           
409       
Note: See TracBrowser for help on using the repository browser.