- Timestamp:
- 04/12/09 16:07:45 (11 years ago)
- Location:
- qesdi/geoplot/trunk/lib/geoplot
- Files:
-
- 2 added
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
qesdi/geoplot/trunk/lib/geoplot/colour_bar.py
r5946 r6089 13 13 import geoplot 14 14 15 from geoplot.colour_scheme import COLOUR_SCHEME_SCALE16 17 18 15 config = geoplot_config.getConfig() 19 16 … … 24 21 ADJUSTED_TICK_FORMAT = "%1.2f" 25 22 23 class COLOUR_BAR_STYLES: 24 LEGEND='legend' 25 CONTINUOUS = 'continuous' 26 27 @staticmethod 28 def all(): 29 return [COLOUR_BAR_STYLES.CONTINUOUS, COLOUR_BAR_STYLES.LEGEND] 30 31 class COLOUR_SCHEME_SCALE: 32 LINEAR='linear' 33 LOG='log' 34 26 35 class ColourBar(object): 27 36 28 def __init__(self, colourBarLabel="",colourBarPosition='horizontal', colourBarStyle= 'continuous'):37 def __init__(self, colourBarLabel="",colourBarPosition='horizontal', colourBarStyle=COLOUR_BAR_STYLES.CONTINUOUS): 29 38 30 39 self._position = None … … 48 57 log.debug("drawing colour bar") 49 58 50 intervalColourbar = isinstance(colourScheme, geoplot.colour_scheme.IntervalColourScheme) 51 52 log.debug("intervalColourbar = %s, self.colourBarStyle = %s" % (intervalColourbar, self.colourBarStyle)) 53 54 if self.colourBarStyle == 'legend' and intervalColourbar: 59 if self.colourBarStyle == 'legend': 55 60 self._drawLegendColourBar(colourBarAxis, colourScheme, fontSize) 56 61 else: … … 90 95 91 96 """ 92 93 #to make a legend colour bar we need an interval colour scheme94 assert isinstance(colourScheme, geoplot.colour_scheme.IntervalColourScheme)95 96 97 kwargs = {} 97 98 … … 99 100 norm = colourScheme.norm 100 101 102 locations, labels = colourScheme.labelLocations, colourScheme.labels 103 101 104 kwargs['orientation'] = self.colourBarPosition 102 105 103 handles = [Rectangle((0,0), 1, 1, fc=cmap(norm(i))) for i in colourScheme.labelLocations]104 labels = colourScheme.labels106 handles = [Rectangle((0,0), 1, 1, fc=cmap(norm(i))) for i in locations] 107 labels = labels 105 108 106 109 if self.colourBarPosition == 'horizontal': … … 126 129 colourBarAxis.set_ylabel(self.colourBarLabel, fontdict=labelDictionary) 127 130 128 129 130 131 return leg 131 132 … … 221 222 intervals=None, 222 223 intervalNames=None, 224 numIntervals=None, 223 225 colourBarStyle='continuous', 224 226 dpi=100): … … 233 235 colourBarMax=colourBarMax, 234 236 colourBarScale=colourBarScale, 237 numIntervals=numIntervals, 235 238 intervals=intervals, 236 239 intervalNames=intervalNames) 237 240 238 colourScheme = schemeBuilder.buildScheme( )241 colourScheme = schemeBuilder.buildScheme(colourBarStyle) 239 242 log.debug("colourScheme.norm.__class__ = %s" % (colourScheme.norm.__class__,)) 240 243 #for agg bakcend -
qesdi/geoplot/trunk/lib/geoplot/colour_scheme.py
r5946 r6089 14 14 from geoplot.range import Range 15 15 from geoplot.fixed_boundary_norm import FixedBoundaryNorm 16 17 import utils 16 from geoplot.colour_bar import COLOUR_BAR_STYLES, COLOUR_SCHEME_SCALE 17 from geoplot.colour_scheme_intervals import ColourSchemeIntervalBuilder 18 18 19 19 MAX_INTERVALS = 20 20 20 21 21 log = logging.getLogger(__name__) 22 23 24 class COLOUR_SCHEME_SCALE:25 LINEAR='linear'26 LOG='log'27 28 22 29 23 class ColourScheme(object): … … 38 32 39 33 class IntervalColourScheme(ColourScheme): 34 40 35 def __init__(self, colourMap, norm, scale, labels, labelLocations): 41 36 self.labels = labels … … 51 46 colourBarScale=COLOUR_SCHEME_SCALE.LINEAR, 52 47 hideOutsideBounds=False, 48 numIntervals=6, 53 49 intervals=None, 54 50 intervalNames=None): 55 51 52 self._numIntervals = None 53 56 54 self.cmap = cmap 57 55 self.colourBarMin = colourBarMin … … 59 57 self.colourBarScale = colourBarScale 60 58 self.hideOutsideBounds = hideOutsideBounds 59 self.numIntervals = numIntervals 61 60 self.intervals = intervals 62 61 self.intervalNames = intervalNames 63 64 def buildScheme(self, grid=None): 65 66 cbRange = self._getCbarRange() 62 self._intervalBuilder = ColourSchemeIntervalBuilder() 63 64 def buildScheme(self, colourBarStyle, grid=None): 65 66 cbRange = self._getCbarRange(grid) 67 67 initialCmap = self._getColourMap() 68 68 69 if self.intervals != None: 70 builder = _IntervalSchemeBuidler(cbRange, self.colourBarScale, initialCmap, self.intervals, self.intervalNames) 71 else: 72 builder = _ConinuousSchemeBuilder(cbRange, self.colourBarScale, initialCmap) 73 74 scheme = builder.buildScheme(grid) 69 assert colourBarStyle in COLOUR_BAR_STYLES.all() 70 71 if colourBarStyle == COLOUR_BAR_STYLES.LEGEND: 72 builder = self._getIntervalBuilder(cbRange, initialCmap) 73 else: 74 builder = self._getContinuousBuilder(cbRange, initialCmap) 75 76 scheme = builder.buildScheme() 77 78 if self.hideOutsideBounds: 79 scheme.norm.clip = False 75 80 76 81 return scheme 82 83 def _getIntervalBuilder(self,cbRange, initialCmap): 84 85 interval = self._intervalBuilder.buildCSInterval(cbRange, self.intervals, self.intervalNames, numIntervals=self.numIntervals) 86 log.debug("interval = %s" % (interval,)) 87 builder = _IntervalSchemeBuidler(cbRange, self.colourBarScale, initialCmap, interval) 88 89 return builder 90 91 def _getContinuousBuilder(self, cbRange, initialCmap): 92 builder = _ConinuousSchemeBuilder(cbRange, self.colourBarScale, initialCmap) 93 return builder 77 94 78 95 def _getColourMap(self): … … 102 119 return cmap 103 120 104 def _getCbarRange(self): 105 cbMin = self.colourBarMin 106 cbMax = self.colourBarMax 121 def _getCbarRange(self, grid=None): 122 123 if not grid is None: 124 cbMin = self.colourBarMin if self.colourBarMin != None else grid.getMinValue() 125 cbMax = self.colourBarMax if self.colourBarMax != None else grid.getMaxValue() 126 else: 127 cbMin = self.colourBarMin if self.colourBarMin != None else 0 128 cbMax = self.colourBarMax if self.colourBarMax != None else 1 129 130 # check for masked values in vmin and vmax, can occur when data is completly masked 131 if cbMin.__class__ == numpy.ma.MaskedArray and cbMin.mask == True: 132 cbMin = None 133 134 if cbMax.__class__ == numpy.ma.MaskedArray and cbMax.mask == True: 135 cbMax = None 107 136 108 137 if cbMin is not None and cbMax is not None and cbMin > cbMax: … … 111 140 112 141 return Range(cbMin, cbMax) 113 142 143 144 145 def __set_numIntervals(self, value): 146 if value <= 0: 147 log.warning("Can't set numIntervals to %s in ColourSchemeBuilder" % (value,)) 148 else: 149 self._numIntervals = value 150 151 def __get_numIntervals(self): 152 return self._numIntervals 153 154 numIntervals = property(__get_numIntervals, __set_numIntervals, None, None) 114 155 115 156 class _ConinuousSchemeBuilder(): … … 123 164 self.cbScale = cbScale 124 165 125 def buildScheme(self , grid=None):166 def buildScheme(self): 126 167 cmap = self._buildColourMap() 127 norm = self._buildNorm( grid)168 norm = self._buildNorm() 128 169 return ContinuousColourScheme(cmap, norm, self.cbScale) 129 170 … … 131 172 return self.initialCmap 132 173 133 def _buildNorm(self , grid):174 def _buildNorm(self): 134 175 135 176 norm = None 136 177 137 cbMin, cbMax = self.cbRange.minimum, self.cbRange.maximum138 139 if not grid is None:140 vmin = cbMin if cbMin != None else grid.getMinValue()141 vmax = cbMax if cbMax != None else grid.getMaxValue()142 else:143 vmin = cbMin144 vmax = cbMax145 146 178 if self.cbScale == 'log': 147 179 148 if vmin is not None and vmin > 0 and vmax is not None and vmax > 0: 149 norm = matplotlib.colors.LogNorm(vmin, vmax) 180 if self.cbRange.minimum is not None and self.cbRange.minimum > 0 \ 181 and self.cbRange.maximum is not None and self.cbRange.maximum > 0: 182 norm = matplotlib.colors.LogNorm(self.cbRange.minimum, self.cbRange.maximum) 150 183 else: 151 184 log.warning("Can't create a log colour scheme with min = %s and max = %s" 152 % ( vmin, vmax))185 % (self.cbRange.minimum, self.cbRange.maximum)) 153 186 154 187 155 188 if norm == None: 156 norm = matplotlib.colors.Normalize(vmin, vmax) 157 158 159 # check for masked values in vmin and vmax, can occur when data is completly masked 160 if norm.vmin.__class__ == numpy.ma.MaskedArray and norm.vmin.mask == True: 161 norm.vmin = None 162 163 if norm.vmax.__class__ == numpy.ma.MaskedArray and norm.vmax.mask == True: 164 norm.vmax = None 165 189 norm = matplotlib.colors.Normalize(self.cbRange.minimum, self.cbRange.maximum) 190 166 191 return norm 167 192 168 193 class _IntervalSchemeBuidler(): 169 194 170 def __init__(self, cbRange, cbScale, initialCmap, intervalBoundsString, intervalLabelsString=None):195 def __init__(self, cbRange, cbScale, initialCmap, csInterval): 171 196 self.cbRange = cbRange 172 197 self.cbScale = cbScale 173 198 self.initialCmap = initialCmap 174 self.intervalBoundsString = intervalBoundsString 175 self.intervalLabelsString = intervalLabelsString 176 177 def buildScheme(self, grid=None): 199 self.csInterval = csInterval 200 201 def buildScheme(self): 178 202 """ 179 203 Builds an interval colour scheme using either the unique values form 180 204 the grid or the bounds in the intervalBoundsString 181 205 """ 182 183 bounds = numpy.array([float(x) for x in self._splitString(self.intervalBoundsString)]) 184 185 bounds = self._filterBoundsUsingCBMinMax(bounds) 186 187 csInterval = self._buildCSIntervalFromBounds(bounds) 188 189 labels = self._getLabels(csInterval) 190 191 cmap = self._buildColourMap(csInterval) 192 norm = self._getNorm(csInterval) 193 194 return IntervalColourScheme(cmap, norm, self.cbScale, labels, csInterval.midpoints) 195 196 def _buildColourMap(self, csInterval): 206 207 labels = self.csInterval.labels 208 cmap = self._buildColourMap() 209 norm = self._getNorm() 210 211 return IntervalColourScheme(cmap, norm, self.cbScale, labels, self.csInterval.midpoints) 212 213 def _buildColourMap(self): 197 214 """ 198 215 Returns a (possibly) modified version of the initialCmap that corresponds … … 201 218 if self.initialCmap.__class__ != matplotlib.colors.ListedColormap: 202 219 203 if len( csInterval.midpoints) == 1:220 if len(self.csInterval.midpoints) == 1: 204 221 #only one interval value so pick the middle of the cmap 205 222 colors = [ self.initialCmap(0.5) ] 206 223 cmap = matplotlib.colors.ListedColormap(colors) 207 224 else: 208 n = matplotlib.colors.Normalize( csInterval.midpoints.min(),209 csInterval.midpoints.max())210 211 colors = [self.initialCmap(n(x)) for x in csInterval.midpoints]225 n = matplotlib.colors.Normalize(self.csInterval.midpoints.min(), 226 self.csInterval.midpoints.max()) 227 228 colors = [self.initialCmap(n(x)) for x in self.csInterval.midpoints] 212 229 cmap = matplotlib.colors.ListedColormap(colors) 213 230 else: … … 216 233 return cmap 217 234 218 def _getNorm(self , csInterval):235 def _getNorm(self): 219 236 """ 220 237 Returns a Boundary Normalisation object for the given _ColourSchemeInterval. 221 238 """ 222 norm = FixedBoundaryNorm( csInterval.bounds, len(csInterval.bounds) - 1 )239 norm = FixedBoundaryNorm(self.csInterval.bounds, len(self.csInterval.bounds) - 1 ) 223 240 return norm 224 241 225 def _getLabels(self, csInterval):226 if self.intervalLabelsString == None:227 labels = csInterval.defalutLabels228 else:229 labels = self._splitString(self.intervalLabelsString)230 if len(labels) != len(csInterval.midpoints):231 log.warning("Number of labels found (%s) is != to the number of midpoints (%s), using default labels instead" \232 % (len(labels), len(csInterval.midpoints)))233 labels = csInterval.defalutLabels234 235 return labels236 237 238 def _splitString(self, csvString):239 """240 Splits a csv string and removes any empty values241 """242 stringList = csvString.split(',')243 stringList = filter(lambda x: x.strip() != '', stringList)244 return stringList245 246 def _buildCSIntervalFromMidpoints(self, midpoints):247 """248 Builds a _ColourSchemeInterval object from a list of midpoint values249 """250 bounds = utils.getBounds(midpoints)251 defaultLabels = [str(utils.round_to_n(x, 2)) for x in midpoints]252 return _ColourSchemeInterval(midpoints, bounds, defaultLabels)253 254 def _buildCSIntervalFromBounds(self, bounds):255 """256 Builds a _ColourSchemeInterval object from a list of bounds.257 """258 midpoints = utils.getMidpoints(bounds)259 boundStrings = [str(utils.round_to_n(x,2)) for x in bounds]260 #log.debug("boundStrings = %s" % (boundStrings,))261 defaultLabels = ["%s - %s" % (boundStrings[index], boundStrings[index + 1]) for index in range(len(boundStrings)-1)]262 return _ColourSchemeInterval(midpoints, bounds, defaultLabels)263 264 def _getBoundsFromValues(self, values):265 """266 This function uses the minimum and maximum of the values to267 create MAX_INTERVALS bounds which are returned as a numpy array.268 """269 values = self._filterValuesUsingCBMinMax(values)270 271 boundsMin, boundsMax = values.min(), values.max()272 273 if self.cbMin != None and self.cbMin > boundsMin:274 boundsMin = self.cbMin275 276 if self.cbMax != None and self.cbMax < boundsMax:277 boundsMax = self.cbMax278 279 interval = (boundsMax - boundsMin)/float(MAX_INTERVALS)280 bounds = numpy.arange(boundsMin, boundsMax, interval)281 282 #include the upper bound283 bounds =numpy.append(bounds, boundsMax)284 285 return bounds286 287 def _filterValuesUsingCBMinMax(self, values):288 #get rid of any values above cbMax289 if self.cbRange.maximum != None:290 values = numpy.array(filter(lambda x: x <= self.cbRange.maximum, values))291 292 # get rid of any bounds less than the minimum293 if self.cbRange.minimum != None:294 values = numpy.array(filter(lambda x: self.cbRange.minimum <= x , values))295 296 return values297 298 def _filterBoundsUsingCBMinMax(self, bounds):299 300 newBounds = bounds301 302 if self.cbRange.minimum != None:303 304 #start with the maximum of the first bound305 for i in range(1, len(bounds)):306 if bounds[i] <= self.cbRange.minimum:307 newBounds = newBounds[1:]308 else:309 break310 311 if self.cbRange.maximum != None:312 313 #start with the lower of the top bound314 for i in range(len(bounds) - 2, 0, -1):315 if bounds[i] > self.cbRange.maximum:316 newBounds = newBounds[:-1]317 else:318 break319 320 return newBounds321 322 323 324 class _ColourSchemeInterval(object):325 """326 Represents interval information required to build an interval colour scheme327 """328 329 def __init__(self, midpoints, bounds, defalutLabels):330 self.midpoints = midpoints331 self.bounds = bounds332 self.defalutLabels = defalutLabels333 -
qesdi/geoplot/trunk/lib/geoplot/grid_drawer.py
r6024 r6089 65 65 """ 66 66 67 67 68 if cmap == None: 68 69 cmap = matplotlib.cm.get_cmap() 69 cmap.set_bad("w") 70 cmap.set_bad("w") 71 72 log.debug("cmap._rgba_under = %s" % (cmap._rgba_under ,)) 70 73 71 74 if norm == None: -
qesdi/geoplot/trunk/lib/geoplot/layer_drawer.py
r5980 r6089 7 7 import logging 8 8 import time 9 import numpy 9 10 10 11 import matplotlib.colors … … 12 13 13 14 import geoplot.utils as geoplot_utils 14 from geoplot.colour_bar import C olourBar15 from geoplot.colour_bar import COLOUR_BAR_STYLES 15 16 from geoplot.grid_factory import GridFactory 16 17 from geoplot.map_factory import MapFactory 17 18 from geoplot.colour_scheme import ColourSchemeBuilder 18 19 import geoplot.utils as utils 20 21 from geoplot.colour_bar import COLOUR_SCHEME_SCALE 19 22 20 23 log = logging.getLogger(__name__) … … 36 39 colourBarMax=None, 37 40 colourBarScale='linear', 41 colourBarStyle=COLOUR_BAR_STYLES.CONTINUOUS, 38 42 intervals=None, 39 43 bgcolour='white'): … … 42 46 self._csBuilder = ColourSchemeBuilder() 43 47 self._bgcolour = 'white' 48 49 self.colourBarStyle = colourBarStyle 44 50 45 51 self.colourBarScale = colourBarScale … … 176 182 177 183 return map 184 185 def _applyMask(self, grid, scheme, hideOutside): 186 """ 187 Masks the data outside the scheme bounds if hideOutside is true, also 188 masks values less than zero if a log scale is being used 189 """ 190 191 if self._hideOutsideBounds: 192 grid.values = numpy.ma.masked_less(grid.values, scheme.norm.vmin) 193 grid.values = numpy.ma.masked_greater(grid.values, scheme.norm.vmax) 194 195 if scheme.scale == COLOUR_SCHEME_SCALE.LOG: 196 grid.values = numpy.ma.masked_less_equal(grid.values, 0.0) 197 198 return grid 178 199 179 200 ### properties ### -
qesdi/geoplot/trunk/lib/geoplot/layer_drawer_contour.py
r5946 r6089 32 32 grid = self._buildGrid(self.cdmsVar, xLimits, yLimits) 33 33 34 scheme = self._csBuilder.buildScheme( grid)34 scheme = self._csBuilder.buildScheme(self.colourBarStyle, grid=grid) 35 35 36 36 #if the projection is 'latlon' then no transformation is needed. -
qesdi/geoplot/trunk/lib/geoplot/layer_drawer_grid.py
r5876 r6089 15 15 "Draw only the layer section of the plot" 16 16 17 def __init__(self, cdmsVar, showGridLines=False, outline=False, **kwargs): 17 def __init__(self, cdmsVar, showGridLines=False, outline=False, 18 hideOutside=False, 19 numIntervals = None, **kwargs): 20 21 self.numIntervals = numIntervals 22 self.hideOutside = hideOutside 23 18 24 19 25 self._gridDrawer = GridDrawer() … … 43 49 # map.basemap.drawcoastlines(ax=axes, xLimits=xLimits, yLimits=yLimits) 44 50 45 scheme = self._csBuilder.buildScheme( grid)51 scheme = self._csBuilder.buildScheme(self.colourBarStyle, grid=grid) 46 52 cmap = scheme.colourMap 47 53 #set the bad colour to transparent 48 54 cmap.set_bad('w', 0.0) 55 56 self._applyMask(grid, scheme, self.hideOutside) 49 57 50 58 #draw the grid on the axis … … 73 81 74 82 outline = property(__get_outline, __set_outline) 75 83 84 def __set_numIntervals(self, value): 85 self._csBuilder.numIntervals = value 86 87 def __get_numIntervals(self): 88 return self._csBuilder.numIntervals 89 90 numIntervals = property(__get_numIntervals, __set_numIntervals, None, None) 91 92 def __set_hideOutside(self, value): 93 self._hideOutsideBounds = value 94 95 def __get_hideOutside(self): 96 return self._hideOutsideBounds 97 98 hideOutside = property(__get_hideOutside, __set_hideOutside, None, None) -
qesdi/geoplot/trunk/lib/geoplot/layer_drawer_grid_fast.py
r5946 r6089 12 12 from geoplot.grid_builder_lat_lon_subset import GridBuilderLatLonSubset 13 13 14 import numpy 15 16 from geoplot.colour_bar import COLOUR_BAR_STYLES 17 14 18 log = logging.getLogger(__name__) 15 19 … … 20 24 showGridLines=False, 21 25 cmap=None, 26 numIntervals=None, 22 27 colourBarMin=None, 23 28 colourBarMax=None, 29 hideOutside=False, 24 30 transparent=False, 25 31 colourBarScale='linear', 32 colourBarStyle=COLOUR_BAR_STYLES.CONTINUOUS, 26 33 intervals=None, 27 34 bgcolour='white'): … … 29 36 self._gridDrawer = GridDrawer() 30 37 self._csBuilder = ColourSchemeBuilder() 38 self.numIntervals = numIntervals 39 self.hideOutside = hideOutside 31 40 41 log.debug("self._csBuilder.hideOutsideBounds = %s" % (self._csBuilder.hideOutsideBounds,)) 42 43 self.colourBarStyle = colourBarStyle 32 44 self.cdmsVar = cdmsVar 33 45 self.showGridLines = showGridLines … … 87 99 Creates a new grid object and draws it onto the axis. 88 100 """ 89 90 scheme = self._csBuilder.buildScheme(grid) 101 102 103 104 scheme = self._csBuilder.buildScheme(self.colourBarStyle, grid=grid) 91 105 cmap = scheme.colourMap 106 107 grid = self._applyMask(grid, scheme, self.hideOutside) 92 108 93 109 if self.transparent: … … 102 118 cmap=cmap, 103 119 assumeBoundsParallel=True) 104 120 121 122 123 105 124 ### properties ### 106 125 … … 146 165 147 166 projection = property(__get_projection, __set_projection, None, None) 167 168 def __set_numIntervals(self, value): 169 170 self._csBuilder.numIntervals = value 171 172 def __get_numIntervals(self): 173 return self._csBuilder.numIntervals 174 175 numIntervals = property(__get_numIntervals, __set_numIntervals, None, None) 176 177 def __set_hideOutside(self, value): 178 self._hideOutsideBounds = value 179 180 def __get_hideOutside(self): 181 return self._hideOutsideBounds 182 183 hideOutside = property(__get_hideOutside, __set_hideOutside, None, None) -
qesdi/geoplot/trunk/lib/geoplot/plot_base.py
r5876 r6089 145 145 grid = self._gridFactory.getGrid(self.xLimits, self.yLimits) 146 146 147 colourScheme = self._schemeBuilder.buildScheme(grid) 147 log.debug("self._colourBar.colourBarStyle = %s" % (self._colourBar.colourBarStyle,)) 148 149 colourScheme = self._schemeBuilder.buildScheme(self._colourBar.colourBarStyle, grid) 150 151 log.debug("colourScheme.__class__ = %s" % (colourScheme.__class__,)) 148 152 149 153 self._drawDiagram(map, grid, self._plotArea.axes, colourScheme) -
qesdi/geoplot/trunk/lib/geoplot/tests/test_utils.py
r5403 r6089 16 16 return abs((f1-f2)/size) < thres 17 17 18 def _areNumericListsEqual (result,answer):18 def _areNumericListsEqualIgnoringOrder(result,answer): 19 19 """ 20 20 tests if two lists are equal (converts all values to float before comparison) … … 37 37 return True 38 38 39 def _areNumericListsEqual(result,answer): 40 """ 41 tests if two lists are equal (converts all values to float before comparison) 42 """ 43 if (len(result) != len(answer)): 44 return False 45 46 for i in range(len(result)): 47 x = float(result[i]) 48 y = float(answer[i]) 49 50 if not _floatCompare(x,y): 51 return False 52 53 return True 54 39 55 def _comparePublicAttribues(A, B): 40 56 -
qesdi/geoplot/trunk/lib/geoplot/tests/unit/test_colour_bar.py
r5946 r6089 7 7 import nose.tools as nt 8 8 9 import numpy10 11 9 from mock import patch, patch_object, Mock, sentinel 12 10 import geoplot.colour_scheme 13 11 import matplotlib 14 import matplotlib.ticker 15 import matplotlib.colorbar 16 import matplotlib.cm 17 18 import geoplot.colour_bar 19 import geoplot.utils 20 import geoplot.tests.test_utils 21 from geoplot.grid import Grid 22 from geoplot.plot_font import PlotFont 23 from geoplot.colour_bar import ColourBar 24 import geoplot.colour_scheme 25 26 import geoplot.tests.test_config as testConfig 27 config = testConfig.getConfig() 28 29 FONTS_SECTION = 'Fonts' 12 import geoplot 30 13 31 14 class Test_ColourBar(object): 32 15 33 16 def setUp(self): 34 #replace the colour bar config 35 self.oldConfig = geoplot.colour_bar.config 36 geoplot.colour_bar.config = config 37 38 self.colourBarLabel = "A label" 39 self.colourBarPosition = "horizontal" 40 self.colourBarRange = (25.0, 75.0) 41 self.cb = ColourBar(colourBarLabel=self.colourBarLabel, 42 colourBarPosition=self.colourBarPosition) 17 self.cb = geoplot.colour_bar.ColourBar('label', 'horizontal', 'legend') 18 self.mockAxes = Mock(spec=matplotlib.axes.Axes) 43 19 44 self.sm = matplotlib.cm.ScalarMappable(cmap=matplotlib.cm.prism)45 self.sm.set_clim(15.5, 95.5)46 20 47 21 def tearDown(self): 48 geoplot.colour_bar.config = self.oldConfig 49 50 def test_001_drawContinuousColourBar(self): 22 pass 51 23 52 cb = ColourBar('label', 'horizontal', 'continuous') 24 @patch('geoplot.colour_bar.ColorbarBase') 25 def test_001_drawContinuousColourBar(self, mockCBBase): 26 self.cb.colourBarStyle = 'continuous' 27 scheme = Mock(spec=['colourMap','norm','scale']) 53 28 54 mockAxes = Mock(spec=matplotlib.axes.Axes) 55 scheme = Mock(spec=geoplot.colour_scheme.ContinuousColourScheme) 29 self.cb.draw(self.mockAxes, scheme) 56 30 57 cb.draw(mockAxes, scheme) 31 nt.assert_equal(mockCBBase.call_count, 1) 32 33 nt.assert_equal(mockCBBase.call_args, 34 ((self.mockAxes,), {'cmap':scheme.colourMap, 35 'orientation':self.cb.colourBarPosition, 36 'norm':scheme.norm}) 37 ) 38 39 def test_002_drawLegendColourBar(self): 58 40 59 41 42 scheme = Mock(spec=geoplot.colour_scheme.IntervalColourScheme) 43 scheme._methods.extend(['colourMap','norm', 'scale', 'labels', 'labelLocations']) 44 scheme.labelLocations = range(10) 45 46 self.cb.draw(self.mockAxes, scheme) 47 48 nt.assert_equal(self.mockAxes.legend.call_count, 1) 49 callArgs = self.mockAxes.legend.call_args 50 51 # check that there were 10 rectangles created 52 nt.assert_equal(len(callArgs[0][0]), 10) 53 nt.assert_equal(callArgs[0][1], scheme.labels) 54 60 55 61 56 62 def te_st_001_checkInitialisaion(self):63 assert(self.cb.colourBarLabel == self.colourBarLabel)64 assert(self.cb.colourBarPosition == self.colourBarPosition)65 assert(self.cb.colourBarMin == self.colourBarRange[0])66 assert(self.cb.colourBarMax == self.colourBarRange[1])67 68 def te_st_002_checkLabelFont(self):69 colourBarFont = config[FONTS_SECTION]['ColourBarLabel']70 assert(self.cb.labelFont.getDict('small') == colourBarFont.getDict('small'))71 assert(self.cb.labelFont.getDict('medium') == colourBarFont.getDict('medium'))72 assert(self.cb.labelFont.getDict('large') == colourBarFont.getDict('large'))73 74 def te_st_003_getNormalize(self):75 #check returns limits when no data provided76 norm = self.cb.getNormalize()77 nt.assert_equal((norm.vmin, norm.vmax), self.colourBarRange)78 #fixes the norm if the limits are given the wrong way round79 self.cb.colourBarMin = self.colourBarRange[1]80 self.cb.colourBarMax = self.colourBarRange[0]81 norm = self.cb.getNormalize()82 nt.assert_equal((norm.vmin, norm.vmax), self.colourBarRange)83 84 #check returns None,None when no data and no limits85 self.cb.colourBarMin = None86 self.cb.colourBarMax = None87 norm = self.cb.getNormalize()88 nt.assert_equal((norm.vmin, norm.vmax), (None, None))89 90 #set up some mock data91 grid = Mock(spec=Grid)92 grid.values = Mock(spec=numpy.ndarray)93 dMin = -10.0; dMax = 143.294 grid.values = numpy.array([-9.43, -10.0, 23.232, 143.2, 13.111])95 96 #still returns set limits when data present97 self.cb.colourBarMin = self.colourBarRange[0]98 self.cb.colourBarMax = self.colourBarRange[1]99 norm = self.cb.getNormalize(grid=grid)100 nt.assert_equal((norm.vmin, norm.vmax), self.colourBarRange)101 102 #returns data minimum when colourBarMin = None103 self.cb.colourBarMin = None104 self.cb.colourBarMax = self.colourBarRange[1]105 norm = self.cb.getNormalize(grid=grid)106 nt.assert_equal((norm.vmin, norm.vmax), (dMin, self.colourBarRange[1]))107 108 #returns data maximum when colourBarMax = None109 self.cb.colourBarMin = self.colourBarRange[0]110 self.cb.colourBarMax = None111 norm = self.cb.getNormalize(grid=grid)112 nt.assert_equal((norm.vmin, norm.vmax), (self.colourBarRange[0], dMax))113 114 #returns data range when limits are both None115 self.cb.colourBarMin = None116 self.cb.colourBarMax = None117 norm = self.cb.getNormalize(grid=grid)118 nt.assert_equal((norm.vmin, norm.vmax), (dMin, dMax))119 120 #check it dosent fall over when data is all masked121 grid.values = numpy.ma.MaskedArray([-9.43, -10.0, 23.232, 143.2, 13.111],122 mask=[True, True, True, True, True])123 dMin = numpy.ma.MaskedArray([0], mask=True)124 dMax = numpy.ma.MaskedArray([0], mask=True)125 126 self.cb.colourBarMin = None127 self.cb.colourBarMax = None128 129 #still returns 0,1 as the default130 norm = self.cb.getNormalize(grid=grid)131 nt.assert_equal((norm.vmin, norm.vmax), (None,None))132 133 #will still use limits when data is masked134 self.cb.colourBarMin = self.colourBarRange[0]135 self.cb.colourBarMax = self.colourBarRange[1]136 norm = self.cb.getNormalize(grid=grid)137 nt.assert_equal((norm.vmin, norm.vmax), self.colourBarRange)138 139 140 #position ticks (if141 def te_st_012_repositionsTicksToDiscreteCmapBounds(self):142 #create a 6 element discreet colour map143 cmap = geoplot.utils.generateDiscreteCmap(144 [(0,0,0), (20,20,20), (40,40,40), (60,60,60), (80,80,80)], "temp")145 #create a mock colour bar, decided not to use a real one as it would146 #involve setting up a figure and an axis147 mcb = MockColourBar(0,6,cmap)148 149 #make sure the max ticks is 10150 geoplot.colour_bar.MAX_CBAR_TICKS = 10151 152 ColourBar._repositionColourBarTicks(mcb)153 154 #check the formatter and the locator have been set correctly and that155 #the .draw_all function has been called156 assert(mcb.locator.__class__ == matplotlib.ticker.FixedLocator)157 assert(mcb.formatter.__class__ == matplotlib.ticker.FormatStrFormatter)158 assert(mcb.redrawn == True)159 assert(geoplot.tests.test_utils._areNumericListsEqual(mcb.locator.locs,160 [0.0, 1.2, 2.4, 3.6, 4.8, 6.0]))161 162 163 def test_013_raiseErrorWhenSettingInvalidPositionValue(self):164 nose.tools.assert_raises(ValueError, setattr, self.cb, 'colourBarPosition', 'sideways')165 166 167 def not_a_method():168 raise Exception("Not a method!")169 170 171 class MockColourBar:172 def __init__(self, vmin, vmax, cmap):173 self.vmin = vmin174 self.vmax = vmax175 self.cmap = cmap176 self.locator = None177 self.formatter = None178 self.redrawn = False179 self.outline = MockOutline()180 self.ax = MockAxes()181 182 def draw_all(self):183 self.redrawn = True184 185 class MockAxes(object):186 def __init__(self):187 self.yaxis = MockAxis()188 self.xaxis = MockAxis()189 190 class MockOutline(object):191 def __init__(self):192 self.linewidth = None193 194 def set_linewidth(self, value):195 self.linewidth = value196 197 class MockAxis(object):198 def __init__(self):199 self._tickPosition = "default"200 201 def get_ticks_position(self):202 return self._tickPosition203 204 def set_ticks_position(self, val):205 self._tickPosition = val206 207 57 if __name__ == '__main__': 208 58 print "Running tests in", __file__ 209 59 nose.runmodule() 210 60 -
qesdi/geoplot/trunk/lib/geoplot/tests/unit/test_colour_scheme_builder.py
r5946 r6089 4 4 """ 5 5 6 import logging 7 6 8 import nose 7 9 import numpy … … 10 12 import nose.tools as nt 11 13 import matplotlib 14 import geoplot 12 15 from geoplot.colour_scheme import ColourSchemeBuilder, _ConinuousSchemeBuilder, _IntervalSchemeBuidler 16 from geoplot.colour_scheme_intervals import ColourSchemeInterval 13 17 from geoplot.grid import Grid 14 18 from geoplot.range import Range 15 19 import geoplot.colour_scheme 20 21 log = logging.getLogger(__name__) 16 22 17 23 class Test_ColourSchemeBuilder(object): … … 73 79 @patch('geoplot.colour_scheme._ConinuousSchemeBuilder', spec=True) 74 80 @patch('geoplot.colour_scheme._IntervalSchemeBuidler', spec=True) 75 def test_003_usesCorrectSchemeBuilders(self, mockIntBuilder, mockContBuilder): 81 def test_003_usesCorrectSchemeBuilders(self, 82 mockIntSchemeBuilder, mockContSchemeBuilder): 76 83 77 84 # make sure that the right scheme builder classes are used to … … 84 91 self.builder.intervalNames = None 85 92 mockGrid = Mock(spec=Grid) 93 mockIntBuilder = Mock(spec=geoplot.colour_scheme_intervals.ColourSchemeIntervalBuilder) 94 mockIntBuilder.buildCSInterval.return_value = Mock(spec=geoplot.colour_scheme_intervals.ColourSchemeInterval) 95 96 self.builder._intervalBuilder = mockIntBuilder 86 97 87 98 # when intervalColourbar is false should use the _ConinuousSchemeBuilder 88 99 self.builder.intervalColourbar = False 89 100 90 scheme = self.builder.buildScheme( mockGrid)91 92 nt.assert_equal(mockCont Builder.call_count, 1)93 nt.assert_equal(mockInt Builder.call_count, 0)94 nt.assert_equals(mockCont Builder.call_args, ((Range(10, 100), self.builder.colourBarScale, self.builder.cmap, ),{}))101 scheme = self.builder.buildScheme('continuous', mockGrid) 102 103 nt.assert_equal(mockContSchemeBuilder.call_count, 1) 104 nt.assert_equal(mockIntSchemeBuilder.call_count, 0) 105 nt.assert_equals(mockContSchemeBuilder.call_args, ((Range(10, 100), self.builder.colourBarScale, self.builder.cmap, ),{})) 95 106 96 107 # check the build command was called on the object returned from the class 97 nt.assert_equal(mockCont Builder.return_value.buildScheme.call_count, 1)98 nt.assert_equals(mockCont Builder.return_value.buildScheme.call_args, ((mockGrid,),{}))108 nt.assert_equal(mockContSchemeBuilder.return_value.buildScheme.call_count, 1) 109 nt.assert_equals(mockContSchemeBuilder.return_value.buildScheme.call_args, ((),{})) 99 110 100 111 # check the scheme is the result of this call 101 nt.assert_equal(mockCont Builder.return_value.buildScheme.return_value, scheme)102 103 mockInt Builder.reset_mock()104 mockCont Builder.reset_mock()112 nt.assert_equal(mockContSchemeBuilder.return_value.buildScheme.return_value, scheme) 113 114 mockIntSchemeBuilder.reset_mock() 115 mockContSchemeBuilder.reset_mock() 105 116 106 117 # when intervalColourbar is true use the _IntervalSchemeBuidler 107 118 108 self.builder.intervals = "5,10,15" 109 110 scheme = self.builder.buildScheme(mockGrid) 111 112 nt.assert_equal(mockIntBuilder.call_count, 1) 113 nt.assert_equal(mockContBuilder.call_count, 0) 114 nt.assert_equals(mockIntBuilder.call_args, ((Range(10, 100), self.builder.colourBarScale, self.builder.cmap, self.builder.intervals, self.builder.intervalNames ),{})) 119 scheme = self.builder.buildScheme('legend',mockGrid) 120 121 nt.assert_equal(mockIntSchemeBuilder.call_count, 1) 122 nt.assert_equal(mockContSchemeBuilder.call_count, 0) 123 nt.assert_equals(mockIntSchemeBuilder.call_args, 124 ((Range(10, 100), 125 self.builder.colourBarScale, 126 self.builder.cmap, 127 mockIntBuilder.buildCSInterval.return_value ),{})) 115 128 116 129 # check the build command was called on the object returned 117 nt.assert_equal(mockInt Builder.return_value.buildScheme.call_count, 1)118 nt.assert_equals(mockInt Builder.return_value.buildScheme.call_args, ((mockGrid,),{}))130 nt.assert_equal(mockIntSchemeBuilder.return_value.buildScheme.call_count, 1) 131 nt.assert_equals(mockIntSchemeBuilder.return_value.buildScheme.call_args, ((),{})) 119 132 120 133 # check the scheme is the result of this call 121 nt.assert_equal(mockInt Builder.return_value.buildScheme.return_value, scheme)134 nt.assert_equal(mockIntSchemeBuilder.return_value.buildScheme.return_value, scheme) 122 135 123 136 … … 152 165 self.builder = _ConinuousSchemeBuilder(Range(10, 100), 'linear' , 153 166 Mock(spec=matplotlib.colors.LinearSegmentedColormap)) 154 self.mockGrid = Mock(spec=Grid)155 167 156 168 def test_001_returnedSchemeIsContinuouse(self): 157 169 158 scheme = self.builder.buildScheme( self.mockGrid)170 scheme = self.builder.buildScheme() 159 171 nt.assert_true(isinstance(scheme, geoplot.colour_scheme.ContinuousColourScheme)) 160 172 … … 164 176 # inital cmap 165 177 166 scheme = self.builder.buildScheme( self.mockGrid)178 scheme = self.builder.buildScheme() 167 179 nt.assert_equal(scheme.colourMap, self.builder.initialCmap) 168 180 nt.assert_equal(scheme.colourMap.method_calls, []) … … 173 185 # min/max is set to None 174 186 175 self.mockGrid.values = numpy.array([1.0,2.0,200.0]) 176 self.mockGrid.getMinValue.return_value = self.mockGrid.values.min() 177 self.mockGrid.getMaxValue.return_value = self.mockGrid.values.max() 178 179 for cbMin, cbMax in ( (None, None), (10,None), (None, 10), (10, 100)): 180 self.builder.cbRange = Range(cbMin, cbMax) 181 scheme = self.builder.buildScheme(self.mockGrid) 187 188 self.builder.cbRange = Range(5.0, 10.0) 189 scheme = self.builder.buildScheme() 182 190 183 v_min = cbMin if cbMin != None else self.mockGrid.values.min() 184 v_max = cbMax if cbMax != None else self.mockGrid.values.max() 185 186 nt.assert_equal((scheme.norm.vmin, scheme.norm.vmax), (v_min, v_max)) 191 nt.assert_equal((scheme.norm.vmin, scheme.norm.vmax), (5.0, 10.0)) 187 192 188 193 def test_004_returnsLogNorm(self): 189 194 self.builder.cbScale = 'log' 190 scheme = self.builder.buildScheme( self.mockGrid)195 scheme = self.builder.buildScheme() 191 196 192 197 nt.assert_true(isinstance(scheme.norm, matplotlib.colors.LogNorm)) … … 195 200 196 201 def setUp(self): 197 self.oldMax = geoplot.colour_scheme.MAX_INTERVALS 198 geoplot.colour_scheme.MAX_INTERVALS = 20 202 interval = ColourSchemeInterval(numpy.array([25.0,35.0,45.0,55.0]), 203 numpy.array([20.0,30.0,40.0,50.0,60.0]), 204 ['a','b','c','d']) 199 205 self.builder = _IntervalSchemeBuidler(Range(10.0, 100.0), 'linear' , 200 206 Mock(spec=matplotlib.colors.LinearSegmentedColormap), 201 "20,30,40,50,60", 202 "a,b,c,d") 203 204 def tearDown(self): 205 geoplot.colour_scheme.MAX_INTERVALS = self.oldMax 207 interval) 206 208 207 209 def test_001_returnedCmapForNamedIntervals(self): 208 210 209 211 #check that the right number of colours appear in the listed colourmap 210 self.builder.intervalBoundsString = "20,30,40,50,60"211 self.builder.cbRange = Range(None, None)212 212 213 213 scheme = self.builder.buildScheme() … … 215 215 nt.assert_equal(scheme.colourMap.N, 4) 216 216 nt.assert_equal(scheme.colourMap.__class__, matplotlib.colors.ListedColormap) 217 218 219 def test_002_returnedNormForNamedIntervals(self): 220 221 #test that the normalisation is correct for the named bounds 222 self.builder.intervalLabelsString = None 223 self.builder.intervalBoundsString = "2.5,7.5,12.5,17.5,22.5" 224 self.builder.cbRange = Range(None, None) 225 226 scheme = self.builder.buildScheme() 227 228 expectedBounds = numpy.array([2.5, 7.5, 12.5, 17.5, 22.5]) 229 nt.assert_true((scheme.norm.boundaries == expectedBounds).all()) 230 231 #add in the cmap min/max 232 233 self.builder.cbRange = Range(7.5,13.0) 234 235 scheme = self.builder.buildScheme() 236 print scheme.norm.boundaries 237 expectedBounds = numpy.array([7.5, 12.5, 17.5]) 238 nt.assert_true((scheme.norm.boundaries == expectedBounds).all()) 239 240 def test_003_returnIntervalCmapUntouched(self): 217 218 219 def test_002_returnIntervalCmapUntouched(self): 241 220 242 221 colours = [(0.4, 0.4, 0.5, 1.0), … … 250 229 nt.assert_equal(scheme.colourMap.name, "test_colourmap") 251 230 252 def test_00 4_returnedLabelsCorrect(self):231 def test_003_returnedLabelsCorrect(self): 253 232 254 233 #labels for the unique values 255 self.builder.intervalLabelsString = None 256 self.builder.intervalBoundsString = None 257 self.builder.cbRange = Range(None, None) 234 self.builder.csInterval.bounds = numpy.array([5.0,15.0,25.0,35.0]) 235 self.builder.csInterval.midpoints = numpy.array([10.0,20.0,30.0]) 236 self.builder.csInterval.labels = ['5.0 - 15.0', '15.0 - 25.0', '25.0 - 35.0'] 237 self.builder.cbRange = Range(0, 100) 258 238 259 239 #labels for specified bounds 260 self.builder.intervalBoundsString = "5,15,25,35" 261 scheme = self.builder.buildScheme() 262 240 scheme = self.builder.buildScheme() 263 241 nt.assert_equal(scheme.labels, ['5.0 - 15.0', '15.0 - 25.0', '25.0 - 35.0']) 264 242 265 243 #labels for given bounds 266 self.builder. intervalLabelsString = "one,two,three"244 self.builder.csInterval.labels = ["one","two","three"] 267 245 scheme = self.builder.buildScheme() 268 246
Note: See TracChangeset
for help on using the changeset viewer.