source: inundation/fit_interpolate/test_fit.py @ 2920

Last change on this file since 2920 was 2897, checked in by duncan, 18 years ago

close to finishing fit, which replaces least squares

File size: 14.2 KB
Line 
1#!/usr/bin/env python
2
3#TEST
4import sys
5import unittest
6from math import sqrt
7
8from Numeric import zeros, take, compress, Float, Int, dot, concatenate, \
9     ArrayType, allclose, array
10
11from fit import *
12from utilities.sparse import Sparse, Sparse_CSR
13from coordinate_transforms.geo_reference import Geo_reference
14from utilities.numerical_tools import ensure_numeric
15from geospatial_data.geospatial_data import Geospatial_data
16
17def distance(x, y):
18    return sqrt( sum( (array(x)-array(y))**2 ))
19
20def linear_function(point):
21    point = array(point)
22    return point[:,0]+point[:,1]
23
24
25class Test_Fit(unittest.TestCase):
26
27    def setUp(self):
28        pass
29
30    def tearDown(self):
31        pass
32
33
34    def test_smooth_attributes_to_mesh(self):
35        a = [0.0, 0.0]
36        b = [0.0, 5.0]
37        c = [5.0, 0.0]
38        points = [a, b, c]
39        triangles = [ [1,0,2] ]   #bac
40
41        d1 = [1.0, 1.0]
42        d2 = [1.0, 3.0]
43        d3 = [3.0,1.0]
44        z1 = 2
45        z2 = 4
46        z3 = 4
47        data_coords = [d1, d2, d3]
48
49        z = [z1, z2, z3]
50        fit = Fit(points, triangles, alpha=0)
51        #print "interp.get_A()", interp.get_A()
52        fit._build_matrix_AtA_Atz(ensure_numeric(data_coords),
53                                  ensure_numeric(z))
54        #print "Atz - from fit", fit.Atz
55        #print "AtA - from fit", fit.AtA.todense()
56        #print "z",z
57
58        assert allclose(fit.Atz, [2.8, 3.6, 3.6], atol=1e-7)
59
60        f = fit.fit()
61       
62        answer = [0, 5., 5.]
63
64        #print "f\n",f
65        #print "answer\n",answer
66
67        assert allclose(f, answer, atol=1e-7)
68
69    def test_smooth_att_to_meshII(self):
70
71        a = [0.0, 0.0]
72        b = [0.0, 5.0]
73        c = [5.0, 0.0]
74        points = [a, b, c]
75        triangles = [ [1,0,2] ]   #bac
76
77        d1 = [1.0, 1.0]
78        d2 = [1.0, 2.0]
79        d3 = [3.0,1.0]
80        data_coords = [d1, d2, d3]
81        z = linear_function(data_coords)
82        #print "z",z
83
84        interp = Fit(points, triangles, alpha=0.0)
85        f = interp.fit(data_coords, z)
86        answer = linear_function(points)
87        #print "f\n",f
88        #print "answer\n",answer
89
90        assert allclose(f, answer)
91
92    def test_smooth_attributes_to_meshIII(self):
93
94        a = [-1.0, 0.0]
95        b = [3.0, 4.0]
96        c = [4.0,1.0]
97        d = [-3.0, 2.0] #3
98        e = [-1.0,-2.0]
99        f = [1.0, -2.0] #5
100
101        vertices = [a, b, c, d,e,f]
102        triangles = [[0,1,3], [1,0,2], [0,4,5], [0,5,2]] #abd bac aef afc
103
104        point_coords = [[-2.0, 2.0],
105                        [-1.0, 1.0],
106                        [0.0,2.0],
107                        [1.0, 1.0],
108                        [2.0, 1.0],
109                        [0.0,0.0],
110                        [1.0, 0.0],
111                        [0.0, -1.0],
112                        [-0.2,-0.5],
113                        [-0.9, -1.5],
114                        [0.5, -1.9],
115                        [3.0,1.0]]
116
117        z = linear_function(point_coords)
118        interp = Fit(vertices, triangles,
119                                alpha=0.0)
120
121        #print 'z',z
122        f = interp.fit(point_coords,z)
123        answer = linear_function(vertices)
124        #print "f\n",f
125        #print "answer\n",answer
126        assert allclose(f, answer)
127
128   
129    def test_smooth_attributes_to_meshIV(self):
130        """ Testing 2 attributes smoothed to the mesh
131        """
132
133        a = [0.0, 0.0]
134        b = [0.0, 5.0]
135        c = [5.0, 0.0]
136        points = [a, b, c]
137        triangles = [ [1,0,2] ]   #bac
138
139        d1 = [1.0, 1.0]
140        d2 = [1.0, 3.0]
141        d3 = [3.0, 1.0]
142        z1 = [2, 4]
143        z2 = [4, 8]
144        z3 = [4, 8]
145        data_coords = [d1, d2, d3]
146
147        z = [z1, z2, z3]
148        fit = Fit(points, triangles, alpha=0)
149       
150        f =  fit.fit(data_coords,z)
151        answer = [[0,0], [5., 10.], [5., 10.]]
152        assert allclose(f, answer)
153
154    def test_smooth_attributes_to_mesh_build_fit_subset(self):
155
156        a = [-1.0, 0.0]
157        b = [3.0, 4.0]
158        c = [4.0,1.0]
159        d = [-3.0, 2.0] #3
160        e = [-1.0,-2.0]
161        f = [1.0, -2.0] #5
162
163        vertices = [a, b, c, d,e,f]
164        triangles = [[0,1,3], [1,0,2], [0,4,5], [0,5,2]] #abd bac aef afc
165
166        interp = Fit(vertices, triangles,
167                                alpha=0.0)
168
169        point_coords = [[-2.0, 2.0],
170                        [-1.0, 1.0],
171                        [0.0,2.0],
172                        [1.0, 1.0],
173                       ]
174
175        z = linear_function(point_coords)
176
177        f = interp.build_fit_subset(point_coords,z)
178       
179        point_coords = [
180                        [2.0, 1.0],
181                        [0.0,0.0],
182                        [1.0, 0.0],
183                        [0.0, -1.0],
184                        [-0.2,-0.5],
185                        [-0.9, -1.5],
186                        [0.5, -1.9],
187                        [3.0,1.0]]
188       
189        z = linear_function(point_coords)
190
191        f = interp.build_fit_subset(point_coords,z)
192       
193        #print 'z',z
194        f = interp.fit()
195        answer = linear_function(vertices)
196        #print "f\n",f
197        #print "answer\n",answer
198        assert allclose(f, answer)
199
200    def test_fit_and_interpolation(self):
201        from mesh import Mesh
202
203        a = [0.0, 0.0]
204        b = [0.0, 2.0]
205        c = [2.0, 0.0]
206        d = [0.0, 4.0]
207        e = [2.0, 2.0]
208        f = [4.0, 0.0]
209
210        points = [a, b, c, d, e, f]
211        #bac, bce, ecf, dbe, daf, dae
212        triangles = [[1,0,2], [1,2,4], [4,2,5], [3,1,4]]
213
214        #Get (enough) datapoints
215        data_points = [[ 0.66666667, 0.66666667],
216                       [ 1.33333333, 1.33333333],
217                       [ 2.66666667, 0.66666667],
218                       [ 0.66666667, 2.66666667],
219                       [ 0.0, 1.0],
220                       [ 0.0, 3.0],
221                       [ 1.0, 0.0],
222                       [ 1.0, 1.0],
223                       [ 1.0, 2.0],
224                       [ 1.0, 3.0],
225                       [ 2.0, 1.0],
226                       [ 3.0, 0.0],
227                       [ 3.0, 1.0]]
228
229        z = linear_function(data_points)
230        interp = Fit(points, triangles,
231                                alpha=0.0)
232
233        answer = linear_function(points)
234
235        f = interp.fit(data_points, z)
236
237        #print "f",f
238        #print "answer",answer
239        assert allclose(f, answer)
240
241       
242    def test_smoothing_and_interpolation(self):
243
244        a = [0.0, 0.0]
245        b = [0.0, 2.0]
246        c = [2.0, 0.0]
247        d = [0.0, 4.0]
248        e = [2.0, 2.0]
249        f = [4.0, 0.0]
250
251        points = [a, b, c, d, e, f]
252        #bac, bce, ecf, dbe, daf, dae
253        triangles = [[1,0,2], [1,2,4], [4,2,5], [3,1,4]]
254
255        #Get (too few!) datapoints
256        data_points = [[ 0.66666667, 0.66666667],
257                       [ 1.33333333, 1.33333333],
258                       [ 2.66666667, 0.66666667],
259                       [ 0.66666667, 2.66666667]]
260
261        z = linear_function(data_points)
262        answer = linear_function(points)
263
264        #Make interpolator with too few data points and no smoothing
265        interp = Fit(points, triangles, alpha=0.0)
266        #Must raise an exception
267        try:
268            f = interp.fit(data_points,z)
269        except ToFewPointsError:
270            pass
271
272        #Now try with smoothing parameter
273        interp = Fit(points, triangles, alpha=1.0e-13)
274
275        f = interp.fit(data_points,z)
276        #f will be different from answer due to smoothing
277        assert allclose(f, answer,atol=5)
278
279
280    #Tests of smoothing matrix
281    def test_smoothing_matrix_one_triangle(self):
282        from Numeric import dot
283        a = [0.0, 0.0]
284        b = [0.0, 2.0]
285        c = [2.0,0.0]
286        points = [a, b, c]
287
288        vertices = [ [1,0,2] ]   #bac
289
290        interp = Fit(points, vertices)
291
292        assert allclose(interp.get_D(), [[1, -0.5, -0.5],
293                                   [-0.5, 0.5, 0],
294                                   [-0.5, 0, 0.5]])
295
296        #Define f(x,y) = x
297        f = array([0,0,2]) #Value at global vertex 2
298
299        #Check that int (df/dx)**2 + (df/dy)**2 dx dy =
300        #           int 1 dx dy = area = 2
301        assert dot(dot(f, interp.get_D()), f) == 2
302
303        #Define f(x,y) = y
304        f = array([0,2,0])  #Value at global vertex 1
305
306        #Check that int (df/dx)**2 + (df/dy)**2 dx dy =
307        #           int 1 dx dy = area = 2
308        assert dot(dot(f, interp.get_D()), f) == 2
309
310        #Define f(x,y) = x+y
311        f = array([0,2,2])  #Values at global vertex 1 and 2
312
313        #Check that int (df/dx)**2 + (df/dy)**2 dx dy =
314        #           int 2 dx dy = 2*area = 4
315        assert dot(dot(f, interp.get_D()), f) == 4
316
317
318    def test_smoothing_matrix_more_triangles(self):
319        from Numeric import dot
320
321        a = [0.0, 0.0]
322        b = [0.0, 2.0]
323        c = [2.0,0.0]
324        d = [0.0, 4.0]
325        e = [2.0, 2.0]
326        f = [4.0,0.0]
327
328        points = [a, b, c, d, e, f]
329        #bac, bce, ecf, dbe, daf, dae
330        vertices = [ [1,0,2], [1,2,4], [4,2,5], [3,1,4]]
331
332        interp = Fit(points, vertices)
333
334
335        #assert allclose(interp.get_D(), [[1, -0.5, -0.5],
336        #                           [-0.5, 0.5, 0],
337        #                           [-0.5, 0, 0.5]])
338
339        #Define f(x,y) = x
340        f = array([0,0,2,0,2,4]) #f evaluated at points a-f
341
342        #Check that int (df/dx)**2 + (df/dy)**2 dx dy =
343        #           int 1 dx dy = total area = 8
344        assert dot(dot(f, interp.get_D()), f) == 8
345
346        #Define f(x,y) = y
347        f = array([0,2,0,4,2,0]) #f evaluated at points a-f
348
349        #Check that int (df/dx)**2 + (df/dy)**2 dx dy =
350        #           int 1 dx dy = area = 8
351        assert dot(dot(f, interp.get_D()), f) == 8
352
353        #Define f(x,y) = x+y
354        f = array([0,2,2,4,4,4])  #f evaluated at points a-f
355
356        #Check that int (df/dx)**2 + (df/dy)**2 dx dy =
357        #           int 2 dx dy = 2*area = 16
358        assert dot(dot(f, interp.get_D()), f) == 16
359
360
361
362    def test_fit_and_interpolation_with_different_origins(self):
363        """Fit a surface to one set of points. Then interpolate that surface
364        using another set of points.
365        This test tests situtaion where points and mesh belong to a different
366        coordinate system as defined by origin.
367        """
368        from mesh import Mesh
369
370        #Setup mesh used to represent fitted function
371        a = [0.0, 0.0]
372        b = [0.0, 2.0]
373        c = [2.0, 0.0]
374        d = [0.0, 4.0]
375        e = [2.0, 2.0]
376        f = [4.0, 0.0]
377
378        points = [a, b, c, d, e, f]
379        #bac, bce, ecf, dbe, daf, dae
380        triangles = [[1,0,2], [1,2,4], [4,2,5], [3,1,4]]
381
382        #Datapoints to fit from
383        data_points1 = [[ 0.66666667, 0.66666667],
384                        [ 1.33333333, 1.33333333],
385                        [ 2.66666667, 0.66666667],
386                        [ 0.66666667, 2.66666667],
387                        [ 0.0, 1.0],
388                        [ 0.0, 3.0],
389                        [ 1.0, 0.0],
390                        [ 1.0, 1.0],
391                        [ 1.0, 2.0],
392                        [ 1.0, 3.0],
393                        [ 2.0, 1.0],
394                        [ 3.0, 0.0],
395                        [ 3.0, 1.0]]
396
397
398        #First check that things are OK when using same origin
399        mesh_origin = (56, 290000, 618000) #zone, easting, northing
400        data_origin = (56, 290000, 618000) #zone, easting, northing
401
402
403        #Fit surface to mesh
404        interp = Fit(points, triangles, 
405                               alpha=0.0,
406                               mesh_origin = mesh_origin)
407
408        data_geo_spatial = Geospatial_data(data_points1,
409                         geo_reference = Geo_reference(56, 290000, 618000))
410        z = linear_function(data_points1) #Example z-values
411        f = interp.fit(data_geo_spatial, z)   #Fitted values at vertices
412
413        #Shift datapoints according to new origins
414        for k in range(len(data_points1)):
415            data_points1[k][0] += mesh_origin[1] - data_origin[1]
416            data_points1[k][1] += mesh_origin[2] - data_origin[2]
417
418
419
420        #Fit surface to mesh
421        interp = Fit(points, triangles, 
422                               alpha=0.0) #,
423                               # mesh_origin = mesh_origin)
424
425        f1 = interp.fit(data_points1,z) #Fitted values at vertices (using same z as before)
426
427        assert allclose(f,f1), 'Fit should have been unaltered'
428
429
430    def test_smooth_attributes_to_mesh_function(self):
431        """ Testing 2 attributes smoothed to the mesh
432        """
433
434        a = [0.0, 0.0]
435        b = [0.0, 5.0]
436        c = [5.0, 0.0]
437        points = [a, b, c]
438        triangles = [ [1,0,2] ]   #bac
439
440        d1 = [1.0, 1.0]
441        d2 = [1.0, 3.0]
442        d3 = [3.0, 1.0]
443        z1 = [2, 4]
444        z2 = [4, 8]
445        z3 = [4, 8]
446        data_coords = [d1, d2, d3]
447        z = [z1, z2, z3]
448
449        f = fit_to_mesh(points, triangles, data_coords, z, alpha=0.0)
450        answer = [[0, 0], [5., 10.], [5., 10.]]
451
452        assert allclose(f, answer)
453
454    def test_fit_to_mesh_w_georef(self):
455        """Simple check that georef works at the fit_to_mesh level
456        """
457       
458        from coordinate_transforms.geo_reference import Geo_reference
459
460        #Mesh
461        vertex_coordinates = [[0.76, 0.76],
462                              [0.76, 5.76],
463                              [5.76, 0.76]]
464        triangles = [[0,2,1]]
465
466        mesh_geo = Geo_reference(56,-0.76,-0.76)
467        #print "mesh_geo.get_absolute(vertex_coordinates)", \
468         #     mesh_geo.get_absolute(vertex_coordinates)
469
470        #Data                       
471        data_points = [[ 201.0, 401.0],
472                       [ 201.0, 403.0],
473                       [ 203.0, 401.0]]
474
475        z = [2, 4, 4]
476       
477        data_geo = Geo_reference(56,-200,-400)
478
479        #print "data_geo.get_absolute(data_points)", \
480        #      data_geo.get_absolute(data_points)
481       
482        #Fit
483        zz = fit_to_mesh(vertex_coordinates, triangles, data_points, z,
484                         data_origin = data_geo.get_origin(),
485                         mesh_origin = mesh_geo.get_origin(),
486                         alpha = 0)
487        assert allclose( zz, [0,5,5] )
488
489
490
491#-------------------------------------------------------------
492if __name__ == "__main__":
493    suite = unittest.makeSuite(Test_Fit,'test')
494    #suite = unittest.makeSuite(Test_Fit,'test_smoothing_and_interpolation')
495    #suite = unittest.makeSuite(Test_Fit,'test_smooth_attributes_to_mesh_one_point')
496    runner = unittest.TextTestRunner(verbosity=1)
497    runner.run(suite)
498
499
500
501
502
Note: See TracBrowser for help on using the repository browser.