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

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

more on !referenceableGrid

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