source: cows/trunk/cows/service/imps/data_reader_geoplot_backend/data_readers/csml_data_reader.py @ 5945

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/cows/trunk/cows/service/imps/data_reader_geoplot_backend/data_readers/csml_data_reader.py@5945
Revision 5945, 7.8 KB checked in by pnorton, 11 years ago (diff)

Improved the csml_data_reader so that it no longer assumes the feature id is the variable name.

Improved the data reader layer so that it now gets the dataset name from the csml file.

Added some code to the geoplot slabs that is used for selecting a log scale.

Line 
1
2import os
3
4import csml
5import cdms2 as cdms
6from copy import copy
7
8from cows.service.imps.csmlbackend.config import config
9from cows.service.imps.csmlbackend.csmlcommon import CSMLConnector
10from cows.service.imps.csmlbackend.wms_csmllayer import CSMLwmsDimension
11import numpy
12import logging
13
14log = logging.getLogger(__name__)
15
16#
17# Global CSML connector instance
18#
19globalCSMLConnector = CSMLConnector()
20
21
22class CSMLDataReader(object):
23   
24    def __init__(self, fileoruri):
25        self._crscat=csml.csmllibs.csmlcrs.CRSCatalogue()
26        self.connector = globalCSMLConnector
27        self.fileoruri = fileoruri
28        self.ds = self.connector.getCsmlDoc(fileoruri)
29        self.varcache = {} 
30       
31
32   
33    def getWMSLayerInfo(self):
34       
35        for feature in csml.csmllibs.csmlextra.listify(self.ds.featureCollection.featureMembers):
36            log.debug("feature.id = %s" % (feature.id,))
37            title, abstract, dimensions, units, crss=self._getWMSInfo(feature)
38            bb = self._getBBox(feature)
39            name = feature.id
40           
41            yield (name, title, abstract, dimensions, units, crss, bb) 
42
43   
44    def _getFeatureTitleAndAbstract(self, feature):
45        ''' given a csml feature, return basic info about the layer/feature/coverage
46        @return:   title, abstract'''
47
48        try:
49            title=feature.name.CONTENT
50        except:
51            title=''
52           
53        try:
54            abstract=feature.description.CONTENT
55        except:
56            abstract=title
57       
58        return title, abstract   
59
60    def _getBBox(self, feature):
61        try: 
62            bb = feature.getCSMLBoundingBox().getBox()
63        except:
64            #default to global
65            bb=[-180,-90,180,90]
66        return bb       
67
68    def _getWMSInfo(self, feature):
69        ''' given a csml feature, return info about the layer/feature
70        @return:   title, abstract, dimensions, units, crss '''
71
72        title, abstract = self._getFeatureTitleAndAbstract(feature)
73        units=feature.getDomainUnits() 
74        dimensions={}
75        tmpunits=copy(units)
76        tmpunits.reverse()
77        domain = feature.getDomain()
78       
79        for dim in feature.getAxisLabels():
80            nextdim=CSMLwmsDimension(domain, dim, tmpunits.pop())
81           
82            if dim not in ['latitude', 'longitude']:
83                dimensions[dim]=nextdim
84               
85        crs=feature.getNativeCRS()
86        crss=[self._crscat.getCRS(crs).twoD]
87       
88        if 'EPSG:4326' in crss:
89            crss.append('CRS:84')
90            crss.append('WGS84')
91                   
92        #the units to return are the units of measure.
93        try:
94            units=feature.value.rangeSet.valueArray.valueComponent.uom
95        except:
96            units='unknown units'
97           
98        return title, abstract, dimensions, units, crss
99
100    def _getFeature(self, id):
101        for feature in csml.csmllibs.csmlextra.listify(self.ds.featureCollection.featureMembers):
102            if feature.id == id:
103                return feature
104           
105        raise Exception("Feature with id %s not found" % (id,))
106 
107
108    def getNetcdfVar(self, featureId,  dimValues):
109        "Opens up the csml and retrieves the variable described by the dimensions"
110       
111
112        log.debug("featureId = %s, dimValues = %s" % (featureId, dimValues))
113       
114        dimList = list(dimValues.items())
115        dimList.sort()
116       
117        cacheKey = "%s:%s" % (featureId, dimList)
118
119        if cacheKey not in self.varcache:
120       
121            feature = self._getFeature(featureId)
122           
123            convertedDimVals = self._convertDimValues(dimValues)
124                 
125            if type(feature) == csml.parser.GridSeriesFeature:
126               
127                randomname= csml.csmllibs.csmlextra.getRandomID() + '.nc'
128               
129                log.debug("getting csml feature tmpdir = %s, ncname = %s, convertedDimVals = %s" \
130                          % (config['tmpdir'], randomname, convertedDimVals))
131               
132                result= feature.subsetToGridSeries(config['tmpdir'], 
133                                            ncname=randomname, **convertedDimVals)
134             
135                extract = result[2]
136
137                variable_name = extract.variableName.CONTENT
138               
139                #for now have to read netcdf back from
140                #disk (limitiation of CSML api)
141                netcdf=cdms.open(result[1])
142                                               
143                #and then delete the temporary file
144                os.system('rm %s'%result[1])
145               
146                log.debug("removed temp file %s" % (result[1],))
147               
148            else:
149                raise NotImplementedError
150           
151            variable =  netcdf(variable_name, squeeze=1)
152           
153            #try to set any NAN variable to masked variables
154            try:
155                #replace any NaN's with masked values
156                are_nan = numpy.isnan(variable)
157
158                if are_nan.any():
159                    # if the mask is just a single value we need to expand it
160                    if variable.mask.shape != variable.shape:
161                       
162                        if variable.mask:
163                            variable.mask = numpy.ones(variable.shape)
164                        else:
165                            variable.mask = numpy.zeros(variable.shape)
166                       
167                    variable[are_nan] = variable.getMissing()
168                    variable.mask[are_nan] = True
169           
170            except:
171                log.exception("Exception occurred while trying to fix NAN numbers in variable.")
172                raise
173           
174            self.varcache[cacheKey] = variable
175        else:
176            variable = self.varcache[cacheKey]
177
178        return variable
179   
180       
181    def _convertDimValues(self, dimValues):
182        """
183        Converts the string dimension values to floats (except for time values)
184        """
185        convertedVals = {}
186       
187        for dimval in dimValues:
188            if dimval != 'time':
189                convertedVals[dimval]=float(dimValues[dimval])
190            else:
191                #remove any trailing Zs from time string
192                if dimValues[dimval] [-1:] in ['Z', 'z']:
193                    convertedVals[dimval]=dimValues[dimval][:-1]
194                else:
195                    convertedVals[dimval] = dimValues[dimval] 
196
197        return convertedVals
198   
199   
200    def getConfigAxisXMLFile(self):
201       
202        xmlPath = None
203        for m in self._getMetadataElements():
204            log.debug("m.text = %s" % (m.text,))
205           
206            if m.text is not None and len(m.text) > 0:
207                metadataValue = m.text.strip()
208               
209                if metadataValue.find('AxisConfigXML') == 0:
210                    xmlPath = metadataValue.split('=')[1]
211       
212        log.debug("xmlPath = %s" % (xmlPath,))
213        return xmlPath
214   
215    def _getMetadataElements(self):
216       
217        featureCollectionElt = None
218        for c in self.ds.elem.getchildren(): 
219            if c.tag.find('CSMLFeatureCollection') > -1:
220                featureCollectionElt = c
221                break
222       
223        metadataElements = []
224        if featureCollectionElt != None:
225            for c in featureCollectionElt.getchildren():
226                if c.tag.find("metaDataProperty") > -1:
227                    metadataElements.append(c)   
228
229        return metadataElements
230       
231    @staticmethod
232    def isDataPresent(fileoruri):
233        global globalCSMLConnector
234       
235        log.debug("globalCSMLConnector.list() = %s" % ([x for x in globalCSMLConnector.list()],))
236        for file in globalCSMLConnector.list():
237            log.debug("file = %s" % (file,))
238            if file == fileoruri:
239                return True
240           
241        return False
242   
243   
Note: See TracBrowser for help on using the repository browser.