Changeset 5479 for qesdi


Ignore:
Timestamp:
13/07/09 13:31:56 (10 years ago)
Author:
pnorton
Message:

Made some more modifications to the ddc WMS. I've tried to reduce the amount of code duplication between the code and the cows egg.

Location:
qesdi/wms_ddc_vis/trunk
Files:
5 added
1 deleted
10 edited

Legend:

Unmodified
Added
Removed
  • qesdi/wms_ddc_vis/trunk/data

    • Property svn:ignore set to
      *
  • qesdi/wms_ddc_vis/trunk/lib

    • Property svn:ignore set to
      wms_ddc_vis.egg-info
  • qesdi/wms_ddc_vis/trunk/lib/wms_ddc_vis/config/routing.py

    r5403 r5479  
    1919    # CUSTOM ROUTES HERE 
    2020    map.connect('coastwms', controller='coastwms') 
     21 
    2122    map.connect(':fileoruri/wms', controller='csmlwms') 
    2223    map.connect('wcsroute', ':fileoruri/wcs', controller='csmlwcs') #wcsroute is a named route. 
  • qesdi/wms_ddc_vis/trunk/lib/wms_ddc_vis/controllers/coastwms.py

    r5403 r5479  
    1717from cows import bbox_util 
    1818 
    19 from geoplot.layer_drawer_grid import LayerDrawerGrid 
    20  
    21 from cows.service.imps.csmlbackend.wms_csmllayer import CSMLwmsLayerMapper 
    22  
    23 from wms_ddc_vis.model.ddc_layer_mapper import DDCLayerMapper 
     19from geoplot.layer_drawer_coastline import LayerDrawerCoastlines 
     20 
    2421log = logging.getLogger(__name__) 
    2522 
    2623class CoastwmsController(ows_controller.OWSController): 
    27     layerMapper = DDCLayerMapper() 
    2824 
    2925    #layers = {}     
     
    4541    validVersions = ['1.1.1', '1.3.0'] 
    4642 
    47     #------------------------------------------------------------------------- 
    48  
    49     def __before__(self, **kwargs): 
    50         """ 
    51         This default implementation of __before__() will pass all routes 
    52         arguments to the layer mapper to retrieve a list of layers for 
    53         this WMS. 
    54  
    55         It will be called automatically by pylons before each action method. 
    56  
    57         @todo: The layer mapper needs to come from somewhere. 
    58  
    59         """ 
    60         pass 
    61         #self.updateSequence = "hello" 
    62 #        log.debug("loading layers") 
    63         #print self.layers 
    64 #        self.layers = self.layerMapper.map(**kwargs) 
    65      
    66         #------------------------------------------------------------------------- 
    67         # Methods implementing stubs in OWSController 
     43 
    6844 
    6945    def _renderCapabilities(self, version, format): 
     
    9066        ows_controller.addOperation('GetMap', formats=self._pilImageFormats.keys()) 
    9167        ows_controller.addOperation('GetContext', formats=['text/xml', 'application/json']) 
    92         ows_controller.addOperation('GetLegend', 
    93                                     formats=['image/png']) 
    94         ows_controller.addOperation('GetInfo') 
     68 
    9569         
    9670        featureInfoFormats = Set() 
     
    155129                                    formats = list(featureInfoFormats)) 
    156130 
    157     def _getLayerParamInfo(self, paramName='layers'): 
    158         """ 
    159         Retrieve the layers parameter enforcing the rule of only 
    160         selecting one layer. 
    161  
    162         @param paramName: Overrides the query string parameter name to 
    163             look for.  This is usefull for implementing GetFeatureInfo. 
    164  
    165         """ 
    166         layerName = self.getOwsParam(paramName) 
    167  
    168         # Select the first layer if several are requested. 
    169         # This plays nicer with mapClient. 
    170         if ',' in layerName: 
    171             #layerName = layerName.split(',')[0] 
    172             raise InvalidParameterValue( 
    173                 'Multi-layer GetLegend requests are not supported', 'layers') 
    174         try: 
    175             layerObj = self.layers[layerName] 
    176         except KeyError: 
    177             raise InvalidParameterValue('Layer %s not found' % layerName, 
    178                                         paramName) 
    179  
    180         return layerName, layerObj 
    181  
    182     def _getLayerParam(self, paramName='layers'): 
    183         """ 
    184         Retrieve the layers parameter enforcing the rule of only 
    185         selecting one layer. 
    186  
    187         @param paramName: Overrides the query string parameter name to 
    188             look for.  This is usefull for implementing GetFeatureInfo. 
    189  
    190         """ 
    191         layers = {} 
    192         layerNames = self.getOwsParam(paramName) 
    193  
    194         # Select the first layer if several are requested. 
    195         # This plays nicer with mapClient. 
    196         #if ',' in layerName: 
    197         layerNames = layerNames.split(',') 
    198         #raise InvalidParameterValue( 
    199         #    'Multi-layer GetMap requests are not supported', 'layers') 
    200         for layerName in layerNames: 
    201             try: 
    202                 layerObj = self.layers[layerName] 
    203                 layers[layerName] = layerObj 
    204             except KeyError: 
    205                 raise InvalidParameterValue('Layer %s not found' % layerName, 
    206                                         paramName) 
    207  
    208         #return layerName, layerObj 
    209         return layers 
    210  
    211     def _getFormatParam(self): 
    212         format = self.getOwsParam('format', default='image/png') 
    213         if format not in self._pilImageFormats: 
    214             raise InvalidParameterValue( 
    215                 'Format %s not supported' % format, 'format') 
    216  
    217         return format 
    218131 
    219132    _escapedDimNames = ['width', 'height', 'version', 'request', 
     
    222135                        'exceptions'] 
    223136 
    224     def _getDimValues(self, layerObj): 
    225         dimValues = {} 
    226         for dimName, dim in layerObj.dimensions.items(): 
    227             defaultValue = dim.extent[0] 
    228             escapedDimName=self._mapDimToParam(dimName) 
    229             dimValues[escapedDimName] = self.getOwsParam(escapedDimName, 
    230                                                   default=defaultValue) 
    231         return dimValues 
    232137 
    233138    def _mapDimToParam(self, dimName): 
     
    244149            return dimName 
    245150         
    246     def _mapParamToDim(self, dimParam): 
    247         """ 
    248         Maps a dimension parameter name to it's real dimension name. 
    249  
    250         @see: _mapDimToParam() 
    251  
    252         """ 
    253         try: 
    254             dimName = re.match(r'(.*)_dim$', dimParam).group(1) 
    255             if dimName.lower() in self._escapedDimNames: 
    256                 return dimName 
    257             else: 
    258                 return dimParam 
    259         except AttributeError: 
    260             return dimParam 
    261  
    262  
    263     def _retrieveSlab(self, layerObj, srs, dimValues, renderOpts): 
    264         # Find the slab in the cache first 
    265         cacheKey = layerObj.getCacheKey(srs, dimValues) 
    266         slab = self._layerSlabCache.get(cacheKey) 
    267         if slab is None: 
    268             slab = layerObj.getSlab(srs, dimValues, renderOpts) 
    269             if cacheKey is not None: 
    270                 self._layerSlabCache[cacheKey] = slab 
    271  
    272         return slab 
    273  
    274     #------------------------------------------------------------------------- 
    275     # OWS Operation methods 
    276151     
    277152    def GetMap(self): 
     
    287162 
    288163        # Layer handling 
    289         #layerName, layerObj = self._getLayerParam() 
    290 #        layers = self._getLayerParam() 
    291 #        log.debug('GetMap request for layer(s) %s  #%s ' % (layers, thread.get_ident(),) ) 
    292164        layerName = self.getOwsParam('layers') 
    293165         
     
    305177            srs = self.getOwsParam('crs') 
    306178 
    307         #if srs not in layerObj.crss: 
    308          #   raise InvalidParameterValue('Layer %s does not support SRS %s' % (layerName, srs)) 
    309  
    310         # Get format 
     179       # Get format 
    311180        format = self.getOwsParam('format') 
    312181        if format not in self._pilImageFormats: 
     
    314183                'Format %s not supported' % format, 'format') 
    315184 
    316  
    317         ldg = LayerDrawerGrid() 
     185        ldg = LayerDrawerCoastlines(transparent=transparent, 
     186                                    resolution=layerName) 
    318187 
    319188        xLimits = (bbox[0], bbox[2]) 
    320189        yLimits = (bbox[1], bbox[3])         
    321         finalImg = ldg.makeImage(xLimits, yLimits, width, height, resolution=layerName, 
    322                                  transparent=transparent)      
     190        finalImg = ldg.makeImage(xLimits, yLimits, width, height)      
    323191       
    324192         
     
    372240 
    373241        if format == 'text/xml': 
     242             
    374243            response.headers['Content-Type'] = format 
    375244            t = ows_controller.templateLoader.load('wms_context_1_1_1.xml') 
    376245            return t.generate(c=c).render() 
     246         
    377247        elif format == 'application/json': 
     248             
    378249            response.headers['Content-Type'] = format 
    379250            t = ows_controller.templateLoader.load('wms_context_json.txt', 
    380251                                                   cls=NewTextTemplate) 
    381252            return t.generate(c=c).render() 
     253         
    382254        else: 
    383255            raise InvalidParameterValue('Format %s not supported' % format) 
    384256 
    385     def GetFeatureInfo(self): 
    386         # Housekeeping 
    387         version = self.getOwsParam('version', default=self.validVersions[0]) 
    388         if version not in self.validVersions: 
    389             raise InvalidParameterValue('Version %s not supported' % version, 
    390                                         'version') 
    391  
    392         # Coordinate parameters 
    393         bbox = tuple(float(x) for x in self.getOwsParam('bbox').split(',')) 
    394         width = int(self.getOwsParam('width')) 
    395         height = int(self.getOwsParam('height')) 
    396        
    397         # Get pixel location 
    398         i = int(self.getOwsParam('i')) 
    399         j = int(self.getOwsParam('j')) 
    400  
    401         # Translate to geo-coordinates 
    402         x, y = bbox_util.pixelToGeo(i, j, bbox, width, height) 
    403         #start preparing GetFeatureInfo response. Assumes "HTML" output format 
    404  
    405         htmlResponse = "<html><body><p> <b>Feature Information about pixel position: "+self.getOwsParam('i')+","+self.getOwsParam('j')+"/geo position: "+str(x)+","+str(y) +"<b/></p>" 
    406          
    407          
    408         layers = self._getLayerParam('query_layers') 
    409         #Adjusts response for multiple layers 
    410         if len(layers) > 1: 
    411             htmlResponse = htmlResponse+" Multiple possible features found as follows:" 
    412    
    413         htmlResponse = htmlResponse+"<ul>" 
    414          
    415         format = self.getOwsParam('info_format', default='text/html') 
    416         for layerName, layerObj in layers.iteritems(): 
    417             log.debug('Format: %s' % format) 
    418             log.debug('Title: %s' % layerObj.title) 
    419             log.debug('FeatureInfoFormats: %s' % layerObj.featureInfoFormats) 
    420              
    421             if format not in layerObj.featureInfoFormats: 
    422                 raise InvalidParameterValue('Layer %s does not support GetFeatureInfo in format %s' %(layerName, format), 'info_format') 
    423  
    424         if version == '1.1.1': 
    425             srs = self.getOwsParam('srs') 
    426         else: 
    427             srs = self.getOwsParam('crs') 
    428  
    429         if srs not in layerObj.crss: 
    430             raise InvalidParameterValue('Layer %s does not support SRS %s' % 
    431                                         (layerName, srs)) 
    432  
    433         # Dimension handling 
    434         dimValues = {} 
    435         for dimName, dim in layerObj.dimensions.items(): 
    436             defaultValue = dim.extent[0] 
    437             dimValues[dimName] = self.getOwsParam(dimName, default=defaultValue) 
    438          
    439         response.headers['Content-Type'] = format 
    440         response.write(layerObj.getFeatureInfo(format, srs, (x, y), dimValues)) 
    441  
    442     def GetLegend(self): 
    443         """ 
    444         Return an image of the legend. 
    445  
    446         """ 
    447         # Parameters 
    448         layerName, layerObj = self._getLayerParamInfo() 
    449         format = self._getFormatParam() 
    450  
    451         # This hook alows extra arguments to be passed to the layer backend.  It 
    452         # is required for UKCP. 
    453         renderOpts = dict(request_params=self._owsParams) 
    454  
    455         img = layerObj.getLegendImage(renderOpts=renderOpts) 
    456  
    457         buf = StringIO() 
    458         img.save(buf, self._pilImageFormats[format]) 
    459  
    460         response.headers['Content-Type'] = format 
    461         response.write(buf.getvalue()) 
    462  
    463  
    464     def GetInfo(self): 
    465         from pprint import pformat 
    466         request.headers['Content-Type'] = 'text/ascii' 
    467         response.write('Some info about this service\n') 
    468         for layer in model.ukcip02.layers: 
    469             response.write('Layer %s: %s\n' % (layer, pformat(g.ukcip02_layers[layer].__dict__))) 
    470  
    471              
  • qesdi/wms_ddc_vis/trunk/lib/wms_ddc_vis/controllers/csmlwms.py

    r5403 r5479  
    11import logging 
    22import Image 
    3 import thread 
    43import re 
    54from StringIO import StringIO 
    6 from sets import Set 
    7 from matplotlib.cm import get_cmap 
    85from pylons import request, response, c 
    9 from routes import url_for 
    10 from routes.util import GenerationException 
    11 from genshi.template import NewTextTemplate 
     6 
     7from cows import bbox_util 
     8 
     9from wms_ddc_vis.model.ddc_layer_mapper import DDCLayerMapper 
     10from wms_ddc_vis.model.ddc_wms_layer import STYLES, RENDERING_OPTIONS 
     11 
    1212from cows.pylons.wms_controller import WMSController 
    13 from cows.model.wms import WmsDatasetSummary, Dimension, DataURL 
    14 from cows.model import PossibleValues, WGS84BoundingBox, BoundingBox, Contents 
    15 from cows.pylons import ows_controller 
    16 from cows.exceptions import * 
    17 from cows import bbox_util 
    18  
    19 from cows.service.imps.csmlbackend.wms_csmllayer import CSMLwmsLayerMapper 
    20  
    21 from wms_ddc_vis.model.ddc_layer_mapper import DDCLayerMapper 
     13 
     14 
    2215log = logging.getLogger(__name__) 
    2316 
    24 class CsmlwmsController(ows_controller.OWSController): 
     17class CsmlwmsController(WMSController): 
    2518    layerMapper = DDCLayerMapper() 
    2619 
    27     #layers = {}     
    28     _pilImageFormats = { 
    29         'image/png': 'PNG', 
    30         'image/jpg': 'JPEG', 
    31         'image/gif': 'GIF', 
    32         'image/tiff': 'TIFF' 
    33         } 
    34      
    35     _layerSlabCache = {} 
    36  
    37     #------------------------------------------------------------------------- 
    38     # Attributes required by OWSController 
    39  
    40     service = 'WMS' 
    41     owsOperations = (ows_controller.OWSController.owsOperations + 
    42         ['GetMap', 'GetContext', 'GetLegend', 'GetFeatureInfo', 'GetInfo']) 
    43     validVersions = ['1.1.1', '1.3.0'] 
    44  
    45     #------------------------------------------------------------------------- 
    46  
    47     def __before__(self, **kwargs): 
    48         """ 
    49         This default implementation of __before__() will pass all routes 
    50         arguments to the layer mapper to retrieve a list of layers for 
    51         this WMS. 
    52  
    53         It will be called automatically by pylons before each action method. 
    54  
    55         @todo: The layer mapper needs to come from somewhere. 
    56  
    57         """ 
    58         #self.updateSequence = "hello" 
    59         log.debug("loading layers") 
    60         #print self.layers 
    61         self.layers = self.layerMapper.map(**kwargs) 
    62      
    63         #------------------------------------------------------------------------- 
    64         # Methods implementing stubs in OWSController 
    65  
    66     def _renderCapabilities(self, version, format): 
    67         if format == 'application/json': 
    68             t = ows_controller.templateLoader.load('wms_capabilities_json.txt', 
    69                                                    cls=NewTextTemplate) 
    70         elif version == '1.1.1': 
    71             t = ows_controller.templateLoader.load('wms_capabilities_1_1_1.xml') 
    72         elif version == '1.3.0': 
    73             t = ows_controller.templateLoader.load('wms_capabilities_1_3_0.xml') 
    74         else: 
    75             # We should never get here!  The framework should raise an exception before now. 
    76             raise RuntimeError("Version %s not supported" % version) 
    77          
    78         return t.generate(c=c).render() 
    79  
    80     def _loadCapabilities(self): 
    81         """ 
    82         @note: Assumes self.layers has already been created by __before__(). 
    83  
    84         """ 
    85         #!TODO: Add json format to GetCapabilities operation 
    86  
    87         ows_controller.addOperation('GetMap', formats=self._pilImageFormats.keys()) 
    88         ows_controller.addOperation('GetContext', formats=['text/xml', 'application/json']) 
    89         ows_controller.addOperation('GetLegend', 
    90                                     formats=['image/png']) 
    91         ows_controller.addOperation('GetInfo') 
    92          
    93         featureInfoFormats = Set() 
    94  
    95         log.debug('Loading capabilities contents') 
    96         c.capabilities.contents = Contents() 
    97         for layerName, layer in self.layers.items(): 
    98             log.debug('LayerName: %s' % layerName) 
    99             log.debug('Loading layer %s' % layerName) 
    100  
    101             wgs84BBox = WGS84BoundingBox(layer.wgs84BBox[:2], 
    102                                          layer.wgs84BBox[2:]) 
    103             # Get CRS/BBOX pairs 
    104             bboxObjs = [] 
    105             for crs in layer.crss: 
    106                 bbox = layer.getBBox(crs) 
    107                 bboxObjs.append(BoundingBox(bbox[:2], bbox[2:], crs=crs)) 
    108             # Get dimensions 
    109             dims = {} 
    110             for dimName, dim in layer.dimensions.items(): 
    111                 dimParam = self._mapDimToParam(dimName) 
    112                 dims[dimParam] = Dimension(valuesUnit=dim.units, 
    113                                           unitSymbol=dim.units, 
    114                                           possibleValues= 
    115                                             PossibleValues.fromAllowedValues(dim.extent)) 
    116             # Does the layer implement GetFeatureInfo? 
    117             if layer.featureInfoFormats: 
    118                 queryable = True 
    119                 featureInfoFormats.union_update(layer.featureInfoFormats) 
    120             else: 
    121                 queryable = False 
    122                  
    123             #URL to WCS - uses named route 'wcsroute' 
    124             #TODO: Allow for a WCS blacklist to opt out of providing dataurls for certain datasets? 
    125             #TODO: How to make this more configurable - what if WCS is not coupled with WMS? 
    126             try: 
    127                 version='1.0.0' #wcs version 
    128                 wcsbaseurl=url_for('wcsroute', fileoruri=c.fileoruri,qualified=True)+'?' 
    129                 dataURLs=[DataURL(format='WCS:CoverageDescription', onlineResource='%sService=WCS&Request=DescribeCoverage&Coverage=%s&Version=%s'%(wcsbaseurl, layerName, version))] 
    130             except GenerationException: 
    131                 log.info("dataURLs not populated: could not generate WCS url with url_for('wcsroute', filedoruri=%s,qualified=True)"%c.fileoruri) 
    132                 dataURLs=[] 
    133             # Create the cows object 
    134             ds = WmsDatasetSummary(identifier=layerName, 
    135                                    titles=[layer.title], 
    136                                    CRSs=layer.crss, 
    137                                    wgs84BoundingBoxes=[wgs84BBox], 
    138                                    boundingBoxes=bboxObjs, 
    139                                    abstracts=[layer.abstract], 
    140                                    dimensions=dims, 
    141                                    queryable=queryable, 
    142                                    dataURLs=dataURLs) 
    143  
    144             # Stuff that should go in the capabilities tree eventually 
    145             ds.legendSize = layer.legendSize 
    146             ds.legendFormats = ['image/png'] 
    147  
    148             c.capabilities.contents.datasetSummaries.append(ds) 
    149  
    150         # Add this operation here after we have found all formats 
    151         ows_controller.addOperation('GetFeatureInfo', 
    152                                     formats = list(featureInfoFormats)) 
    153  
    154     def _getLayerParamInfo(self, paramName='layers'): 
     20    def _getLayerParam(self, paramName='layers'): 
    15521        """ 
    15622        Retrieve the layers parameter enforcing the rule of only 
     
    16127 
    16228        """ 
    163         layerName = self.getOwsParam(paramName) 
    164  
     29        layers = {} 
     30        layerNames = self.getOwsParam(paramName) 
     31         
    16532        # Select the first layer if several are requested. 
    16633        # This plays nicer with mapClient. 
    167         if ',' in layerName: 
    168             #layerName = layerName.split(',')[0] 
    169             raise InvalidParameterValue( 
    170                 'Multi-layer GetLegend requests are not supported', 'layers') 
    171         try: 
    172             layerObj = self.layers[layerName] 
    173         except KeyError: 
    174             raise InvalidParameterValue('Layer %s not found' % layerName, 
    175                                         paramName) 
    176  
    177         return layerName, layerObj 
    178  
    179     def _getLayerParam(self, paramName='layers'): 
    180         """ 
    181         Retrieve the layers parameter enforcing the rule of only 
    182         selecting one layer. 
    183  
    184         @param paramName: Overrides the query string parameter name to 
    185             look for.  This is usefull for implementing GetFeatureInfo. 
    186  
    187         """ 
    188         layers = {} 
    189         layerNames = self.getOwsParam(paramName) 
    190  
    191         # Select the first layer if several are requested. 
    192         # This plays nicer with mapClient. 
    193         #if ',' in layerName: 
    19434        layerNames = layerNames.split(',') 
    195         #raise InvalidParameterValue( 
    196         #    'Multi-layer GetMap requests are not supported', 'layers') 
     35         
     36        layerObjects = [] 
     37         
    19738        for layerName in layerNames: 
    19839            try: 
    19940                layerObj = self.layers[layerName] 
    200                 layers[layerName] = layerObj 
     41                layerObjects.append(layerObj) 
     42#                layers[layerName] = layerObj 
    20143            except KeyError: 
    20244                raise InvalidParameterValue('Layer %s not found' % layerName, 
    20345                                        paramName) 
    20446 
    205         #return layerName, layerObj 
    206         return layers 
    207  
    208     def _getFormatParam(self): 
    209         format = self.getOwsParam('format', default='image/png') 
    210         if format not in self._pilImageFormats: 
    211             raise InvalidParameterValue( 
    212                 'Format %s not supported' % format, 'format') 
    213  
    214         return format 
    215  
    216     _escapedDimNames = ['width', 'height', 'version', 'request', 
    217                         'layers', 'styles', 'crs', 'srs', 'bbox', 
    218                         'format', 'transparent', 'bgcolor', 
    219                         'exceptions'] 
    220  
    221     def _getDimValues(self, layerObj): 
    222         dimValues = {} 
    223         for dimName, dim in layerObj.dimensions.items(): 
    224             defaultValue = dim.extent[0] 
    225             escapedDimName=self._mapDimToParam(dimName) 
    226             dimValues[escapedDimName] = self.getOwsParam(escapedDimName, 
    227                                                   default=defaultValue) 
    228         return dimValues 
    229  
    230     def _mapDimToParam(self, dimName): 
    231         """ 
    232         Dimension names might clash with WMS parameter names, making 
    233         them inaccessible in WMS requests.  This method maps a 
    234         dimension name to a parameter name that appears in the 
    235         capabilities document and WMS requests. 
    236  
    237         """ 
    238         if dimName.lower() in self._escapedDimNames: 
    239             return dimName+'_dim' 
    240         else: 
    241             return dimName 
    242          
    243     def _mapParamToDim(self, dimParam): 
    244         """ 
    245         Maps a dimension parameter name to it's real dimension name. 
    246  
    247         @see: _mapDimToParam() 
    248  
    249         """ 
    250         try: 
    251             dimName = re.match(r'(.*)_dim$', dimParam).group(1) 
    252             if dimName.lower() in self._escapedDimNames: 
    253                 return dimName 
    254             else: 
    255                 return dimParam 
    256         except AttributeError: 
    257             return dimParam 
    258  
    259  
    260     def _retrieveSlab(self, layerObj, srs, dimValues, renderOpts): 
     47        return layerNames, layerObjects 
     48        #return layers 
     49 
     50 
     51         
     52    def _retrieveSlab(self, layerObj, srs, dimValues, style, transparent, renderOpts): 
     53         
    26154        # Find the slab in the cache first 
    262         cacheKey = layerObj.getCacheKey(srs, dimValues) 
     55        cacheKey = layerObj.getCacheKey(srs, style, transparent, dimValues, renderOpts) 
    26356        slab = self._layerSlabCache.get(cacheKey) 
     57         
    26458        if slab is None: 
    265             slab = layerObj.getSlab(srs, dimValues, renderOpts) 
     59             
     60            slab = layerObj.getSlab(srs, style, transparent, dimValues, renderOpts) 
     61             
    26662            if cacheKey is not None: 
    26763                self._layerSlabCache[cacheKey] = slab 
     
    27672        # Housekeeping 
    27773        version = self.getOwsParam('version', default=self.validVersions[0]) 
     74         
    27875        if version not in self.validVersions: 
    27976            raise InvalidParameterValue('Version %s not supported' % version, 
    28077                                        'version') 
     78         
     79         
     80        renderingOptions = {} 
     81        for opt in RENDERING_OPTIONS: 
     82            if self.getOwsParam(opt, default=None) != None: 
     83                renderingOptions[opt] = self.getOwsParam(opt) 
     84         
     85        log.debug("renderingOptions = %s" % (renderingOptions,)) 
     86         
     87 
     88         
     89        transparent = self.getOwsParam('transparent', default='FALSE') 
     90         
     91        transparent = transparent.lower() == 'true' 
     92         
     93        bgcolor = self.getOwsParam('bgcolor', default='0xFFFFFF') 
     94 
     95        # Layer handling 
     96        layerNames, layerObjects = self._getLayerParam() 
     97#        layers = self._getLayerParam() 
     98         
     99        log.debug("layerNames = %s" % (layerNames,)) 
     100        log.debug("layerObjects = %s" % (layerObjects,)) 
     101         
    281102        styles = self.getOwsParam('styles', default='') 
    282         transparent = self.getOwsParam('transparent', default='FALSE') 
    283         bgcolor = self.getOwsParam('bgcolor', default='0xFFFFFF') 
    284  
    285         # Layer handling 
    286         #layerName, layerObj = self._getLayerParam() 
    287         layers = self._getLayerParam() 
    288         log.debug('GetMap request for layer(s) %s  #%s ' % (layers, thread.get_ident(),) ) 
     103         
     104        if styles != None: 
     105            styles = styles.split(',') 
     106            assert len(styles) == len(layerNames) 
     107         
     108        log.debug("style = %s" % (styles,))         
     109         
    289110        # Coordinate parameters 
    290111        bbox = tuple(float(x) for x in self.getOwsParam('bbox').split(',')) 
     
    306127                'Format %s not supported' % format, 'format') 
    307128 
     129 
    308130        finalImg = Image.new('RGBA', (width, height), (0,0,0,0)) 
    309      
     131 
    310132        # Multiple Layers handling..   
    311         for layerName, layerObj in layers.iteritems(): 
     133#        for layerName, layerObj in layers.iteritems(): 
     134        for i in range(len(layerNames)): 
     135             
     136            layerName = layerNames[i] 
     137            layerObj = layerObjects[i] 
     138            if styles != None: 
     139                style = styles[i] 
     140            else: 
     141                style = "" 
     142                 
     143            if style == "": 
     144                style = STYLES.DEFAULT 
     145                 
     146             
    312147            if srs not in layerObj.crss: 
    313148                raise InvalidParameterValue('Layer %s does not support SRS %s' % (layerName, srs)) 
     
    325160            #!TODO: Minimum and maximum values 
    326161 
    327             slab = self._retrieveSlab(layerObj, srs, restoredDimValues, 
    328                                       dict(minValue=0, maxValue=100)) 
     162            slab = self._retrieveSlab(layerObj, srs, restoredDimValues, style, 
     163                                      transparent, renderingOptions) 
    329164 
    330165            # We must request a bbox within the layer's bbox. 
     
    336171            log.debug('ibbox = %s' % (ibbox,)) 
    337172 
    338  
    339             finalImg = slab.getImage(bbox, width, height) 
    340              
    341 #            # If bbox is not within layerObj.bbox then we need to calculate the 
    342 #            # pixel offset of the inner bbox, request the right width/height 
    343 #            # and paste the image into a blank background 
    344 #            if bbox == ibbox: 
    345 #                img = slab.getImage(bbox, width, height) 
    346 #                log.debug('slab image.size = %s' % (img.size,)) 
    347 #             
    348 #            else: 
    349 #                 
    350 #                ix0, iy0 = bbox_util.geoToPixel(ibbox[0], ibbox[3], bbox, width, height, 
    351 #                                                roundUpY=True) 
    352 #                ix1, iy1 = bbox_util.geoToPixel(ibbox[2], ibbox[1], bbox, width, height, 
    353 #                                                roundUpX=True) 
    354 #                iw = ix1-ix0 
    355 #                ih = iy1-iy0 
    356 #                log.debug('Deduced inner image: %s, (%d x %d)' % ((ix0, iy0, ix1, iy1), iw, ih)) 
    357 #                img1 = slab.getImage(ibbox, iw, ih) 
    358 # 
    359 #                img = Image.new('RGBA', (width, height)) 
    360 #                img.paste(img1, (ix0, iy0)) 
    361 #         
    362 #            finalImg = Image.composite(finalImg, img, finalImg)     
    363              
    364        
    365        
    366          
     173            log.debug("width, height = %s, %s" % (width, height,)) 
     174            img = slab.getImage(bbox, width, height) 
     175             
     176            log.debug("img = %s format=%s, size=%s, mode=%s" % (img, img.format, img.size, img.mode)) 
     177            log.debug("finalImg = %s format=%s, size=%s, mode=%s" % (finalImg, finalImg.format, finalImg.size, finalImg.mode)) 
     178 
     179            finalImg = Image.composite(finalImg, img, finalImg)     
     180 
     181             
    367182        # IE < 7 doesn't display the alpha layer right.  Here we sniff the 
    368183        # user agent and remove the alpha layer if necessary. 
     
    381196        response.write(buf.getvalue()) 
    382197 
    383  
    384     def GetContext(self): 
    385         """ 
    386         Return a WebMap Context document for a given set of layers. 
    387  
    388         """ 
    389         # Parameters 
    390         layers = self.getOwsParam('layers', default=None) 
    391         format = self.getOwsParam('format', default='text/xml') 
    392  
    393         # Filter self.layers for selected layers 
    394         if layers is not None: 
    395             newLayerMap = {} 
    396             for layerName in layers.split(','): 
    397                 try: 
    398                     newLayerMap[layerName] = self.layers[layerName] 
    399                 except KeyError: 
    400                     raise InvalidParameterValue('Layer %s not found' % layerName, 
    401                                                 'layers') 
    402                      
    403             self.layers = newLayerMap 
    404  
    405         # Automatically select the first bbox/crs for the first layer 
    406         aLayer = self.layers.values()[0] 
    407         crs = aLayer.crss[0] 
    408         bb = aLayer.getBBox(crs) 
    409         c.bbox = BoundingBox(bb[:2], bb[2:], crs) 
    410  
    411         # Initialise as if doing GetCapabilities 
    412         ows_controller.initCapabilities() 
    413         self._loadCapabilities() 
    414  
    415         if format == 'text/xml': 
    416             response.headers['Content-Type'] = format 
    417             t = ows_controller.templateLoader.load('wms_context_1_1_1.xml') 
    418             return t.generate(c=c).render() 
    419         elif format == 'application/json': 
    420             response.headers['Content-Type'] = format 
    421             t = ows_controller.templateLoader.load('wms_context_json.txt', 
    422                                                    cls=NewTextTemplate) 
    423             return t.generate(c=c).render() 
    424         else: 
    425             raise InvalidParameterValue('Format %s not supported' % format) 
    426  
    427     def GetFeatureInfo(self): 
    428         # Housekeeping 
    429         version = self.getOwsParam('version', default=self.validVersions[0]) 
    430         if version not in self.validVersions: 
    431             raise InvalidParameterValue('Version %s not supported' % version, 
    432                                         'version') 
    433  
    434         # Coordinate parameters 
    435         bbox = tuple(float(x) for x in self.getOwsParam('bbox').split(',')) 
    436         width = int(self.getOwsParam('width')) 
    437         height = int(self.getOwsParam('height')) 
    438        
    439         # Get pixel location 
    440         i = int(self.getOwsParam('i')) 
    441         j = int(self.getOwsParam('j')) 
    442  
    443         # Translate to geo-coordinates 
    444         x, y = bbox_util.pixelToGeo(i, j, bbox, width, height) 
    445         #start preparing GetFeatureInfo response. Assumes "HTML" output format 
    446  
    447         htmlResponse = "<html><body><p> <b>Feature Information about pixel position: "+self.getOwsParam('i')+","+self.getOwsParam('j')+"/geo position: "+str(x)+","+str(y) +"<b/></p>" 
    448          
    449          
    450         layers = self._getLayerParam('query_layers') 
    451         #Adjusts response for multiple layers 
    452         if len(layers) > 1: 
    453             htmlResponse = htmlResponse+" Multiple possible features found as follows:" 
    454    
    455         htmlResponse = htmlResponse+"<ul>" 
    456          
    457         format = self.getOwsParam('info_format', default='text/html') 
    458         for layerName, layerObj in layers.iteritems(): 
    459             log.debug('Format: %s' % format) 
    460             log.debug('Title: %s' % layerObj.title) 
    461             log.debug('FeatureInfoFormats: %s' % layerObj.featureInfoFormats) 
    462              
    463             if format not in layerObj.featureInfoFormats: 
    464                 raise InvalidParameterValue('Layer %s does not support GetFeatureInfo in format %s' %(layerName, format), 'info_format') 
    465  
    466         if version == '1.1.1': 
    467             srs = self.getOwsParam('srs') 
    468         else: 
    469             srs = self.getOwsParam('crs') 
    470  
    471         if srs not in layerObj.crss: 
    472             raise InvalidParameterValue('Layer %s does not support SRS %s' % 
    473                                         (layerName, srs)) 
    474  
    475         # Dimension handling 
    476         dimValues = {} 
    477         for dimName, dim in layerObj.dimensions.items(): 
    478             defaultValue = dim.extent[0] 
    479             dimValues[dimName] = self.getOwsParam(dimName, default=defaultValue) 
    480          
    481         response.headers['Content-Type'] = format 
    482         response.write(layerObj.getFeatureInfo(format, srs, (x, y), dimValues)) 
    483  
    484198    def GetLegend(self): 
    485199        """ 
     
    493207        # This hook alows extra arguments to be passed to the layer backend.  It 
    494208        # is required for UKCP. 
    495         renderOpts = dict(request_params=self._owsParams) 
    496  
    497         img = layerObj.getLegendImage(renderOpts=renderOpts) 
     209#        renderOpts = dict(request_params=self._owsParams) 
     210      
     211        renderingOptions = {} 
     212        for opt in RENDERING_OPTIONS: 
     213            if self.getOwsParam(opt, default=None) != None: 
     214                renderingOptions[opt] = self.getOwsParam(opt) 
     215         
     216#        log.debug("renderingOptions = %s" % (renderingOptions,)) 
     217 
     218        img = layerObj.getLegendImage(renderOpts=renderingOptions) 
    498219 
    499220        buf = StringIO() 
     
    503224        response.write(buf.getvalue()) 
    504225 
    505  
    506     def GetInfo(self): 
    507         from pprint import pformat 
    508         request.headers['Content-Type'] = 'text/ascii' 
    509         response.write('Some info about this service\n') 
    510         for layer in model.ukcip02.layers: 
    511             response.write('Layer %s: %s\n' % (layer, pformat(g.ukcip02_layers[layer].__dict__))) 
    512  
    513              
  • qesdi/wms_ddc_vis/trunk/lib/wms_ddc_vis/model/ddc_wms_layer.py

    r5403 r5479  
    1818from cows.service.imps.csmlbackend.wms_csmllayer import CSMLwmsLayerSlab 
    1919from wms_ddc_vis.model.ddc_wms_layer_slab import DDCWmsLayerSlab 
     20from wms_ddc_vis.model.ddc_wms_layer_slab_contour import DDCWmsLayerSlabContour 
     21from wms_ddc_vis.model.ddc_render_options_parser import DDCRenderOptionsParser  
     22 
     23import geoplot.colour_bar 
     24 
     25import matplotlib.cm as cm 
     26from wms_ddc_vis.model.rgba_renderer import RGBARenderer 
     27import Image 
     28import ImageFont 
     29import ImageDraw 
     30 
     31 
     32class STYLES: 
     33    CONTOUR = 'contour' 
     34    GRID = 'grid' 
     35    DEFAULT = GRID 
     36 
     37RENDERING_OPTIONS = ['cmap', 'cmap_min', 'cmap_max', 'num_levels', 'show_grid'] 
    2038 
    2139class DDCWmsLayer(IwmsLayer): 
     
    3856            #default to global 
    3957            bb=[-180,-90,180,90] 
     58             
    4059        #convert 0 - 360 to -180, 180 as per common WMS convention 
    4160        if abs(bb[2]-bb[0]) >= 359 and abs(bb[2]-bb[0]) < 361: 
    4261            bb[0], bb[2]=-180, 180 
     62             
    4363        self.wgs84BBox = bb 
    4464        self.featureInfoFormats = ['text/html'] 
     65         
    4566        try: 
    4667            self.wgs84BBox = self.getBBox('EPSG:4326') 
     
    4869            raise ValueError("Layer must provide a bounding box in EPSG:4326 " 
    4970                             "coordinates for compatibility with WMS-1.3.0") 
     71             
    5072        self.featureinfofilecache={} #used for caching netcdf file in getFeatureInfo 
    5173         
     
    6385        #raise NotImplementedError 
    6486         
    65     def getSlab(self, crs, dimValues=None, renderOpts={}): 
     87    def getSlab(self, crs, style, transparent, dimValues=None, renderOpts={}): 
    6688        """ 
    6789        Creates a slab of the layer in a particular CRS and set of 
     
    93115             
    94116            randomname= csml.csmllibs.csmlextra.getRandomID() + '.nc' 
    95             result= self._feature.subsetToGridSeries(config['tmpdir'], ncname=randomname, **dimValues) 
     117             
     118            log.debug("self._feature = %s" % (self._feature,)) 
     119             
     120            log.debug("dir(self._feature) = %s" % (dir(self._feature),)) 
     121             
     122            log.debug("self._feature.id = %s" % (self._feature.id,)) 
     123            log.debug("self._feature.name = %s" % (self._feature.name,)) 
     124            log.debug("self._feature.getTimeAxis() = %s" % (self._feature.getTimeAxis(),)) 
     125            
     126            log.debug("config['tmpdir'] = %s" % (config['tmpdir'],)) 
     127            log.debug("randomname = %s" % (randomname,)) 
     128            log.debug("dimValues = %s" % (dimValues,)) 
     129             
     130            result= self._feature.subsetToGridSeries(config['tmpdir'],  
     131                                        ncname=randomname, **dimValues) 
    96132             
    97133            #for now have to read netcdf back from  
     
    104140            bbox=self.getBBox(crs) 
    105141             
    106             slab = DDCWmsLayerSlab(netcdf, self, crs, dimValues, renderOpts, bbox) 
     142            if style == STYLES.CONTOUR: 
     143                slabClass = DDCWmsLayerSlabContour 
     144            elif style == STYLES.GRID: 
     145                slabClass = DDCWmsLayerSlab 
     146            else: 
     147                raise Exception("Unknown style %s" % (style,)) 
     148             
     149            slab = slabClass(netcdf, self, crs, dimValues, transparent, renderOpts, bbox) 
    107150             
    108151            self._minval=slab.minval #needed for legend rendering. 
     
    113156            raise NotImplementedError 
    114157         
    115     def getCacheKey(self, crs, dimValues=None, renderOpts={}): 
     158    def getCacheKey(self, crs, style, transparent, dimValues=None, renderOpts={}): 
    116159        """ 
    117160        Create a unique key for use in caching a slab. 
     
    126169        dimList = list(dimValues.items()) 
    127170        dimList.sort() 
    128         return '%s:%s:%s' % (self._feature.id, crs, dimList) 
     171        return '%s:%s:%s:%s:%s:%s' % (self._feature.id, crs, style, transparent, dimList, renderOpts) 
    129172 
    130173    def getFeatureInfo(self, format, crs, point, dimValues): 
     
    209252                height = renderOpts['height'] 
    210253                 
    211         cmap = cm.get_cmap(config['colourmap']) 
    212         renderer=RGBARenderer(self._minval, self._maxval) 
    213          
    214         if orientation =='vertical': 
    215             legendImage= renderer.renderColourbar(630, 30, cmap, isVertical=True) 
    216         else: 
    217             legendImage= renderer.renderColourbar(630, 30, cmap, isVertical=False) 
    218                 
    219         imageWithLabels=Image.new('RGBA', (630, 80), "white") 
    220         imageWithLabels.paste(legendImage, (0,0)) 
    221          
    222         #add minvalue label 
    223         minvalueImg=self._simpletxt2image(str(self._minval), (49,25)) 
    224         imageWithLabels.paste(minvalueImg,(0,40)) 
    225          
    226         #add midvalue  label 
    227         midvalue=self._minval+(self._maxval-self._minval)/2 
    228          
    229         #add maxvalue label 
    230         midvalueImg=self._simpletxt2image(str(midvalue),(49,25)) 
    231         imageWithLabels.paste(midvalueImg,(280,40)) 
    232          
    233         #add maxvalue label 
    234         maxvalueImg=self._simpletxt2image(str(self._maxval), (49,25)) 
    235         imageWithLabels.paste(maxvalueImg,(575,40)) 
    236          
    237         #add units: 
    238         unitsImg=self._simpletxt2image('Units of measure: %s'%str(self.units), (200,25)) 
    239         imageWithLabels.paste(unitsImg,(240,60)) 
    240               
    241 #        return imageWithLabels                          
    242         return imageWithLabels.resize((width, height))  
     254#        cmap = cm.get_cmap(config['colourmap']) 
     255        parser = DDCRenderOptionsParser(renderOpts,None) 
     256        cmap = parser.getOption('cmap') 
     257 
     258        im = geoplot.colour_bar.getColourBarImage(width, height,  
     259                                             label='Units of measure: %s'%str(self.units),  
     260                                             cmap=cmap,  
     261                                             cmapRange=(self._minval, self._maxval),  
     262                                             orientation=orientation) 
     263         
     264        return im 
     265         
     266#        renderer=RGBARenderer(self._minval, self._maxval) 
     267#         
     268#        if orientation =='vertical': 
     269#            legendImage= renderer.renderColourbar(630, 30, cmap, isVertical=True) 
     270#        else: 
     271#            legendImage= renderer.renderColourbar(630, 30, cmap, isVertical=False) 
     272#                
     273#        imageWithLabels=Image.new('RGBA', (630, 80), "white") 
     274#        imageWithLabels.paste(legendImage, (0,0)) 
     275#         
     276#        #add minvalue label 
     277#        minvalueImg=self._simpletxt2image(str(self._minval), (49,25)) 
     278#        imageWithLabels.paste(minvalueImg,(0,40)) 
     279#         
     280#        #add midvalue  label 
     281#        midvalue=self._minval+(self._maxval-self._minval)/2 
     282#         
     283#        #add maxvalue label 
     284#        midvalueImg=self._simpletxt2image(str(midvalue),(49,25)) 
     285#        imageWithLabels.paste(midvalueImg,(280,40)) 
     286#         
     287#        #add maxvalue label 
     288#        maxvalueImg=self._simpletxt2image(str(self._maxval), (49,25)) 
     289#        imageWithLabels.paste(maxvalueImg,(575,40)) 
     290#         
     291#        #add units: 
     292#        unitsImg=self._simpletxt2image('Units of measure: %s'%str(self.units), (200,25)) 
     293#        imageWithLabels.paste(unitsImg,(240,60)) 
     294#              
     295##        return imageWithLabels                          
     296#        return imageWithLabels.resize((width, height))  
    243297     
    244298    def _simpletxt2image(self, text, size): 
  • qesdi/wms_ddc_vis/trunk/lib/wms_ddc_vis/model/ddc_wms_layer_slab.py

    r5403 r5479  
    1  
     1import time 
    22import logging 
    33 
     
    66from cows.service.imps.csmlbackend.config import config 
    77 
    8 from wms_ddc_vis.model.rgba_renderer import RGBARenderer 
    9 from wms_ddc_vis.model.geoplot_slab_renderer import GeoplotSlabRenderer 
    10 from wms_ddc_vis.model.grid import Grid 
    11 import thread 
    12 from geoplot.layer_drawer import LayerDrawer 
    13 from geoplot.layer_drawer_contour import LayerDrawerContour 
     8from geoplot.layer_drawer_grid import LayerDrawerGrid 
     9 
     10from wms_ddc_vis.model.ddc_render_options_parser import DDCRenderOptionsParser 
    1411 
    1512log = logging.getLogger(__name__) 
     
    3027    """ 
    3128 
    32     def __init__(self, netcdf, layer, crs, dimValues, renderOpts, bbox): 
     29    def __init__(self, netcdf, layer, crs, dimValues, transparent, renderOpts, bbox): 
    3330         
    3431        log.debug("Creating slab: netcdf = %s, layer = %s, crs = %s, dimValues = %s, renderOpts = %s, bbox = %s" % (netcdf, layer, crs, dimValues, renderOpts, bbox)) 
     
    4138        self.bbox=bbox 
    4239         
    43         #set colour map for ALL images from this slab 
    44         v=self._netcdf(layer.title) 
    45         tvar=v(squeeze=1) 
    46         #get the min and max values to use for the colourmapping. 
    47         #change the fill values to ensure they aren't picked up as false max/mins. 
    48         tvar.missing_value=999999999 
    49         value=tvar.getValue() 
    50         self.minval=min(min(l) for l in value) 
    51         tvar.missing_value=-0.000000001 
    52         value=tvar.getValue() 
    53         self.maxval=max(max(l) for l in value) 
    54          
    5540        self.variable =  self._netcdf(self.layer.title, squeeze=1)  
    5641         
     42        self.minval = self.variable.min() 
     43        self.maxval = self.variable.max() 
    5744         
    58         cmap = cm.get_cmap(config['colourmap']) 
    59         cmapRange=(self.variable.min(), self.variable.max()) 
     45        self.parser = DDCRenderOptionsParser(renderOpts, self.variable) 
    6046         
    61         self.ld = LayerDrawer(cmap=cmap, showGridLines=False, cmapRange=cmapRange) 
     47        cmapRange = (self.parser.getOption('cmap_min'), self.parser.getOption('cmap_max')) 
    6248         
    63         self.cd = LayerDrawerContour(cmap=cmap, cmapRange=cmapRange) 
    64  
    65          
     49        self.ld = LayerDrawerGrid(self.variable,  
     50                                  cmap=self.parser.getOption('cmap'),  
     51                              showGridLines=False,  
     52                              cmapRange=cmapRange, 
     53                              transparent=transparent) 
     54     
    6655    def getImage(self, bbox, width, height): 
    6756        """ 
     
    7564        """ 
    7665 
    77         log.debug('getImage(%s, %s, %s) #%s' % (bbox, width, height, thread.get_ident())) 
     66        log.debug('getImage(%s, %s, %s)' % (bbox, width, height)) 
    7867         
    79         import time 
    8068        xLimits = (bbox[0], bbox[2]) 
    8169        yLimits = (bbox[1], bbox[3]) 
    8270                         
    8371        st = time.time() 
    84         im = self.ld.makeImage(self.variable, xLimits, yLimits, width, height) 
     72        im = self.ld.makeImage(xLimits, yLimits, width, height) 
    8573         
    86 #        im = self.cd.makeImage(self.variable, xLimits, yLimits, width, height) 
    87          
    88         log.debug("generated image in %.2fs" % (time.time() - st,)) 
    89          
    90  
    91         im.save('/tmp/out.png') 
     74        log.debug("generated grid image id=%s (%sx%s, lon=%s, lat=%s in %.2fs" % \ 
     75                  (self.variable.id, width, height, xLimits, yLimits,  time.time() - st,)) 
    9276         
    9377        return im 
    94  
    95 #        import time 
    96 #        st = time.time() 
    97 # 
    98 #        cmap = cm.get_cmap(config['colourmap']) 
    99 #        grid=Grid(self.layer, self._netcdf, bbox, width, height) 
    100 # 
    101 #        minval=self.minval 
    102 #        maxval=self.maxval 
    103 # 
    104 #        renderer=GeoplotSlabRenderer(minval, maxval)          
    105 #         
    106 #        im = renderer.renderGrid(grid, bbox, width, height, cmap) 
    107 #        log.debug(" rendered grid in %.2fs" % (time.time() - st,)) 
    108 #        im.save('/tmp/raw1.png') 
    109 #        return im 
  • qesdi/wms_ddc_vis/trunk/lib/wms_ddc_vis/public

    • Property svn:ignore set to
      openlayers
  • qesdi/wms_ddc_vis/trunk/lib/wms_ddc_vis/tests/__init__.py

    r5403 r5479  
    2222 
    2323here_dir = os.path.dirname(os.path.abspath(__file__)) 
    24 conf_dir = os.path.dirname(os.path.dirname(here_dir)) 
     24conf_dir = os.path.dirname(os.path.dirname(os.path.dirname(here_dir))) 
    2525 
    2626sys.path.insert(0, conf_dir) 
  • qesdi/wms_ddc_vis/trunk/tmp

    • Property svn:ignore set to
      *
Note: See TracChangeset for help on using the changeset viewer.