Changeset 5688


Ignore:
Timestamp:
07/09/09 12:52:39 (10 years ago)
Author:
pnorton
Message:

Improved the colour bar code so it now accepts the data array instead of just a minimum + maximum. It also now defaults to creating a Normalize instance with vmin=None and vmax=None instead of 0 and 1.

Also modified the layer_drawer objects to use the ColourBar? class instead of implementing it themselves.

Location:
qesdi/geoplot/trunk/lib/geoplot
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • qesdi/geoplot/trunk/lib/geoplot/colour_bar.py

    r5610 r5688  
    22import math 
    33import logging 
     4import numpy 
    45 
    56import matplotlib.colors 
     
    89from matplotlib.colorbar import ColorbarBase 
    910import matplotlib.cm as cm 
     11import operator 
    1012 
    1113import geoplot.config as geoplot_config 
     
    1820 
    1921FONTS_SECTION = 'Fonts' 
    20  
    21  
    2222MAX_CBAR_TICKS = 10 
    2323ADJUSTED_TICK_FORMAT = "%1.2f" 
     
    2626 
    2727    def __init__(self, colourBarLabel="",colourBarPosition='horizontal',  
    28                        cmap=None, colourBarMin=None, colourBarMax=None ): 
     28                       cmap=None, colourBarMin=None, colourBarMax=None, 
     29                       hideOutsideBounds=False): 
    2930 
    3031        self._position = None 
     
    3738        self.colourBarMin = colourBarMin 
    3839        self.colourBarMax = colourBarMax 
     40        self.hideOutsideBounds = hideOutsideBounds 
    3941         
    4042        self.labelFont = config[FONTS_SECTION]['ColourBarLabel'] 
    4143 
    42     def draw(self, colourBarAxis, fontSize='medium', dataMin=None, dataMax=None): 
     44    def draw(self, colourBarAxis, fontSize='medium', data=None): 
    4345        """ 
    4446        Adds the colour bar to the (and optionally a label) to the figure. 
     
    5355        cmap = self.getColourMap() 
    5456 
    55         norm = self.getNormalize(dataMin, dataMax) 
     57        norm = self.getNormalize(data) 
    5658         
    5759        cb = ColorbarBase(colourBarAxis, 
     
    7880        else: 
    7981            cmap = self.cmap 
     82             
     83        if self.hideOutsideBounds: 
     84            log.debug("self.hideOutsideBounds = %s" % (self.hideOutsideBounds,)) 
     85            cmap.set_under('0.25', alpha=0.0) 
     86            cmap.set_over('0.75', alpha=0.0) 
    8087             
    8188        return cmap 
     
    149156            cb.ax.xaxis.set_ticks_position('default') 
    150157     
    151     def getNormalize(self, dataMin=None, dataMax=None): 
    152          
    153         min, max = self.colourBarMin, self.colourBarMax 
    154          
    155         if dataMax.__class__.__name__ == 'MaskedArray': 
    156             dataMax = None 
    157              
    158         if dataMin.__class__.__name__ == 'MaskedArray': 
    159             dataMin = None 
    160          
    161         if min is None and not dataMin is None: 
    162             min = dataMin 
    163         elif min is None: 
    164             min = 0 
    165              
    166         if max is None and not dataMax is None: 
    167             max = dataMax 
    168         elif max is None: 
    169             max = 1 
    170          
    171         if min > max: 
    172             log.warning("min(=%s) > max(=%s) reversing values" % (min, max)) 
    173             max, min = min, max 
    174              
    175          
    176         return matplotlib.colors.Normalize(min,  max) 
    177      
     158    def getNormalize(self, data=None): 
     159         
     160        cbMin = self.colourBarMin 
     161        cbMax = self.colourBarMax 
     162         
     163        if cbMin is not None and cbMax is not None and cbMin > cbMax: 
     164            log.warning("min(=%s) > max(=%s) reversing values" % (cbMin, cbMax)) 
     165            cbMax, cbMin = cbMin, cbMax 
     166         
     167        norm = matplotlib.colors.Normalize(cbMin,  cbMax) 
     168         
     169        # this should work event if data is none (as N.ma.maximum(None) = None) 
     170        norm.autoscale_None(data) 
     171         
     172        # check for masked values in vmin and vmax, can occur when data is completly masked 
     173        if norm.vmin.__class__ == numpy.ma.MaskedArray and norm.vmin.mask == True: 
     174            norm.vmin = None 
     175             
     176        if norm.vmax.__class__ == numpy.ma.MaskedArray and norm.vmax.mask == True: 
     177            norm.vmax = None 
     178 
     179        return norm 
     180     
     181    def _getColourBarLimit(self, limit, data=None): 
     182        assert limit in ['min','max'] 
     183         
     184        #use the value set 
     185        if limit == 'min': 
     186            setVal = self.colourBarMin 
     187        else: 
     188            setVal = self.colourBarMax 
     189         
     190        # if there is no vlaue set try using the data to get 
     191        # the min and max 
     192        if setVal is None: 
     193             
     194            dataVal = None 
     195             
     196            if data is not None: 
     197                if limit == 'min': 
     198                    dataVal = data.min() 
     199                else: 
     200                    dataVal = data.max() 
     201                 
     202                # can't use a masked array as the min or max value 
     203                if dataVal.__class__.__name__ == 'MaskedArray': 
     204                    dataMin = None 
     205             
     206            if dataVal is not None: 
     207                setVal = dataVal 
     208            else: 
     209                if limit == 'min': 
     210                    setVal = 0 
     211                else: 
     212                    setVal = 1 
     213         
     214        return setVal 
    178215     
    179216     
     
    236273        log.warning("cmapRange[0] > cmapRange[1], swapping values") 
    237274        cmapRange = (cmapRange[1], cmapRange[0]) 
    238  
    239     cb = ColorbarBase(axes, cmap=cmap, norm=matplotlib.colors.Normalize(cmapRange[0],cmapRange[1]),  
    240                       orientation=orientation) 
    241      
    242     if label != None: 
    243         cb.set_label(label, weight='normal') 
     275     
     276    cb = ColourBar(colourBarLabel=label,  
     277                   colourBarPosition=orientation,  
     278                   cmap=cmap,  
     279                   colourBarMin=cmapRange[0],  
     280                   colourBarMax=cmapRange[1] ) 
     281     
     282    cb.draw(axes)     
     283     
     284#    cb = ColorbarBase(axes, cmap=cmap, norm=matplotlib.colors.Normalize(cmapRange[0],cmapRange[1]),  
     285#                      orientation=orientation) 
     286#     
     287#    if label != None: 
     288#        cb.set_label(label, weight='normal') 
    244289 
    245290    return geoplot.utils.figureToImage(fig) 
  • qesdi/geoplot/trunk/lib/geoplot/grid_plot.py

    r5612 r5688  
    6060        log.debug("grid.values.max() = %s" % (grid.values.max(),)) 
    6161         
    62         norm = self._colourBar.getNormalize(dataMin=grid.values.min(), dataMax=grid.values.max()) 
     62        norm = self._colourBar.getNormalize(data=grid.values) 
    6363        cmap = self._colourBar.getColourMap() 
    6464         
  • qesdi/geoplot/trunk/lib/geoplot/layer_drawer.py

    r5636 r5688  
    2222import geoplot.utils as geoplot_utils 
    2323 
     24from geoplot.colour_bar import ColourBar 
     25 
    2426log = logging.getLogger(__name__) 
    2527 
     
    3537                 transparent=False, 
    3638                 projection='latlon', 
    37                  resolution='c'): 
    38          
     39                 resolution=None, 
     40                 cmap=None,  
     41                 cmapRange=(None,None), ): 
     42         
     43        self._cb = ColourBar() 
    3944        self.transparent = transparent 
    40         #self.gridType = gridType 
     45        self.cmap = cmap 
     46        self.cmapRange = cmapRange 
    4147         
    4248        self._gridFactory = GridFactory(dataType=gridType) 
     
    209215    def __get_projection(self): 
    210216        return self._mapFactory.projection 
    211      
     217 
     218    def __set_cmap(self, value): 
     219        self._cb.cmap = value 
     220         
     221    def __get_cmap(self): 
     222        return self._cb.cmap  
     223     
     224    cmap = property(__get_cmap, __set_cmap) 
     225     
     226    def __set_cmapRange(self, value): 
     227        self._cb.colourBarMin = value[0] 
     228        self._cb.colourBarMax = value[1] 
     229         
     230    def __get_cmapRange(self): 
     231        return (self._cb.colourBarMin, self._cb.colourBarMax) 
     232     
     233    cmapRange = property(__get_cmapRange, __set_cmapRange) 
     234     
     235 
    212236    projection = property(__get_projection, __set_projection, None, None) 
    213237     
  • qesdi/geoplot/trunk/lib/geoplot/layer_drawer_contour.py

    r5605 r5688  
    99import StringIO 
    1010import thread 
    11  
    12 from matplotlib.colors import Normalize 
    1311 
    1412from geoplot.contour_drawer import ContourDrawer 
     
    2624         
    2725        self._contourDrawer = ContourDrawer() 
    28          
    29         self.cmap = cmap 
    3026        self.numLines = numLines 
    31         self.cmapRange = cmapRange 
    3227        self.cdmsVar = cdmsVar 
    3328        self.fontSize = fontSize 
    3429        self.labelInterval =labelInterval 
    3530         
    36         LayerDrawerBase.__init__(self, gridType, transparent, projection) 
     31        LayerDrawerBase.__init__(self, gridType=gridType, transparent=transparent, cmap=cmap, cmapRange=cmapRange) 
    3732         
    3833    def _drawToAxes(self, axes, xLimits, yLimits): 
     
    5045            basemap = map.basemap         
    5146         
    52         norm = Normalize(self.cmapRange[0], self.cmapRange[1]) 
    53         self._contourDrawer.draw(axes, grid, normalize=norm, cmap=self.cmap, 
     47        norm = self._cb.getNormalize() 
     48         
     49        self._contourDrawer.draw(axes, grid, normalize=norm, cmap=self._cb.getColourMap(), 
    5450                                 basemap=basemap, fontSize=self.fontSize) 
    5551     
    5652    ### properties ### 
    57          
    58     def __set_cmap(self, value): 
    59         self._cmap = value 
    60          
    61     def __get_cmap(self): 
    62         return self._cmap  
    63      
    64     cmap = property(__get_cmap, __set_cmap) 
    65      
     53           
    6654    def __set_numLines(self, value): 
    6755        self._contourDrawer.numContourLines = value 
     
    8977    labelInterval = property(__get_labelInterval, __set_labelInterval) 
    9078 
    91     def __set_cmapRange(self, value): 
    92         self._cmapRange = value 
    9379         
    94     def __get_cmapRange(self): 
    95         return self._cmapRange 
    96      
    97     cmapRange = property(__get_cmapRange, __set_cmapRange)     
    98          
  • qesdi/geoplot/trunk/lib/geoplot/layer_drawer_grid.py

    r5612 r5688  
    2727 
    2828from geoplot.layer_drawer import LayerDrawerBase 
     29from geoplot.colour_bar import ColourBar 
    2930 
    3031from matplotlib.colors import Normalize 
     
    4041                 transparent=False): 
    4142         
    42         self._cmap = None 
     43 
    4344        self._gridDrawer = GridDrawer() 
    4445         
     
    5051         
    5152        self.cdmsVar = cdmsVar 
    52         self.cmap = cmap 
    53         self.cmapRange = cmapRange 
    5453        self.showGridLines = showGridLines 
    5554        self.outline = outline 
    5655         
    57         LayerDrawerBase.__init__(self, gridType, transparent) 
     56        LayerDrawerBase.__init__(self, gridType=gridType, transparent=transparent, cmap=cmap, cmapRange=cmapRange) 
    5857         
    5958    def _drawToAxes(self, axes, xLimits, yLimits): 
     
    7271            basemap = map.basemap         
    7372         
    74         norm = Normalize(self.cmapRange[0], self.cmapRange[1]) 
    75          
     73        norm = self._cb.getNormalize() 
     74                 
    7675        #draw the grid on the axis 
    7776        self._gridDrawer.draw(axes, grid, 
     
    7978                              limits=(xLimits, yLimits), 
    8079                              norm=norm, 
    81                               cmap=self.cmap) 
     80                              cmap=self._cb.getColourMap()) 
    8281                               
    8382     
     
    9291    showGridLines = property(__get_showGridLines, __set_showGridLines)  
    9392     
    94     def __set_cmap(self, value): 
    95         self._cmap = value 
    96          
    97     def __get_cmap(self): 
    98         return self._cmap  
    99      
    100     cmap = property(__get_cmap, __set_cmap) 
    101      
    102     def __set_cmapRange(self, value): 
    103         self._cmapRange = value 
    104          
    105     def __get_cmapRange(self): 
    106         return self._cmapRange 
    107      
    108     cmapRange = property(__get_cmapRange, __set_cmapRange) 
    109      
    11093    def __set_outline(self, value): 
    11194        self._gridDrawer.outline = value 
  • qesdi/geoplot/trunk/lib/geoplot/plot_base.py

    r5646 r5688  
    152152        if self.drawColourBar: 
    153153            self._colourBar.draw(self._plotArea.cbAxes, self.fontSize,  
    154                                  dataMin=grid.values.min(), 
    155                                  dataMax=grid.values.max()) 
     154                                 data=grid.values) 
    156155 
    157156    def drawToImage(self): 
  • qesdi/geoplot/trunk/lib/geoplot/tests/drawing/draw_test_colourbar.py

    r5605 r5688  
    33import logging 
    44 
    5 from geoplot.tests.drawing import getDrawingOutputDir 
    65from geoplot.colour_bar import ColourBar 
    76 
     
    2524if __name__ == '__main__': 
    2625 
     26    from geoplot.tests.drawing import getDrawingOutputDir 
    2727    from geoplot.log_util import SHORT_LOG_FORMAT_STRING 
    2828    logging.basicConfig(level=logging.DEBUG, format=SHORT_LOG_FORMAT_STRING) 
  • qesdi/geoplot/trunk/lib/geoplot/tests/unit/test_colour_bar.py

    r5636 r5688  
    6060 
    6161    def test_003_getNormalize(self): 
    62          
     62        #check returns limits when no data provided 
    6363        norm = self.cb.getNormalize() 
    6464        nt.assert_equal((norm.vmin, norm.vmax), self.colourBarRange) 
    6565         
     66        #fixes the norm if the limits are given the wrong way round 
     67        self.cb.colourBarMin = self.colourBarRange[1]         
     68        self.cb.colourBarMax = self.colourBarRange[0]         
     69        norm = self.cb.getNormalize() 
     70        nt.assert_equal((norm.vmin, norm.vmax), self.colourBarRange)         
     71         
     72        #check returns None,None when no data and no limits 
     73        self.cb.colourBarMin = None 
     74        self.cb.colourBarMax = None 
     75        norm = self.cb.getNormalize() 
     76        nt.assert_equal((norm.vmin, norm.vmax), (None, None)) 
     77         
     78        #set up some mock data 
     79        data = numpy.array([-9.43, -10.0, 23.232, 143.2, 13.111]) 
    6680        dMin = -10.0; dMax = 143.2 
    6781         
     82        #still returns set limits when data present 
     83        self.cb.colourBarMin = self.colourBarRange[0]         
     84        self.cb.colourBarMax = self.colourBarRange[1]         
     85        norm = self.cb.getNormalize(data=data) 
     86        nt.assert_equal((norm.vmin, norm.vmax), self.colourBarRange) 
     87         
     88        #returns data minimum when colourBarMin = None 
    6889        self.cb.colourBarMin = None 
    69         norm = self.cb.getNormalize(dataMin=dMin, dataMax=dMax) 
     90        self.cb.colourBarMax = self.colourBarRange[1] 
     91        norm = self.cb.getNormalize(data=data) 
    7092        nt.assert_equal((norm.vmin, norm.vmax), (dMin, self.colourBarRange[1])) 
    7193         
     94        #returns data maximum when colourBarMax = None 
    7295        self.cb.colourBarMin = self.colourBarRange[0] 
    7396        self.cb.colourBarMax = None 
    74         norm = self.cb.getNormalize(dataMin=dMin, dataMax=dMax) 
     97        norm = self.cb.getNormalize(data=data) 
    7598        nt.assert_equal((norm.vmin, norm.vmax), (self.colourBarRange[0], dMax)) 
    7699         
     100        #returns data range when limits are both None 
    77101        self.cb.colourBarMin = None 
    78         norm = self.cb.getNormalize(dataMin=dMin, dataMax=dMax) 
     102        self.cb.colourBarMax = None 
     103        norm = self.cb.getNormalize(data=data) 
    79104        nt.assert_equal((norm.vmin, norm.vmax), (dMin, dMax)) 
    80105         
     106        #check it dosent fall over when data is all masked 
     107        data = numpy.ma.MaskedArray([-9.43, -10.0, 23.232, 143.2, 13.111], 
     108                                    mask=[True, True, True, True, True]) 
    81109        dMin = numpy.ma.MaskedArray([0], mask=True) 
    82110        dMax = numpy.ma.MaskedArray([0], mask=True) 
     111                 
     112        self.cb.colourBarMin = None 
     113        self.cb.colourBarMax = None 
    83114         
    84         norm = self.cb.getNormalize(dataMin=dMin, dataMax=dMax) 
    85         nt.assert_equal((norm.vmin, norm.vmax), (0.0, 1.0)) 
     115        #still returns 0,1 as the default 
     116        norm = self.cb.getNormalize(data=data) 
     117        nt.assert_equal((norm.vmin, norm.vmax), (None,None)) 
     118         
     119        #will still use limits when data is masked 
     120        self.cb.colourBarMin = self.colourBarRange[0]         
     121        self.cb.colourBarMax = self.colourBarRange[1] 
     122        norm = self.cb.getNormalize(data=data) 
     123        nt.assert_equal((norm.vmin, norm.vmax), self.colourBarRange) 
     124         
    86125 
    87126    #position ticks (if 
  • qesdi/geoplot/trunk/lib/geoplot/utils.py

    r5683 r5688  
    157157def isValueInLimits(val, limits):    
    158158    return  val >= limits[0] and val <= limits[1] 
     159 
     160def isListUnique(items): 
     161    seen = {} 
     162     
     163    for item in items: 
     164        if item in seen: 
     165            return False 
     166         
     167        seen[item] = 1 
     168         
     169    return True            
     170  
     171def getUniqueList(items): 
     172    seen = {} 
     173    l = [] 
     174    for item in items: 
     175        if item in seen: 
     176            continue 
     177         
     178        seen[item] = 1 
     179        l.append(item) 
     180         
     181    return l 
Note: See TracChangeset for help on using the changeset viewer.