source: TI02-CSML/trunk/Scanner/csmllibs/csmlfeaturetypes.py @ 1404

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI02-CSML/trunk/Scanner/csmllibs/csmlfeaturetypes.py@1404
Revision 1404, 22.5 KB checked in by domlowe, 14 years ago (diff)

split out some internal utility methods that are common to all features

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