|
|
@ -23,7 +23,7 @@ import xlsxwriter
|
|
|
|
import math
|
|
|
|
import math
|
|
|
|
from cycler import cycler
|
|
|
|
from cycler import cycler
|
|
|
|
|
|
|
|
|
|
|
|
from survey_tools import call_lastools
|
|
|
|
from survey_tools import call_lastools, extract_pts, update_survey_output
|
|
|
|
|
|
|
|
|
|
|
|
###############################################################################
|
|
|
|
###############################################################################
|
|
|
|
########################## FIXED INPUTS #######################################
|
|
|
|
########################## FIXED INPUTS #######################################
|
|
|
@ -99,91 +99,6 @@ def make_raster(las, output, lastools_loc, keep_only_ground=False, step=0.2):
|
|
|
|
return None
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def extract_pts(las_in, cp_in, survey_date, beach, keep_only_ground=True):
|
|
|
|
|
|
|
|
"""Extract elevations from a las surface based on x and y coordinates.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Requires lastools in system path.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
|
|
las_in: input point cloud (las)
|
|
|
|
|
|
|
|
cp_in: point coordinates with columns: id, x, y, z (csv)
|
|
|
|
|
|
|
|
survey_date: survey date string, e.g. '19700101'
|
|
|
|
|
|
|
|
beach: beach name
|
|
|
|
|
|
|
|
keep_only_ground: only keep points classified as 'ground' (boolean)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
Dataframe containing input coordinates with extracted elevations
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cmd = ['lascontrol', '-i', las_in, '-cp', cp_in, '-parse', 'sxyz']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if keep_only_ground == True:
|
|
|
|
|
|
|
|
cmd += ['-keep_class', '2']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Call lastools
|
|
|
|
|
|
|
|
process = subprocess.Popen(
|
|
|
|
|
|
|
|
cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
|
|
|
|
|
stdout, stderr = process.communicate()
|
|
|
|
|
|
|
|
errcode = process.returncode
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Handle errors, if detected
|
|
|
|
|
|
|
|
if errcode != 0:
|
|
|
|
|
|
|
|
print("Error. lascontrol failed on {}".format(
|
|
|
|
|
|
|
|
os.path.basename(las_in)))
|
|
|
|
|
|
|
|
print(stderr.decode())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Load result into pandas dataframe
|
|
|
|
|
|
|
|
df = pd.read_csv(io.BytesIO(stdout))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Tidy up dataframe
|
|
|
|
|
|
|
|
df = df.drop(columns=['diff'])
|
|
|
|
|
|
|
|
df['lidar_z'] = pd.to_numeric(df['lidar_z'], errors='coerce')
|
|
|
|
|
|
|
|
df['Beach'] = beach
|
|
|
|
|
|
|
|
df = df[[
|
|
|
|
|
|
|
|
'Beach', 'ProfileNum', 'Easting', 'Northing', 'Chainage', 'lidar_z'
|
|
|
|
|
|
|
|
]]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Rename columns
|
|
|
|
|
|
|
|
new_names = {
|
|
|
|
|
|
|
|
'ProfileNum': 'Profile',
|
|
|
|
|
|
|
|
'lidar_z': 'Elevation_{}'.format(survey_date),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
df = df.rename(columns=new_names)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return df
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def update_survey_output(df, output_dir):
|
|
|
|
|
|
|
|
"""Update survey profile output csv files with current survey.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
|
|
df: dataframe containing current survey elevations
|
|
|
|
|
|
|
|
output_dir: directory where csv files are saved
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
# Merge current survey with existing data
|
|
|
|
|
|
|
|
profiles = df['Profile'].unique()
|
|
|
|
|
|
|
|
for profile in profiles:
|
|
|
|
|
|
|
|
csv_name = os.path.join(output_csv_dir, profile + '.csv')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Extract survey data for current profile
|
|
|
|
|
|
|
|
current_profile = df[df['Profile'] == profile]
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
# Load existing results
|
|
|
|
|
|
|
|
master = pd.read_csv(csv_name)
|
|
|
|
|
|
|
|
except FileNotFoundError:
|
|
|
|
|
|
|
|
master = current_profile.copy()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Add (or update) current survey
|
|
|
|
|
|
|
|
current_survey_col = df.columns[-1]
|
|
|
|
|
|
|
|
master[current_survey_col] = current_profile[current_survey_col]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Export updated results
|
|
|
|
|
|
|
|
master.to_csv(csv_name)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def plot_profiles(profile_info, profile, output_loc, LL_limit):
|
|
|
|
def plot_profiles(profile_info, profile, output_loc, LL_limit):
|
|
|
|
#plot the profile. expects output from CC_split_profile
|
|
|
|
#plot the profile. expects output from CC_split_profile
|
|
|
|
|
|
|
|
|
|
|
@ -377,13 +292,11 @@ for i in range(0, len(params_file)): #0, len(params_file)
|
|
|
|
output_poly_dir=params_file['SHP RASTER FOLDER'][i]
|
|
|
|
output_poly_dir=params_file['SHP RASTER FOLDER'][i]
|
|
|
|
output_tif_dir=params_file['TIF OUTPUT FOLDER'][i]
|
|
|
|
output_tif_dir=params_file['TIF OUTPUT FOLDER'][i]
|
|
|
|
cp_csv=params_file['INPUT CSV'][i]
|
|
|
|
cp_csv=params_file['INPUT CSV'][i]
|
|
|
|
# tmp_csv = params_file['TMP CSV'][i]
|
|
|
|
profile_limit_file=params_file['PROFILE LIMIT FILE'][i]
|
|
|
|
LL_file=params_file['LL FILE'][i]
|
|
|
|
csv_output_dir=params_file['CSV OUTPUT FOLDER'][i]
|
|
|
|
# csv_loc=params_file['OUT CSV LOC'][i]
|
|
|
|
graph_loc = params_file['PNG OUTPUT FOLDER'][i]
|
|
|
|
graph_loc = params_file['GRAPH LOC'][i]
|
|
|
|
volume_output=params_file['CSV VOLUMES FOLDER'][i]
|
|
|
|
volume_output=params_file['VOLUME OUTPUT'][i]
|
|
|
|
tmp_dir=params_file['TMP FOLDER'][i]
|
|
|
|
tmp_dir=params_file['TEMP DIR'][i]
|
|
|
|
|
|
|
|
int_dir=params_file['INTERIM DIR'][i]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get base name of input las
|
|
|
|
# Get base name of input las
|
|
|
|
las_basename = os.path.splitext(os.path.basename(original_las))[0]
|
|
|
|
las_basename = os.path.splitext(os.path.basename(original_las))[0]
|
|
|
@ -410,11 +323,22 @@ for i in range(0, len(params_file)): #0, len(params_file)
|
|
|
|
# las_boundary(heatmap_las, output_poly_name, output_poly_dir, path_2_lastools, zone_MGA)
|
|
|
|
# las_boundary(heatmap_las, output_poly_name, output_poly_dir, path_2_lastools, zone_MGA)
|
|
|
|
|
|
|
|
|
|
|
|
#make a raster
|
|
|
|
#make a raster
|
|
|
|
make_raster(heatmap_las, output_raster, path_2_lastools, keep_only_ground=True)
|
|
|
|
# make_raster(heatmap_las, output_raster, path_2_lastools, keep_only_ground=True)
|
|
|
|
|
|
|
|
tif_name = os.path.join(output_tif_dir, las_basename + '.tif')
|
|
|
|
|
|
|
|
call_lastools('blast2dem', input=input_las, output=tif_name,
|
|
|
|
|
|
|
|
args=['-step', 0.2], verbose=False)
|
|
|
|
|
|
|
|
|
|
|
|
#extract the points and get volumes
|
|
|
|
#extract the points and get volumes
|
|
|
|
df = extract_pts(final_las, cp_csv, survey_date, beach, keep_only_ground=True)
|
|
|
|
# df = extract_pts(final_las, cp_csv, survey_date, beach, keep_only_ground=True)
|
|
|
|
update_survey_output(df, csv_loc)
|
|
|
|
df = extract_pts(
|
|
|
|
|
|
|
|
las_data,
|
|
|
|
|
|
|
|
cp_csv,
|
|
|
|
|
|
|
|
survey_date,
|
|
|
|
|
|
|
|
beach,
|
|
|
|
|
|
|
|
args=['-parse', 'sxyz', '-keep_class', '2'],
|
|
|
|
|
|
|
|
verbose=False)
|
|
|
|
|
|
|
|
update_survey_output(df, csv_output_dir)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#colourise the point cloud
|
|
|
|
#colourise the point cloud
|
|
|
|
|
|
|
|
|
|
|
|