Hi list,
Based on a discussion in the list archive, I copied and edited a script that
parallelizes the r.horizon module across multiple cores
(link)<http://osgeo-org.1560.x6.nabble.com/Simultaneous-r-horizon-processes-tp4676325p4892854.html>.
I have updated this script to work with the current module parameter naming
schemes where required. Additionally I added a for loop to the main() function,
as I want it to do the r.horizon module for several areas sequentially (setting
g.region, etc...).
I have several issues:
1. Each time it creates the workers for the last r.horizon angles for a list
item, it also creates the workers for the first angles of the next item in the
list. But it should finish the first workers, copy the raster from the
temporary mapsets to the current mapset and delete the temporary mapsets before
creating new workers and starting the process again.
2. It doesn't calculate the last angles of the last area part of the list that
it loops over. Though I think this is because of the first issue which is that
the order of execution is off.
Why doesn't it follow the correct order as per the script but move on to the
next step before finishing the last? I run the script from the simple python
editor in Grass 7.2.0.
#!/usr/bin/env python
import sys, os, shutil, re
import datetime as dt
import multiprocessing as mp
import subprocess
import atexit
gisbase = os.environ['GISBASE'] = r'C:\\Program Files\\GRASS GIS 7.2.0\\'
gisdbase = r'C:\data\grass'
sys.path.append(os.path.join(os.environ['GISBASE'], "etc", "python"))
import grass.script as grass
import grass.script.setup as gsetup
# code to create list with name of vectors to iterate over
className = "bykerne" + "Net"
mapName = className + '@Solar' # counting layers (sample clusters)
result = grass.read_command('v.info', # in vector file
flags = 'e',
map = mapName)
result = str.split(result, '\n')
layerCount = result[12] # dblink_num = layers
layerCount = str.split(layerCount, '=')
layerCount = layerCount[1] # number of layers
layerCount = int(layerCount)
layerN = 1 # start layer count
outputName = className + '_' + str(layerN - 1)
vectorList = grass.read_command('g.list', type = 'vector', mapset = 'Solar')
vectorList = str.split(vectorList, '\n')
vectorList = ''.join(vectorList)
vectorList = str.split(vectorList, '\r')
vectorList.pop(0)
vectorList.pop(0)
vectorList.pop(-1) # final vector list
# parameters
location = 'Denmark'
mhorizon = 'Solar'
maxDistance = '500'
hstep = 15
distance = '1.0'
# start of function definitions:
def worker_horizon(cpu,demh,azimuth, outputNameS):
# Setup Grass Environment, including temporary mapset
mtemp = 'temp'+str(cpu).zfill(2)
gsetup.init(gisbase, gisdbase, location, mtemp)
grass.run_command("g.region",vector = outputNameS +"@Solar")
# map names
prefhor = demh+'hor'
demh = demh+'@Solar'
# run r.horizon for one azimuth angle
azi = str(azimuth)
grass.run_command("r.horizon", elevation=demh, \
direction=azi, maxdistance=maxDistance, \
output=prefhor, dist=distance, overwrite = True)
# rename horizon map to proper azimuth name
az = str(azimuth).zfill(3)
tempmap = prefhor+'_0'
horizonmap = prefhor+'_'+az
cmd = tempmap+","+horizonmap
grass.run_command("g.rename",rast=cmd,overwrite = True)
def create_temp(cores):
gsetup.init(gisbase, gisdbase, location, 'PERMANENT')
for count in range(0,cores,1):
temp = 'temp'+str(count).zfill(2)
temp_path = gisdbase+'/'+location+'/'+temp
if(os.path.exists(temp_path) == False):
grass.run_command("g.mapset",flags="c", mapset=temp,
quiet=1)
print(temp+" mapset created.")
else:
print(temp+" mapset already exists. skipping...")
def remove_temp(cores):
# setup is in the target mapset, not temp mapsets
gsetup.init(gisbase, gisdbase, location, mhorizon)
# Delete the temp mapset
for count in range(0,cores):
mapset_temp = 'temp'+str(count).zfill(2)
grass.run_command("g.mapsets", mapset=mapset_temp, operation =
'remove')
temp_path = gisdbase+'/'+location+'/'+mapset_temp
shutil.rmtree(temp_path)
if os.path.exists(temp_path):
shutil.rmtree(temp_path)
def copy_mapset(mapset_from,mapset_to,regfilter,overwrite):
# list contents of temp mapset
grass.run_command("g.mapset", mapset=mapset_from, quiet=1)
raster_list = grass.list_pairs(type = 'rast')
# Switch to target mapset and copy rasters over
grass.run_command("g.mapset", mapset=mapset_to,quiet=1)
for rast in raster_list:
if(rast[1] != 'PERMANENT' and re.search(regfilter,rast[0])):
old = rast[0]+ '@' + rast[1]
new = rast[0]
cmd = old+","+new
grass.run_command("g.copy", rast=cmd, overwrite= True)
def printout(str_text):
timestamp = dt.datetime.strftime(dt.datetime.now(),"%H:%M:%S")
lf.write(timestamp+": "+str_text+'\n')
print timestamp+": "+str_text
def main():
for i in vectorList:
outputNameS = i
dem = outputNameS
##################################
# HORIZON CALCULATIONS
##################################
global cores
global lf
cores = mp.cpu_count()
# Open log file
tlog = dt.datetime.strftime(dt.datetime.now(),"%Y-%m-%d_h%Hm%M")
lf = open('rhorizon_'+tlog+'.log', 'w')
# write params to log file
print("STARTING R.HORIZON")
# start logging
start = dt.datetime.now()
starttime = dt.datetime.strftime(start,"%m-%d %H:%M:%S")
print('START r.horizon '+ starttime)
# Create one temp directory for each CPU core
print("Creating Temporary directories, one per cpu core.")
create_temp(cores)
# Spawn process for r.horizon DEM
jobs = []
c = 0
for az in range(0,360,hstep):
if(c < cores):
p = mp.Process(target=worker_horizon,
args=(c,dem,az, outputNameS))
p.start()
jobs.append(p)
pid = str(p.pid)
printout("R.Horizon: dem = "+dem+" process id =
"+pid)
c += 1
else:
# Wait for all the Processes to finish
print("R.Horizon. Cores maxed out. Waiting for
processes up to "+str(az)+" to finish.")
c = 0
for p in jobs:
pid = str(p.pid)
p.join()
printout("R3. r.horizon. dem = "+dem+", pid
= "+pid+" joined.")
print("R.Horizon finished for "+dem)
# Copy all the files back over to horizon mapset
print("R.Horizon finished. copying files back to "+mhorizon)
for cpu in range(0,cores):
mtemp = 'temp'+str(cpu).zfill(2)
suf = 'hor_'
copy_mapset(mtemp, mhorizon, suf, 1)
# Delete the temp mapsets
print("Removing temporary mapsets")
remove_temp(cores)
# Stop Logging and record total processing time.
end = dt.datetime.now()
endtime = dt.datetime.strftime(end,"%m-%d %H:%M:%S")
processingtime = end - start
print('END r.horizon, processing time: '+str(processingtime))
lf.close()
sys.exit("Finished")
if __name__ == '__main__':
#options, flags = grass.parser()
#atexit.register(cleanup)
main()_______________________________________________
grass-user mailing list
[email protected]
https://lists.osgeo.org/mailman/listinfo/grass-user