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

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

aggregatedArray created outside of rangeSet

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