Optimise code

etta-drone
Dan Howe 6 years ago
parent fd5ddea7f2
commit db8bffa092

@ -1,170 +1,16 @@
# 2017088 Central Coast job import os
import sys
# this is aimed at recieving a large lidar file and import argparse
#first cropping the lidar to a chosen shp (ie to a single beach)
#second try to reclassify vegetation and buildings where possible
#cropping the las file to remove the wave runup zone (and making a shapefile to crop it) --> This is a deliverable
#make a raster at a given step value and crop by the above shapefile --> this is what will be used to extract all the values and do heat maps
#cropping the las file to remove the wave runup zone (and making a shapefile to crop it) --> This is a deliverable
# extract values along a given line --> This is a deliverable
########################### IMPORTS ###########################################
import subprocess import subprocess
import pandas as pd from tqdm import tqdm
import numpy as np import numpy as np
import shapefile
from scipy import interpolate from scipy import interpolate
from shapely.geometry import Point import pandas as pd
import os import geopandas as gpd
from tqdm import tqdm from shapely.geometry import Point, Polygon
###############################################################################
########################## FIXED INPUTS #######################################
#path to LasTools NOTE THERE CAN BE NO SPACES
path_2_lastools='C:/ProgramData/chocolatey/'
#input_file=r"J:\Project\wrl2017088 Central Coast Council Aerial Survey and Coastal Analysis\04_Working\Python\Parameter Files\Survey 2\las manipulation survey2.xlsx"
# input_file=r"J:\Project\wrl2017088 Central Coast Council Aerial Survey and Coastal Analysis\04_Working\Python\Parameter Files\Survey 2\las manipulation patonga2.xlsx"
input_file='Parameter Files/las manipulation survey2.xlsx'
##################### UNCOMMENT THIS SECTION IF YOU WANT TO DO INDIVIDUAL BEACHES#########
##STEP ONE
#input_las1="C:\\Users\\z3331378\\Desktop\\LAStools\\XXFiles\\Wamberal2013\\wamberal2013.las" #CANNOT HAVE SPACES
#initial_crop_poly="C:\\Users\\z3331378\\Desktop\\LAStools\\XXFiles\\CC_Crop\\copacabana.shp"
#temp_las1 = "C:\\Users\\z3331378\\Desktop\\LAStools\\XXFiles\\Temp\\tmp1.las"
#
##STEP TWO
#input_las2 = temp_las1
#temp_las2= "C:\\Users\\z3331378\\Desktop\\LAStools\\XXFiles\\Temp\\tmp2.las"
#step_veg=5 #step size to remove vege. Probably don't change
#temp_las3="C:\\Users\\z3331378\\Desktop\\LAStools\\XXFiles\\Temp\\tmp3.las"
#step_build=35 #step size to remove buildings. May need to change. bigger buildings mean bigger step etc
#
##STEP THREE
#input_las3=temp_las3
#temp_xyz= "C:\\Users\\z3331378\\Desktop\\LAStools\\XXFiles\\Temp\\tmp_thinned.xyz"
#zone_MGA=56 #assumes it is in MGA
#check_value=1 #m AHD value above which you believe, shouldn't delete
#direct = 'west_east' #at the moment can only be north_south or west_east, wont work if it is south_north
#check_distance=1000 #maximum distance you can crop away from the desnified polygon (should probably be somewhere between 10 - 50m)
#polygon_name="copacabana_crop"
#path_2_poly="C:\\Users\\z3331378\\Desktop\\LAStools\\XXFiles\\Results\\"
#tmp_dir="C:\\Users\\z3331378\\Desktop\\LAStools\\XXFiles\\Temp"
###############################################################################
############################### SUB ROUTINES ##################################
def check_output(command,console):
if console == True:
process = subprocess.Popen(command)
else:
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
output,error = process.communicate()
returncode = process.poll()
return returncode,output
def crop_las(las, shp, output, lastools_loc):
# output is the full path and filename (inc extension) to put in
path_2_lasclip=lastools_loc+"\\bin\\lasclip"
command="%s -i %s -poly %s -o %s" % (path_2_lasclip, las, shp, output)
returncode,output = check_output(command, False)
if returncode!= 0:
print("Error. lasclip failed on %s" % shp.split('//')[-1].split('.')[0])
else:
return None
def colour_las(las, tif, out_las, lastools_loc):
# output is the full path and filename (inc extension) to put in
path_2_lascolor=lastools_loc+"\\bin\\lascolor"
command="%s -i %s -image %s -o %s" % (path_2_lascolor, las, tif, out_las)
returncode,output = check_output(command, False)
if returncode!= 0:
print("Error. lascolor failed on")
else:
return None
def remove_veg(las, output, lastools_loc, step=5):
# output is the full path and filename (inc extension) to put in
#step is how the features are removes - the step size should be able to distinguish between the features you are removing
#I THINK that the way lasground works is to create a tin at the step size specified and find points that don't make sense
# by comparing to the tin
#to remove veg, a step size of 3 - 5 is typically used
path_2_lasground=lastools_loc+"\\bin\\lasground_new"
command="%s -i %s -o %s -step 5" % (path_2_lasground, las, output)
returncode,output = check_output(command, False)
if returncode!= 0:
print("Error. lasground failed on %s" % las.split('\\')[-1].split('.')[0])
else:
return None
def remove_buildings(las, output, lastools_loc, step=50):
# output is the full path and filename (inc extension) to put in
#step is how the features are removes - the step size should be able to distinguish between the features you are removing
#I THINK that the way lasground works is to create a tin at the step size specified and find points that don't make sense
# by comparing to the tin
#to remove buildings, a step size of 10 -50 is typically used
#too high a step size will miss small buildings (eg garages, SLSC huts etc), too small will miss large buildings (ie stadiums and warehouses)
# use a step size of ~25m for houses etc.
path_2_lasground=lastools_loc+"\\bin\\lasground_new"
command="%s -i %s -o %s -step %s" % (path_2_lasground, las, output, step)
returncode,output = check_output(command, False)
if returncode!= 0:
print("Error. lasground failed on %s" % las.split('\\')[-1].split('.')[0])
else:
return None
def make_raster(las, output, lastools_loc, keep_only_ground=False):
#not that keep ground only option only rasters points classified as "2" in the lidar (ie ground)
#this effectively creates a "bare earth dem"
#note that this should only be used after remove_veg and/or remove_buildings has been run
path_2_blastdem=lastools_loc+"\\bin\\blast2dem"
if keep_only_ground==False:
command="%s -i %s -o %s -step 0.2" % (path_2_blastdem, las, output)
else:
command="%s -i %s -o %s -step 0.2 -keep_class 2" % (path_2_blastdem, las, output)
returncode,output2 = check_output(command, False)
if returncode!= 0:
print("Error. blast2dem failed on %s" % las.split('\\')[-1].split('.')[0])
else:
return None
def make_xyz(las, output, lastools_loc, step=1):
#to thin the las and create regular grid to allow the computation of the wave runup polygon
#output must have location and .xyz file extension
path_2_blastdem=lastools_loc+"\\bin\\blast2dem"
command="%s -i %s -o %s -step %s" % (path_2_blastdem, las, output, step)
returncode,output2 = check_output(command, False) from survey_tools import call_lastools
if returncode!= 0:
print("Error. blast2dem failed on %s" % las.split('\\')[-1].split('.')[0])
else:
return None
def remove_problems(x_list, y_list, z_list, x_now, y_now, check_value): def remove_problems(x_list, y_list, z_list, x_now, y_now, check_value):
@ -342,8 +188,7 @@ def distance_point_to_poly(x_list, y_list, x_now, y_now):
return dist return dist
def polygon_wave_runup(xyz_1m, direction, path_2_crop_polygon, crop_poly_name, set_check_value, distance_check, zone): def polygon_wave_runup(xyz_1m, direction, shp_name, set_check_value, distance_check, zone):
#print('starting processing of wave runup') #print('starting processing of wave runup')
all_data=pd.read_csv(xyz_1m, header=None, names=['X','Y','Z']) all_data=pd.read_csv(xyz_1m, header=None, names=['X','Y','Z'])
@ -477,24 +322,11 @@ def polygon_wave_runup(xyz_1m, direction, path_2_crop_polygon, crop_poly_name, s
#print('exceeded the manual distance_check %s%% of the time. manually cropping undertaken' % (round(len(exceed_list)/a,2)*100)) #print('exceeded the manual distance_check %s%% of the time. manually cropping undertaken' % (round(len(exceed_list)/a,2)*100))
#making the cropping shapefile #making the cropping shapefile
#print('making the crop polygon') #print('making the crop polygon')
w = shapefile.Writer(shapefile.POLYGON)
w.poly(parts=[for_shape])
fname = crop_poly_name
zone=56
w.field('FIRST_FLD','C','40')
w.field('SECOND_FLD','C','40')
w.record('Poly','PolyTest')
w.save('%s%s' % (path_2_crop_polygon,fname))
prjfname='%s%s.prj'%(path_2_crop_polygon,fname)
prj=open(prjfname, 'w')
if zone==56:
prj.write('PROJCS["GDA_1994_MGA_Zone_56",GEOGCS["GCS_GDA_1994",DATUM["D_GDA_1994",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",10000000.0],PARAMETER["Central_Meridian",153.0],PARAMETER["Scale_Factor",0.9996],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0]]')
elif zone==55:
prj.write('PROJCS["GDA_1994_MGA_Zone_55",GEOGCS["GCS_GDA_1994",DATUM["D_GDA_1994",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",10000000.0],PARAMETER["Central_Meridian",147.0],PARAMETER["Scale_Factor",0.9996],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0]]')
elif zone==57:
prj.write('PROJCS["GDA_1994_MGA_Zone_57",GEOGCS["GCS_GDA_1994",DATUM["D_GDA_1994",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",10000000.0],PARAMETER["Central_Meridian",159.0],PARAMETER["Scale_Factor",0.9996],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0]]')
prj.close()
# Export polygon as shapefile
df = gpd.GeoDataFrame(geometry=[Polygon(for_shape)])
df.crs = {'init': 'epsg:283{}'.format(zone), 'no_defs': True}
df.to_file(shp_name + '.shp', driver='ESRI Shapefile')
return None return None
@ -503,42 +335,71 @@ def remove_temp_files(directory):
os.unlink(os.path.join(directory, f)) os.unlink(os.path.join(directory, f))
return None return None
###############################################################################
############################### CODE ######################################### def main():
parser = argparse.ArgumentParser()
parser.add_argument(
'input_file',
metavar='PARAMS_FILE',
help='name of parameter file',
default=None)
# Print usage if no arguments are provided
if len(sys.argv) == 1:
parser.print_help(sys.stderr)
sys.exit(1)
args = parser.parse_args()
# read the parameters file and scroll through it # read the parameters file and scroll through it
input_file = args.input_file
input_file = 'Parameter Files/las manipulation survey2.xlsx'
params_file=pd.read_excel(input_file, sheet_name="PARAMS") params_file=pd.read_excel(input_file, sheet_name="PARAMS")
for i in range(0, len(params_file)): #0, len(params_file) for i, row in params_file.iterrows():
print("Starting to process %s" % params_file['Beach'][i]) print("Starting to process %s" % row['Beach'])
input_las1=params_file['INPUT LAS1'][i] input_las1 = row['INPUT LAS1']
initial_crop_poly=params_file['INITIAL CROP POLY'][i] initial_crop_poly = row['INITIAL CROP POLY']
temp_las1=params_file['TEMP LAS1'][i] # temp_las1 = row['TEMP LAS1']
temp_las2 = params_file['TEMP LAS2'][i] # temp_las2 = row['TEMP LAS2']
step_veg = params_file['STEP VEG'][i] step_veg = row['STEP VEG']
temp_las3 = params_file['TEMP LAS3'][i] # temp_las3 = row['TEMP LAS3']
step_build= params_file['STEP BUILD'][i] step_build = row['STEP BUILD']
temp_xyz=params_file['TEMP XYZ'][i] temp_xyz = row['TEMP XYZ']
zone_MGA=params_file['ZONE MGA'][i] zone_MGA = row['ZONE MGA']
check_value=params_file['CHECK VALUE'][i] check_value = row['CHECK VALUE']
direct=params_file['DIRECTION'][i] direct = row['DIRECTION']
check_distance=params_file['CHECK DISTANCE'][i] check_distance = row['CHECK DISTANCE']
polygon_name=params_file['POLYGON NAME'][i] polygon_name = row['POLYGON NAME']
path_2_poly = params_file['PATH TO POLYGON'][i] path_2_poly = row['PATH TO POLYGON']
temp_las4= params_file['TEMP LAS4'][i] # temp_las4 = row['TEMP LAS4']
picture= params_file['PICTURE'][i] picture = row['PICTURE']
tmp_dir=params_file['TMP FOLDER'][i] tmp_dir = row['TMP FOLDER']
#STEP ONE CROP TO BEACH # Crop to beach boundary
crop_las(input_las1,initial_crop_poly, temp_las1, path_2_lastools) print('Clipping...')
las_data = call_lastools('lasclip', input=input_las1, output='-stdout',
#STEP TWO REMOVE VEG args=['-poly', initial_crop_poly], verbose=False)
remove_veg(temp_las1, temp_las2, path_2_lastools, step=step_veg)
remove_buildings(temp_las2, temp_las3, path_2_lastools, step=step_build) # Remove vegetation
print('Removing vegetation...')
#STEP THREE MAKE WAVE RUNUP REMOVAL POLYGON las_data = call_lastools('lasground_new', input=las_data, output='-stdout',
make_xyz(temp_las3, temp_xyz, path_2_lastools) args=['-step', step_veg], verbose=False)
polygon_wave_runup(temp_xyz, direct, path_2_poly, polygon_name, check_value, check_distance, zone_MGA) # Remove buildings
print('Removing buildings...')
las_data = call_lastools('lasground_new', input=las_data, output='-stdout',
args=['-step', step_build], verbose=False)
# Interpolate point cloud onto a grid
print('Interpolating to grid...')
call_lastools('las2dem', input=las_data, output=temp_xyz,
args=['-step', 1], verbose=False)
# Make runup clipping mask
print('Calculating runup clipping mask...')
shp_name = os.path.join(path_2_poly, polygon_name)
polygon_wave_runup(temp_xyz, direct, shp_name, check_value, check_distance, zone_MGA)
#NOTE THAT YOU NEED TO CHECK THE OUTPUT SHP FILE AND ADJUST AS REQUIRED #NOTE THAT YOU NEED TO CHECK THE OUTPUT SHP FILE AND ADJUST AS REQUIRED
#STEP FOUR COLOURISE THE LAS #STEP FOUR COLOURISE THE LAS
@ -546,3 +407,7 @@ for i in range(0, len(params_file)): #0, len(params_file)
#delete the temp files #delete the temp files
remove_temp_files(tmp_dir) remove_temp_files(tmp_dir)
if __name__ == '__main__':
main()

Loading…
Cancel
Save