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 | |
---|
9 | import csml.parser as cp |
---|
10 | import csml.csmllibs |
---|
11 | import sys |
---|
12 | import pdb |
---|
13 | |
---|
14 | |
---|
15 | class featureBuilder(object): |
---|
16 | def __init__(self, dataset_element, featureCollection_element, ffmap,fileExtractDictionary, timedim, timestorage,spatialstorage,valuestorage,minaxes): |
---|
17 | self.ds_element=dataset_element |
---|
18 | self.featureCollection = featureCollection_element |
---|
19 | self.ffmap = ffmap |
---|
20 | self.fileExtractDictionary = fileExtractDictionary |
---|
21 | self.timedim = timedim |
---|
22 | self.timestorage=timestorage |
---|
23 | self.spatialstorage=spatialstorage |
---|
24 | self.valuestorage=valuestorage |
---|
25 | self.minaxes=minaxes |
---|
26 | |
---|
27 | #empty list to hold featureMembers |
---|
28 | self.fms =[] |
---|
29 | |
---|
30 | #at the moment, only one featuretype per CSML Dataset is supported. |
---|
31 | #get the featuretype of the first representative file in the ffmap object |
---|
32 | self.featuretype= self.ffmap.getRepresentativeFiles()[0].getFeatureType() |
---|
33 | #and create the features |
---|
34 | print 'determining feature type' |
---|
35 | print self.featuretype |
---|
36 | if self.featuretype == 'GridSeries': |
---|
37 | self.createCSMLGridSeriesFeatures() |
---|
38 | elif self.featuretype == 'PointSeries': |
---|
39 | self.createCSMLPointSeriesFeatures() |
---|
40 | elif self.featuretype == 'ProfileSeries': |
---|
41 | self.createCSMLProfileSeriesFeatures() |
---|
42 | #after the features have been generated append all featureMembers to the feature collection |
---|
43 | self.featureCollection.featureMembers=self.fms |
---|
44 | |
---|
45 | #Some internal methods that are of use to all feature types: |
---|
46 | def _getDescriptiveName(self,DI): |
---|
47 | #given a data interface class with the variable or axis set, try to get a descriptive name |
---|
48 | #eg. long name |
---|
49 | try: |
---|
50 | descName=DI.getVariableAttribute('long_name') |
---|
51 | descName |
---|
52 | except AttributeError: |
---|
53 | descName = "missing name" |
---|
54 | descName=descName.replace('&','&') #remove ampersands TODO- extend this |
---|
55 | return descName |
---|
56 | |
---|
57 | def _populateListOfFiles(self,repfile): |
---|
58 | #given a representative file, get list of files: one representative file + all related files |
---|
59 | listOfFiles=[] |
---|
60 | repfilename=repfile.getRepresentativeFileName() |
---|
61 | listOfFiles.append(repfilename) |
---|
62 | relfiles = repfile.getRelatedFiles() |
---|
63 | for f in relfiles: |
---|
64 | fname = f.getRelatedFileName() |
---|
65 | listOfFiles.append(fname) |
---|
66 | return repfilename,listOfFiles |
---|
67 | |
---|
68 | def _getFilesAndTimes(self): |
---|
69 | #TODO try and speed up csmllibs.csmltime.getFileTimeList |
---|
70 | OrderedFileTimeList,self.caltype,self.units = csml.csmllibs.csmltime.getFileTimeList(self.listOfFiles,self.timedim) |
---|
71 | #build strings to hold times/filenames for current gridseriesfeature |
---|
72 | self.timeString ='' |
---|
73 | self.filesinDir = '' |
---|
74 | lastf='' |
---|
75 | for j in range (0, len(OrderedFileTimeList)): |
---|
76 | t= OrderedFileTimeList[j][0] |
---|
77 | f = OrderedFileTimeList[j][1] |
---|
78 | self.timeString = self.timeString + ' ' + str(t) |
---|
79 | if f != lastf: |
---|
80 | self.filesinDir = self.filesinDir + ' ' + f |
---|
81 | lastf=f |
---|
82 | |
---|
83 | def _getCorrectExtractType(self): |
---|
84 | #returns an empty parser file extract object of the correct type. |
---|
85 | if self.extractType=='NetCDFExtract': |
---|
86 | fe = csml.parser.NetCDFExtract() |
---|
87 | if self.extractType=='NASAAmesExtract': |
---|
88 | fe = csml.parser.NASAAmesExtract() |
---|
89 | if self.extractType=='GRIBExtract': |
---|
90 | fe = csml.parser.GRIBExtract() |
---|
91 | if self.extractType=='PPExtract': |
---|
92 | fe = csml.parser.NetCDFExtract() |
---|
93 | return fe |
---|
94 | |
---|
95 | |
---|
96 | |
---|
97 | #the following __functions are used by all or most feature types: |
---|
98 | |
---|
99 | def __getVarInfo(self, representativeFile): |
---|
100 | self.repfilename,self.listOfFiles=self._populateListOfFiles(representativeFile) |
---|
101 | self._getFilesAndTimes() |
---|
102 | #Open representative file and create feature members: |
---|
103 | self.DI = csml.csmllibs.csmldataiface.DataInterface() |
---|
104 | self.DI=self.DI.getUnknownInterfaceType(self.repfilename) |
---|
105 | self.DI.openFile(self.repfilename) |
---|
106 | allVarNames=self.DI.getListofVariables() |
---|
107 | checkedVars=[] |
---|
108 | for var in allVarNames: |
---|
109 | self.DI.setVariable(var) |
---|
110 | numaxes=len(self.DI.getVariableAxes()) |
---|
111 | #ignore any variables below the specified dimension threshold |
---|
112 | if numaxes > self.minaxes: |
---|
113 | checkedVars.append(var) |
---|
114 | numFeatures=len(checkedVars) |
---|
115 | return checkedVars, numFeatures |
---|
116 | |
---|
117 | def __getGridCoordinatesTable(self,dimNames, crs,axisorder): |
---|
118 | #referenceableGrid/GridCoordinatesTable |
---|
119 | gcT=cp.GridCoordinatesTable() |
---|
120 | #timeHref is used to store a referencable timepositionlist for reuse |
---|
121 | if not hasattr(self, 'timeHref'): |
---|
122 | self.timeHref = None |
---|
123 | ##add an axisName element(s) for each spatial dimension. |
---|
124 | #and an ordinate element |
---|
125 | axes='' |
---|
126 | for axis in dimNames: |
---|
127 | axes =axes + ' '+ axis |
---|
128 | ordinates=[] |
---|
129 | for dimName in enumerate(dimNames): |
---|
130 | ord=cp.GridOrdinateDescription() |
---|
131 | #map the grid axis to the crs axis |
---|
132 | #default to empty element |
---|
133 | ord.coordAxisLabel=cp.csString('') |
---|
134 | ord.gridAxesSpanned=cp.csString('') |
---|
135 | for axis in axisorder: |
---|
136 | if axisorder[axis]==dimName[0]: |
---|
137 | ord.coordAxisLabel=cp.csString(axis) |
---|
138 | ord.gridAxesSpanned=cp.csString(dimName[1]) |
---|
139 | break |
---|
140 | seqRule= cp.SequenceRule() |
---|
141 | seqRule.CONTENT='Linear' |
---|
142 | seqRule.axisOrder='+1' #TO DO. Work this out. |
---|
143 | ord.sequenceRule=seqRule |
---|
144 | sptList=csml.parser.SpatialOrTemporalPositionList() |
---|
145 | sptList.id =csml.csmllibs.csmlextra.getRandomID() |
---|
146 | if dimName[1]==self.timedim: |
---|
147 | #this is the time dimension. handle calendaring etc when getting the data. |
---|
148 | if self.timestorage=='fileextract': |
---|
149 | #look up file extract name in dictionary |
---|
150 | #(axisid stored in dictionary = current filename + variable name) |
---|
151 | axisid=self.repfilename+dimName[1] |
---|
152 | sptList.timePositionList=cp.TimePositionList(self.fileExtractDictionary[axisid]) |
---|
153 | else: |
---|
154 | if self.timeHref == None: |
---|
155 | self.timeHref=sptList.id |
---|
156 | timeposList=cp.TimePositionList() |
---|
157 | timeposList.CONTENT=self.timeString |
---|
158 | timeposList.frame='ndg:%s'%self.caltype |
---|
159 | sptList.timePositionList=timeposList |
---|
160 | else: |
---|
161 | sptList.href='#' +self.timeHref |
---|
162 | sptList.show='embed' |
---|
163 | sptList.arcrole='http://ndg.nerc.ac.uk/xlinkUsage/insert#timePositionList' |
---|
164 | sptList.role='http://ndg.nerc.ac.uk/fileFormat/csmlStorageDescriptor' |
---|
165 | sptList.timePositionList=cp.TimePositionList() |
---|
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]) #todo, fix xlink |
---|
172 | sptList.href='#'+self.fileExtractDictionary[axisid] |
---|
173 | sptList.show='embed' |
---|
174 | sptList.arcrole='http://ndg.nerc.ac.uk/xlinkUsage/insert#coordinateList' |
---|
175 | sptList.role='http://ndg.nerc.ac.uk/fileFormat/csmlStorageDescriptor' |
---|
176 | else: |
---|
177 | #store inline |
---|
178 | self.DI.setAxis(dimName[1]) |
---|
179 | sptList.coordinateList=cp.csString(csml.csmllibs.csmlextra.cleanString(str(self.DI.getDataForAxis()))) |
---|
180 | |
---|
181 | ord.coordAxisValues=sptList |
---|
182 | gcT.addChildElem('gridOrdinates',ord) |
---|
183 | return gcT |
---|
184 | |
---|
185 | def __getLocation(self): |
---|
186 | #attempts to get a fixed location, eg for a ProfileSeriesFeature. |
---|
187 | lonval=None |
---|
188 | latval=None |
---|
189 | heightval=None |
---|
190 | vars=self.DI.getListofVariables() |
---|
191 | cat = csml.csmllibs.csmlcrs.CRSCatalogue() |
---|
192 | axes=[] |
---|
193 | for var in vars: |
---|
194 | self.DI.setVariable(var) |
---|
195 | unitname=self.DI.getVariableAttribute('units') |
---|
196 | unittype=cat.getUnitType(unitname) |
---|
197 | if unittype == 'latitude': |
---|
198 | latval=self.DI.getDataForVar() |
---|
199 | axes.append(unittype) |
---|
200 | elif unittype == 'longitude': |
---|
201 | lonval=self.DI.getDataForVar() |
---|
202 | axes.append(unittype) |
---|
203 | elif unittype=='height': |
---|
204 | heightval=self.DI.getDataForVar() |
---|
205 | axes.append(unittype) |
---|
206 | |
---|
207 | #returns lat lon height, but note that any of these may be None |
---|
208 | crs=cat.determineCRS(knownCRSAxes =axes) #TODO, may need to rethink csmlcrs module a bit |
---|
209 | srsName= crs[0].srsName |
---|
210 | return latval, lonval, heightval, srsName |
---|
211 | |
---|
212 | def __getCRS(self,varName,catalogue): |
---|
213 | self.DI.setVariable(varName) |
---|
214 | dimNames=self.DI.getVariableAxes() |
---|
215 | if len(dimNames) <= 1: |
---|
216 | #it's an axis or bounds not a feature, try next variable |
---|
217 | return None, None, None |
---|
218 | unitlist=[] |
---|
219 | stdNames=[] |
---|
220 | for dim in dimNames: |
---|
221 | self.DI.setAxis(dim) |
---|
222 | units=self.DI.getAxisAttribute('units') #need to make special case of units in DI layer |
---|
223 | stdname =None |
---|
224 | try: |
---|
225 | stdname=self.DI.getAxisAttribute('standard_name') |
---|
226 | except: |
---|
227 | pass |
---|
228 | stdNames.append(stdname) |
---|
229 | unitlist.append(units) |
---|
230 | crs, axisorder=catalogue.determineCRS(dimNames,unitlist, stdNames) |
---|
231 | return crs, axisorder, dimNames |
---|
232 | |
---|
233 | def __getStdName(self, varName): |
---|
234 | '''look for the 'standard_name' attribute. Assumes it's a cf compliant standard_name. If not found returns None''' |
---|
235 | self.DI.setVariable(varName) |
---|
236 | sn=self.DI.getVariableAttribute('standard_name') |
---|
237 | if sn is None: |
---|
238 | sname = None |
---|
239 | else: |
---|
240 | sname='http://cfconventions.org/standard_names/%s'%sn |
---|
241 | return sname |
---|
242 | |
---|
243 | |
---|
244 | def __featureMetadata(self,feature, varName): |
---|
245 | feature.id=csml.csmllibs.csmlextra.getRandomID() |
---|
246 | feature.name=csml.parser.csString(varName) |
---|
247 | desc = self._getDescriptiveName(self.DI) |
---|
248 | feature.description=csml.parser.csString(desc) |
---|
249 | |
---|
250 | def __getGMLRangeset(self,varName): |
---|
251 | #GML RANGESET |
---|
252 | rs=csml.parser.RangeSet() |
---|
253 | self.DI.setVariable(varName) |
---|
254 | arrSz = self.DI.getArraySizeOfVar() |
---|
255 | try: |
---|
256 | strUom = self.DI.getVariableAttribute('units') |
---|
257 | strUom=strUom.replace(' ','.') |
---|
258 | if strUom=='': |
---|
259 | strUom='dimensionless_or_units_not_determined' |
---|
260 | except AttributeError: |
---|
261 | # if units attribute doesn't exist: |
---|
262 | strUom ="dimensionless-or_units_not_determined" |
---|
263 | if self.valuestorage=='inline': |
---|
264 | #TO DO, store the rangeset inline - use Datablock class??? |
---|
265 | pass |
---|
266 | else: |
---|
267 | #store the rangeSet as an aggregatedArray |
---|
268 | aa=cp.AggregatedArray() |
---|
269 | aa.arraySize=cp.csString(arrSz) |
---|
270 | aa.uom=cp.csString(strUom) |
---|
271 | aa.aggType=cp.csString('new') #can it be anything else? |
---|
272 | aa.aggIndex=cp.csString('1') |
---|
273 | #FileExtract (fe) element will be NetCDF/GRIB/PPExtract element (As defined earlier in ExtractType) |
---|
274 | self.extractType= self.DI.extractType |
---|
275 | fe = self._getCorrectExtractType() |
---|
276 | varSize=self.DI.getShapeOfVar() |
---|
277 | varSize=csml.csmllibs.csmlextra.cleanString1(str(varSize)) |
---|
278 | fe.arraySize=cp.csString(varSize) |
---|
279 | fl=cp.FileList() |
---|
280 | fl.fileNames=cp.csString(self.filesinDir) |
---|
281 | fe.fileList=fl |
---|
282 | fe.variableName=cp.csString(varName) |
---|
283 | aa.components=[fe] |
---|
284 | aa.id=csml.csmllibs.csmlextra.getRandomID() |
---|
285 | if hasattr(self.ds_element, 'storageDescriptor'): |
---|
286 | self.ds_element.storageDescriptor.descriptors.append(aa) |
---|
287 | else: |
---|
288 | sd =csml.parser.CSMLStorageDescriptor() |
---|
289 | sd.descriptors=[aa] |
---|
290 | setattr(self.ds_element, 'storageDescriptor',sd) |
---|
291 | va=csml.parser.ValueArray() |
---|
292 | vc=csml.parser.MeasureOrNullList() |
---|
293 | vc.href='#%s'%aa.id |
---|
294 | vc.arcrole="http://ndg.nerc.ac.uk/xlinkUsage/insert#QuantityList" |
---|
295 | vc.role="http://ndg.nerc.ac.uk/fileFormat/csmlStorageDescriptor" |
---|
296 | vc.show='embed' |
---|
297 | vc.uom=strUom |
---|
298 | va.valueComponent=vc |
---|
299 | va.id=csml.csmllibs.csmlextra.getRandomID() |
---|
300 | rs.valueArray=va |
---|
301 | return rs |
---|
302 | |
---|
303 | |
---|
304 | #the following functions are for creation of specific feature types (and call the __functions above) |
---|
305 | def createCSMLGridSeriesFeatures(self): |
---|
306 | #This method assumes that the variables (features) are shared across identically structured files |
---|
307 | #should be supplied with a featurefilemap object (see csmlfiles for FileMapMaker) |
---|
308 | representativeFiles=self.ffmap.getRepresentativeFiles() |
---|
309 | cat=csml.csmllibs.csmlcrs.CRSCatalogue() |
---|
310 | for repfile in representativeFiles: |
---|
311 | #get the names of all the variables in the files: |
---|
312 | allVarNames, numFeatures = self.__getVarInfo(repfile) |
---|
313 | #Create a GridSeriesFeature for each variable: |
---|
314 | for i in range(0, numFeatures): |
---|
315 | crs,axisorder, dimNames=self.__getCRS(allVarNames[i], cat) |
---|
316 | if crs == None: |
---|
317 | continue #try next variable |
---|
318 | gsFeature=cp.GridSeriesFeature() |
---|
319 | self.__featureMetadata(gsFeature,allVarNames[i]) |
---|
320 | #VALUE (coverage) |
---|
321 | gsCoverage=cp.GridSeriesCoverage() |
---|
322 | gsCoverage.id = csml.csmllibs.csmlextra.getRandomID() |
---|
323 | gsDomain=cp.GridSeriesDomain() |
---|
324 | gsDomain.id = csml.csmllibs.csmlextra.getRandomID() |
---|
325 | gsDomain.srsName=crs.srsName |
---|
326 | gsDomain.axisLabels=crs.axisLabels # note this is the xml attribute axisLabels, not the child element (aLabels) |
---|
327 | gsDomain.srsDimension=crs.srsDimension |
---|
328 | gsDomain.dimension=gsDomain.srsDimension |
---|
329 | if crs.units is not None: |
---|
330 | gsDomain.uomLabels=crs.units |
---|
331 | else: |
---|
332 | gsDomain.uomLabels="could not get units" |
---|
333 | aLabels='' |
---|
334 | for dim in dimNames: |
---|
335 | aLabels=aLabels + dim + ' ' |
---|
336 | gsDomain.aLabels=cp.csString(aLabels) |
---|
337 | limits=cp.GridEnvelope() |
---|
338 | limits.low=cp.csString('0 0 0') |
---|
339 | limits.high=cp.csString('0 0 0') |
---|
340 | gsDomain.limits=limits |
---|
341 | gcT=self.__getGridCoordinatesTable(dimNames, crs,axisorder) |
---|
342 | gsDomain.coordTransformTable=gcT |
---|
343 | gsCoverage.gridSeriesDomain=gsDomain |
---|
344 | |
---|
345 | #COVERAGE FUNCTION |
---|
346 | #mr =csml.csmllibs.csmlextra.getMappingRule(len(dimNames)) |
---|
347 | #gsCoverage.coverageFunction=cp.csString(mr) |
---|
348 | rs=self.__getGMLRangeset(allVarNames[i]) |
---|
349 | |
---|
350 | #RANGESET |
---|
351 | gsCoverage.rangeSet=rs |
---|
352 | |
---|
353 | #phenomenon |
---|
354 | param=self.__getStdName(allVarNames[i]) |
---|
355 | if not param: |
---|
356 | param='http://badc.rl.ac.uk/localparams#%s'%allVarNames[i] |
---|
357 | gsFeature.parameter=csml.parser.Phenomenon(href=param) |
---|
358 | gsFeature.value=gsCoverage |
---|
359 | self.fms.append(gsFeature) |
---|
360 | self.DI.closeFile() |
---|
361 | ###End of createCSMLGridSeriesFeatures### |
---|
362 | |
---|
363 | def createCSMLProfileSeriesFeatures(self): |
---|
364 | #This method assumes that the variables (features) are shared across identically structured files |
---|
365 | #should be supplied with a featurefilemap object (see csmlfiles for FileMapMaker) |
---|
366 | representativeFiles=self.ffmap.getRepresentativeFiles() |
---|
367 | cat=csml.csmllibs.csmlcrs.CRSCatalogue() |
---|
368 | for repfile in representativeFiles: |
---|
369 | #get the names of all the variables in the files: |
---|
370 | allVarNames, numFeatures = self.__getVarInfo(repfile) |
---|
371 | #Create a ProfileSeriesFeature for each variable: |
---|
372 | for i in range(0, numFeatures): |
---|
373 | crs,axisorder, dimNames=self.__getCRS(allVarNames[i], cat) |
---|
374 | if crs == None: |
---|
375 | print 'none' |
---|
376 | continue #try next variable |
---|
377 | psFeature=cp.ProfileSeriesFeature() |
---|
378 | self.__featureMetadata(psFeature,allVarNames[i]) |
---|
379 | #VALUE (coverage) |
---|
380 | psCoverage=cp.ProfileSeriesCoverage() |
---|
381 | psDomain=cp.ProfileSeriesDomain() |
---|
382 | psDomain.srsName=crs.srsName |
---|
383 | psDomain.axisLabels=crs.axisLabels # note this is the xml attribute axisLabels, not the child element (aLabels) |
---|
384 | psDomain.srsDimension=crs.srsDimension |
---|
385 | if crs.units is not None: |
---|
386 | psDomain.uomLabels=crs.units |
---|
387 | else: |
---|
388 | psDomain.uomLabels="could not get units" |
---|
389 | aLabels='' |
---|
390 | for dim in dimNames: |
---|
391 | aLabels=aLabels + dim + ' ' |
---|
392 | psDomain.aLabels=cp.csString(aLabels) |
---|
393 | gcT=self.__getGridCoordinatesTable(dimNames, crs,axisorder) |
---|
394 | psDomain.coordTransformTable=gcT |
---|
395 | psCoverage.profileSeriesDomain=psDomain |
---|
396 | |
---|
397 | ##COVERAGE FUNCTION |
---|
398 | #mr =csml.csmllibs.csmlextra.getMappingRule(len(dimNames)) |
---|
399 | #psCoverage.coverageFunction=cp.csString(mr) |
---|
400 | rs=self.__getGMLRangeset(allVarNames[i]) |
---|
401 | |
---|
402 | #RANGESET |
---|
403 | psCoverage.rangeSet=rs |
---|
404 | psFeature.parameter=csml.parser.Phenomenon(href='http://badc.rl.ac.uk/localparams#%s'%allVarNames[i]) |
---|
405 | psFeature.value=psCoverage |
---|
406 | (latval, lonval, heightval, srs)=self.__getLocation() |
---|
407 | posString ='%s %s %s'%(latval, lonval, heightval) |
---|
408 | |
---|
409 | psFeature.location=csml.parser.DirectPositionList(CONTENT=posString, srsName=srs) |
---|
410 | self.fms.append(psFeature) |
---|
411 | self.DI.closeFile() |
---|
412 | ###End of createCSMLProfileSeriesFeatures### |
---|
413 | |
---|
414 | #BELOW THIS POINT ALL NEEDS REWRITING |
---|
415 | #################################### |
---|
416 | def createCSMLPointSeriesFeatures(self): |
---|
417 | |
---|
418 | representativeFiles=self.ffmap.getRepresentativeFiles() |
---|
419 | for repfile in representativeFiles: |
---|
420 | self.repfilename,self.listOfFiles=self._populateListOfFiles(repfile) |
---|
421 | self._getFilesAndTimes() |
---|
422 | DI = csml.csmllibs.csmldataiface.DataInterface() |
---|
423 | DI=DI.getUnknownInterfaceType(self.repfilename) |
---|
424 | DI.openFile(self.repfilename) |
---|
425 | allVarNames=DI.getListofVariables() |
---|
426 | numFeatures=len(allVarNames) |
---|
427 | try: |
---|
428 | DI.setAxis(self.timedim) |
---|
429 | times=DI.getDataForAxis() |
---|
430 | except: |
---|
431 | times = DI.getTimes() |
---|
432 | #Create features: |
---|
433 | for i in range (0, numFeatures): |
---|
434 | PointSeriesFeature_element=csml.parser.PointSeriesFeature() |
---|
435 | if str(allVarNames[i]).upper() in ['ERROR FLAG', 'ERROR']: #might need to extend this list |
---|
436 | break |
---|
437 | PointSeriesFeature_element.id=str(allVarNames[i]) |
---|
438 | desc=self._getDescriptiveName(DI) |
---|
439 | PointSeriesFeature_element.description=csml.parser.Description(desc) |
---|
440 | #DOMAIN |
---|
441 | psDomain=csml.parser.PointSeriesDomain() |
---|
442 | t=csml.parser.Trajectory() |
---|
443 | t.srsName='urn:EPSG:geographicCRS:4326' #TO Do |
---|
444 | t.locations =csml.parser.DirectPositionList(vals='1 1') |
---|
445 | |
---|
446 | if self.timestorage =='inline': |
---|
447 | tpl =csml.parser.TimePositionList() |
---|
448 | tpl.timePositions=self.timeString |
---|
449 | tpl.frame='%s:%s'%(self.caltype,self.units) |
---|
450 | t.times=tpl |
---|
451 | else: |
---|
452 | # do something to create a single extract for the times (from the representative file). |
---|
453 | tpl.timePositions = csml.csmllibs.csmlfileextracts.createSingleExtract(self.extractType, repfilename, self.timedim, len(self.timeString.split())) |
---|
454 | tpl.frame='%s:%s'%(self.caltype,self.units) |
---|
455 | |
---|
456 | |
---|
457 | # if self.timestorage =='inline': |
---|
458 | # t.times=csmllibs.Parser.TimePositionList('#RefSysX',str(times)) |
---|
459 | # else: |
---|
460 | # #todo: depends on the file mapping??? |
---|
461 | # t.times=csmllibs.Parser.TimePositionList('#RefSysX','blah') #blah = dummy times |
---|
462 | # print 'times: ' + str(allVarNames[i]) |
---|
463 | # print len(times) |
---|
464 | # print len(listOfFiles) |
---|
465 | # arraySize=len(times) * len(listOfFiles) |
---|
466 | # fextract=csmllibs.csmlfileextracts.createSingleExtract(self.extractType,filenames,self.timedim,arraySize) |
---|
467 | # tplist = csmllibs.Parser.TimePositionList(timePositions=fextract) |
---|
468 | # t.times=tplist |
---|
469 | filenames=csml.csmllibs.csmlextra.cleanString(str(self.listOfFiles)) |
---|
470 | psDomain.domainReference=t |
---|
471 | #RANGESET |
---|
472 | DI.setVariable(allVarNames[i]) |
---|
473 | try: |
---|
474 | strUom = DI.getVariableAttribute('units') |
---|
475 | strUom=strUom.replace(' ','.') |
---|
476 | except AttributeError: |
---|
477 | #if units attribute doesn't exist: |
---|
478 | strUom ="dimensionless_or_units_not_determined" |
---|
479 | |
---|
480 | try: |
---|
481 | measuredvalues = DI.getDataForVar() |
---|
482 | except: |
---|
483 | measuredvalues = ' could not get values ' |
---|
484 | rs=csml.parser.RangeSet() |
---|
485 | if self.valuestorage=='inline': |
---|
486 | #encode inline |
---|
487 | rs.quantityList=csml.parser.MeasureOrNullList(uom=strUom, val=str(measuredvalues)[1:-1]) |
---|
488 | else: |
---|
489 | #create a file extract link |
---|
490 | arraySize=len(measuredvalues)*len(self.listOfFiles) |
---|
491 | #TODO this needs to be able to handle inline, use VALUESTORAGE to determine which to use: |
---|
492 | self.extractType=DI.extractType |
---|
493 | fextract=csml.csmllibs.csmlfileextracts.createSingleExtract(self.extractType,filenames,allVarNames[i],arraySize) |
---|
494 | qlist = csml.parser.MeasureOrNullList(val=fextract) |
---|
495 | rs.quantityList=qlist |
---|
496 | PointSeriesFeature_element.rangeSet=rs |
---|
497 | #COVERAGEFUNCTION |
---|
498 | #PARAMETER |
---|
499 | #need to do parameter and coverageFunction elements |
---|
500 | PointSeriesFeature_element.domain=psDomain |
---|
501 | self.fms.append(PointSeriesFeature_element) |
---|
502 | DI.closeFile() |
---|
503 | |
---|
504 | |
---|
505 | #This function needs revising in light of a) csml parser and b) new profile feature types |
---|
506 | def createCSMLProfileFeature(csmldoc, dataset_element, gml_FeatureCollection_element, ffmap, timedim): |
---|
507 | representativeFiles=ffmap.getRepresentativeFiles() |
---|
508 | listOfFiles=[] |
---|
509 | for repfile in representativeFiles: |
---|
510 | repfilename=repfile.getRepresentativeFileName() |
---|
511 | listOfFiles.append(repfilename) |
---|
512 | relfiles = repfile.getRelatedFiles() |
---|
513 | for f in relfiles: |
---|
514 | #hopefully there are no related files at the moment! |
---|
515 | fname = f.getRelatedFileName() |
---|
516 | listOfFiles.append(fname) |
---|
517 | #print listOfFiles |
---|
518 | |
---|
519 | for file in listOfFiles: |
---|
520 | DI = csmllibs.csmldataiface.DataInterface() |
---|
521 | DI=DI.getUnknownInterfaceType(file) |
---|
522 | print'opening file' |
---|
523 | DI.openFile(file) |
---|
524 | print 'getting variables' |
---|
525 | allVarNames=DI.getListofVariables() |
---|
526 | print 'getting feature count' |
---|
527 | numFeatures=len(allVarNames) |
---|
528 | |
---|
529 | print "FEATURES" |
---|
530 | print "***********" |
---|
531 | for i in range (0, len(allVarNames)): |
---|
532 | print allVarNames[i] |
---|
533 | |
---|
534 | for i in range (0, numFeatures): |
---|
535 | gml_featureMember_element=csmldoc.createElement("gml:featureMember") |
---|
536 | ProfileFeature_element=csmldoc.createElement("ProfileFeature") |
---|
537 | ProfileFeature_element.setAttribute('gml:id',str(allVarNames[i])) |
---|
538 | gml_description_element = csmldoc.createElement("gml:description") |
---|
539 | gml_featureMember_element.appendChild(ProfileFeature_element) |
---|
540 | #*********************************************************************** |
---|
541 | #PointSeriesDomain: |
---|
542 | #*********************************************************************** |
---|
543 | ProfileDomain_element=csmldoc.createElement("ProfileDomain") |
---|
544 | |
---|
545 | |
---|
546 | #*********************************************************************** |
---|
547 | # domainReference element (and sub-elements) |
---|
548 | #*********************************************************************** |
---|
549 | domainReference_element=csmldoc.createElement("domainReference") |
---|
550 | #orientedPosition_element=csmldoc.createElement("OrientedPosition") |
---|
551 | #locations_element=csmldoc.createElement("locations") |
---|
552 | #times_element=csmldoc.createElement("times") |
---|
553 | #trajectory_element.appendChild(locations_element) |
---|
554 | #trajectory_element.appendChild(times_element) |
---|
555 | #domainReference_element.appendChild(orientedPosition_element) |
---|
556 | |
---|
557 | #gml_timePositionList_element = csmldoc.createElement("gml:TimePositionList") |
---|
558 | #gml_timePositionList_element.appendChild(csmldoc.createTextNode(self.timeString)) |
---|
559 | #domainReference_element.appendChild(gml_timePositionList_element) |
---|
560 | ProfileDomain_element.appendChild(domainReference_element) |
---|
561 | #*********************************************************************** |
---|
562 | domainComplement_element=csmldoc.createElement("domainComplement") |
---|
563 | ProfileDomain_element.appendChild(domainComplement_element) |
---|
564 | |
---|
565 | #*********************************************************************** |
---|
566 | # gml:rangeSet_element |
---|
567 | #*********************************************************************** |
---|
568 | |
---|
569 | gml_rangeSet_element=csmldoc.createElement("gml:rangeSet") |
---|
570 | |
---|
571 | #*********************************************************************** |
---|
572 | # gml:coverageFunction element (and sub-element MappingRule) |
---|
573 | #*********************************************************************** |
---|
574 | gml_coverageFunction_element=csmldoc.createElement("gml:coverageFunction") |
---|
575 | MappingRule_element=csmldoc.createElement("MappingRule") |
---|
576 | #MappingRule_element.setAttribute('scanOrder',csmllibs.csmlextra.getMappingRule(len(dimNames))) |
---|
577 | MappingRule_element.setAttribute('scanOrder','tba') |
---|
578 | gml_coverageFunction_element.appendChild(MappingRule_element) |
---|
579 | |
---|
580 | |
---|
581 | gml_featureMember_element.appendChild(ProfileDomain_element) |
---|
582 | gml_featureMember_element.appendChild(gml_rangeSet_element) |
---|
583 | gml_featureMember_element.appendChild(gml_coverageFunction_element) |
---|
584 | gml_FeatureCollection_element.appendChild(gml_featureMember_element) |
---|
585 | |
---|
586 | return |
---|
587 | |
---|
588 | |
---|