Ignore:
Timestamp:
08/05/09 14:26:31 (11 years ago)
Author:
domlowe
Message:

adding separate cowsclient pylons app

File:
1 copied

Legend:

Unmodified
Added
Removed
  • cows/branches/cows-vis/cows/service/imps/pywms/render_impddc.py

    r5052 r5265  
    1 # BSD Licence 
    2 # Copyright (c) 2009, Science & Technology Facilities Council (STFC) 
    3 # All rights reserved. 
    4 # 
    5 # See the LICENSE file in the source distribution of this software for 
    6 # the full license text. 
    7  
     1# Adapted for numpy/ma/cdms2 by convertcdms.py 
    82""" 
    93Implementation of grid rendering classes. 
     
    148from view import GridRenderer 
    159import ImageColor, Image 
    16 import numpy as N 
     10from cdms_compat import Numeric as N, byteTypecode, arrayAny, arrayMask 
     11import utils 
    1712import logging 
    1813from matplotlib import cm, colors 
    1914 
    20 logger = logging.getLogger(__name__) 
    21  
    22 class RGBARenderer(GridRenderer): 
     15logger = logging.getLogger('pywms.render_imp') 
     16 
     17class RgbaPNGRenderer(GridRenderer): 
    2318    """Creates an RGBA PNG with a selectable matplotlib colour scale. 
     19    @todo: This shouldn't be called RgbaPNGRenderer because it produces PIL RGBA images, not just PNG. 
    2420    """ 
    2521 
     
    2723 
    2824    def __init__(self, varmin, varmax): 
     25        self.setMinMax(varmin, varmax) 
     26         
     27    def setMinMax(self, varmin, varmax): 
    2928        self.varmin = varmin 
    3029        self.varmax = varmax 
    3130        self._norm = colors.normalize(varmin, varmax) 
     31         
     32        logger.debug('Instantiating RgbaPNGRenderer with varmin=%s, varmax=%s' 
     33                     % (varmin, varmax)) 
    3234 
    3335    def renderColourbar(self, width, height, cmap, isVertical=True): 
     
    3941            shape = (256, 1) 
    4042 
    41         cbar = (cmap(a) * 255).astype('b').tostring() 
     43        cbar = (cmap(a) * 255).astype(byteTypecode).tostring() 
    4244        img = Image.frombuffer("RGBA", shape, cbar, "raw", "RGBA", 0, 1) 
    4345        img = img.resize((width, height)) 
     
    4850        cmap.set_bad('#ffffff', 0.0) 
    4951 
    50         logger.debug('grid %s, %s, %s, %s, %s, %s %s, %s' % 
    51                     (grid.x0, grid.y0, grid.dx, grid.dy, grid.nx, grid.ny, 
    52                      grid.ix, grid.iy)) 
    53         logger.debug('bbox %s' % (bbox,)) 
     52        logger.info('grid %s, %s, %s, %s, %s, %s' % 
     53                    (grid.lon0, grid.lat0, grid.dlon, grid.dlat, grid.nlon, grid.nlat)) 
    5454 
    5555        # Get a pixel = grid-box image for the grid 
     
    5757 
    5858        # Calculate the pixel-size of a grid box 
    59         pxPerDeg_x = float(width) / (bbox[2] - bbox[0]) 
    60         pxPerDeg_y = float(height) / (bbox[3] - bbox[1]) 
    61         pxPerGrid_x = grid.dx * pxPerDeg_x 
    62         pxPerGrid_y = grid.dy * pxPerDeg_y 
     59        pxPerDeg_lon = float(width) / (bbox[2] - bbox[0]) 
     60        pxPerDeg_lat = float(height) / (bbox[3] - bbox[1]) 
     61        pxPerGrid_x = grid.dlon * pxPerDeg_lon 
     62        pxPerGrid_y = grid.dlat * pxPerDeg_lat 
    6363 
    6464        # Scale Img to the right size 
    65         img = img.resize(((abs(pxPerGrid_x * grid.nx), 
    66                            abs(pxPerGrid_y * grid.ny)))) 
    67  
    68         #!NO: We assume the grid points represent the centre of the grid boxes 
    69         #!NO: therefore we can calculate the upper-left position of the image 
    70         # Adapted so that the grid points represent the lower left corner of grid boxes 
     65        img = img.resize((pxPerGrid_x * grid.nlon, pxPerGrid_y * grid.nlat)) 
     66 
     67        # We assume the grid points represent the centre of the grid boxes 
     68        # therefore we can calculate the upper-left position of the image 
    7169 
    7270        # Find top-left corner of grid 
    73         if grid.dx > 0: 
    74             leftX = grid.x0 
    75         else: 
    76             leftX = grid.x0 + (grid.dx * (grid.nx - 1)) 
    77         if grid.dy > 0: 
    78             topY = grid.y0 + (grid.dy * (grid.ny - 1)) 
    79         else: 
    80             topY = grid.y0 
    81  
    82         logger.debug('top-left = %s x, %s y' % (leftX, topY)) 
     71        if grid.dlon > 0: 
     72            leftLon = grid.lon0 
     73        else: 
     74            leftLon = grid.lon0 + (grid.dlon * (grid.nlon - 1)) 
     75        if grid.dlat > 0: 
     76            topLat = grid.lat0 + (grid.dlat * (grid.nlat - 1)) 
     77        else: 
     78            topLat = grid.lat0 
     79 
     80        logger.info('top-left = %s lon, %s lat' % (leftLon, topLat)) 
    8381 
    8482        # Find pixel position of top left centre grid box 
    85         cx = width * ((leftX - bbox[0])/ (bbox[2] - bbox[0])) 
    86         cy = height * ((bbox[3] - topY) / (bbox[3] - bbox[1])) 
    87         logger.debug('top-left centre pixel = %s x, %s y' % (cx, cy)) 
     83        cx = width * ((leftLon - bbox[0])/ (bbox[2] - bbox[0])) 
     84        cy = height * ((bbox[3] - topLat) / (bbox[3] - bbox[1])) 
    8885 
    8986        # Apply half width of grid box 
    90         #ox = int(cx - pxPerGrid_x / 2) 
    91         #oy = int(cy - pxPerGrid_y / 2) 
    92         ox,oy = int(cx), int(cy-pxPerGrid_y) 
    93         logger.debug('Offset: %s x, %s y' % (ox, oy)) 
    94  
     87        ox = int(cx - pxPerGrid_x / 2) 
     88        oy = int(cy - pxPerGrid_y / 2) 
    9589 
    9690        # Paste the grid image into the tile image 
    9791        tileImg = Image.new('RGBA', (width, height)) 
    98         logger.debug('Pasting image img%s into tileImg%s at (%s,%s)' % (img.size, tileImg.size, ox, oy)) 
     92        logger.info('Pasting image img%s into tileImg%s at (%s,%s)' % (tileImg.size, img.size, ox, oy)) 
    9993        tileImg.paste(img, (ox, oy)) 
    10094 
     
    107101        """ 
    108102        a = self._norm(grid.value) 
    109         img_buf = (cmap(a) * 255).astype('b') 
    110  
    111         # This code assumes the axis ordering is either (y, x, time) or (x, y, time) 
    112         if min(grid.iy, grid.ix) != 0 and max(grid.iy, grid.ix) != 1: 
    113             raise ValueError("X and Y must be the first 2 dimensions!") 
    114  
    115         if grid.iy < grid.ix: 
    116             yxOrdering = True 
    117         else: 
    118             yxOrdering = False 
     103        img_buf = (cmap(a) * 255).astype(byteTypecode) 
     104        if arrayAny(arrayMask(a)): 
     105            logger.info('Masking grid') 
     106            alpha_buf = (-arrayMask(a)*255 + 255).astype(byteTypecode) 
     107        else: 
     108            alpha_buf = None 
     109 
     110        # This code assumes the axis ordering is either (lat, lon, time) or (lon, lat, time) 
     111        if min(grid.ilat, grid.ilon) != 0 and max(grid.ilat, grid.ilon) != 1: 
     112            raise ValueError("Latitude and longitude must be the first 2 dimensions!") 
     113 
     114        if grid.ilat < grid.ilon: 
     115            latLonOrdering = True 
     116        else: 
     117            latLonOrdering = False 
     118 
     119        if latLonOrdering: 
     120            (y, x, c) = img_buf.shape 
     121            shape = (x, y) 
     122        else: 
     123            (x, y, c) = img_buf.shape 
     124            shape = (y, x) 
    119125     
    120         img = Image.frombuffer("RGBA", img_buf.shape[1::-1], img_buf.tostring(), "raw", "RGBA", 0, 1) 
    121         img.save('tmp/raw1.png') 
    122  
    123         # Rotate if axis order is x, y 
    124         if not yxOrdering: 
    125             img = img.transpose(Image.ROTATE_90) 
    126  
    127         # Flip if x or y are ordered the wrong way 
    128         if grid.dy > 0: 
     126        img = Image.frombuffer("RGBA", shape, img_buf.tostring(), "raw", "RGBA", 0, 1) 
     127        if alpha_buf is not None: 
     128            alpha = Image.frombuffer("L", shape, alpha_buf.tostring(), "raw", "L", 0, 1) 
     129            img.putalpha(alpha) 
     130 
     131        # Flip if lon or lat are ordered the wrong way 
     132        if grid.dlat > 0 and latLonOrdering: 
    129133            logger.debug('Flipping y') 
    130134            img = img.transpose(Image.FLIP_TOP_BOTTOM) 
    131         if grid.dx < 0: 
     135        if grid.dlon < 0: 
    132136            logger.debug('Flipping x') 
    133137            img = img.transpose(Image.FLIP_LEFT_RIGHT) 
    134138 
    135  
    136         return img 
    137  
    138  
    139 #--------------------------------------------------------------------------------- 
    140  
     139        # Rotate if axis order is lon, lat 
     140        if not latLonOrdering: 
     141            img = img.transpose(Image.ROTATE_90) 
     142 
     143 
     144        return img 
     145 
     146 
     147class RainbowPNGRenderer(GridRenderer): 
     148    """Creates an indexed PNG with a rainbow palette. 
     149 
     150    @deprecated 
     151    """ 
     152 
     153    mimeType = 'image/png' 
     154 
     155    def __init__(self, varmin, varmax): 
     156        palette = [] 
     157        for x in range(256): 
     158            palette.extend(ImageColor.getrgb('hsl(%d,100%%,50%%)' % x)) 
     159        self._palette = palette 
     160 
     161        self.varmin = varmin 
     162        self.varmax = varmax 
     163 
     164    def renderColourbar(self, width, height, isVertical=True): 
     165        if isVertical: 
     166            s = N.arrayrange(255, -1, -1, typecode='b').tostring() 
     167            shape = (1, 256) 
     168        else: 
     169            s = N.arrayrange(256, typecode='b').tostring() 
     170            shape = (256, 1) 
     171 
     172        img = Image.frombuffer("P", shape, s, 'raw', 'P', 0, 1) 
     173        img = img.resize((width, height)) 
     174        img.putpalette(self._palette) 
     175 
     176        return img 
     177 
     178    def renderGrid(self, grid, bbox, width, height): 
     179 
     180        bboxObj = utils.BBox(bbox) 
     181 
     182        # If a non-CRS:84 bbox is requested we must retrieve the valid 
     183        # sub-bbox and paste it into an image of the correct size. 
     184        # It is assumed that grid can wrap around in the longitude and therefore only 
     185        # needs adjusting in the latitude. 
     186        if bbox != bboxObj.crs84: 
     187            img = Image.new('P', (width, height)) 
     188            img.putpalette(self._palette) 
     189            (ox, oy) = bboxObj.getCrs84OffsetInImage(width, height) 
     190            nwidth, nheight = bboxObj.getCrs84ImageSize(width, height) 
     191            # If the image is too small just send a blank image 
     192            if bboxObj.crs84Width > abs(grid.dlon) and bboxObj.crs84Height > abs(grid.dlat): 
     193                img1 = self._grid2Img(grid, width, nheight) 
     194                img.paste(img1, (0, oy)) 
     195        else: 
     196            img = self._grid2Img(grid, width, height) 
     197 
     198        return img 
     199 
     200    def _grid2Img(self, grid, width, height): 
     201        var = grid.value 
     202        a = ((var - self.varmin) / self.varmax * 255).filled(0).astype(byteTypecode) 
     203 
     204        img = Image.frombuffer('P', list(var.shape)[::-1], a.tostring(), 'raw', 'P', 0, 1) 
     205        img.putpalette(self._palette) 
     206 
     207        if grid.dlat > 0: 
     208            img = img.transpose(Image.FLIP_TOP_BOTTOM) 
     209        if grid.dlon < 0: 
     210            img = img.transpose(Image.FLIP_LEFT_RIGHT) 
     211 
     212        return img.resize((width, height)) 
Note: See TracChangeset for help on using the changeset viewer.