Changeset 4633 for cows


Ignore:
Timestamp:
15/12/08 10:14:53 (11 years ago)
Author:
domlowe
Message:

More progress on merging.

Location:
cows/branches/wcsmerge/cows
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • cows/branches/wcsmerge/cows/pylons/wcs_controller.py

    r4581 r4633  
    213213#        return slab 
    214214     
    215     def _retrieveSubset(self, layerObj, srs, dimValues): 
    216         # Find the slab in the cache first 
    217         cacheKey = layerObj.getCacheKey(srs, dimValues) 
    218          
    219         slab = self._layerSlabCache.get(cacheKey) 
    220         if slab is None: 
    221             slab = layerObj.getSubset(srs, dimValues) 
    222             if cacheKey is not None: 
    223                 self._layerSlabCache[cacheKey] = slab 
    224                  
    225         return slab 
     215#    def _retrieveSubset(self, layerObj, srs, dimValues): 
     216#        # Find the slab in the cache first 
     217#        cacheKey = layerObj.getCacheKey(srs, dimValues) 
     218#         
     219#        slab = self._layerSlabCache.get(cacheKey) 
     220#        if slab is None: 
     221#             
     222#            slab = layerObj.getCvg(srs, dimValues) 
     223#            slab = layerObj.getCvg(srs, dimValues) 
     224#            if cacheKey is not None: 
     225#                self._layerSlabCache[cacheKey] = slab 
     226#                 
     227#        return slab 
    226228     
    227229    #------------------------------------------------------------------------- 
     
    260262                 
    261263        #------------------------------------------------------- 
    262         # The real work 
    263264        #!TODO: Minimum and maximum values 
    264         filepath = self._retrieveSubset(layerObj, srs, restoredDimValues) 
     265#        filepath = self._retrieveSubset(layerObj, srs, bbox, restoredDimValues) 
     266        filepath = layerObj.getCvg(bbox) 
    265267        fileToReturn=open(filepath, 'r') 
    266268        mType='application/cf-netcdf' 
  • cows/branches/wcsmerge/cows/service/imps/csmlbackend/csmlcommon.py

    r4352 r4633  
    66import logging 
    77import csml 
     8import tempfile 
    89from pylons import config, request, session  #config must have tmpfilebuffer and csmlstore values 
    910import ConfigParser 
     
    1718 
    1819from cows.service.wxs_iface import ILayerMapper 
     20 
     21def extractToNetCDF(feature, sel, publish=False): 
     22    """ 
     23       performs the CSML subset and returns a filename of the netcdf extract 
     24       publish flag is used to indicate that the netcdf file should be made available to the webserver (for asynchronous delivery) 
     25    """ 
     26 
     27    if publish: 
     28        #if publishing to download directory is required, do so and return publishable file name 
     29        #used e.g. in WCS when "STORE = true" 
     30        extract_dir=config['publish_dir'] 
     31    else: 
     32        extract_dir = config['tmpfilebuffer'] 
     33          
     34    # Subset the feature 
     35    (fd, filename) = tempfile.mkstemp('.nc', 'csml_wxs_', extract_dir); os.close(fd) 
     36    if type(feature) is csml.parser.GridSeriesFeature: 
     37        feature.subsetToGridSeries(ncname=os.path.basename(filename), outputdir=os.path.dirname(filename) ,**sel) 
     38    elif type(feature) is csml.parser.TrajectoryFeature: 
     39        feature.subsetToTrajectory(ncname=os.path.basename(filename), outputdir=os.path.dirname(filename) ,**sel) 
     40    elif type(feature) is csml.parser.PointSeriesFeature: 
     41        del sel['longitude'] #delete dummy values 
     42        del sel['latitude'] #delete dummy values 
     43        feature.subsetToPointSeries(ncname=os.path.basename(filename), outputdir=os.path.dirname(filename) ,**sel) 
     44    elif type(feature) is csml.parser.RaggedSectionFeature: 
     45        del sel['longitude'] #delete dummy values 
     46        del sel['latitude'] #delete dummy values 
     47        feature.subsetByTime(ncname=os.path.basename(filename), outputdir=os.path.dirname(filename) ,**sel) 
     48    return filename 
     49 
    1950 
    2051class CSMLLayerMapper(ILayerMapper): 
     
    3162     
    3263    def getInfo(self, feature): 
    33         ''' given a csml feature, return basic info about the layer/feature 
     64        ''' given a csml feature, return basic info about the layer/feature/coverage 
    3465        @return:   title, abstract''' 
    3566 
  • cows/branches/wcsmerge/cows/service/imps/csmlbackend/wcs_csmllayer.py

    r4581 r4633  
    1919from cows.model.contents import DatasetSummary 
    2020from cows.service.wms_iface import IwmsLayer, IwmsDimension, IwmsLayerSlab 
    21 from cows.service.imps.csmlbackend.csmlcommon import CSMLLayerMapper, CSMLConnector 
     21from cows.service.imps.csmlbackend.csmlcommon import CSMLLayerMapper, CSMLConnector, extractToNetCDF 
    2222from cows.service.imps.csmlbackend.wms_csmllayer import CSMLwmsLayerMapper, CSMLwmsLayer 
    2323 
    24 class CSMLwcsLayerMapper(CSMLLayerMapper): 
    25     """ 
    26     Map keyword arguments to a collection of layers. 
    27     Supports the retrieval of sets of layers according to arbitrary 
    28     keyword/value pairs. 
    29     Implements  CSMLLayerMapper  
    30      
     24 
     25class CSMLwcsCoverageMapper(CSMLLayerMapper): 
     26    """ 
     27    Map keyword arguments to a collection of layers (coverages) 
     28    Supports the retrieval of coverages according to arbitrary 
     29    keyword/value pairs.   
    3130    """ 
    3231    def __init__(self): 
    33         super(CSMLwcsLayerMapper, self).__init__() 
    34     
    35      
     32        super(CSMLwcsCoverageMapper, self).__init__() 
     33        
    3634     
    3735    def getInfo(self, feature): 
     
    3937        @return:   title, abstract, dimensions, units, crss ''' 
    4038 
    41         title, abstract = super(CSMLwcsLayerMapper, self).getInfo(feature) 
     39        title, abstract = super(CSMLwcsCoverageMapper, self).getInfo(feature) 
    4240        units=feature.getDomainUnits() 
    4341        dimensions={} 
     
    125123        return self.wgs84BBox 
    126124     
    127     def getSubset(self, crs, dimValues=None): 
     125    def getCvg(self, bbox, time=None, crs=None, response_crs=None): 
    128126        """ 
    129127        Creates a subset of the layer in a particular CRS and set of 
    130128        dimensions. 
    131  
     129        #TODO: this is all out of synch 
    132130        @param crs: The coordinate reference system. 
    133131        @param dimValues: A mapping of dimension names to dimension values 
     
    139137        """ 
    140138 
    141         log.debug('getSlab(%s, %s)' % (crs, dimValues)) 
    142          
    143         #unicode conversion 
    144         for dimval in dimValues: 
    145             if dimval != 'time': 
    146                 dimValues[dimval]=float(dimValues[dimval]) 
     139        log.debug('WCS: getSubset(%s, %s, %s)' % (bbox, time, crs)) 
     140        #unpack the Boundingbox. 
     141         
     142         
     143        ############################# from old WCS stack ################# 
     144        boundingbox=bbox 
     145        lon=self._feature.getLongitudeAxis() 
     146        lat=self._feature.getLatitudeAxis() 
     147        t=self._feature.getTimeAxis() 
     148        if None in [lon, lat, t]: 
     149            #TODO need to return a suitable wcs error. 
     150            print 'warning, could not get correct axis info' 
     151            #best guess! 
     152            if t is None: 
     153                t='time' 
     154            if lon is None: 
     155                lon = 'longitude' 
     156            if lat is None: 
     157                lat = 'latitude' 
     158         
     159        #create selection dictionary: 
     160        sel={} 
     161        sel[lat]=(boundingbox[1], boundingbox[3]) 
     162        sel[lon]=(boundingbox[0], boundingbox[2]) 
     163        if time is not None: 
     164            if  type(time) is unicode: 
     165                sel[t]=str(time) 
    147166            else: 
    148                 #remove any trailing Zs from time string 
    149                 if dimValues[dimval] [-1:] in ['Z', 'z']: 
    150                     dimValues[dimval]=dimValues[dimval][:-1] 
    151         if type(self._feature) == csml.parser.GridSeriesFeature: 
    152             randomname= csml.csmllibs.csmlextra.getRandomID() + '.nc' 
    153             result= self._feature.subsetToGridSeries(config['tmpfilebuffer'], ncname=randomname, **dimValues) 
    154             return result[1] 
    155         else: 
    156             raise NotImplementedError 
    157      
    158      
    159     def getCacheKey(self, crs, dimValues=None): 
    160         """ 
    161         Create a unique key for use in caching a slab. 
    162  
    163         The intention here is that most of the work should be done when 
    164         instantiating an ILayerSlab object.  These can be cached by the 
    165         server for future use.  The server will first call getCacheKey() 
    166         for the slab creation arguments and if the key is in it's cache 
    167         it will use a pre-generated ILayerSlab object. 
    168  
    169         """ 
    170         dimList = list(dimValues.items()) 
    171         dimList.sort() 
    172         return '%s:%s' % (crs, dimList) 
    173      
    174 class CSMLwcsLayer(CSMLwmsLayer): 
    175     """ 
    176      representing a WMS layer.    Implements IwmsLayer 
    177  
    178     @ivar title: The layer title.  As seen in the Capabilities document. 
    179     @ivar abstract:  Abstract as seen in the Capabilities document. 
    180     @ivar dimensions: A dictionary of IDimension objects. 
    181     @ivar units: A string describing the units. 
    182     @ivar crss: A sequence of SRS/CRSs supported by this layer. 
    183  
    184     @todo: Do we need minValue/maxValue? 
    185  
    186     """ 
    187      
    188     def __init__(self, title, abstract, dimensions, units, crss, feature): 
    189         self.featureInfoFormats=None #NotImplemented 
    190         self.title=title 
    191         self.abstract=abstract 
    192         self.dimensions=dimensions 
    193         self.units=units 
    194         self.crss=crss 
    195         self._feature=feature 
    196         self.legendSize=(30,100) 
    197         bb= self._feature.getCSMLBoundingBox().getBox() 
    198         #convert 0 - 360 to -180, 180 as per common WMS convention 
    199         if abs(bb[2]-bb[0]) >= 359 and abs(bb[2]-bb[0]) < 361: 
    200             bb[0], bb[2]=-180, 180 
    201         self.wgs84BBox = bb 
    202         self.featureInfoFormats = ['text/html'] 
    203         try: 
    204             self.wgs84BBox = self.getBBox('EPSG:4326') 
    205         except: 
    206             raise ValueError("Layer must provide a bounding box in EPSG:4326 " 
    207                              "coordinates for compatibility with WMS-1.3.0") 
    208         self.featureinfofilecache={} #used for caching netcdf file in getFeatureInfo 
    209          
    210     def getBBox(self, crs): 
    211         """ 
    212         @return: A 4-typle of the bounding box in the given coordinate 
    213             reference system. 
    214         """ 
    215         #bb= self._feature.getCSMLBoundingBox().getBox() 
    216         #convert 0 - 360 to -180, 180 as per common WMS convention 
    217         #if abs(bb[2]-bb[0]) >= 359 and abs(bb[2]-bb[0]) < 361: 
    218         #    bb[0], bb[2]=-180, 180 
    219         #self.wgs84BBox = bb 
    220         return self.wgs84BBox 
    221         #raise NotImplementedError 
    222      
    223     def getSubset(self, crs, dimValues=None): 
    224         """ 
    225         Creates a subset of the layer in a particular CRS and set of 
    226         dimensions. 
    227  
    228         @param crs: The coordinate reference system. 
    229         @param dimValues: A mapping of dimension names to dimension values 
    230             as specified in the IDimension.extent 
    231         @param renderOpts: A generic mapping object for passing rendering 
    232             options 
    233         @return: An object implementing ILayerSlab 
    234         #create netcdf for whole lat/lon for given dimValues, use to init slab 
    235         """ 
    236  
    237         log.debug('getSlab(%s, %s)' % (crs, dimValues)) 
    238          
    239         #unicode conversion 
    240         for dimval in dimValues: 
    241             if dimval != 'time': 
    242                 dimValues[dimval]=float(dimValues[dimval]) 
    243             else: 
    244                 #remove any trailing Zs from time string 
    245                 if dimValues[dimval] [-1:] in ['Z', 'z']: 
    246                     dimValues[dimval]=dimValues[dimval][:-1] 
    247         if type(self._feature) == csml.parser.GridSeriesFeature: 
    248             randomname= csml.csmllibs.csmlextra.getRandomID() + '.nc' 
    249             result= self._feature.subsetToGridSeries(config['tmpfilebuffer'], ncname=randomname, **dimValues) 
    250             return result 
    251         else: 
    252             raise NotImplementedError 
    253          
    254 #    def getSlab(self, crs, dimValues=None, renderOpts={}): 
    255 #        """ 
    256 #        Creates a slab of the layer in a particular CRS and set of 
    257 #        dimensions. 
    258 # 
    259 #        @param crs: The coordinate reference system. 
    260 #        @param dimValues: A mapping of dimension names to dimension values 
    261 #            as specified in the IDimension.extent 
    262 #        @param renderOpts: A generic mapping object for passing rendering 
    263 #            options 
    264 #        @return: An object implementing ILayerSlab 
    265 #        #create netcdf for whole lat/lon for given dimValues, use to init slab 
    266 #        """ 
    267 # 
    268 #        log.debug('getSlab(%s, %s)' % (crs, dimValues)) 
     167                sel[t]=time 
     168        #z is the 4th axis (eg height or pressure). 
     169        #NOTE, need to decide whether bounding box is of form: x1,y1,z1,x2,y2,z2 or x1,y1,x2,y2,z1,z2 
     170        #currently the latter is implemented.  
     171             
     172        if len(boundingbox)  == 6: 
     173            for ax in self._feature.getAxisLabels(): 
     174                if ax not in [lat, lon, t]: 
     175                    #must be Z   
     176                    z=str(ax) 
     177                    sel[z]=(boundingbox[4], boundingbox[5]) 
     178             
     179             
     180        axisNames=self._feature.getAxisLabels() 
     181        ################################################################## 
     182         
     183        filename = extractToNetCDF(self._feature, sel) 
     184        return filename 
     185         
     186         
     187         
    269188#         
    270189#        #unicode conversion 
     
    279198#            randomname= csml.csmllibs.csmlextra.getRandomID() + '.nc' 
    280199#            result= self._feature.subsetToGridSeries(config['tmpfilebuffer'], ncname=randomname, **dimValues) 
    281 #            #for now have to read netcdf back from  
    282 #            #disk (limitiation of CSML api) 
    283 #            netcdf=cdms.open(result[1]) 
    284 #            #and then delete the temporary file 
    285 #            os.system('rm %s'%result[1]) 
    286 #            bbox=self.getBBox(crs) 
    287 #            return CSMLwmsLayerSlab(netcdf, self, crs, dimValues, renderOpts, bbox) 
     200#            return result[1] 
    288201#        else: 
    289202#            raise NotImplementedError 
    290          
    291     def getCacheKey(self, crs, dimValues=None, renderOpts={}): 
     203     
     204     
     205    def getCacheKey(self, crs, dimValues=None): 
    292206        """ 
    293207        Create a unique key for use in caching a slab. 
     
    303217        dimList.sort() 
    304218        return '%s:%s' % (crs, dimList) 
    305  
    306     def getFeatureInfo(self, format, crs, point, dimValues): 
    307         """ 
    308         Return a response string descibing the feature at a given 
    309         point in a given CRS. 
    310  
    311         Currently only "html" is supported as output format 
    312  
    313         @param format: One of self.featureInfoFormats.  Defines which 
    314             format the response will be in. 
    315         @param crs: One of self.crss 
    316         @param point: a tuple (x, y) in the supplied crs of the point 
    317             being selected. 
    318         @param dimValues: A mapping of dimension names to dimension values. 
    319         @return: A string containing the response. 
    320  
    321         """ 
    322          
    323         #cached netcdf is indexed by a tuple of feature id and dimvalues - i.e. typically a particular time and Z value for that feature. 
    324         #look in dictionary for cached copy, and if so use that as the file object. 
    325         dictindex=str((self._feature.id, dimValues)) 
    326         if dictindex in self.featureinfofilecache: 
    327             log.debug('calling cache') 
    328             f=self.featureinfofilecache[dictindex] 
    329         else: #else, use the csml api to subset the feature afresh 
    330             log.debug('not calling cache') 
    331             randomname= csml.csmllibs.csmlextra.getRandomID() + '.nc' 
    332             result= self._feature.subsetToGridSeries(config['tmpfilebuffer'], ncname=randomname, **dimValues) 
    333             #for now have to read netcdf back from disk (limitation of CSML api) 
    334             f=cdms.open(result[1]) 
    335             #append to cache: 
    336             self.featureinfofilecache[dictindex]=f 
    337             #and then delete the temporary file 
    338             os.system('rm %s'%result[1]) 
    339          
    340         netcdf = f(self.title)  #netcdf here is a cdms transient variable 
    341          
    342         
    343         #Now grab the netCDF object for the point specified. 
    344         #The reason for the 'cob' option is so that if the grid the data  
    345         #is defined on does not have a grid point at the point specified,  
    346         #we should  still get the nearest location 
    347          
    348         t_point = netcdf(latitude=(point[1], point[1], 'cob'), longitude=(point[0], point[0], 'cob')) 
    349         #now get the value recorded at this location 
    350         value = t_point.getValue().tolist() 
    351         log.debug(value) 
    352         log.debug(t_point.fill_value()) 
    353         #and the fill_value too 
    354         fill_value = t_point.fill_value() 
    355         #value is actually embedded in a multi dimensional list,  
    356         #so we need to extract the actual value from the list 
    357         while type(value) is list: 
    358                 value = value[0] 
    359  
    360         #now check if the value is actually the fill_value rather than  
    361         #a value recorded at the point specified 
    362         log.debug('%s %s' % (value, fill_value)) 
    363         if (2*fill_value) == value: 
    364                 value = "No value found at position: "+str(point[1])+", "+str(point[0]) 
    365         else: 
    366                 value = "Value found at position: "+str(point[1])+", "+str(point[0])+" is: "+str(value) 
    367         # finally return the value 
    368         return value 
     219     
     220#class CSMLwcsLayer(CSMLwmsLayer): 
     221#    """ 
     222#     representing a WMS layer.    Implements IwmsLayer 
     223# 
     224#    @ivar title: The layer title.  As seen in the Capabilities document. 
     225#    @ivar abstract:  Abstract as seen in the Capabilities document. 
     226#    @ivar dimensions: A dictionary of IDimension objects. 
     227#    @ivar units: A string describing the units. 
     228#    @ivar crss: A sequence of SRS/CRSs supported by this layer. 
     229# 
     230#    @todo: Do we need minValue/maxValue? 
     231# 
     232#    """ 
     233#     
     234#    def __init__(self, title, abstract, dimensions, units, crss, feature): 
     235#        self.featureInfoFormats=None #NotImplemented 
     236#        self.title=title 
     237#        self.abstract=abstract 
     238#        self.dimensions=dimensions 
     239#        self.units=units 
     240#        self.crss=crss 
     241#        self._feature=feature 
     242#        self.legendSize=(30,100) 
     243#        bb= self._feature.getCSMLBoundingBox().getBox() 
     244#        #convert 0 - 360 to -180, 180 as per common WMS convention 
     245#        if abs(bb[2]-bb[0]) >= 359 and abs(bb[2]-bb[0]) < 361: 
     246#            bb[0], bb[2]=-180, 180 
     247#        self.wgs84BBox = bb 
     248#        self.featureInfoFormats = ['text/html'] 
     249#        try: 
     250#            self.wgs84BBox = self.getBBox('EPSG:4326') 
     251#        except: 
     252#            raise ValueError("Layer must provide a bounding box in EPSG:4326 " 
     253#                             "coordinates for compatibility with WMS-1.3.0") 
     254#        self.featureinfofilecache={} #used for caching netcdf file in getFeatureInfo 
     255#         
     256#    def getBBox(self, crs): 
     257#        """ 
     258#        @return: A 4-typle of the bounding box in the given coordinate 
     259#            reference system. 
     260#        """ 
     261#        #bb= self._feature.getCSMLBoundingBox().getBox() 
     262#        #convert 0 - 360 to -180, 180 as per common WMS convention 
     263#        #if abs(bb[2]-bb[0]) >= 359 and abs(bb[2]-bb[0]) < 361: 
     264#        #    bb[0], bb[2]=-180, 180 
     265#        #self.wgs84BBox = bb 
     266#        return self.wgs84BBox 
     267#        #raise NotImplementedError 
     268#     
     269#    def getSubset(self, crs, dimValues=None): 
     270#        """ 
     271#        Creates a subset of the layer in a particular CRS and set of 
     272#        dimensions. 
     273# 
     274#        @param crs: The coordinate reference system. 
     275#        @param dimValues: A mapping of dimension names to dimension values 
     276#            as specified in the IDimension.extent 
     277#        @param renderOpts: A generic mapping object for passing rendering 
     278#            options 
     279#        @return: An object implementing ILayerSlab 
     280#        #create netcdf for whole lat/lon for given dimValues, use to init slab 
     281#        """ 
     282# 
     283#        log.debug('getSlab(%s, %s)' % (crs, dimValues)) 
     284#         
     285#        #unicode conversion 
     286#        for dimval in dimValues: 
     287#            if dimval != 'time': 
     288#                dimValues[dimval]=float(dimValues[dimval]) 
     289#            else: 
     290#                #remove any trailing Zs from time string 
     291#                if dimValues[dimval] [-1:] in ['Z', 'z']: 
     292#                    dimValues[dimval]=dimValues[dimval][:-1] 
     293#        if type(self._feature) == csml.parser.GridSeriesFeature: 
     294#            randomname= csml.csmllibs.csmlextra.getRandomID() + '.nc' 
     295#            result= self._feature.subsetToGridSeries(config['tmpfilebuffer'], ncname=randomname, **dimValues) 
     296#            return result 
     297#        else: 
     298#            raise NotImplementedError 
     299#         
     300##    def getSlab(self, crs, dimValues=None, renderOpts={}): 
     301##        """ 
     302##        Creates a slab of the layer in a particular CRS and set of 
     303##        dimensions. 
     304## 
     305##        @param crs: The coordinate reference system. 
     306##        @param dimValues: A mapping of dimension names to dimension values 
     307##            as specified in the IDimension.extent 
     308##        @param renderOpts: A generic mapping object for passing rendering 
     309##            options 
     310##        @return: An object implementing ILayerSlab 
     311##        #create netcdf for whole lat/lon for given dimValues, use to init slab 
     312##        """ 
     313## 
     314##        log.debug('getSlab(%s, %s)' % (crs, dimValues)) 
     315##         
     316##        #unicode conversion 
     317##        for dimval in dimValues: 
     318##            if dimval != 'time': 
     319##                dimValues[dimval]=float(dimValues[dimval]) 
     320##            else: 
     321##                #remove any trailing Zs from time string 
     322##                if dimValues[dimval] [-1:] in ['Z', 'z']: 
     323##                    dimValues[dimval]=dimValues[dimval][:-1] 
     324##        if type(self._feature) == csml.parser.GridSeriesFeature: 
     325##            randomname= csml.csmllibs.csmlextra.getRandomID() + '.nc' 
     326##            result= self._feature.subsetToGridSeries(config['tmpfilebuffer'], ncname=randomname, **dimValues) 
     327##            #for now have to read netcdf back from  
     328##            #disk (limitiation of CSML api) 
     329##            netcdf=cdms.open(result[1]) 
     330##            #and then delete the temporary file 
     331##            os.system('rm %s'%result[1]) 
     332##            bbox=self.getBBox(crs) 
     333##            return CSMLwmsLayerSlab(netcdf, self, crs, dimValues, renderOpts, bbox) 
     334##        else: 
     335##            raise NotImplementedError 
     336#         
     337#    def getCacheKey(self, crs, dimValues=None, renderOpts={}): 
     338#        """ 
     339#        Create a unique key for use in caching a slab. 
     340# 
     341#        The intention here is that most of the work should be done when 
     342#        instantiating an ILayerSlab object.  These can be cached by the 
     343#        server for future use.  The server will first call getCacheKey() 
     344#        for the slab creation arguments and if the key is in it's cache 
     345#        it will use a pre-generated ILayerSlab object. 
     346# 
     347#        """ 
     348#        dimList = list(dimValues.items()) 
     349#        dimList.sort() 
     350#        return '%s:%s' % (crs, dimList) 
     351# 
     352#    def getFeatureInfo(self, format, crs, point, dimValues): 
     353#        """ 
     354#        Return a response string descibing the feature at a given 
     355#        point in a given CRS. 
     356# 
     357#        Currently only "html" is supported as output format 
     358# 
     359#        @param format: One of self.featureInfoFormats.  Defines which 
     360#            format the response will be in. 
     361#        @param crs: One of self.crss 
     362#        @param point: a tuple (x, y) in the supplied crs of the point 
     363#            being selected. 
     364#        @param dimValues: A mapping of dimension names to dimension values. 
     365#        @return: A string containing the response. 
     366# 
     367#        """ 
     368#         
     369#        #cached netcdf is indexed by a tuple of feature id and dimvalues - i.e. typically a particular time and Z value for that feature. 
     370#        #look in dictionary for cached copy, and if so use that as the file object. 
     371#        dictindex=str((self._feature.id, dimValues)) 
     372#        if dictindex in self.featureinfofilecache: 
     373#            log.debug('calling cache') 
     374#            f=self.featureinfofilecache[dictindex] 
     375#        else: #else, use the csml api to subset the feature afresh 
     376#            log.debug('not calling cache') 
     377#            randomname= csml.csmllibs.csmlextra.getRandomID() + '.nc' 
     378#            result= self._feature.subsetToGridSeries(config['tmpfilebuffer'], ncname=randomname, **dimValues) 
     379#            #for now have to read netcdf back from disk (limitation of CSML api) 
     380#            f=cdms.open(result[1]) 
     381#            #append to cache: 
     382#            self.featureinfofilecache[dictindex]=f 
     383#            #and then delete the temporary file 
     384#            os.system('rm %s'%result[1]) 
     385#         
     386#        netcdf = f(self.title)  #netcdf here is a cdms transient variable 
     387#         
     388#        
     389#        #Now grab the netCDF object for the point specified. 
     390#        #The reason for the 'cob' option is so that if the grid the data  
     391#        #is defined on does not have a grid point at the point specified,  
     392#        #we should  still get the nearest location 
     393#         
     394#        t_point = netcdf(latitude=(point[1], point[1], 'cob'), longitude=(point[0], point[0], 'cob')) 
     395#        #now get the value recorded at this location 
     396#        value = t_point.getValue().tolist() 
     397#        log.debug(value) 
     398#        log.debug(t_point.fill_value()) 
     399#        #and the fill_value too 
     400#        fill_value = t_point.fill_value() 
     401#        #value is actually embedded in a multi dimensional list,  
     402#        #so we need to extract the actual value from the list 
     403#        while type(value) is list: 
     404#                value = value[0] 
     405# 
     406#        #now check if the value is actually the fill_value rather than  
     407#        #a value recorded at the point specified 
     408#        log.debug('%s %s' % (value, fill_value)) 
     409#        if (2*fill_value) == value: 
     410#                value = "No value found at position: "+str(point[1])+", "+str(point[0]) 
     411#        else: 
     412#                value = "Value found at position: "+str(point[1])+", "+str(point[0])+" is: "+str(value) 
     413#        # finally return the value 
     414#        return value 
    369415 
    370416 
     
    397443            self.units='ISO8601' 
    398444        
    399 class CSMLwmsLayerSlab(IwmsLayerSlab): 
    400     """ 
    401     Implements LayerSlab 
    402     Represents a particular horizontal slice of a WMS layer. 
    403  
    404     ILayerSlab objects are designed to be convenient to cache. 
    405     They should be pickleable to enable memcached support in the future. 
    406  
    407     @ivar layer: The source ILayer instance. 
    408     @ivar crs: The coordinate reference system. 
    409     @ivar dimValues: A mapping of dimension values of this view. 
    410     @ivar renderOpts: The renderOpts used to create this view. 
    411     @ivar bbox: The bounding box as a 4-tuple. 
    412     """ 
    413  
    414     def __init__(self, netcdf, layer, crs, dimValues, renderOpts, bbox): 
    415         self._netcdf=netcdf 
    416         self.layer = layer 
    417         self.crs = crs 
    418         self.dimValues = dimValues 
    419         self.renderOpts=renderOpts 
    420         self.bbox=bbox 
    421          
    422         #set colour map for ALL images from this slab 
    423         v=self._netcdf(layer.title) 
    424         tvar=v(squeeze=1) 
    425         #get the min and max values to use for the colourmapping. 
    426         #change the fill values to ensure they aren't picked up as false max/mins. 
    427         tvar.missing_value=999999999 
    428         value=tvar.getValue() 
    429         self.minval=min(min(l) for l in value) 
    430         tvar.missing_value=-0.000000001 
    431         value=tvar.getValue() 
    432         self.maxval=max(max(l) for l in value) 
    433  
    434          
    435     def getImage(self, bbox, width, height): 
    436         """ 
    437         Create an image of a sub-bbox of a given size. 
    438  
    439         @ivar bbox: A bbox 4-tuple. 
    440         @ivar width: width in pixels.`   
    441         @ivar height: height in pixels. 
    442         @return: A PIL Image object. 
    443  
    444         """ 
    445  
    446         log.debug('getImage(%s, %s, %s)' % (bbox, width, height)) 
    447          
    448  
    449         cmap=eval(config['colourmap']) # renderOpts is hook for colourmap, for now use config 
    450         grid=Grid(self.layer, self._netcdf, bbox, width, height) 
    451         #how to handle varmin,varmax? ..read array? 
    452         #minval, maxval=genutil.minmax(grid.value) 
    453         #minval=min(min(l) for l in grid.value) 
    454         #maxval=max(max(l) for l in grid.value) 
    455         minval=self.minval 
    456         maxval=self.maxval 
    457         renderer=RGBARenderer(minval, maxval)          
    458         return renderer.renderGrid(grid, bbox, width, height, cmap) 
    459      
    460 class Grid(object): 
    461     """A class encapsulating a simple regularly spaced, rectilinear 
    462     grid.  This is the only type of grid pywms is expected to 
    463     understand and adaptors should be provided to connect to 
    464     underlying implementations such as cdms or csml. 
    465  
    466     @cvar crs: Coordinate reference system 
    467  
    468     @ivar x0: coordinate of the lower left corner. 
    469     @ivar y0: coordinate of the lower left corner. 
    470     @ivar dx: The x grid spacing. 
    471     @ivar dy: The y grid spacing. 
    472     @ivar nx: The number of x grid points. 
    473     @ivar ny: The number of y grid points. 
    474     @ivar value: A masked array of the grid values. 
    475     @ivar ix: The dimension index of longidude in value 
    476     @ivar iy: The dimension index of latitude in value 
    477     @ivar long_name: The name of the field. 
    478     @ivar units: The units of the field. 
    479     """ 
    480     def __init__(self, layer, netcdf, bbox, width, height): 
    481         #we know the axes are called latitude and longitude as the CSML code has written it: 
    482         v=netcdf(layer.title) 
    483         tvar=v(latitude=(bbox[1], bbox[3]), longitude=(bbox[0],bbox[2]),squeeze=1) 
    484         order=tvar.getOrder() 
    485         #array of data 
    486         self.value=tvar.getValue() 
    487         if order == 'xy': 
    488             self.ix=0 
    489             self.iy=1 
    490         else: 
    491             self.ix=1 
    492             self.iy=0 
    493         lat = tvar.getLatitude() 
    494         lon = tvar.getLongitude() 
    495         self.x0=lon[0] 
    496         self.y0=lat[0] 
    497         self.dx=abs(lon[0]-lon[1]) 
    498         self.dy=abs(lat[0]-lat[1]) 
    499          
    500             
    501  
    502         self.nx=len(lon) 
    503         self.ny=len(lat) 
    504         self.long_name=tvar.id  #TODO, get long name from feature 
    505         self.units=tvar.units 
  • cows/branches/wcsmerge/cows/service/imps/csmlbackend/wfs_csmllayer.py

    r4534 r4633  
    2020    Supports the retrieval of sets of layers according to arbitrary 
    2121    keyword/value pairs. 
    22     Implements  ILayerMapper  
     22    Implements  ILayerMapper (does it? TODO: check) 
    2323     
    2424    WFS differs from WMS/WCS in that the 'layers' are feature types, not instances. 
Note: See TracChangeset for help on using the changeset viewer.