Changeset 9219
- Timestamp:
- Jun 25, 2014, 4:55:20 PM (10 years ago)
- Location:
- trunk/anuga_core/source/anuga/utilities
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/anuga_core/source/anuga/utilities/quantity_setting_functions.py
r9202 r9219 78 78 Make a 'composite function' to set quantities -- applies different functions inside different polygon regions. 79 79 80 fun_poly_pairs = [ [f0, p0], [f1, p1], ...] where fi is a function and pi is a polygon, or None, or 'All' 80 fun_poly_pairs = [ [f0, p0], [f1, p1], ...] 81 where fi is a function, or a constant, or the name of a gdal-compatible rasterFile; 82 and pi is a polygon, or None, or 'All' (or it can be 'Extent' in the case that fi is a rasterFile name) 81 83 82 84 IMPORTANT: When polygons overlap, the first elements of the list are given priority. … … 90 92 fun_poly_pairs = [ [f0, p0], [f1, p1], ...] 91 93 92 where fi(x,y) are functions returning quantity values at points, and 93 pi are polygons where we want to use fi inside 94 where fi(x,y) are functions returning quantity values at 95 points, or constants in which case points in the polygon are set to that 96 value, or (string) rasterFile names which can be passed to quantityRasterFun to make a function 97 98 and pi are polygons where we want to use fi inside 94 99 95 100 If any pi = 'All', then we assume that ALL unset points are set 96 97 101 using the function. This CAN ONLY happen in the last [fi,pi] pair where pi is 102 not None (since fi will be applied to all remaining points -- so anything else is probably an input mistake) 98 103 99 104 If any pi = None, then that [fi,pi] pair is skipped 100 105 106 if pi='Extent' and fi is the name of a raster file, then the 107 extent of the raster file is used to define the polygon 108 101 109 domain = ANUGA domain object 102 110 … … 105 113 domain.set_quantity('elevation', F) 106 114 """ 115 import os 107 116 import scipy 108 117 from matplotlib import path … … 136 145 fi = fun_poly_pairs[i][0] # The function 137 146 pi = fun_poly_pairs[i][1] # The polygon 147 148 # Quick exit 149 if(pi is None): 150 continue 151 138 152 # Get a 'true/false' flag for whether the point is in pi, and not set 139 153 if(pi is 'All'): 140 154 fInside=(1-isSet) 141 elif(pi is None):142 continue143 155 else: 144 # Try matplotlib -- make the path a matplotlib path object 145 pi_path=path.Path(scipy.array(pi)) 156 if(pi is 'Extent' and type(fi) is str and os.path.exists(fi)): 157 # Here fi MUST be a gdal-compatible raster 158 # Then we get the extent from the raster itself 159 import anuga.utilities.spatialInputUtil as su 160 newpi=su.getRasterExtent(fi,asPolygon=True) 161 pi_path=path.Path(scipy.array(newpi)) 162 else: 163 # Try matplotlib -- make the path a matplotlib path object 164 pi_path=path.Path(scipy.array(pi)) 165 146 166 fInside=xy_array_trans[:,0]*0. 147 167 for j in range(len(fInside)): … … 153 173 fInds=(fInside==1.).nonzero()[0] 154 174 if(len(fInds)>0): 155 quantityVal[fInds] = fi(x[fInds], y[fInds]) 175 if(hasattr(fi,'__call__')): 176 # fi is a function 177 quantityVal[fInds] = fi(x[fInds], y[fInds]) 178 elif isinstance(fi, (int, long, float)): 179 # fi is a numerical constant 180 quantityVal[fInds]=fi*1.0 181 elif ( type(fi) is str and os.path.exists(fi)): 182 # fi is a file which is assumed to be 183 # a gdal-compatible raster 184 newfi = quantityRasterFun(domain, fi) 185 quantityVal[fInds] = newfi(x[fInds], y[fInds]) 186 156 187 isSet[fInds]=1 157 188 … … 191 222 ################################################################################# 192 223 193 def elevation_from_Pt_Pol_Data_and_Raster(Pt_Pol_Data, elevation_raster, domain): 194 """ 195 Function to make a function F(x,y) which returns the elevation on elevation_raster, 196 except if x,y is inside the polygon associated with any element of Pt_Pol_Data, 197 in which case a Pt_Pol_-specific nearest neighbour interpolator is used. 224 def quantity_from_Pt_Pol_Data_and_Raster(Pt_Pol_Data, quantity_raster, domain): 225 """ 226 Function to make a function F(x,y) which returns the corresponding 227 values on quantity_raster, except if x,y is inside the polygon associated with 228 any element of Pt_Pol_Data, in which case a Pt_Pol_-specific nearest neighbour 229 interpolator is used. 198 230 199 231 INPUT: … … 201 233 [ Polygon_1, Pt_XYZ_1], 202 234 ... ] 203 elevation_raster = A GDAL-compatible elevation raster 235 Here Polygon_i is a polygon in ANUGA format, 236 and Pt_XYZ_i is a 3 column array of x,y,Value points 237 quantity_raster = A GDAL-compatible quantity raster 204 238 domain = ANUGA domain 205 239 """ 206 240 207 # Function to set elevationfrom raster208 elevFun1=quantityRasterFun(domain, rasterFile=elevation_raster)209 210 # List of function/polygon pairs defining the Pt_Pol_ elevationdata211 elevFunChanList=[]241 # Function to set quantity from raster 242 qFun1=quantityRasterFun(domain, rasterFile=quantity_raster) 243 244 # List of function/polygon pairs defining the Pt_Pol_ quantity data 245 qFunChanList=[] 212 246 for i in range(len(Pt_Pol_Data)): 213 elevFunChanList.append([247 qFunChanList.append([ 214 248 make_nearestNeighbour_quantity_function(Pt_Pol_Data[i][1], domain), 215 249 Pt_Pol_Data[i][0] … … 217 251 218 252 # 219 elevFun=composite_quantity_setting_function(elevFunChanList+[[elevFun1, 'All']], domain)220 221 return elevFun253 qFun=composite_quantity_setting_function(qFunChanList+[[qFun1, 'All']], domain) 254 255 return qFun -
trunk/anuga_core/source/anuga/utilities/spatialInputUtil.py
r9212 r9219 502 502 else: 503 503 return [L1, L2] 504 504 505 ########################################################### 506 def getRasterExtent(rasterFile, asPolygon=False): 507 """ 508 Sometimes we need to know the extent of a raster 509 i.e. the minimum x, maximum x, minimum y, and maximum y values 510 511 INPUT: 512 rasterFile -- a gdal compatible rasterfile 513 asPolygon -- if False, return [xmin,xmax,ymin,ymax]. 514 If True, return [ [xmin,ymin],[xmax,ymin],[xmax,ymax],[xmin,ymax]] 515 OUTPUT 516 The extent as defined above 517 518 """ 519 raster = gdal.Open(rasterFile) 520 transform=raster.GetGeoTransform() 521 xOrigin = transform[0] 522 yOrigin = transform[3] 523 xPixels=raster.RasterXSize 524 yPixels=raster.RasterYSize 525 526 # Compute the other extreme corner 527 x2=xOrigin + xPixels*transform[1]+yPixels*transform[2] 528 y2=yOrigin + xPixels*transform[4]+yPixels*transform[5] 529 530 xmin=min(xOrigin,x2) 531 xmax=max(xOrigin,x2) 532 533 ymin=min(yOrigin,y2) 534 ymax=max(yOrigin,y2) 535 536 if(asPolygon): 537 return [ [xmin,ymin], [xmax,ymin], [xmax,ymax], [xmin,ymax]] 538 else: 539 return [xmin,xmax,ymin,ymax] 540 541 505 542 ########################################################### 506 543 def rasterValuesAtPoints(xy, rasterFile, band=1): … … 548 585 print 'You might need to edit this code to read the data type' 549 586 raise Exception, 'Stopping' 550 587 588 # Upper bounds for pixel values, so we can fail gracefully 589 xMax=raster.RasterXSize 590 yMax=raster.RasterYSize 591 if(px.max()<xMax and px.min()>=0 and py.max()<yMax and py.min()>=0): 592 pass 593 else: 594 raise Exception, 'Trying to extract point values that exceed the raster extent' 595 551 596 # Get values -- seems we have to loop, but it is efficient enough 552 597 for i in range(len(px)): -
trunk/anuga_core/source/anuga/utilities/test_quantity_setting_functions.py
r9202 r9219 140 140 return 141 141 142 def test_elevation_from_Pt_Pol_Data_and_Raster(self): 143 # 144 # 145 # 142 def test_composite_quantity_setting_function(self): 143 # Test the composite_quantity_setting_function 144 146 145 domain=self.create_domain(1.0, 0.0) 147 148 # Evolve the model 149 #for t in domain.evolve(yieldstep=0.2, finaltime=1.0): 150 # pass 151 146 152 147 # Make a raster from the elevation data 153 148 from anuga.utilities import plot_utils as util … … 162 157 # Make a polygon-point pair which we use to set elevation in a 'channel' 163 158 trenchPoly=[[minX+40., minY], [minX+40., minY+100.], [minX+60., minY+100.], [minX+60., minY]] 159 160 ################################################################# 161 162 # This example uses a constant, and a raster, to set the quantity 163 F=qs.composite_quantity_setting_function([[-1000., trenchPoly], ['PointData_ElevTest.tif', 'Extent']],\ 164 domain) 165 166 # Points where we test the function 167 testPts_X=numpy.array([50., 3.]) 168 testPts_Y=numpy.array([1., 20.]) 169 fitted=F(testPts_X,testPts_Y) 170 171 # The fitted value in the trench should be -1000. 172 assert(fitted[0]==-1000.) 173 174 # Find the nearest domain point to the second test point 175 # This will have been used in constructing the elevation raster 176 nearest=((domain.centroid_coordinates[:,0]-3.)**2 + (domain.centroid_coordinates[:,1]-20.)**2).argmin() 177 nearest_x=domain.centroid_coordinates[nearest,0] 178 assert(numpy.allclose(fitted[1],-nearest_x/150.)) 179 180 ######################################################################### 181 182 # This example uses a function, and a raster, to set the quantity 183 def f0(x,y): 184 return x/10. 185 F=qs.composite_quantity_setting_function([[f0, trenchPoly], ['PointData_ElevTest.tif', 'Extent']],\ 186 domain) 187 fitted=F(testPts_X,testPts_Y) 188 # Now the fitted value in the trench should be determined by f0 189 assert(numpy.allclose(fitted[0],50./10.)) 190 # The second test point should be as before 191 nearest=((domain.centroid_coordinates[:,0]-3.)**2 + (domain.centroid_coordinates[:,1]-20.)**2).argmin() 192 nearest_x=domain.centroid_coordinates[nearest,0] 193 assert(numpy.allclose(fitted[1],-nearest_x/150.)) 194 195 ########################################################################## 196 197 # This example uses 'All' as a polygon 198 F=qs.composite_quantity_setting_function([[f0, 'All'], ['PointData_ElevTest.tif', None]],\ 199 domain) 200 fitted=F(testPts_X,testPts_Y) 201 # Now the fitted value in the trench should be determined by f0 202 assert(numpy.allclose(fitted[0],50./10.)) 203 assert(numpy.allclose(fitted[1],3./10.)) 204 205 ########################################################################### 206 # This example should fail 207 try: 208 F=qs.composite_quantity_setting_function([[f0, 'All'], ['PointData_ElevTest.tif', 'All']],\ 209 domain) 210 raise Exception, 'The last command should fail' 211 except: 212 assert True 213 214 return 215 216 def test_quantity_from_Pt_Pol_Data_and_Raster(self): 217 # 218 # 219 # 220 domain=self.create_domain(1.0, 0.0) 221 222 # Evolve the model 223 #for t in domain.evolve(yieldstep=0.2, finaltime=1.0): 224 # pass 225 226 # Make a raster from the elevation data 227 from anuga.utilities import plot_utils as util 228 xs=domain.centroid_coordinates[:,0]+domain.geo_reference.xllcorner 229 ys=domain.centroid_coordinates[:,1]+domain.geo_reference.yllcorner 230 elev=domain.quantities['elevation'].centroid_values 231 232 allDat=numpy.vstack([xs,ys,elev]).transpose() 233 util.Make_Geotif(allDat, output_quantities=['ElevTest'], EPSG_CODE=32756, 234 output_dir='.', CellSize=1.) 235 236 # Make a polygon-point pair which we use to set elevation in a 'channel' 237 trenchPoly=[[minX+40., minY], [minX+40., minY+100.], [minX+60., minY+100.], [minX+60., minY]] 164 238 trenchPts=numpy.array([minX+50., minY+50., -1000.]) 165 239 # 166 240 PtPolData=[[trenchPoly, trenchPts]] 167 F=qs. elevation_from_Pt_Pol_Data_and_Raster(PtPolData, 'PointData_ElevTest.tif', domain)241 F=qs.quantity_from_Pt_Pol_Data_and_Raster(PtPolData, 'PointData_ElevTest.tif', domain) 168 242 169 243 testPts_X=numpy.array([50., 3.]) -
trunk/anuga_core/source/anuga/utilities/test_spatialInputUtil.py
r9212 r9219 29 29 def tearDown(self): 30 30 pass 31 32 def make_me_a_tif(self): 33 # We need to make a .tif to test some functions 34 # This does the job 35 # 36 from anuga.utilities import plot_utils as util 37 # 38 # Do it with Make_Geotif 39 # Pick a domain that makes sense in EPSG:32756 40 x=numpy.linspace(307000., 307100., 101) 41 y=numpy.linspace(6193000., 6193100., 101) 42 xG,yG=numpy.meshgrid(x, y) 43 xG=xG.flatten() 44 yG=yG.flatten() 45 # Surface is z=x+y 46 fakeZ=xG-min(xG)+yG -min(yG) 47 dataToGrid=numpy.vstack([xG,yG,fakeZ]).transpose() 48 # 49 util.Make_Geotif(dataToGrid, output_quantities=['TestData'], 50 EPSG_CODE=32756, output_dir='.',CellSize=1.0) 31 51 32 52 def test_compute_square_distance_to_segment(self): … … 281 301 assert(all(pip[:,0]+pip[:,1]>=10.)) 282 302 303 304 def test_getRasterExtent(self): 305 self.make_me_a_tif() 306 307 extentOut=su.getRasterExtent('PointData_TestData.tif') 308 assert(numpy.allclose(extentOut[0], 307000.-0.5)) 309 assert(numpy.allclose(extentOut[1], 307100.+0.5)) 310 assert(numpy.allclose(extentOut[2], 6193000.-0.5)) 311 assert(numpy.allclose(extentOut[3], 6193100.+0.5)) 312 313 extentOut=su.getRasterExtent('PointData_TestData.tif',asPolygon=True) 314 assert(numpy.allclose(extentOut[0][0], 307000.-0.5)) 315 assert(numpy.allclose(extentOut[3][0], 307000.-0.5)) 316 assert(numpy.allclose(extentOut[1][0], 307100.+0.5)) 317 assert(numpy.allclose(extentOut[2][0], 307100.+0.5)) 318 assert(numpy.allclose(extentOut[0][1], 6193000.-0.5)) 319 assert(numpy.allclose(extentOut[1][1], 6193000.-0.5)) 320 assert(numpy.allclose(extentOut[2][1], 6193100.+0.5)) 321 assert(numpy.allclose(extentOut[3][1], 6193100.+0.5)) 322 283 323 def test_rasterValuesAtPoints(self): 284 324 # We need to make a .tif to test this function. 285 from anuga.utilities import plot_utils as util 286 # Do it with Make_Geotif 287 # Pick a domain that makes sense in EPSG:32756 288 x=numpy.linspace(307000., 307100., 101) 289 y=numpy.linspace(6193000., 6193100., 101) 290 xG,yG=numpy.meshgrid(x, y) 291 xG=xG.flatten() 292 yG=yG.flatten() 293 # Surface is z=x+y 294 fakeZ=xG-min(xG)+yG -min(yG) 295 dataToGrid=numpy.vstack([xG,yG,fakeZ]).transpose() 296 297 util.Make_Geotif(dataToGrid, output_quantities=['TestData'], 298 EPSG_CODE=32756, output_dir='.',CellSize=1.0) 299 325 self.make_me_a_tif() 326 327 # Get the range of the tif 328 tifRange=su.getRasterExtent('PointData_TestData.tif') 300 329 301 330 # Now try to get some point values -- note they will be rounded to the 302 331 # nearest cell 303 xA=numpy.array([0., 10.3, 50.9, 100.])+ x.min()304 yA=numpy.array([0., 20.1, 75.1, 100.])+ y.min()305 z_predicted=numpy.round(xA)+numpy.round(yA)- x.min()-y.min()332 xA=numpy.array([0., 10.3, 50.9, 100.])+tifRange[0]+0.5 333 yA=numpy.array([0., 20.1, 75.1, 100.])+tifRange[2]+0.5 334 z_predicted=numpy.round(xA)+numpy.round(yA)-tifRange[0]-tifRange[2]-1.0 306 335 InDat=numpy.vstack([xA,yA]).transpose() 307 336 z_fitted=su.rasterValuesAtPoints(InDat, rasterFile='PointData_TestData.tif')
Note: See TracChangeset
for help on using the changeset viewer.