[GRASS-dev] [GRASS GIS] #3227: g.gui.rlisetup: possibility to execute in command line ?
GRASS GIS
trac at osgeo.org
Mon Apr 29 08:32:28 PDT 2019
#3227: g.gui.rlisetup: possibility to execute in command line ?
--------------------------+-------------------------
Reporter: tgrippa | Owner: grass-dev@…
Type: enhancement | Status: new
Priority: normal | Milestone: 7.0.7
Component: Raster | Version: unspecified
Resolution: | Keywords:
CPU: Unspecified | Platform: All
--------------------------+-------------------------
Comment (by tgrippa):
Here is the function. It allows to create setup file for landscape
polygons. If there are several base rasters (the categorical raster on
which to compute landscape metrics using r.li), it allows for the creation
of multiple setup file.
I'm sure this function could be improved but at least has the merit of
existing ;)
{{{
##### Function that create the r.li configuration file for a list of
landcover raster.
### It enable to create in one function as many configuration file as the
number of raster provided in 'listoflandcoverraster'.
### It could be use only in case study with a several landcover raster and
only one landscape unit layer.
### So, the landscape unit layer if fixed and there are the landcover
raster which change.
# 'listoflandcoverraster' wait for a list with the name (string) of
landcover rasters.
# 'landscape_polygons' wait for the name (string) of the vector layer
containing the polygons to be used as landscape units.
# 'masklayerhardcopy' wait for a boolean value (True/False) depending if
the user want to create hard copy of the landscape units mask layers or
not.
# 'returnlistpath' wait for a boolean value (True/False) according to the
fact that a list containing the path to the configuration files is
desired.
# 'ncores' wait for a integer corresponding to the number of desired cores
to be used for parallelization.
# Import GRASS lib
import grass.script as gscript
# Import libraries for multiprocessing
import multiprocessing
from multiprocessing import Pool
from functools import partial
# Function that copy the landscape unit raster masks on a new layer with
name corresponding to the current 'landcover_raster'
def
copy_landscapeunitmasks(current_landcover_raster,base_landcover_raster,landscape_polygons,landscapeunit_bbox,cat):
### Copy the landscape units mask for the current 'cat'
# Define the name of the current "current_landscapeunit_rast" layer
current_landscapeunit_rast=current_landcover_raster.split("@")[0]+"_"+landscape_polygons.split("@")[0]+"_"+str(cat)
base_landscapeunit_rast=base_landcover_raster.split("@")[0]+"_"+landscape_polygons.split("@")[0]+"_"+str(cat)
# Copy the the landscape unit created for the first landcover map in
order to match the name of the current landcover map
gscript.run_command('g.copy', overwrite=True, quiet=True,
raster=(base_landscapeunit_rast,current_landscapeunit_rast))
# Add the line to the text variable
text="MASKEDOVERLAYAREA
"+current_landscapeunit_rast+"|"+landscapeunit_bbox[cat]
return text
# Function that create the r.li configuration file for the base landcover
raster and then for all the binary rasters
def create_rli_configfile(listoflandcoverraster,landscape_polygons,
masklayerhardcopy=False,returnlistpath=True,ncores=2):
# Check if 'listoflandcoverraster' is not empty
if len(listoflandcoverraster)==0:
sys.exit("The list of landcover raster is empty and should contain
at least one raster name")
# Check if rasters provided in 'listoflandcoverraster' exists to avoid
error in mutliprocessing
for cur_rast in listoflandcoverraster:
try:
mpset=cur_rast.split("@")[1]
except:
mpset=""
if cur_rast.split("@")[0] not in [x[0] for x in
gscript.list_pairs(type='raster',mapset=mpset)]:
sys.exit('Raster <%s> not found' %cur_rast)
# Check if rasters provided in 'listoflandcoverraster' have the same
extend and spatial resolution
raster={}
for x, rast in enumerate(raster_list):
raster[x]=gscript.raster_info(rast)
key_list=raster.keys()
for x in key_list[1:]:
for info in ('north','south','east','west','ewres','nsres'):
if not raster[0][info]==raster[x][info]:
sys.exit("Some raster provided in the list have different
spatial resolution or extend, please check")
# Get the version of GRASS GIS
version=grass.version()['version'].split('.')[0]
# Define the folder to save the r.li configuration files
if sys.platform=="win32":
rli_dir=os.path.join(os.environ['APPDATA'],"GRASS"+version,"r.li")
else:
rli_dir=os.path.join(os.environ['HOME'],".grass"+version,"r.li")
if not os.path.exists(rli_dir):
os.makedirs(rli_dir)
## Create an ordered list with the 'cat' value of landscape units to
be processed.
list_cat=[int(x) for x in gscript.parse_command('v.db.select',
quiet=True,
map=landscape_polygons, column='cat', flags='c')]
list_cat.sort()
# Declare a empty dictionnary which will contains the north, south,
east, west values for each landscape unit
landscapeunit_bbox={}
# Declare a empty list which will contain the path of the configation
files created
listpath=[]
# Declare a empty string variable which will contains the core part of
the r.li configuration file
maskedoverlayarea_1=""
# Duplicate 'listoflandcoverraster' in a new variable called
'tmp_list'
tmp_list=list(listoflandcoverraster)
# Set the current landcover raster as the first of the list
base_landcover_raster=tmp_list.pop(0) #The pop function return the
first item of the list and delete it from the list at the same time
# Loop trough the landscape units
for cat in list_cat:
# Extract the current landscape unit polygon as temporary vector
tmp_vect="tmp_"+base_landcover_raster.split("@")[0]+"_"+landscape_polygons.split("@")[0]+"_"+str(cat)
gscript.run_command('v.extract', overwrite=True, quiet=True,
input=landscape_polygons, cats=cat,
output=tmp_vect)
# Set region to match the extent of the current landscape polygon,
with resolution and alignement matching the landcover raster
gscript.run_command('g.region', vector=tmp_vect,
align=base_landcover_raster)
# Rasterize the landscape unit polygon
landscapeunit_rast=tmp_vect[4:]
gscript.run_command('v.to.rast', overwrite=True, quiet=True,
input=tmp_vect, output=landscapeunit_rast, use='cat', memory='3000')
# Remove temporary vector
gscript.run_command('g.remove', quiet=True, flags="f",
type='vector', name=tmp_vect)
# Set the region to match the raster landscape unit extent and
save the region info in a dictionary
region_info=gscript.parse_command('g.region',
raster=landscapeunit_rast, flags='g')
n=str(round(float(region_info['n']),5)) #the config file need 5
decimal for north and south
s=str(round(float(region_info['s']),5))
e=str(round(float(region_info['e']),6)) #the config file need 6
decimal for east and west
w=str(round(float(region_info['w']),6))
# Save the coordinates of the bbox in the dictionary (n,s,e,w)
landscapeunit_bbox[cat]=n+"|"+s+"|"+e+"|"+w
# Add the line to the maskedoverlayarea_1 variable
maskedoverlayarea_1+="MASKEDOVERLAYAREA
"+landscapeunit_rast+"|"+landscapeunit_bbox[cat]+"\n"
# Compile the content of the r.li configuration file
config_file_content="SAMPLINGFRAME 0|0|1|1\n"
config_file_content+=maskedoverlayarea_1
config_file_content+="RASTERMAP "+base_landcover_raster+"\n"
config_file_content+="VECTORMAP "+landscape_polygons+"\n"
# Create a new file and save the content
configfilename=base_landcover_raster.split("@")[0]+"_"+landscape_polygons.split("@")[0]
path=os.path.join(rli_dir,configfilename)
listpath.append(path)
f=open(path, 'w')
f.write(config_file_content)
f.close()
# Continue creation of r.li configuration file and landscape unit
raster the rest of the landcover raster provided
while len(tmp_list)>0:
# Initialize 'maskedoverlayarea_2' variable as an empty string
maskedoverlayarea_2=""
# Set the current landcover raster as the first of the list
current_landcover_raster=tmp_list.pop(0) #The pop function return
the first item of the list and delete it from the list at the same time
if masklayerhardcopy: # If the user asked for hard copy of the
landscape units mask layers
# Copy all the landscape units masks for the current landcover
raster
p=Pool(ncores) #Create a pool of processes and launch them
using 'map' function
func=partial(copy_landscapeunitmasks,current_landcover_raster,base_landcover_raster,landscape_polygons,landscapeunit_bbox)
# Set fixed argument of the function
maskedoverlayarea_2=p.map(func,list_cat) # Launch the
processes for as many items in the list and get the ordered results using
map function
p.close()
p.join()
# Compile the content of the r.li configuration file
config_file_content="SAMPLINGFRAME 0|0|1|1\n"
config_file_content+="\n".join(maskedoverlayarea_2)+"\n"
config_file_content+="RASTERMAP
"+current_landcover_raster+"\n"
config_file_content+="VECTORMAP "+landscape_polygons+"\n"
else: # If the user not asked for hard copy
# Compile the content of the r.li configuration file
config_file_content="SAMPLINGFRAME 0|0|1|1\n"
config_file_content+=maskedoverlayarea_1 # If user do not
asked for hard copy, the mask layers are the same than for the first
configuration file
config_file_content+="RASTERMAP
"+current_landcover_raster+"\n" # But the name of the RASTERMAP should be
the one of the current landcover raster
config_file_content+="VECTORMAP "+landscape_polygons+"\n"
# Create a new file and save the content
configfilename=current_landcover_raster.split("@")[0]+"_"+landscape_polygons.split("@")[0]
path=os.path.join(rli_dir,configfilename)
listpath.append(path)
f=open(path, 'w')
f.write(config_file_content)
f.close()
# Return a list of path of configuration files creates if option
actived
if returnlistpath:
return list_cat,listpath
else:
return list_cat
}}}
--
Ticket URL: <https://trac.osgeo.org/grass/ticket/3227#comment:7>
GRASS GIS <https://grass.osgeo.org>
More information about the grass-dev
mailing list