source: TI02-CSML/trunk/csml/csmllibs/csmlfeaturetypes.py @ 2001

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

several changes made to enable proper use of CRS

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