def bspline_param(vectormap, depvar): """Get output bspline parameter estimates""" stfact = Module("v.surf.bspline", flags="ec", input=vectormap, column=depvar, memory=1024, stdout_=PIPE).outputs.stdout stepdist = float(stfact.split(':')[-1].strip()) stfact = Module("v.surf.bspline", flags="c", input=vectormap, ew_step=stepdist, ns_step=stepdist, column=depvar, memory=1024, stdout_=PIPE).outputs.stdout stfact = stfact.replace(" ", "") stfact = stfact.split("\n")[1:-1] stfact = [z.split("|") for z in stfact] stfact = [[float(x) for x in y if x != ''] for y in stfact] minlambda = min(stfact, key=lambda x: abs(x[1]))[0] return (stepdist, minlambda)
def main(options, flags): # Check if running in GRASS gisbase = os.getenv("GISBASE") if not gisbase: gs.fatal( _("$GISBASE not defined. You must be in GRASS GIS to run \ this program")) return 0 # Input IP = options['input'] OP = options['output'] CSV = options['csv'] QGIS = options['qgis'] flags_n = flags['n'] # Check if raster is integer iscell = gs.raster.raster_info(IP)["datatype"] if iscell != u'CELL': gs.error(_('Input should be an integer raster layer')) # Get map category values and their labels CATV = Module('r.category', map=IP, stdout_=PIPE).outputs.stdout RCAT = CATV.split('\n') RCAT = filter(None, RCAT) RID = [z.split('\t')[0] for z in RCAT] RIDI = map(int, RID) # Get full color table RCOL = gs.read_command("r.colors.out", map=IP).split('\n') RCOL = [x for x in RCOL if "nv" not in x and 'default' not in x] RCOL = filter(None, RCOL) CCAT = [z.split(' ')[0] for z in RCOL] idx = [i for i, item in enumerate(CCAT) if not re.search('\.', item)] CCAT = [CCAT[i] for i in idx] RCOL = [RCOL[i] for i in idx] CCAT = map(int, CCAT) # Set strings / list to be used in loop CR = "" RECO = "" CL = "" CV = [] # recode to consecutive category values if flags_n: RIDN = range(1, len(RID) + 1) RLAB = [z.split('\t')[1] for z in RCAT] for j in xrange(len(RID)): RECO = '{0}{1}:{1}:{2}\n'.format(RECO, RID[j], RIDN[j]) A = map(int, [i for i, x in enumerate(CCAT) if x == RIDI[j]]) CV.append(RCOL[A[0]].split(' ')[1]) CR = '{}{} {}\n'.format(CR, RIDN[j], CV[j]) CL = '{}{}|{}\n'.format(CL, RIDN[j], RLAB[j]) CR = '{}nv 255:255:255\ndefault 255:255:255\n'.format(CR) Module("r.recode", flags="a", input=IP, output=OP, rules="-", stdin_=RECO, quiet=True) Module("r.colors", map=OP, rules="-", stdin_=CR, quiet=True) Module("r.category", map=OP, rules="-", stdin_=CL, quiet=True, separator="pipe") else: # Check if new layer should be created if len(OP) > 0: k = '{},{}'.format(IP, OP) gs.run_command("g.copy", raster=k) else: OP = IP # Remove redundant categories Module('r.category', map=OP, rules="-", stdin_=CATV, quiet=True) # Write color rules and assign colors for j in xrange(len(RIDI)): A = map(int, [i for i, x in enumerate(CCAT) if x == RIDI[j]]) CV.append(RCOL[A[0]].split(' ')[1]) CR = CR + str(RIDI[j]) + " " + CV[j] + "\n" CR = '{}nv 255:255:255\ndefault 255:255:255\n'.format(CR) Module("r.colors", map=OP, rules="-", stdin_=CR, quiet=True) # If attribute table (csv format) should be written if len(CSV) > 0: if flags_n: RCAT1 = [w.replace('|', ',') for w in filter(None, CL.split('\n'))] else: RCAT1 = [w.replace('\t', ',') for w in RCAT] RCAT1.insert(0, "CATEGORY,CATEGORY LABEL") CV1 = list(CV) CV1.insert(0, "RGB") with open(CSV, "w") as text_file: for k in xrange(len(RCAT1)): text_file.write('{},{}\n'.format(RCAT1[k], CV1[k])) # If QGIS Color Map text files should be written if len(QGIS) > 0: RGB = [w.replace(':', ',') for w in CV] if flags_n: RCAT = filter(None, CL.split('\n')) RCAT = [w.replace('|', ',') for w in RCAT] else: RCAT = [w.replace('\t', ',') for w in RCAT] with open(QGIS, "w") as text_file: text_file.write('# QGIS color map for {}\n'.format(OP)) text_file.write("INTERPOLATION:EXACT\n") for k in xrange(len(RCAT)): RC2 = RCAT[k].split(',') text_file.write('{},{},255,{}\n'.format( RC2[0], RGB[k], RC2[1]))
def compute(pnt, dem, obs_heigh, maxdist, hcurv, downward, oradius, i, nprocs, obsabselev, memory): try: #the followig lines help to set a delay between a process and the others starting.acquire() # no other process can get it until it is released threading.Timer(0.1, starting.release).start() # release in a 0.1 seconds #using temporary regions (on the same mapset) for the different parallel computations gscript.use_temp_region() #extracting a point from the map of the locations Module("v.extract", input=pnt, output="zzpnt"+i, cats=i, flags="t", overwrite=True, quiet=True) #getting goordinates of the point location coords=Module("v.to.db", flags="p", map="zzpnt"+i, type="point", option="coor", separator="|", stdout_=PIPE) coords=coords.outputs.stdout.splitlines()[1:][0] x=float(coords.split("|")[1]) y=float(coords.split("|")[2]) z=float(coords.split("|")[3]) coords=str(x)+","+str(y) #get elevation of the terrain at the point location querydem=Module("r.what", coordinates=coords.split(), map=dem, stdout_=PIPE) obselev=float(querydem.outputs.stdout.split("|")[3]) #setting the working region around the point location Module("g.region", vector="zzpnt"+i) region = grasscore.region() E = region['e'] W = region['w'] N = region['n'] S = region['s'] #Module("g.region", flags="a", e=E+maxdist, w=W-maxdist, s=S-maxdist, n=N+maxdist) Module("g.region", align=dem, e=E+maxdist, w=W-maxdist, s=S-maxdist, n=N+maxdist) #now we check if the size of the object for which we calculate solid angle in each pixel is equal to half the resolution or is set by the user if oradius == 0: circle_radius=region['nsres']/2 else: circle_radius=oradius #Executing viewshed analysis if obsabselev: relative_height = z - obselev #message1 = "* Considered elevation of dem/dsm is: %s *" #message2 = "* Relative height of observer above the dem/dsm is: %s *" #message3 = "* Absolute elevation of observer used in r.viewshed is: %s *" #gscript.message(message1 % (str(obselev)) ) #gscript.message(message2 % (str(relative_height))) #gscript.message(message3 % (str(z))) if hcurv: Module("r.viewshed", input=dem, output="zzview"+i, coordinates=coords.split(), memory=memory, observer_elevation=relative_height, max_distance=maxdist, flags="c", overwrite=True, quiet=True) else: Module("r.viewshed", input=dem, output="zzview"+i, coordinates=coords.split(), memory=memory, observer_elevation=relative_height, max_distance=maxdist, overwrite=True, quiet=True) if downward: #Since UAV nor Satellite are not expected to see above their level (they are only looking to the ground) vertical angles above 90 are set to null. Module("r.mapcalc", expression="zzview{I} = if(zzview{I}>90 && zzview{I}<180,null(),zzview{I})".format(I=i), overwrite=True, quiet=True) else: #message1 = "* Considered elevation of dem/dsm is: %s *" #message2 = "* Relative height of observer above the dem/dsm is: %s *" #message3 = "* Absolute elevation of observer used in r.viewshed is: %s *" #gscript.message(message1 % (str(obselev)) ) #gscript.message(message2 % (str(obs_heigh))) #gscript.message(message3 % (str(obselev + obs_heigh))) if hcurv: Module("r.viewshed", input=dem, output="zzview"+i, coordinates=coords.split(), memory=memory, observer_elevation=obs_heigh, max_distance=maxdist, flags="c", overwrite=True, quiet=True) else: Module("r.viewshed", input=dem, output="zzview"+i, coordinates=coords.split(), memory=memory, observer_elevation=obs_heigh, max_distance=maxdist, overwrite=True, quiet=True) #Since r.viewshed set the cell of the output visibility layer to 180 under the point, this cell is set to 0.01 Module("r.mapcalc",expression="zzview{I} = if(zzview{I}==180,0,zzview{I})".format(I=i), overwrite=True, quiet=True) #estimating the layer of the horizontal angle between point and each visible cell (angle of the horizontal line of sight) Module("r.mapcalc", expression="{A} = \ if( y()>{py} && x()>{px}, atan(({px}-x())/({py}-y())), \ if( y()<{py} && x()>{px}, 180+atan(({px}-x())/({py}-y())), \ if( y()<{py} && x()<{px}, 180+atan(({px}-x())/({py}-y())), \ if( y()>{py} && x()<{px}, 360+atan(({px}-x())/({py}-y())), \ if( y()=={py} && x()>{px}, 90, \ if( y()<{py} && x()=={px}, 180, \ if( y()=={py} && x()<{px}, 270, \ if( y()>{py} && x()=={px}, 0 \ ) ) ) ) ) ) ) )".format(A='zzview_angle'+i,py=y, px=x), overwrite=True, quiet=True) #estimating the layer of the vertical angle between point and each visible cell (angle of the vertical line of sight) () Module("r.mapcalc", expression="zzview90_{I} = zzview{I} - 90".format(I=i), overwrite=True, quiet=True) #evaluate the vertical component of the versor oriented along the line of sight Module("r.mapcalc", expression="zzc_view{I} = sin(zzview90_{I})".format(I=i), overwrite=True, quiet=True) #evaluate the northern component of the versor oriented along the line of sight Module("r.mapcalc", expression="zzb_view{I} = cos(zzview90_{I})*cos(zzview_angle{I})".format(I=i), overwrite=True, quiet=True) #evaluate the eastern component of the versor oriented along the line of sight Module("r.mapcalc", expression="zza_view{I} = cos(zzview90_{I})*sin(zzview_angle{I})".format(I=i), overwrite=True, quiet=True) #estimate the three-dimensional distance between the point and each visible cell if obsabselev: Module("r.mapcalc", expression="{D} = pow(pow(abs(y()-{py}),2)+pow(abs(x()-{px}),2)+pow(abs({dtm}-{Z}),2),0.5)".format(D='zzdistance'+i, dtm=dem, Z=z, py=y, px=x), overwrite=True, quiet=True) else: Module("r.mapcalc", expression="{D} = pow(pow(abs(y()-{py}),2)+pow(abs(x()-{px}),2)+pow(abs({dtm}-({obs}+{obs_h})),2),0.5)".format(D='zzdistance'+i, dtm=dem, obs=obselev, obs_h=obs_heigh, py=y, px=x), overwrite=True, quiet=True) #estimating the layer of the angle between the versor of the terrain and the line of sight Module("r.mapcalc", expression="zzangle{I} = acos((zza_view{I}*zza_dem+zzb_view{I}*zzb_dem+zzc_view{I}*zzc_dem)/(sqrt(zza_view{I}*zza_view{I}+zzb_view{I}*zzb_view{I}+zzc_view{I}*zzc_view{I})*sqrt(zza_dem*zza_dem+zzb_dem*zzb_dem+zzc_dem*zzc_dem)))".format(I=i), overwrite=True, quiet=True) #in rare cases the angles may results, erroneusly, less than 90. Setting them to 90 Module("r.mapcalc", expression="zzangle{I} = if(zzangle{I} > 90, zzangle{I}, 90)".format(I=i), overwrite=True, quiet=True) #filtering 3d distance based on angle{I} map Module("r.mapcalc", expression="{D} = if(isnull(zzangle{I}),null(),{D})".format(D="zzdistance"+str(i),I=i), overwrite=True, quiet=True) #calculating H1 and H2 that are the distances from the observer to the more distant and less distant points of the inclinded circle representing the pixel Module("r.mapcalc", expression="zzH1_{I} = pow(pow({r},2)+pow({d},2)-(2*{r}*{d}*cos(270-zzangle{I})),0.5)".format(r=circle_radius,d="zzdistance"+str(i),I=i), overwrite=True, quiet=True) Module("r.mapcalc", expression="zzH2_{I} = pow(pow({r},2)+pow({d},2)-(2*{r}*{d}*cos(zzangle{I}-90)),0.5)".format(r=circle_radius,d="zzdistance"+str(i),I=i), overwrite=True, quiet=True) #calculating B1 and B2 that are the angles between the line passing through the observer and the center of the pixel and the distant and less distant points of the inclinded circle representing the pixel Module("r.mapcalc", expression="zzB1_{I} = acos( (pow({r},2)-pow(zzH1_{I},2)-pow({d},2)) / (-2*zzH1_{I}*{d}) ) ".format(r=circle_radius,d="zzdistance"+str(i),I=i), overwrite=True, quiet=True) Module("r.mapcalc", expression="zzB2_{I} = acos( (pow({r},2)-pow(zzH2_{I},2)-pow({d},2)) / (-2*zzH2_{I}*{d}) ) ".format(r=circle_radius,d="zzdistance"+str(i),I=i), overwrite=True, quiet=True) #calculating solid angle considering that the area of an asimetric ellipse is equal to the one of an ellipse having the minor axis equal to the sum of the tqo unequal half minor axes Module("r.mapcalc", expression="zzsangle{I} = ({pi}*{r}*( {d}*tan(zzB1_{I}) + {d}*tan(zzB2_{I}) )/2 ) / (pow({r},2)+pow({d},2)) ".format(r=circle_radius,d="zzdistance"+str(i),I=i,pi=pi), overwrite=True, quiet=True) #approximations for calculating solid angle can create too much larger values under or very close the position of the oserver. in such a case we assume that the solid angle is half of the visible sphere (2*pi) #The same occur when it is used an object_radius that is larger than the pixel size. In some cases this can produce negative values of zzB2 with the effect of creating negative values Module("r.mapcalc", expression="zzsangle{I} = if(zzsangle{I}>2*{pi} || zzB2_{I}>=90,2*{pi},zzsangle{I})".format(I=i, pi=pi), overwrite=True, quiet=True) #removing temporary region gscript.del_temp_region() except: #cleaning termporary layers #cleanup() #message = " ******** Something went wrong: please try to reduce the number of CPU (parameter 'procs') ******* " #gscript.message(message) #sys.exit() f = open("error_cat_"+i+".txt", "x") f.write("error in category: "+i) f.close()
def main(options, flags): # Check if running in GRASS gisbase = os.getenv("GISBASE") if not gisbase: gs.fatal( _("$GISBASE not defined. You must be in GRASS GIS to run \ this program")) return 0 # Input input_raster = options["input"] output_raster = options["output"] output_csv = options["csv"] output_colorfile = options["qgis"] flag_recode = flags["n"] # Check if raster is integer iscell = gs.raster.raster_info(input_raster)["datatype"] if iscell != "CELL": gs.error(_("Input should be an integer raster layer")) # Get map category values and their labels rcategory_output = Module("r.category", map=input_raster, stdout_=PIPE).outputs.stdout raster_cats = rcategory_output.split("\n") raster_cats = [_f for _f in raster_cats if _f] raster_id = [z.split("\t")[0] for z in raster_cats] raster_id_list = list(map(int, raster_id)) # Get full color table raster_color = gs.read_command("r.colors.out", map=input_raster).split("\n") raster_color = [ x for x in raster_color if "nv" not in x and "default" not in x ] raster_color = [_f for _f in raster_color if _f] raster_color_cat = [z.split(" ")[0] for z in raster_color] idx = [ i for i, item in enumerate(raster_color_cat) if not re.search("\.", item) ] raster_color_cat = [raster_color_cat[i] for i in idx] raster_color = [raster_color[i] for i in idx] raster_color_cat = list(map(int, raster_color_cat)) # Set strings / list to be used in loop color_rules = "" recode_rules = "" category_string = "" cv_string = [] # recode to consecutive category values if flag_recode: raster_id_new = list(range(1, len(raster_id) + 1)) raster_lab = [z.split("\t")[1] for z in raster_cats] for j in range(len(raster_id)): recode_rules = "{0}{1}:{1}:{2}\n".format(recode_rules, raster_id[j], raster_id_new[j]) select_color = list( map( int, [ i for i, x in enumerate(raster_color_cat) if x == raster_id_list[j] ], )) if select_color: add_color = raster_color[select_color[0]].split(" ")[1] color_rules = "{}{} {}\n".format(color_rules, raster_id_new[j], add_color) category_string = "{}{}|{}\n".format(category_string, raster_id_new[j], raster_lab[j]) cv_string.append(add_color) color_rules = "{}nv 255:255:255\ndefault 255:255:255\n".format( color_rules) Module( "r.recode", flags="a", input=input_raster, output=output_raster, rules="-", stdin_=recode_rules, quiet=True, ) Module("r.colors", map=output_raster, rules="-", stdin_=color_rules, quiet=True) Module( "r.category", map=output_raster, rules="-", stdin_=category_string, quiet=True, separator="pipe", ) else: # Check if new layer should be created if len(output_raster) > 0: k = "{},{}".format(input_raster, output_raster) gs.run_command("g.copy", raster=k) else: output_raster = input_raster # Remove redundant categories Module( "r.category", map=output_raster, rules="-", stdin_=rcategory_output, quiet=True, ) # Write color rules and assign colors for j in range(len(raster_id_list)): select_color = list( map( int, [ i for i, x in enumerate(raster_color_cat) if x == raster_id_list[j] ], )) if select_color: add_color = raster_color[select_color[0]].split(" ")[1] color_rules = (color_rules + str(raster_id_list[j]) + " " + add_color + "\n") cv_string.append(add_color) color_rules = "{}nv 255:255:255\ndefault 255:255:255\n".format( color_rules) Module("r.colors", map=output_raster, rules="-", stdin_=color_rules, quiet=True) # If attribute table (csv format) should be written if len(output_csv) > 0: if flag_recode: raster_cat1 = [ w.replace("|", ",'") for w in [_f for _f in category_string.split("\n") if _f] ] else: raster_cat1 = [w.replace("\t", ",'") for w in raster_cats] raster_cat1 = ["{}'".format(w) for w in raster_cat1] raster_cat1.insert(0, "CATEGORY,CATEGORY LABEL") cv_string1 = list(cv_string) cv_string1.insert(0, "RGB") with open(output_csv, "w") as text_file: for k in range(len(raster_cat1)): text_file.write("{},{}\n".format(raster_cat1[k], cv_string1[k])) # If QGIS Color Map text files should be written if len(output_colorfile) > 0: rgb_string = [w.replace(":", ",") for w in cv_string] if flag_recode: raster_cats = [_f for _f in category_string.split("\n") if _f] else: raster_cats = [w.replace("\t", "|") for w in raster_cats] with open(output_colorfile, "w") as text_file: text_file.write("# QGIS color map for {}\n".format(output_raster)) text_file.write("INTERPOLATION:EXACT\n") for k in range(len(raster_cats)): raster_cats2 = raster_cats[k].split("|") if raster_cats2[1]: text_file.write("{},{},255,{}\n".format( raster_cats2[0], rgb_string[k], raster_cats2[1])) else: text_file.write("{},{},255,{}\n".format( raster_cats2[0], rgb_string[k], "-"))