kopia lustrzana https://github.com/OpenDroneMap/WebODM
Grass engine refactoring, volume calculations using python
rodzic
16b8e03fd5
commit
5c5aa188da
|
@ -4,8 +4,6 @@ import tempfile
|
|||
import subprocess
|
||||
import os
|
||||
|
||||
from string import Template
|
||||
|
||||
from webodm import settings
|
||||
|
||||
logger = logging.getLogger('app.logger')
|
||||
|
@ -30,12 +28,12 @@ class GrassEngine:
|
|||
|
||||
|
||||
class GrassContext:
|
||||
def __init__(self, grass_binary, tmpdir = None, template_args = {}, location = None, auto_cleanup=True):
|
||||
def __init__(self, grass_binary, tmpdir = None, script_opts = {}, location = None, auto_cleanup=True):
|
||||
self.grass_binary = grass_binary
|
||||
if tmpdir is None:
|
||||
tmpdir = os.path.basename(tempfile.mkdtemp('_grass_engine', dir=settings.MEDIA_TMP))
|
||||
self.tmpdir = tmpdir
|
||||
self.template_args = template_args
|
||||
self.script_opts = script_opts
|
||||
self.location = location
|
||||
self.auto_cleanup = auto_cleanup
|
||||
|
||||
|
@ -48,15 +46,15 @@ class GrassContext:
|
|||
dst_path = os.path.abspath(os.path.join(self.get_cwd(), filename))
|
||||
with open(dst_path, 'w') as f:
|
||||
f.write(source)
|
||||
self.template_args[param] = dst_path
|
||||
self.script_opts[param] = dst_path
|
||||
|
||||
if use_as_location:
|
||||
self.set_location(self.template_args[param])
|
||||
self.set_location(self.script_opts[param])
|
||||
|
||||
return dst_path
|
||||
|
||||
def add_param(self, param, value):
|
||||
self.template_args[param] = value
|
||||
self.script_opts[param] = value
|
||||
|
||||
def set_location(self, location):
|
||||
"""
|
||||
|
@ -75,25 +73,12 @@ class GrassContext:
|
|||
|
||||
script = os.path.abspath(script)
|
||||
|
||||
# Create grass script via template substitution
|
||||
try:
|
||||
with open(script) as f:
|
||||
script_content = f.read()
|
||||
except FileNotFoundError:
|
||||
raise GrassEngineException("Script does not exist: {}".format(script))
|
||||
|
||||
tmpl = Template(script_content)
|
||||
|
||||
# Write script to disk
|
||||
if not os.path.exists(self.get_cwd()):
|
||||
os.mkdir(self.get_cwd())
|
||||
|
||||
with open(os.path.join(self.get_cwd(), 'script.sh'), 'w') as f:
|
||||
f.write(tmpl.substitute(self.template_args))
|
||||
# Create param list
|
||||
params = ["{}={}".format(opt,value) for opt,value in self.script_opts.items()]
|
||||
|
||||
# Execute it
|
||||
logger.info("Executing grass script from {}: {} -c {} location --exec sh script.sh".format(self.get_cwd(), self.grass_binary, self.location))
|
||||
p = subprocess.Popen([self.grass_binary, '-c', self.location, 'location', '--exec', 'sh', 'script.sh'],
|
||||
logger.info("Executing grass script from {}: {} -c {} location --exec python {} {}".format(self.get_cwd(), self.grass_binary, self.location, script, " ".join(params)))
|
||||
p = subprocess.Popen([self.grass_binary, '-c', self.location, 'location', '--exec', 'python', script] + params,
|
||||
cwd=self.get_cwd(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
out, err = p.communicate()
|
||||
|
||||
|
@ -108,14 +93,15 @@ class GrassContext:
|
|||
def serialize(self):
|
||||
return {
|
||||
'tmpdir': self.tmpdir,
|
||||
'template_args': self.template_args,
|
||||
'script_opts': self.script_opts,
|
||||
'location': self.location,
|
||||
'auto_cleanup': self.auto_cleanup
|
||||
}
|
||||
|
||||
def cleanup(self):
|
||||
if os.path.exists(self.get_cwd()):
|
||||
shutil.rmtree(self.get_cwd())
|
||||
pass
|
||||
# if os.path.exists(self.get_cwd()):
|
||||
# shutil.rmtree(self.get_cwd())
|
||||
|
||||
def __del__(self):
|
||||
if self.auto_cleanup:
|
||||
|
|
|
@ -41,7 +41,7 @@ class TaskVolume(TaskView):
|
|||
|
||||
celery_task_id = execute_grass_script.delay(os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"calc_volume.grass"
|
||||
"calc_volume.py"
|
||||
), context.serialize()).task_id
|
||||
|
||||
return Response({'celery_task_id': celery_task_id}, status=status.HTTP_200_OK)
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
# area_file: Geospatial file containing the area to measure
|
||||
# points_file: Geospatial file containing the points defining the area
|
||||
# dsm_file: GeoTIFF DEM containing the surface
|
||||
# ------
|
||||
# output: prints the volume to stdout
|
||||
|
||||
#Import raster and vector
|
||||
v.import input=${area_file} output=polygon_area --overwrite
|
||||
v.import input=${points_file} output=polygon_points --overwrite
|
||||
v.buffer -s --overwrite input=polygon_area type=area output=region distance=1 minordistance=1
|
||||
r.external input=${dsm_file} output=dsm --overwrite
|
||||
|
||||
# Set Grass region to vector bbox
|
||||
g.region vector=region
|
||||
|
||||
# Create a mask to speed up computation
|
||||
r.mask vect=region
|
||||
|
||||
# Transfer dsm raster data to vector
|
||||
v.what.rast map=polygon_points raster=dsm column=height
|
||||
|
||||
# Decimate DSM and generate interpolation of new terrain
|
||||
v.surf.rst --overwrite input=polygon_points zcolumn=height elevation=dsm_below_pile
|
||||
|
||||
# Compute difference between dsm and new dsm
|
||||
r.mapcalc expression='pile_height_above_dsm=dsm-dsm_below_pile' --overwrite
|
||||
|
||||
# Set region to polygon area to calculate volume
|
||||
g.region vect=polygon_area
|
||||
|
||||
# Volume output from difference
|
||||
r.volume -f input=pile_height_above_dsm
|
|
@ -0,0 +1,89 @@
|
|||
#%module
|
||||
#% description: Calculate volume of area and prints the volume to stdout
|
||||
#%end
|
||||
#%option
|
||||
#% key: area_file
|
||||
#% type: string
|
||||
#% required: yes
|
||||
#% multiple: no
|
||||
#% description: Geospatial file containing the area to measure
|
||||
#%end
|
||||
#%option
|
||||
#% key: points_file
|
||||
#% type: string
|
||||
#% required: yes
|
||||
#% multiple: no
|
||||
#% description: Geospatial file containing the points defining the area
|
||||
#%end
|
||||
#%option
|
||||
#% key: dsm_file
|
||||
#% type: string
|
||||
#% required: yes
|
||||
#% multiple: no
|
||||
#% description: GeoTIFF DEM containing the surface
|
||||
#%end
|
||||
|
||||
import sys
|
||||
from grass.pygrass.modules import Module
|
||||
import grass.script as grass
|
||||
|
||||
def main():
|
||||
# Import raster and vector
|
||||
Module("v.import", input=opts['area_file'], output="polygon_area", overwrite=True)
|
||||
Module("v.import", input=opts['points_file'], output="polygon_points", overwrite=True)
|
||||
Module("v.buffer", input="polygon_area", s=True, type="area", output="region", distance=1, minordistance=1, overwrite=True)
|
||||
Module("r.external", input=opts['dsm_file'], output="dsm", overwrite=True)
|
||||
|
||||
# Set Grass region to vector bbox
|
||||
Module("g.region", vector="region")
|
||||
|
||||
# Create a mask to speed up computation
|
||||
Module("r.mask", vector="region")
|
||||
|
||||
# Transfer dsm raster data to vector
|
||||
Module("v.what.rast", map="polygon_points", raster="dsm", column="height")
|
||||
|
||||
# Decimate DSM and generate interpolation of new terrain
|
||||
Module("v.surf.rst", input="polygon_points", zcolumn="height", elevation="dsm_below_pile", overwrite=True)
|
||||
|
||||
# Compute difference between dsm and new dsm
|
||||
Module("r.mapcalc", expression='pile_height_above_dsm=dsm-dsm_below_pile', overwrite=True)
|
||||
|
||||
# Set region to polygon area to calculate volume
|
||||
Module("g.region", vector="polygon_area")
|
||||
|
||||
# Volume output from difference
|
||||
Module("r.volume", input="pile_height_above_dsm", f=True)
|
||||
|
||||
return 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
opts, _ = grass.parser()
|
||||
sys.exit(main())
|
||||
|
||||
#Import raster and vector
|
||||
# v.import input=${area_file} output=polygon_area --overwrite
|
||||
# v.import input=${points_file} output=polygon_points --overwrite
|
||||
# v.buffer -s --overwrite input=polygon_area type=area output=region distance=1 minordistance=1
|
||||
# r.external input=${dsm_file} output=dsm --overwrite
|
||||
#
|
||||
# # Set Grass region to vector bbox
|
||||
# g.region vector=region
|
||||
#
|
||||
# # Create a mask to speed up computation
|
||||
# r.mask vect=region
|
||||
#
|
||||
# # Transfer dsm raster data to vector
|
||||
# v.what.rast map=polygon_points raster=dsm column=height
|
||||
#
|
||||
# # Decimate DSM and generate interpolation of new terrain
|
||||
# v.surf.rst --overwrite input=polygon_points zcolumn=height elevation=dsm_below_pile
|
||||
#
|
||||
# # Compute difference between dsm and new dsm
|
||||
# r.mapcalc expression='pile_height_above_dsm=dsm-dsm_below_pile' --overwrite
|
||||
#
|
||||
# # Set region to polygon area to calculate volume
|
||||
# g.region vect=polygon_area
|
||||
#
|
||||
# # Volume output from difference
|
||||
# r.volume -f input=pile_height_above_dsm
|
Ładowanie…
Reference in New Issue