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

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

fixed multiple glitches in scanner

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