source: qesdi/geoplot/trunk/lib/geoplot/tests/unit/test_colour_scheme_builder.py @ 5946

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/qesdi/geoplot/trunk/lib/geoplot/tests/unit/test_colour_scheme_builder.py@5946
Revision 5946, 10.9 KB checked in by pnorton, 11 years ago (diff)

Added the ability to set the scale on the colour scheme to a log scale.

Line 
1#/urs/bin/env python
2"""
3test_grid_builder_base.py
4"""
5
6import nose
7import numpy
8from mock import Mock, patch, patch_object
9
10import nose.tools as nt
11import matplotlib
12from geoplot.colour_scheme import ColourSchemeBuilder, _ConinuousSchemeBuilder, _IntervalSchemeBuidler
13from geoplot.grid import Grid
14from geoplot.range import Range
15import geoplot.colour_scheme
16
17class Test_ColourSchemeBuilder(object):
18   
19    def setUp(self):
20        self.builder = ColourSchemeBuilder()
21   
22    @patch('matplotlib.cm.get_cmap')
23    def test_001_getColouMap(self, mockGetCmap):
24       
25        # make sure that the _getColourMap function returns the correct
26        # colour map for the value of the cmap attribute
27       
28        # when a cmap object is provided then that is used as the initial
29        # colour map
30        self.builder.cmap = Mock(spec=matplotlib.colors.ListedColormap)
31        returnedCmap = self.builder._getColourMap()
32        nt.assert_equal(id(self.builder.cmap), id(returnedCmap))       
33       
34        # when a string is provided then the named colour map is retireved
35        self.builder.cmap = 'jet'
36       
37        returnedCmap = self.builder._getColourMap()
38        nt.assert_equal(mockGetCmap.call_count, 1) # called the get_cmap function
39        nt.assert_equal(mockGetCmap.call_args, (('jet',), {})) # called with the right name
40        #check that the bad colour has been set on the new cmap
41        nt.assert_equal(returnedCmap.method_calls, [('set_bad', ('w',), {})])
42       
43        mockGetCmap.reset_mock()
44       
45        # when cmap is None then get_cmap is called with no arguments to return
46        # the defaul colourmap
47        self.builder.cmap = None
48       
49        returnedCmap = self.builder._getColourMap()
50        nt.assert_equal(mockGetCmap.call_count, 1) # called the get_cmap function
51        nt.assert_equal(mockGetCmap.call_args, ((), {})) # called with no arguments
52        #check that the bad colour has been set on the new cmap
53        nt.assert_equal(returnedCmap.method_calls, [('set_bad', ('w',), {})])
54       
55    def test_002_getCBMinMaxSwapsValues(self):
56       
57        # when the values are the wrong way round the getCBMinMax function
58        # swaps them round the right way
59       
60        # test them the right way first
61        minVal, maxVal = 10, 100
62        self.builder.colourBarMin, self.builder.colourBarMax =  minVal, maxVal
63        nt.assert_equal(
64            Range(minVal, maxVal), self.builder._getCbarRange()
65        )
66       
67        # now set them round the wrong way
68        self.builder.colourBarMin, self.builder.colourBarMax =  maxVal, minVal
69        nt.assert_equal(
70            Range(minVal, maxVal), self.builder._getCbarRange()
71        )       
72   
73    @patch('geoplot.colour_scheme._ConinuousSchemeBuilder', spec=True)
74    @patch('geoplot.colour_scheme._IntervalSchemeBuidler', spec=True)
75    def test_003_usesCorrectSchemeBuilders(self, mockIntBuilder, mockContBuilder):
76       
77        # make sure that the right scheme builder classes are used to
78        # build the colour schemes.
79       
80        # set the attributes
81        self.builder.cmap = Mock()
82        self.builder.colourBarMin, self.builder.colourBarMax =  10, 100
83        self.builder.intervals = None
84        self.builder.intervalNames = None
85        mockGrid = Mock(spec=Grid)
86       
87        # when intervalColourbar is false should use the _ConinuousSchemeBuilder
88        self.builder.intervalColourbar = False
89       
90        scheme = self.builder.buildScheme(mockGrid)
91       
92        nt.assert_equal(mockContBuilder.call_count, 1)
93        nt.assert_equal(mockIntBuilder.call_count, 0)
94        nt.assert_equals(mockContBuilder.call_args, ((Range(10, 100), self.builder.colourBarScale, self.builder.cmap, ),{}))
95
96        # check the build command was called on the object returned from the class
97        nt.assert_equal(mockContBuilder.return_value.buildScheme.call_count, 1)
98        nt.assert_equals(mockContBuilder.return_value.buildScheme.call_args, ((mockGrid, ),{}))
99       
100        # check the scheme is the result of this call
101        nt.assert_equal(mockContBuilder.return_value.buildScheme.return_value, scheme)
102       
103        mockIntBuilder.reset_mock()
104        mockContBuilder.reset_mock()
105       
106        # when intervalColourbar is true use the _IntervalSchemeBuidler
107       
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 ),{}))
115
116        # check the build command was called on the object returned
117        nt.assert_equal(mockIntBuilder.return_value.buildScheme.call_count, 1)
118        nt.assert_equals(mockIntBuilder.return_value.buildScheme.call_args, ((mockGrid, ),{}))
119       
120        # check the scheme is the result of this call
121        nt.assert_equal(mockIntBuilder.return_value.buildScheme.return_value, scheme)
122               
123       
124    def test_004_checkHideOutsideBoundsSet(self):
125       
126        # when HideOutsideBounds is true the set_under and set_over methods
127        # should be called on the colour map
128       
129        # test without first
130        self.builder.hideOutsideBounds = False       
131        self.builder.cmap = Mock(spec=matplotlib.colors.ListedColormap)
132        returnedCmap = self.builder._getColourMap()
133       
134        nt.assert_equal(self.builder.cmap, returnedCmap)
135        nt.assert_equal(returnedCmap.method_calls, [])
136       
137        self.builder.cmap.reset_mock()
138       
139        #test with
140        self.builder.hideOutsideBounds = True
141        returnedCmap = self.builder._getColourMap()
142       
143        nt.assert_equal(self.builder.cmap, returnedCmap)
144        nt.assert_equal(returnedCmap.method_calls, [('set_under', ('0.25',), {'alpha': 0.0}), ('set_over', ('0.75',), {'alpha': 0.0})])
145       
146        self.builder.cmap.reset_mock()
147       
148
149class Test_ContinuousColourSchemeBuilder(object):
150   
151    def setUp(self):
152        self.builder = _ConinuousSchemeBuilder(Range(10, 100), 'linear' ,
153                                               Mock(spec=matplotlib.colors.LinearSegmentedColormap))
154        self.mockGrid = Mock(spec=Grid)
155   
156    def test_001_returnedSchemeIsContinuouse(self):
157       
158        scheme = self.builder.buildScheme(self.mockGrid)
159        nt.assert_true(isinstance(scheme, geoplot.colour_scheme.ContinuousColourScheme))
160   
161    def test_002_returndCmapIsUnchanged(self):
162       
163        # for a continuous colour scheme the cmap should be unchanged form the
164        # inital cmap
165       
166        scheme = self.builder.buildScheme(self.mockGrid)
167        nt.assert_equal(scheme.colourMap, self.builder.initialCmap)
168        nt.assert_equal(scheme.colourMap.method_calls, [])
169   
170    def test_003_returnedNormHasVminVmaxSet(self):
171       
172        # make sure the min/max of the grid values are used when the colour bar
173        # min/max is set to None
174       
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)
182           
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))                   
187       
188    def test_004_returnsLogNorm(self):
189        self.builder.cbScale = 'log'
190        scheme = self.builder.buildScheme(self.mockGrid)
191
192        nt.assert_true(isinstance(scheme.norm, matplotlib.colors.LogNorm))
193       
194class Test_IntervalSchemeBuidler(object):
195   
196    def setUp(self):
197        self.oldMax = geoplot.colour_scheme.MAX_INTERVALS
198        geoplot.colour_scheme.MAX_INTERVALS = 20
199        self.builder = _IntervalSchemeBuidler(Range(10.0, 100.0),  'linear' ,
200                                              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
206   
207    def test_001_returnedCmapForNamedIntervals(self):
208       
209        #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       
213        scheme = self.builder.buildScheme()
214               
215        nt.assert_equal(scheme.colourMap.N, 4)
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):
241       
242        colours = [(0.4, 0.4, 0.5, 1.0),
243                   (0.5, 0.5, 0.6, 1.0),
244                   (0.6, 0.6, 0.7, 1.0),]
245       
246        self.builder.initialCmap = matplotlib.colors.ListedColormap(colours, "test_colourmap")
247       
248        scheme = self.builder.buildScheme()
249        nt.assert_equal(scheme.colourMap.colors, colours)
250        nt.assert_equal(scheme.colourMap.name, "test_colourmap")
251   
252    def test_004_returnedLabelsCorrect(self):
253       
254        #labels for the unique values
255        self.builder.intervalLabelsString = None
256        self.builder.intervalBoundsString = None
257        self.builder.cbRange = Range(None, None)
258
259        #labels for specified bounds
260        self.builder.intervalBoundsString = "5,15,25,35"
261        scheme = self.builder.buildScheme()
262       
263        nt.assert_equal(scheme.labels, ['5.0 - 15.0', '15.0 - 25.0', '25.0 - 35.0'])
264
265        #labels for given bounds
266        self.builder.intervalLabelsString = "one,two,three"
267        scheme = self.builder.buildScheme()
268       
269        nt.assert_equal(scheme.labels, ["one", "two", "three"])
270               
271
272     
273
274if __name__ == '__main__':
275
276    nose.runmodule()
Note: See TracBrowser for help on using the repository browser.