/[thuban]/branches/WIP-pyshapelib-bramz/test/test_layer.py
ViewVC logotype

Annotation of /branches/WIP-pyshapelib-bramz/test/test_layer.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2552 - (hide annotations)
Fri Jan 28 15:54:00 2005 UTC (20 years, 1 month ago) by jonathan
Original Path: trunk/thuban/test/test_layer.py
File MIME type: text/x-python
File size: 20873 byte(s)
Make layer's use_mask flag default to true. Support a bit array describing
the mask to use. Improve error handling in ProjectRasterFile (also addresses
RT #2947).

1 bh 2229 # Copyright (c) 2002, 2003, 2004 by Intevation GmbH
2 bh 331 # Authors:
3     # Bernhard Herzog <[email protected]>
4     #
5     # This program is free software under the GPL (>=v2)
6     # Read the file COPYING coming with Thuban for details.
7    
8     """
9     Test the Layer class
10     """
11    
12     __version__ = "$Revision$"
13     # $Source$
14     # $Id$
15    
16     import os
17     import unittest
18    
19 bh 1587 import mockgeo
20 bh 331 import support
21     support.initthuban()
22    
23     import shapelib
24 bh 336 import dbflib
25 bh 331
26 bh 723 from Thuban.Model.session import Session
27 bh 1538 from Thuban.Model.layer import BaseLayer, Layer, RasterLayer
28     from Thuban.Model.data import SHAPETYPE_POLYGON, SHAPETYPE_ARC, SHAPETYPE_POINT
29 bh 331 from Thuban.Model.messages import LAYER_LEGEND_CHANGED, \
30 bh 1142 LAYER_VISIBILITY_CHANGED, LAYER_SHAPESTORE_REPLACED, LAYER_CHANGED
31 bh 1088 from Thuban.Model.table import FIELDTYPE_DOUBLE, FIELDTYPE_STRING, MemoryTable
32 jonathan 947 from Thuban.Model.proj import Projection
33 bh 996 from Thuban.Model.data import DerivedShapeStore
34 bh 1452 from Thuban.Model.classification import Classification, ClassGroupSingleton, \
35     ClassGroupRange
36 jonathan 2551 from Thuban.Model.color import Color
37 bh 331
38 jonathan 1174 import Thuban.Model.resource
39    
40 bh 331 class TestLayer(unittest.TestCase, support.FileTestMixin,
41     support.FloatComparisonMixin):
42    
43     """Test cases for different layer (shape) types"""
44    
45 bh 723 def setUp(self):
46 bh 996 """Create a session self.session and initialize self.layer to None"""
47 bh 723 self.session = Session("Test session for %s" % self.__class__)
48 bh 996 self.layer = None
49 bh 723
50     def tearDown(self):
51 bh 996 """Call the layer's Destroy method and set session and layer to None"""
52 bh 1681 self.session.Destroy()
53 bh 723 self.session = None
54 bh 996 if self.layer is not None:
55     self.layer.Destroy()
56     self.layer = None
57 bh 723
58 jonathan 947 def build_path(self, filename):
59     return os.path.join("..", "Data", "iceland", filename)
60 bh 996
61 bh 839 def open_shapefile(self, filename):
62     """Open and return a shapestore for filename in the iceland data set"""
63 jonathan 947 return self.session.OpenShapefile(self.build_path(filename))
64 bh 839
65 jonathan 947 def test_base_layer(self):
66 bh 996 layer = self.layer = BaseLayer("Test BaseLayer")
67 jonathan 947 self.assertEquals(layer.Title(), "Test BaseLayer")
68     self.failUnless(layer.Visible())
69    
70     # toggle visibility
71     layer.SetVisible(False)
72     self.failIf(layer.Visible())
73    
74     layer.SetVisible(True)
75     self.failUnless(layer.Visible())
76    
77     self.failIf(layer.HasClassification())
78 jonathan 1278 self.failIf(layer.HasShapes())
79    
80 jonathan 947 self.assertEquals(layer.GetProjection(), None)
81    
82     # set/get projection
83 bh 1687 proj = Projection(["proj=utm", "zone=26", "ellps=clrk66"])
84 jonathan 947
85     layer.SetProjection(proj)
86     self.failUnless(layer.GetProjection() is proj)
87    
88     # __init__ with other arguments
89     layer = BaseLayer("Test BaseLayer", False, proj)
90     self.failIf(layer.Visible())
91     self.failUnless(layer.GetProjection() is proj)
92    
93 bh 331 def test_arc_layer(self):
94     """Test Layer with arc shapes"""
95 bh 996 layer = self.layer = Layer("Test Layer",
96     self.open_shapefile("roads-line.shp"))
97 jonathan 1278 self.failUnless(layer.HasClassification())
98     self.failUnless(layer.HasShapes())
99 bh 331 self.assertEquals(layer.ShapeType(), SHAPETYPE_ARC)
100     self.assertEquals(layer.NumShapes(), 839)
101     shape = layer.Shape(32)
102 bh 1551 self.assertPointListEquals(shape.Points(),
103     [[(-15.082174301147461, 66.27738189697265),
104     (-15.026350021362305, 66.27339172363281)]])
105 bh 331 self.assertFloatSeqEqual(layer.BoundingBox(),
106     [-24.450359344482422, 63.426830291748047,
107     -13.55668830871582, 66.520111083984375])
108 bh 1593 shapes = layer.ShapesInRegion((-24.0, 64.0, -23.75, 64.25))
109     self.assertEquals([s.ShapeID() for s in shapes],
110 bh 331 [613, 726, 838])
111 jonathan 832
112     self.assertFloatSeqEqual(layer.ShapesBoundingBox([32]),
113     [-15.082174301147461, 66.27339172363281,
114     -15.026350021362305, 66.27738189697265])
115    
116     shape = layer.Shape(33)
117 bh 1551 self.assertPointListEquals(shape.Points(),
118     [[(-22.24850654602050, 66.30645751953125),
119     (-22.23273086547851, 66.29407501220703),
120     (-22.23158073425293, 66.2876892089843),
121     (-22.24631881713867, 66.27006530761718)]])
122 jonathan 832
123     self.assertFloatSeqEqual(layer.ShapesBoundingBox([32, 33]),
124     [-22.248506546020508, 66.270065307617188,
125     -15.026350021362305, 66.30645751953125])
126    
127     self.assertEquals(layer.ShapesBoundingBox([]), None)
128     self.assertEquals(layer.ShapesBoundingBox(None), None)
129    
130 bh 331 def test_polygon_layer(self):
131     """Test Layer with polygon shapes"""
132 bh 996 layer = self.layer = Layer("Test Layer",
133     self.open_shapefile("political.shp"))
134 jonathan 1278 self.failUnless(layer.HasClassification())
135     self.failUnless(layer.HasShapes())
136 bh 331 self.assertEquals(layer.ShapeType(), SHAPETYPE_POLYGON)
137     self.assertEquals(layer.NumShapes(), 156)
138     shape = layer.Shape(4)
139 bh 1551 self.assertPointListEquals(shape.Points(),
140     [[(-22.40639114379882, 64.714111328125),
141     (-22.41621208190918, 64.7160034179687),
142     (-22.40605163574218, 64.719200134277),
143     (-22.40639114379882, 64.714111328125)]])
144 bh 331 self.assertFloatSeqEqual(layer.BoundingBox(),
145     [-24.546524047851562, 63.286754608154297,
146     -13.495815277099609, 66.563774108886719])
147 bh 1593 shapes = layer.ShapesInRegion((-24.0, 64.0, -23.9, 64.1))
148     self.assertEquals([s.ShapeID() for s in shapes],
149 bh 331 [91, 92, 144, 146, 148, 150, 152, 153])
150    
151     def test_point_layer(self):
152     """Test Layer with point shapes"""
153 bh 996 layer = self.layer = Layer("Test Layer",
154     self.open_shapefile("cultural_landmark-point.shp"))
155 jonathan 1278 self.failUnless(layer.HasClassification())
156     self.failUnless(layer.HasShapes())
157 bh 331 self.assertEquals(layer.ShapeType(), SHAPETYPE_POINT)
158     self.assertEquals(layer.NumShapes(), 34)
159     shape = layer.Shape(0)
160 bh 1551 self.assertPointListEquals(shape.Points(),
161     [[(-22.711074829101562, 66.36572265625)]])
162 bh 331 self.assertFloatSeqEqual(layer.BoundingBox(),
163     [-23.806047439575195, 63.405960083007812,
164     -15.12291431427002, 66.36572265625])
165 bh 1593 shapes = layer.ShapesInRegion((-24.0, 64.0, -23.80, 64.1))
166     self.assertEquals([s.ShapeID() for s in shapes],
167 bh 331 [0, 1, 2, 3, 4, 5, 27, 28, 29, 30, 31])
168    
169 bh 1983 def test_arc_layer_with_projection(self):
170 bh 1587 """Test Layer with point shapes and a projection"""
171     # We use mock data here so that we have precise control over the
172     # values
173     table = MemoryTable([("FOO", FIELDTYPE_STRING)], [("bla",)])
174 bh 1983 store = mockgeo.SimpleShapeStore(SHAPETYPE_ARC,
175 bh 1987 [[[(9884828.7209840547, 5607720.9774499247),
176     (11298336.04640449, 9287823.2044059951)]]],
177 bh 1983 table)
178 bh 1587 layer = self.layer = Layer("Test Layer", store)
179    
180 bh 1987 proj = Projection(["proj=lcc", "lon_0=0", "lat_1=20n", "lat_2=60n",
181     "ellps=clrk66"])
182 bh 1587 layer.SetProjection(proj)
183    
184 bh 1983 self.assertFloatSeqEqual(layer.BoundingBox(),
185 bh 1987 (9884828.7209840547, 5607720.9774499247,
186     11298336.04640449, 9287823.2044059951))
187 bh 1983 self.assertFloatSeqEqual(layer.LatLongBoundingBox(),
188 bh 1987 (90.0, -8.90043373, 120, 11.1616263))
189 bh 1983 shapes = layer.ShapesInRegion((100, -10, 150, +10))
190 bh 1593 self.assertEquals([s.ShapeID() for s in shapes], [0])
191 bh 1983 self.assertFloatSeqEqual(layer.ShapesBoundingBox([0]),
192 bh 1987 (90.0, -8.90043373, 120, 11.1616263))
193 bh 1587
194 silke 2339 self.assertFloatSeqEqual(layer.ClipBoundingBox((-180, -6, 100, +120)),
195 bh 2351 (90.0, -6, 100, 11.1616263))
196 silke 2339 shapes = layer.ShapesInRegion((-180, -170, 200, +120))
197     self.assertEquals([s.ShapeID() for s in shapes],[0])
198    
199 bh 331 def test_empty_layer(self):
200     """Test Layer with empty shape file"""
201     # create an empty shape file
202     shapefilename = self.temp_file_name("layer_empty.shp")
203     shp = shapelib.create(shapefilename, shapelib.SHPT_POLYGON)
204     shp.close()
205 bh 336 # create an empty DBF file too because Thuban can't cope yet
206     # with missing DBF file.
207     dbffilename = self.temp_file_name("layer_empty.dbf")
208     dbf = dbflib.create(dbffilename)
209     dbf.add_field("NAME", dbflib.FTString, 20, 0)
210 bh 1768 dbf.close()
211 bh 331
212 bh 336 # Now try to open it.
213 bh 996 layer = self.layer = Layer("Empty Layer",
214     self.session.OpenShapefile(shapefilename))
215 bh 331 self.assertEquals(layer.BoundingBox(), None)
216     self.assertEquals(layer.LatLongBoundingBox(), None)
217     self.assertEquals(layer.NumShapes(), 0)
218    
219 bh 839 def test_get_field_type(self):
220     """Test Layer.GetFieldType()"""
221 bh 996 layer = self.layer = Layer("Test Layer",
222     self.open_shapefile("roads-line.shp"))
223 bh 839 self.assertEquals(layer.GetFieldType("LENGTH"), FIELDTYPE_DOUBLE)
224     self.assertEquals(layer.GetFieldType("non existing"), None)
225 bh 331
226 jonathan 947 def test_raster_layer(self):
227 jonathan 1174 if not Thuban.Model.resource.has_gdal_support():
228 bh 1555 raise support.SkipTest("No gdal support")
229 jonathan 1174
230 jonathan 947 filename = self.build_path("island.tif")
231     layer = RasterLayer("Test RasterLayer", filename)
232 jonathan 1278 self.failIf(layer.HasClassification())
233     self.failIf(layer.HasShapes())
234 jonathan 2552 self.failUnless(layer.UseMask())
235 bh 1599 self.assertEquals(layer.GetImageFilename(), os.path.abspath(filename))
236 jonathan 947 self.assertFloatSeqEqual(layer.BoundingBox(),
237     [-24.5500000, 63.2833330,
238     -13.4916670, 66.5666670])
239     self.assertFloatSeqEqual(layer.LatLongBoundingBox(),
240     [-24.5500000, 63.2833330,
241     -13.4916670, 66.5666670])
242 bh 839
243 jonathan 2551 info = layer.ImageInfo()
244     self.failIf(info is None)
245     self.failUnless(info.has_key("nBands"))
246     self.failUnless(info.has_key("Size"))
247     self.failUnless(info.has_key("Driver"))
248     self.failUnless(info.has_key("BandData"))
249    
250     self.assertEquals(info["nBands"], 1)
251     self.assertEquals(info["Size"], (5002, 394))
252     self.assertEquals(info["Driver"], "GTiff")
253     self.assertEquals(info["BandData"], [(0.0, 140.0)])
254    
255 bh 996 def test_derived_store(self):
256     """Test layer with derived store"""
257     layer = self.layer = Layer("Test Layer",
258     self.open_shapefile("roads-line.shp"))
259     try:
260     store = layer.ShapeStore()
261     derived = DerivedShapeStore(store, store.Table())
262     layer.SetShapeStore(derived)
263     self.assert_(layer.ShapeStore() is derived)
264 jonathan 1262
265 bh 1538 self.assertEquals(layer.ShapeType(), SHAPETYPE_ARC)
266     self.assertEquals(layer.NumShapes(), 839)
267     shape = layer.Shape(32)
268 bh 1551 self.assertPointListEquals(shape.Points(),
269     [[(-15.082174301147, 66.277381896972),
270     (-15.026350021362, 66.273391723632)]])
271 bh 1538 self.assertFloatSeqEqual(layer.BoundingBox(),
272     [-24.450359344482422, 63.426830291748047,
273     -13.55668830871582, 66.520111083984375])
274 bh 1593 shapes = layer.ShapesInRegion((-24.0, 64.0, -23.75, 64.25))
275     self.assertEquals([s.ShapeID() for s in shapes],
276 bh 1538 [613, 726, 838])
277 jonathan 1262
278 bh 1538 self.assertFloatSeqEqual(layer.ShapesBoundingBox([32]),
279     [-15.082174301147461, 66.27339172363281,
280     -15.026350021362305, 66.27738189697265])
281    
282 bh 996 finally:
283     store = derived = None
284 jonathan 947
285 bh 996
286 bh 1142 class SetShapeStoreTests(unittest.TestCase, support.SubscriberMixin):
287 bh 1088
288     def setUp(self):
289     """Create a layer with a classification as self.layer"""
290 bh 1142 self.clear_messages()
291 bh 1088 self.session = Session("Test session for %s" % self.__class__)
292     self.shapefilename = os.path.join("..", "Data", "iceland",
293     "cultural_landmark-point.dbf")
294     self.store = self.session.OpenShapefile(self.shapefilename)
295     self.layer = Layer("test layer", self.store)
296 jonathan 1438 self.classification = Classification()
297 bh 1088 self.classification.AppendGroup(ClassGroupSingleton("FARM"))
298 bh 1452 self.layer.SetClassificationColumn("CLPTLABEL")
299 bh 1088 self.layer.SetClassification(self.classification)
300 bh 1142 self.layer.UnsetModified()
301     self.layer.Subscribe(LAYER_SHAPESTORE_REPLACED,
302     self.subscribe_with_params,
303     LAYER_SHAPESTORE_REPLACED)
304     self.layer.Subscribe(LAYER_CHANGED,
305     self.subscribe_with_params, LAYER_CHANGED)
306 bh 1088
307     def tearDown(self):
308 bh 1142 self.clear_messages()
309 bh 1088 self.layer.Destroy()
310     self.session.Destroy()
311     self.session = self.layer = self.store = self.classification = None
312    
313     def test_sanity(self):
314 bh 1142 """SetShapeStoreTests sanity check
315    
316     Test the initial state of the test case instances after setUp.
317     """
318 bh 1088 cls = self.layer.GetClassification()
319     self.assert_(cls is self.classification)
320 bh 1452 field = self.layer.GetClassificationColumn()
321 jonathan 1438 self.assertEquals(field, "CLPTLABEL")
322     self.assertEquals(self.layer.GetFieldType(field), FIELDTYPE_STRING)
323 bh 1088 self.assertEquals(self.layer.GetClassification().GetNumGroups(), 1)
324 bh 1142 self.failIf(self.layer.WasModified())
325 bh 1088
326 bh 1142 def test_set_shape_store_modified_flag(self):
327     """Test whether Layer.SetShapeStore() sets the modified flag"""
328     memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
329     [("bla",)] * self.layer.ShapeStore().Table().NumRows())
330     self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
331    
332     self.assert_(self.layer.WasModified())
333    
334 bh 1088 def test_set_shape_store_different_field_name(self):
335     """Test Layer.SetShapeStore() with different column name"""
336     memtable = MemoryTable([("FOO", FIELDTYPE_STRING)],
337     [("bla",)] * self.layer.ShapeStore().Table().NumRows())
338     self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
339     # The classification should contain only the default group now.
340     self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
341 bh 1142 self.check_messages([(self.layer, LAYER_CHANGED),
342     (self.layer, LAYER_SHAPESTORE_REPLACED)])
343 bh 1088
344     def test_set_shape_store_same_field(self):
345     """Test Layer.SetShapeStore() with same column name and type"""
346     memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_STRING)],
347     [("bla",)] * self.layer.ShapeStore().Table().NumRows())
348     self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
349     # The classification should be the same as before
350     self.assert_(self.layer.GetClassification() is self.classification)
351 bh 1142 self.check_messages([(self.layer, LAYER_SHAPESTORE_REPLACED)])
352 bh 1088
353     def test_set_shape_store_same_field_different_type(self):
354     """Test Layer.SetShapeStore() with same column name but different type
355     """
356     memtable = MemoryTable([("CLPTLABEL", FIELDTYPE_DOUBLE)],
357     [(0.0,)] * self.layer.ShapeStore().Table().NumRows())
358     self.layer.SetShapeStore(DerivedShapeStore(self.store, memtable))
359     # The classification should contain only the default group now.
360     self.assertEquals(self.layer.GetClassification().GetNumGroups(), 0)
361 bh 1142 self.check_messages([(self.layer, LAYER_CHANGED),
362     (self.layer, LAYER_SHAPESTORE_REPLACED)])
363 bh 1088
364    
365 bh 1452 class TestLayerModification(unittest.TestCase, support.SubscriberMixin):
366 bh 331
367     """Test cases for Layer method that modify the layer.
368     """
369    
370     def setUp(self):
371 bh 723 """Clear the list of received messages and create a layer and a session
372 bh 331
373 bh 723 The layer is bound to self.layer and the session to self.session.
374 bh 331 """
375     self.clear_messages()
376 bh 723 self.session = Session("Test session for %s" % self.__class__)
377 bh 2229 self.filename = os.path.join("..", "Data", "iceland", "political.shp")
378 bh 331 self.layer = Layer("Test Layer",
379 bh 2229 self.session.OpenShapefile(self.filename))
380 bh 331 self.layer.Subscribe(LAYER_LEGEND_CHANGED, self.subscribe_with_params,
381     LAYER_LEGEND_CHANGED)
382     self.layer.Subscribe(LAYER_VISIBILITY_CHANGED,
383     self.subscribe_with_params,
384     LAYER_VISIBILITY_CHANGED)
385 bh 1452 self.layer.Subscribe(LAYER_CHANGED, self.subscribe_with_params,
386     LAYER_CHANGED)
387 bh 331
388     def tearDown(self):
389     """Clear the list of received messages and explictly destroy self.layer
390     """
391     self.layer.Destroy()
392 bh 723 self.layer = None
393     self.session.Destroy()
394     self.session = None
395 bh 331 self.clear_messages()
396    
397 jonathan 2551 def build_path(self, filename):
398     return os.path.join("..", "Data", "iceland", filename)
399    
400 bh 1452 def test_sanity(self):
401     """TestLayerModification Sanity Checks"""
402 bh 331 # test default settings
403     self.failIf(self.layer.WasModified())
404     self.assertEquals(self.layer.Visible(), 1)
405     # no messages should have been produced
406     self.check_messages([])
407    
408     def test_visibility(self):
409     """Test Layer visibility"""
410     self.layer.SetVisible(0)
411     self.assertEquals(self.layer.Visible(), 0)
412     self.check_messages([(self.layer, LAYER_VISIBILITY_CHANGED)])
413    
414     # currently, modifying the visibility doesn't count as changing
415     # the layer.
416     self.failIf(self.layer.WasModified())
417    
418 bh 1452 def test_set_classification(self):
419     """Test Layer.SetClassification"""
420     classification = Classification()
421     classification.AppendGroup(ClassGroupRange((0.0, 0.1)))
422    
423     self.layer.SetClassification(classification)
424     self.layer.SetClassificationColumn("AREA")
425    
426     self.check_messages([(self.layer, LAYER_CHANGED),
427     (self.layer, LAYER_CHANGED)])
428     self.failUnless(self.layer.WasModified())
429    
430     self.clear_messages()
431     self.layer.UnsetModified()
432    
433     # change only the classification column. This should issue a
434     # LAYER_CHANGED message as well.
435     self.layer.SetClassificationColumn("PERIMETER")
436    
437     self.check_messages([(self.layer, LAYER_CHANGED)])
438     self.failUnless(self.layer.WasModified())
439    
440    
441 bh 2229 def test_tree_info(self):
442     """Test Layer.TreeInfo"""
443     self.assertEquals(self.layer.TreeInfo(),
444     ("Layer 'Test Layer'",
445     ['Filename: %s' % os.path.abspath(self.filename),
446     'Shown',
447     'Shapes: 156',
448     'Extent (lat-lon): (-24.5465, 63.2868, -13.4958, 66.5638)',
449     'Shapetype: Polygon',
450     self.layer.GetClassification()]))
451 bh 331
452 jonathan 2551 def test_raster_layer(self):
453     if not Thuban.Model.resource.has_gdal_support():
454     raise support.SkipTest("No gdal support")
455 bh 331
456 jonathan 2551
457     filename = self.build_path("island.tif")
458     layer = RasterLayer("Test RasterLayer", filename)
459    
460     layer.Subscribe(LAYER_CHANGED, self.subscribe_with_params,
461     LAYER_CHANGED)
462    
463 jonathan 2552 self.failUnless(layer.UseMask())
464    
465     layer.SetUseMask(False)
466 jonathan 2551 self.failIf(layer.UseMask())
467 jonathan 2552 self.check_messages([(layer, LAYER_CHANGED)])
468     self.clear_messages()
469 jonathan 2551
470 jonathan 2552 layer.SetUseMask(False)
471     self.failIf(layer.UseMask())
472     self.check_messages([])
473     self.clear_messages()
474    
475 jonathan 2551 layer.SetUseMask(True)
476     self.failUnless(layer.UseMask())
477     self.check_messages([(layer, LAYER_CHANGED)])
478     self.clear_messages()
479    
480     layer.SetUseMask(True)
481     self.failUnless(layer.UseMask())
482     self.check_messages([])
483     self.clear_messages()
484    
485    
486 bh 331 if __name__ == "__main__":
487 bh 599 support.run_tests()

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26