source: TI02-CSML/trunk/newparser/csmlio.py @ 875

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI02-CSML/trunk/newparser/csmlio.py@875
Revision 875, 11.2 KB checked in by domlowe, 14 years ago (diff)

Basic csml i/o - reading csml doc and extracting correct data from file

Line 
1#csmlio.py
2#Contains Parser wrapper'functions to enable reading of data
3
4from  Parser import *
5import nappy
6import cdms
7import parser_extra
8from xml.dom.minidom import parseString
9import elementtree.ElementTree as etree
10
11#import the DataInterface module from the Scanner, assumes it is in a sibling directory to the one containing csmlio.py
12#TODO - how best to organise modules...
13import os
14currentPath=os.getcwd()
15parentPath=os.sep.join(currentPath.split(os.sep)[:-1])
16parserPath=parentPath + '/Scanner/csmllibs'
17sys.path.append(parserPath) #append the parser path to sys.path
18try:
19    import csmldataiface
20except:
21    print 'Could not import CSML Data Interface module. Make sure the Parser code is in ../newparser directory on the same level as ../Scanner directory.'
22    sys.exit()
23
24
25class CSMLinterface:
26    #Wrapper class containing methods to read/write from/to CSML
27    #Uses parser.
28    def __init__(self):
29        self.dataset=None
30        self.currentFeature=None
31        self.currentArrayDescriptor = None
32        #this is a fix to the  ElementTree namespace problem that namespaces are usually represented as ns0, ns1, ns2 etc.
33        etree._namespace_map.update({
34        'http://www.opengis.net/om': 'om',  'http://www.opengis.net/gml': 'gml','http://ndg.nerc.ac.uk/csml' : 'csml', 'http://www.w3.org/1999/xlink':'xlink'})
35   
36    def __setFeature(self,featureID):
37        #given a featureID, set the currentFeature if it is not already set
38        #this is used to check the correct feature is always set.   
39            for member in self.dataset.featureCollection.members:
40                if member.id == featureID:
41                    self.currentFeature = member
42
43    def __setArrayDescriptor(self,fileExtractID):
44        #given a fileExtractID, set the currentArrayDescriptor if it is not already set
45        if self.currentArrayDescriptor is None:
46            for arrayDescriptor in self.dataset.arrayDescriptors:
47                if arrayDescriptor.id == fileExtractID:
48                    self.currentArrayDescriptor=arrayDescriptor
49        if self.currentArrayDescriptor.id != fileExtractID:
50            for arrayDescriptor in self.dataset.arrayDescriptors:
51                if arrayDescriptor.id == fileExtractID:
52                    self.currentArrayDescriptor=arrayDescriptor
53
54    def parse(self,csmldoc):
55        #takes incoming csml document and parses it.
56        tree = ElementTree(file=csmldoc)
57        self.dataset=Dataset()
58        self.dataset.fromXML(tree.getroot())
59        self.dataset =parser_extra.ParserPostProcessor(self.dataset).resolveReferences()
60        #self.currentFeature holds a feature object
61        self.currentFeature = None
62       
63    def getDatasetObj(self):
64        #if you want to bypass this wrapper layer, call this method and it will
65        #return a Parser.Dataset object, which you can interrogate...
66        return self.dataset
67
68    def getCSMLasString(self):
69        #returns csml document as a string
70        strCSML=self.dataset.toXML()
71        #strCSML= parseString(tostring(strCSML)).toprettyxml()
72        #strCSML= parser_extra.removeInlineNS(strCSML)
73        return strCSML
74
75    def getFeatureList(self):
76        #returns a list of feature ids
77        self.featureList = []
78        for member in self.dataset.featureCollection.members:
79             self.featureList.append(member.id)
80        return self.featureList
81       
82    def getFeatureType(self,featureID):
83        self.__setFeature(featureID)
84        if isinstance(self.currentFeature, PointFeature):
85            featureType = 'PointFeature'
86        elif isinstance(self.currentFeature, PointSeriesFeature):
87            featureType = 'PointSeriesFeature'
88        elif isinstance(self.currentFeature, ProfileFeature):
89            featureType = 'ProfileFeature'
90        elif isinstance(self.currentFeature, ProfileSeriesFeature):
91            featureType = 'ProfileSeriesFeature'
92        elif isinstance(self.currentFeature, GridFeature):
93            featureType = 'GridFeature'
94        elif isinstance(self.currentFeature, GridSeriesFeature):
95            featureType = 'GridSeriesFeature'
96        elif isinstance(self.currentFeature, TrajectoryFeature):
97            featureType = 'TrajectoryFeature'
98        else:
99             featureType = 'Unknown feature'
100        return featureType
101   
102    def getFeatureDescription(self,featureID):
103        #returns gml:description (== long name) of feature
104        #returns empty string if not available
105        self.__setFeature(featureID)
106        if hasattr(self.currentFeature, 'description'):
107            desc = self.currentFeature.description
108        else:
109            desc =""
110        return desc
111       
112    def getFileExtractList(self):
113        fileExtractList=[]
114        for arrayDescriptor in self.dataset.arrayDescriptors:
115            fileExtractList.append(arrayDescriptor.id)
116        return fileExtractList
117   
118    def subsetList(self, fileExtractID, valueList, minValue, maxValue):
119        #This is a simple list subsetter. Given a List of values (which may have been extracted from a NetCDF/NASAAmes file
120        #or may have been taken from inline CSML, it doesn't matter) this function returns a subset based on max and min values.
121        #There is inefficiency here as you have to read in the whole  'axis' before subsetting       
122        # Also It assumes monotonically varying axis (although a non-monotonically varying axis 'might' work depending on it's shape)
123        #find position of minValue in list:
124#         self.__setArrayDescriptor(fileExtractID)
125#         
126#         DI=csmldataiface.DataInterface()
127#         DI=DI.getUnknownInterfaceType(self.currentArrayDescriptor.fileName)
128#         variable = self.currentArrayDescriptor.variableName
129#         DI = csmldataiface.DataInterface()
130#         DI=DI.getUnknownInterfaceType(file)       
131#         DI.openFile(file)
132#         DI.setAxis(variable)
133#         DI.getSubsetOfDataForVar(
134        #find position of maxValue in list:
135        pass
136        #slice list:
137       
138        return subset
139       
140   
141
142   
143    def getDataForExtract(self, fileExtractID):
144        #getDataForExtract, given the gml:id of a file extract, returns the (full) data for that extract
145        self.__setArrayDescriptor(fileExtractID)
146        file = self.currentArrayDescriptor.fileName
147        variable = self.currentArrayDescriptor.variableName
148        DI = csmldataiface.DataInterface()
149        DI=DI.getUnknownInterfaceType(file)       
150        DI.openFile(file)
151        DI.setAxis(variable)
152        fulldata = DI.getDataForAxis()
153        DI.closeFile()
154        print fulldata
155        return fulldata
156       
157   
158    def getDataForFeature(self, featureID):
159        #getDataForFeature, given the gml:id of a file extract, returns the (full) data for that feature
160        #i.e. the rangeSet
161        #Needs to use the rangeSet, domainReference and domainComplement to work out how to
162        def getDataForVariable(file, variable):
163            #given a filename and a variable name, get values for that variable from data interface
164            DI = csmldataiface.DataInterface()
165            DI=DI.getUnknownInterfaceType(file)       
166            DI.openFile(file)
167            DI.setVariable(variable)
168            data = DI.getDataForVar()
169            return data
170        #extract the data from file
171        self.__setFeature(featureID)
172        #The RangeSet can be one of:
173        #QuantityList
174        #DataBlock
175        #ArrayDescriptor
176        #AggregatedArray
177        print self.currentFeature.rangeSet
178        if hasattr(self.currentFeature.rangeSet, 'quantityList'):
179            print self.currentFeature.rangeSet.quantityList
180        elif hasattr(self.currentFeature.rangeSet, 'dataBlock'):
181            print self.currentFeature.rangeSet.dataBlock
182        elif hasattr(self.currentFeature.rangeSet, 'arrayDescriptor'):
183            print self.currentFeature.rangeSet.arrayDescriptor
184        elif hasattr(self.currentFeature.rangeSet, 'aggregatedArray'):
185            print self.currentFeature.rangeSet.aggregatedArray
186            fulldata=None
187            for comp in self.currentFeature.rangeSet.aggregatedArray.component:
188                var = comp.variableName
189                for file in comp.fileName.split():
190                    data = getDataForVariable(file, var)
191                    print file + '  ' + var
192   
193                    if fulldata is None:
194                        fulldata = data.tolist()
195                    else:
196                        #print data
197                        for item in data.tolist():
198                            fulldata.append(item)
199                        #print fulldata
200                        print 'length' + str(len(fulldata))
201                        #note, for now treat masked arrays as lists
202        return fulldata
203       
204        #return fulldata
205   
206   
207#     def getSubset(self, featureID, subsetDefinition):
208#         #featureID = gml:id of feature
209#         #subsetDefinition = dictionary containing subset definition
210#         
211#         
212#         [("1999-01-01T00:00:00", "1999-01-01T06:00:00"), "axis_1.1.1.1":(30,-30), "axis_1.1.1.2":(30,-30)]
213   
214    def getDomainReference(self, featureID):
215        #This will return a list containing one or more ordinates:
216        #currently in form [Name, values]
217        self.__setFeature(featureID)
218        #domainReference could be one of:
219        #Trajectory
220        #OrientedTrajectory
221        #TimePositionList
222        if isinstance(self.currentFeature.domain.domainReference,TimePositionList):
223#             time = []
224#             time.append('t')
225#             time.append(self.currentFeature.domain.domainReference.timePositions)
226#             domainref.append(time)
227           
228            time = {}
229            time['t'] = self.currentFeature.domain.domainReference.timePositions
230            domainref  = time
231           
232        #Position
233        #OrientedPosition
234        #TimeInstant
235        return domainref
236   
237    def getDomainComplement(self, featureID):
238        #This will return a list containing one or more ordinates:
239        #currently in form [Name, values]
240        domaincomp ={}
241        self.__setFeature(featureID)
242        dc = self.currentFeature.domain.domainComplement
243       
244        #domainComplement could be one of:
245        #Null
246        #DirectPositionList
247        #Grid
248        if isinstance(dc, Grid):
249       
250            for ordinate in dc.ordinates:
251                domaincomp[ordinate.definesAxis]=self.getDataForExtract(ordinate.axisValues.id)
252#                 newaxis = []
253#                 newaxis.append(ordinate.definesAxis)
254#                 data = self.getData(ordinate.axisValues.id) # axisValues has already been resolved to the fileExtract so the gml:id can be passed straight to getData()
255#                 newaxis.append(data)
256#                 domaincomp.append(newaxis)
257        return domaincomp
258   
259    def getDomain(self, featureID):
260        #returns both the domain reference axes and domain compliment axes in a single domain dictionary
261        #axes are in no particular order
262        domain = {}
263        dc=self.getDomainComplement(featureID)
264        dr=self.getDomainReference(featureID)
265        for key in dc.keys():
266            domain[key]=dc[key]
267        for key in dr.keys():
268            domain[key]=dr[key]
269           
270        #domain.append(self.getDomainComplement(featureID))
271        #domain.append(self.getDomainReference(featureID))
272        return domain
Note: See TracBrowser for help on using the repository browser.