lazer.config¶
We process airborne LiDAR data using fairly consistent settings that we establish via configuration files. Many processing configurations are managed via yaml
files in the lazer/config/
directory, which are read and mapped in the lazer.config
module.
LAStoolsPaths
¶
Stores os-specific paths to LAStools executables.
__init__(self, system='Linux', lastools_directory='/home/cba/src/lastools/bin')
special
¶
Creates a config object that stores OS-specific paths to LAStools executables.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
system |
str |
the operating system to build paths for. Options include ["Linux", "CentOS", "Windows", "Darwin"]. |
'Linux' |
lastools_directory |
str |
path to the lastools executables. |
'/home/cba/src/lastools/bin' |
Source code in lazer/config/__init__.py
def __init__(self, system: str = SYSTEM, lastools_directory: str = LTBASE) -> None:
"""Creates a config object that stores OS-specific paths to LAStools executables.
Args:
system: the operating system to build paths for.
Options include ["Linux", "CentOS", "Windows", "Darwin"].
lastools_directory: path to the lastools executables.
"""
if system.lower() in ["linux", "centos", "darwin"]:
self.blast2dem = f"wine {os.path.join(lastools_directory, 'blast2dem.exe')}"
self.las2dem = f"wine {os.path.join(lastools_directory, 'las2dem.exe')}"
self.las2las = f"wine {os.path.join(lastools_directory, 'las2las.exe')}"
self.lasboundary = (
f"wine {os.path.join(lastools_directory, 'lasboundary.exe')}"
)
self.lascanopy = f"wine {os.path.join(lastools_directory, 'lascanopy.exe')}"
self.lasclassify = (
f"wine {os.path.join(lastools_directory, 'lasclassify.exe')}"
)
self.lasclip = f"wine {os.path.join(lastools_directory, 'lasclip.exe')}"
self.lasgrid = f"wine {os.path.join(lastools_directory, 'lasgrid.exe')}"
self.lasground = f"wine {os.path.join(lastools_directory, 'lasground.exe')}"
self.lasheight = f"wine {os.path.join(lastools_directory, 'lasheight.exe')}"
self.lasinfo = f"wine {os.path.join(lastools_directory, 'lasinfo.exe')}"
self.lasindex = f"wine {os.path.join(lastools_directory, 'lasindex.exe')}"
self.lasmerge = f"wine {os.path.join(lastools_directory, 'lasmerge.exe')}"
self.lasnoise = f"wine {os.path.join(lastools_directory, 'lasnoise.exe')}"
self.lastile = f"wine {os.path.join(lastools_directory, 'lastile.exe')}"
self.laszip = f"wine {os.path.join(lastools_directory, 'laszip.exe')}"
elif system.lower() == "windows":
self.blast2dem = "blast2dem.exe"
self.las2dem = "las2dem.exe"
self.las2las = "las2las.exe"
self.lasboundary = "lasboundary.exe"
self.lascanopy = "lascanopy.exe"
self.lasclassify = "lasclassify.exe"
self.lasclip = "lasclip.exe"
self.lasgrid = "lasgrid.exe"
self.lasground = "lasground.exe"
self.lasheight = "lasheight.exe"
self.lasinfo = "lasinfo.exe"
self.lasindex = "lasindex.exe"
self.lasmerge = "lasmerge.exe"
self.lasnoise = "lasnoise.exe"
self.lastile = "lastile.exe"
self.laszip = "laszip.exe"
else:
raise KeyError(f"OS not recognized: {system}")
MetricConfig
¶
Stores information for lidar-derived environmental metrics.
Attributes:
Name | Type | Description |
---|---|---|
name |
str |
the formatted metric name |
units |
str |
the unit of measurement for this unit |
odix |
str |
the string to append output raster files if batch processed by lastools |
__init__(self, metric)
special
¶
Get metadata (units, name, etc.) for a specific lidar metric.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
metric |
str |
the lidar metric to get the configuration for.
you can retrieve the available metrics with |
required |
Source code in lazer/config/__init__.py
def __init__(self, metric: str):
"""Get metadata (units, name, etc.) for a specific lidar metric.
Args:
metric: the lidar metric to get the configuration for.
you can retrieve the available metrics with `config.list_metrics()`.
"""
available = list_metrics()
assert (
metric in available
), f"Invalid metric: {metric}. Valid metrics: {', '.join(available)}"
self.name = METRICS[metric]["name"]
self.units = METRICS[metric]["units"]
self.odix = METRICS[metric]["odix"]
PipelineConfig
¶
Stores critical parameters for chained processing pipelines
__init__(self, config={'data': {'buffer_size': 20, 'tile_size': 600, 'drop_above': 150, 'drop_below': -1, 'nodata': -9999, 'slicer_nodata': 255, 'resolution': 1.0, 'slicer_resolution': 10.0, 'slicer_vertical_resolution': 1.0, 'set_horizontal_srs': True, 'target_precision': 0.01, 'target_elevation_precision': 0.01, 'fill': 5, 'subcircle': 0.4, 'epsg': 'none', 'raster_extension': '.tif', 'raster_format': 'GTiff', 'raster_options': ['BIGTIFF=YES', 'TILED=YES', 'COMPRESS=DEFLATE', 'NUM_THREADS=ALL_CPUS'], 'vector_extension': '.shp', 'vector_format': 'ESRI Shapefile', 'cpu_count': 'none', 'ram_mb': 1000}, 'forestry': {'canopy_density_base': 4, 'ladder_fuel_base': 1.0, 'ladder_fuel_ceiling': 4.0, 'max_tch': 99, 'max_base_height': 40, 'overstory_threshold': 4, 'vertical_layer_threshold': 3, 'planar_threshold': 0.25, 'planar_search_radius': 5, 'min_treetop_height': 5, 'min_istree_height': 2, 'crown_search_radius': 3, 'crown_height_decrease_rate': 0.5, 'crown_height_grouping_rate': 0.5, 'max_crown_diameter': 8}, 'terrain': {'town': False, 'city': False, 'metro': False, 'coarse': False, 'extra_coarse': False, 'extra_fine': False, 'fine': True, 'egm_file': '/data/egm2008.tif'}, 'meta': {'creator': 'Salo Sciences', 'license': 'CC BY-NC-SA-4.0', 'license_reference': 'https://creativecommons.org/licenses/by-nc-sa/4.0/'}})
special
¶
Creates the pipeline configuration options object.
Assumes that there's a one-level nesting of the configuration options, and all second-level attributes will be stored as attributes in the output PipelineConfig object.
I wrote the class this way to make it easy to update the config file with new options without having to update the code to make corresponding changes.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
config |
Union[dict, str] |
the configuration options to pass to this object. If it's a string, it assumes a path to a yaml file. If it's a dictionary, it assumes the config was already read. |
{'data': {'buffer_size': 20, 'tile_size': 600, 'drop_above': 150, 'drop_below': -1, 'nodata': -9999, 'slicer_nodata': 255, 'resolution': 1.0, 'slicer_resolution': 10.0, 'slicer_vertical_resolution': 1.0, 'set_horizontal_srs': True, 'target_precision': 0.01, 'target_elevation_precision': 0.01, 'fill': 5, 'subcircle': 0.4, 'epsg': 'none', 'raster_extension': '.tif', 'raster_format': 'GTiff', 'raster_options': ['BIGTIFF=YES', 'TILED=YES', 'COMPRESS=DEFLATE', 'NUM_THREADS=ALL_CPUS'], 'vector_extension': '.shp', 'vector_format': 'ESRI Shapefile', 'cpu_count': 'none', 'ram_mb': 1000}, 'forestry': {'canopy_density_base': 4, 'ladder_fuel_base': 1.0, 'ladder_fuel_ceiling': 4.0, 'max_tch': 99, 'max_base_height': 40, 'overstory_threshold': 4, 'vertical_layer_threshold': 3, 'planar_threshold': 0.25, 'planar_search_radius': 5, 'min_treetop_height': 5, 'min_istree_height': 2, 'crown_search_radius': 3, 'crown_height_decrease_rate': 0.5, 'crown_height_grouping_rate': 0.5, 'max_crown_diameter': 8}, 'terrain': {'town': False, 'city': False, 'metro': False, 'coarse': False, 'extra_coarse': False, 'extra_fine': False, 'fine': True, 'egm_file': '/data/egm2008.tif'}, 'meta': {'creator': 'Salo Sciences', 'license': 'CC BY-NC-SA-4.0', 'license_reference': 'https://creativecommons.org/licenses/by-nc-sa/4.0/'}} |
Source code in lazer/config/__init__.py
def __init__(self, config: Union[dict, str] = PIPELINE):
"""Creates the pipeline configuration options object.
Assumes that there's a one-level nesting of the configuration options,
and all second-level attributes will be stored as attributes in the
output PipelineConfig object.
I wrote the class this way to make it easy to update the config file with
new options without having to update the code to make corresponding changes.
Args:
config: the configuration options to pass to this object.
If it's a string, it assumes a path to a yaml file.
If it's a dictionary, it assumes the config was already read.
"""
if type(config) is str:
with open(config, "r") as handler:
configuration = yaml.load(handler)
else:
configuration = config
metas = list(configuration.keys())
for meta in metas:
for key, value in configuration[meta].items():
setattr(self, key, value)
list_metrics()
¶
Returns key names for all metrics specified in the config.
Source code in lazer/config/__init__.py
def list_metrics() -> list:
"""Returns key names for all metrics specified in the config."""
return list(METRICS.keys())