source: grass-addons/grass7/vector/v.flexure/v.flexure.py

Last change on this file was 73971, checked in by neteler, 6 years ago

vector addons: Python3 compatibility changes, using 2to3 from python-tools

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-python
File size: 9.0 KB
Line 
1#!/usr/bin/env python
2############################################################################
3#
4# MODULE: v.flexure
5#
6# AUTHOR(S): Andrew Wickert
7#
8# PURPOSE: Calculate flexure of the lithosphere under a specified
9# set of loads and with a given elastic thickness (scalar)
10#
11# COPYRIGHT: (c) 2014, 2015 Andrew Wickert
12#
13# This program is free software under the GNU General Public
14# License (>=v2). Read the file COPYING that comes with GRASS
15# for details.
16#
17#############################################################################
18#
19# REQUIREMENTS:
20# - gFlex: http://csdms.colorado.edu/wiki/gFlex
21# (should be downloaded automatically along with the module)
22# github repository: https://github.com/awickert/gFlex
23
24# More information
25# Started 20 Jan 2015 to add GRASS GIS support for distributed point loads
26# and their effects on lithospheric flexure
27
28#%module
29#% description: Lithospheric flexure: gridded deflections from scattered point loads
30#% keyword: vector
31#% keyword: geophysics
32#%end
33
34#%option G_OPT_V_INPUT
35#% key: input
36#% description: Vector map of loads (thickness * area * density * g) [N]
37#% guidependency: layer,column
38#%end
39
40#%option G_OPT_V_FIELD
41#% key: layer
42#% description: Layer containing load values
43#% guidependency: column
44#%end
45
46#%option G_OPT_DB_COLUMNS
47#% key: column
48#% description: Column containing load values [N]
49#% required : yes
50#%end
51
52#%option
53#% key: te
54#% type: double
55#% description: Elastic thicnkess: scalar; unis chosen in "te_units"
56#% required : yes
57#%end
58
59#%option
60#% key: te_units
61#% type: string
62#% description: Units for elastic thickness
63#% options: m, km
64#% required : yes
65#%end
66
67#%option G_OPT_V_OUTPUT
68#% key: output
69#% description: Output vector points map of vertical deflections [m]
70#% required : yes
71#%end
72
73#%option G_OPT_R_OUTPUT
74#% key: raster_output
75#% description: Output raster map of vertical deflections [m]
76#% required : no
77#%end
78
79#%option
80#% key: g
81#% type: double
82#% description: gravitational acceleration at surface [m/s^2]
83#% answer: 9.8
84#% required : no
85#%end
86
87#%option
88#% key: ym
89#% type: double
90#% description: Young's Modulus [Pa]
91#% answer: 65E9
92#% required : no
93#%end
94
95#%option
96#% key: nu
97#% type: double
98#% description: Poisson's ratio
99#% answer: 0.25
100#% required : no
101#%end
102
103#%option
104#% key: rho_fill
105#% type: double
106#% description: Density of material that fills flexural depressions [kg/m^3]
107#% answer: 0
108#% required : no
109#%end
110
111#%option
112#% key: rho_m
113#% type: double
114#% description: Mantle density [kg/m^3]
115#% answer: 3300
116#% required : no
117#%end
118
119
120##################
121# IMPORT MODULES #
122##################
123
124# PYTHON
125import numpy as np
126# GRASS
127import grass.script as grass
128from grass.pygrass import vector
129
130
131####################
132# UTILITY FUNCTION #
133####################
134
135def get_points_xy(vect_name):
136 """
137 to find x and y using pygrass, see my (A. Wickert's) StackOverflow answer:
138 http://gis.stackexchange.com/questions/28061/how-to-access-vector-coordinates-in-grass-gis-from-python
139 """
140 points = vector.VectorTopo(vect_name)
141 points.open('r')
142 coords = []
143 for i in range(len(points)):
144 coords.append(points.read(i+1).coords())
145 coords = np.array(coords)
146 return coords[:,0], coords[:,1] # x, y
147
148
149############################
150# PASS VARIABLES AND SOLVE #
151############################
152
153def main():
154 """
155 Superposition of analytical solutions in gFlex for flexural isostasy in
156 GRASS GIS
157 """
158
159 options, flags = grass.parser()
160 # if just interface description is requested, it will not get to this point
161 # so gflex will not be needed
162
163 # GFLEX
164 # try to import gflex only after we know that
165 # we will actually do the computation
166 try:
167 import gflex
168 except:
169 print("")
170 print("MODULE IMPORT ERROR.")
171 print("In order to run r.flexure or g.flexure, you must download and install")
172 print("gFlex. The most recent development version is available from")
173 print("https://github.com/awickert/gFlex")
174 print("Installation instructions are available on the page.")
175 grass.fatal("Software dependency must be installed.")
176
177 ##########
178 # SET-UP #
179 ##########
180
181 # This code is for 2D flexural isostasy
182 flex = gflex.F2D()
183 # And show that it is coming from GRASS GIS
184 flex.grass = True
185
186 # Method
187 flex.Method = 'SAS_NG'
188
189 # Parameters that are often changed for the solution
190 ######################################################
191
192 # x, y, q
193 flex.x, flex.y = get_points_xy(options['input'])
194 # xw, yw: gridded output
195 if len(grass.parse_command('g.list', type='vect', pattern=options['output'])):
196 if not grass.overwrite():
197 grass.fatal("Vector map '" + options['output'] + "' already exists. Use '--o' to overwrite.")
198 # Just check raster at the same time if it exists
199 if len(grass.parse_command('g.list', type='rast', pattern=options['raster_output'])):
200 if not grass.overwrite():
201 grass.fatal("Raster map '" + options['raster_output'] + "' already exists. Use '--o' to overwrite.")
202 grass.run_command('v.mkgrid', map=options['output'], type='point', overwrite=grass.overwrite(), quiet=True)
203 grass.run_command('v.db.addcolumn', map=options['output'], columns='w double precision', quiet=True)
204 flex.xw, flex.yw = get_points_xy(options['output']) # gridded output coordinates
205 vect_db = grass.vector_db_select(options['input'])
206 col_names = np.array(vect_db['columns'])
207 q_col = (col_names == options['column'])
208 if np.sum(q_col):
209 col_values = np.array(list(vect_db['values'].values())).astype(float)
210 flex.q = col_values[:, q_col].squeeze() # Make it 1D for consistency w/ x, y
211 else:
212 grass.fatal("provided column name, "+options['column']+" does not match\nany column in "+options['q0']+".")
213 # Elastic thickness
214 flex.Te = float(options['te'])
215 if options['te_units'] == 'km':
216 flex.Te *= 1000
217 elif options['te_units'] == 'm':
218 pass
219 else:
220 grass.fatal("Inappropriate te_units. How? Options should be limited by GRASS.")
221 flex.rho_fill = float(options['rho_fill'])
222
223 # Parameters that often stay at their default values
224 ######################################################
225 flex.g = float(options['g'])
226 flex.E = float(options['ym']) # Can't just use "E" because reserved for "east", I think
227 flex.nu = float(options['nu'])
228 flex.rho_m = float(options['rho_m'])
229
230 # Set verbosity
231 if grass.verbosity() >= 2:
232 flex.Verbose = True
233 if grass.verbosity() >= 3:
234 flex.Debug = True
235 elif grass.verbosity() == 0:
236 flex.Quiet = True
237
238 # Check if lat/lon and let user know if verbosity is True
239 if grass.region_env()[6] == '3':
240 flex.latlon = True
241 flex.PlanetaryRadius = float(grass.parse_command('g.proj', flags='j')['+a'])
242 if flex.Verbose:
243 print("Latitude/longitude grid.")
244 print("Based on r_Earth = 6371 km")
245 print("Computing distances between load points using great circle paths")
246
247 ##########
248 # SOLVE! #
249 ##########
250
251 flex.initialize()
252 flex.run()
253 flex.finalize()
254
255 # Now to use lower-level GRASS vector commands to work with the database
256 # table and update its entries
257 # See for help:
258 # http://nbviewer.ipython.org/github/zarch/workshop-pygrass/blob/master/02_Vector.ipynb
259 w = vector.VectorTopo(options['output'])
260 w.open('rw') # Get ready to read and write
261 wdb = w.dblinks[0]
262 wtable = wdb.table()
263 col = int((np.array(wtable.columns.names()) == 'w').nonzero()[0]) # update this column
264 for i in range(1, len(w)+1):
265 # ignoring 1st column: assuming it will be category (always true here)
266 wnewvalues = list(w[i].attrs.values())[1:col] + tuple([flex.w[i-1]]) + list(w[i].attrs.values())[col+1:]
267 wtable.update(key=i, values=wnewvalues)
268 wtable.conn.commit() # Save this
269 w.close(build=False) # don't build here b/c it is always verbose
270 grass.run_command('v.build', map=options['output'], quiet=True)
271
272 # And raster export
273 # "w" vector defined by raster resolution, so can do direct v.to.rast
274 # though if this option isn't selected, the user can do a finer-grained
275 # interpolation, which shouldn't introduce much error so long as these
276 # outputs are spaced at << 1 flexural wavelength.
277 if options['raster_output']:
278 grass.run_command('v.to.rast', input=options['output'], output=options['raster_output'], use='attr', attribute_column='w', type='point', overwrite=grass.overwrite(), quiet=True)
279 # And create a nice colormap!
280 grass.run_command('r.colors', map=options['raster_output'], color='differences', quiet=True)
281
282def install_dependencies():
283 print("PLACEHOLDER")
284
285if __name__ == "__main__":
286 import sys
287 if len(sys.argv) > 1 and sys.argv[1] == '--install-dependencies':
288 install_dependencies()
289 else:
290 main()
291
Note: See TracBrowser for help on using the repository browser.