Welcome to forest3d’s documentation!¶
Getting Started¶
Option A: For the non-coder¶
If you don’t want to do any coding yourself and instead just want to view and execute the code we’ve already written using our Jupyter Notebooks, use this link: Binder and a computing environment will be set up for you in the cloud (for free). This setup process can take several minutes, so be patient. Once that setup is done, you should be able to navigate to the “notebooks” folder of the repository and open and execute the Jupyter Notebooks without having to install anything on your own machine.
Option B: For the coder¶
Use the conda package manager to reproduce the computing environment we used in developing this repo. Get Anaconda or Miniconda to do so.
- Clone this repo onto your local machine:
git clone https://github.com/d-diaz/Lidar_Plot_Registration.git
- Create a conda environment from the environment.yml file included in this repo:
conda env create --name forest3d --file environment.yml
- Activate this new conda environment:
source activate forest3d
(Linux, OSX) oractivate forest3d
(Windows) - Start a Jupyter session:
jupyter notebook
- In your web browser Jupyter session, navigate to the “notebooks” folder in this repo and open up one of the Jupyter Notebooks!
Functional Specification¶
Background¶
Natural resource assessments, such as inventory or monitoring campaigns, typically involve sampling a relatively limited portion of the landscape of interest. Traditionally, these samples are statistically extrapolated across a landscape based on a simple random or stratified random sampling design. However, the emergence of remote sensing systems has fueled a growing interest in imputation models built to use remotely-sensed data and field plots as training examples. The models, which are increasingly applying machine learning algorithms for the task, can be applied to generate wall-to-wall maps that “fill in the gaps” between forest plots measured on the ground based on remotely-sensed predictor variables.
Misalignment between field-measured plots and remote sensing data introduces error into predictive models trained to classify or quantify forest conditions. More precise and accurate co-registration of field plots with remotely sensed data can thus help reduce the error introduced into predictive models approach and increase the precision with which varying forest conditions across the landscape can be distinguished.
The primary goals of this project are:
- Providing a set of functions that generate 3D point clouds representing trees based on tree measurements that are commonly collected in the field
- Interactive 3D visualization of a list of measured trees
- Implementation of an optimization algorithm which minimizes misalignment of trees simulated from ground-based measurements with a point cloud collected by an airborne laser scanner (lidar)
- Reporting goodness-of-fit and corresponding model parameters from the optimization
- 3D visualization of the optimization process
User Profile¶
The user is a forest manager interested in forest inventory or forest stand mensuration. They understand parameters usually measured during forest inventories, including tree species, diameter at breast height, height to live crown, etc. They also have an intuition for reasonable forms of trees and common differences between different species and sizes of trees.
The user knows how to browse the web, and can download, install, and run software packages if a clear set of reproducible instructions are provided. They probably cannot program in Python. They would probably be able to execute a Jupyter Notebook if the setup of the computing environment can be handled for them (e.g., using Binder to host a Jupyter Notebook).
Data Sources¶
There are two types of data used in this project:
- Field-based measurements of forest plots and trees, identifying plot location, stem location, tree diameter, tree height, species, etc. These will be formatted as text files containing lists of trees with associated parameters, and list of plots with associated parameters. Example plot data (stem maps and associated tree measurements) have been gathered from publicly-available sources for the Wind River Experimental Forest and HJ Andrews Experimental Forest.
- Lidar point clouds collected from airborne laser scanning which overlap the forests where field measurements have been collected. These point clouds are generally formatted as LAS (or compressed as LAZ) files produced by lidar vendors. Example lidar point clouds from publicly-available sources have been gathered from the HJ Andrews and Wind River forest areas.
Use Cases¶
A. Checking Format of a User-Provided Data¶
Objective: The user wants to check whether a treelist they have prepared conforms with formatting requirements for 3D modeling and optimization using this package.
Interactions:
- The user opens a Jupyter Notebook named
01_Check Data Formats.ipynb
. - The user reads instructions in the Notebook directing them to execute cells one-at-a-time in the Notebook.
- Into a Jupyter Notebook cell, the user types in a path to the treelist saved as a textfile or stored in memory as a Pandas DataFrame. (Optional ->) The user types in a path to the lidar point cloud file saved as a LAS or LAZ file). These are assigned to Python objects when the user executes this cell.
- The user executes the next Jupyter Notebook cell which calls a function that loads the inputs and checks their formatting, including whether coordinates of trees in the tree list fall entirely within the footprint of the lidar point cloud. The function returns a message indicating whether the user’s tree list (and point cloud) conform to the formatting requirements for this package.
- If the user-provided tree list (and/or point cloud) did not meet specifications, the function returns an error message indicating the source of non-compliance and documentation or links to documentation with formatting requirements including field names and formats.
B. Inspecting Parameters of the 3D TreeModel, Visualizing a Single Tree¶
Objective: The user wants to see which parameters are involved in the generation of the 3D TreeModel, and manipulate those parameters interactively to change the shape of a tree.
Interactions:
- The user opens a Jupyter Notebook named
02_Visualize a Single Tree in 3D.ipynb
. - The user reads instructions in the Notebook directing them to run all the cells in the Notebook.
- The user executes all cells in the Notebook.
- The user is presented with a 3D graphic using default 3D TreeModel parameter settings. Slider widgets are laid out with the graphic labeled for each 3D TreeModel parameter.
- The user moves a slider widget for a 3D TreeModel parameter.
- The graphic reacts to user inputs, updating the 3D TreeModel (near-)instantaneously.
- The user grabs, rotates, etc. the 3D graphic to visually inspect the tree’s shape.
C. Drawing a Forest Plot in 3D¶
Objective: The user wants to visualize a list of several measured trees in 3D. Optionally, they may also want to see how this visualization of their tree list compares with a lidar point cloud.
Interactions:
- The user opens a Jupyter Notebook named
03_Visualize a Forest Plot in 3D.ipynb
. - The user reads instructions in the Notebook directing them to execute cells one-at-a-time in the Notebook.
- In a Jupyter Notebook cell, the user types in a path to a text file containing a list of trees or the name of a Pandas DataFrame containing a list of trees. (Optional ->) The user also types in a path to a lidar point cloud file saved as a LAS or LAZ file. The treelist (and optionally, point cloud) are assigned to Python objects when the user executes this cell.
- The user executes the next Jupyter Notebook cell, which calls a function that checks if the tree list (and lidar point cloud) is formatted correctly, returning an appropriate error message if not. If the input data are formatted correcly, the cell returns an interactive graphic showing the 3D model of the tree list, optionally overlaid with a lidar point cloud.
- The user grabs, rotates, etc. the 3D graphic to visually inspect the plot.
D. Co-registering a Tree List with a Lidar Point Cloud¶
Objective: The user wants to estimate the location of a field-measured tree list within a lidar point cloud covering the same area.
Interactions:
- The user opens a Jupyter Notebook named
04_Co-register a Tree List with a Lidar Point Cloud.ipynb
. - The user reads instructions in the Notebook directing them to execute cells one-at-a-time in the Notebook.
- In a Jupyter Notebook cell, the user types in a path to the tree list text file or the name of a Pandas DataFrame, as well as a path to the lidar point cloud file. These are assigned to Python objects when the user executes this cell.
- The user executes a Jupyter Notebook cell which runs a function to check the input formatting and begins the optimization routine if the inputs are formatted correctly. The optimization routine provides graphical or text updates during the optimization process, such as the number of simulations to be conducted and the value of the objective function at periodic increments.
- When the optimization is completed, the user executes another Jupyter Notebook cell, which produces a table output summary of the optimization results.
- The user executes another Jupyter Notebook cell, which produces a 3D visualization showing the optimal co-registration of the simulated 3D TreeModels for their treelist and the point cloud they provided.
- (Optional) The user executes another Jupyter Notebook cell, which produces a 3D visualization where they can see how the simulated 3D TreeModels changed over time during the optimization.
Component Specification¶
Data Loading and Pre-Processing Components¶
Tree List Pre-Processors¶
Aspect | Description |
---|---|
What it does | Transforms plot data from different formats into a consistent format. |
Input | Tree data from external sources are currently in two formats: text files, and a shapefile. |
Output | A text file (CSV or TXT) for each plot containing consistently formatted tree measurements from that plot. |
Tree List Format Checker¶
Aspect | Description |
---|---|
What it does | Checks to see whether a user-provided tree list conforms with format being used for 3D modeling |
Input | A text file (CSV or TXT) or Pandas DataFrame containing information about a single tree on each line/row. |
Output | True/False indication of whether user-specifie d treelist conforms to our format requirements. |
Tree List Within Lidar Bounds Checker¶
Aspect | Description |
---|---|
What it does | Checks to see whether the locations of trees within a user-provided tree list fall within the bounding box of a user-provided lidar point cloud file |
Input | A text file (CSV or TXT) or Pandas DataFrame containing information about a single tree on each line/row, path to a lidar point cloud in LAS or LAZ format. |
Output | True/False indication of whether user-specifie d treelist falls entirely within the bounds of the point cloud. |
Geometry Components¶
Point Cloud Mesher¶
Aspect | Description |
---|---|
What it does | Reads a lidar point cloud, defines geographic coordinate system, generates a Poisson surface mesh. |
Input | Path to a lidar point cloud in LAS or LAZ format. |
Output | A Poisson surface mesh saved to hard drive in PLY format. |
3D Tree Modeler / Simulator¶
Aspect | Description |
---|---|
What it does | A
TreeModel
class which
has at least
two simulator
methods:
generate_hu
ll()
and
generate_vo
lume()
to generate
3D point
clouds
depicting the
trunk and
crown of a
tree. Modeled
off of
``skimage.dr
aw.ellipsoid
` <https://gi
thub.com/scik
it-image/scik
it-image/blob
/master/skima
ge/draw/draw3
d.py#L5>`__. |
Input | TreeModel
class is
initialized
with
parameters
describing
the location,
size, and
shape of the
tree. |
Output | An instance
of the
TreeModel
class which
has simulator
methods that
can be called
to generate
Numpy arrays
of shape (N,
3) containing
N 3D points
representing
the tree. |
3D Plot Modeler¶
Aspect | Description |
---|---|
What it does | Generates a collection of 3D Tree Models from a list of trees |
Input | A text file (CSV or TXT) or Pandas DataFrame containing information about a single tree on each line/row. |
Output | A list or
array of
instances of
the
TreeModel
class
initiated
with the
values of
each tree in
the tree
list. |
Co-registration / Optimization Components¶
Point Cloud Distance Array Generator¶
Aspect | Description |
---|---|
What it does | Reads a PLY formatted Poisson surface mesh, and calculates the distance from each point on a regular 3D grid (Numpy meshgrid) to the nearest point on the mesh. |
Input | Path to a Poisson surface mesh in PLY format which contains (x,y,z) coordinates of each point in the mesh; specification of desired grid resolution/sp acing in x, y, and z dimensions; and specification of distance metric (e.g., ‘euclidean’, ‘squared euclidean’) and whether or not that metric is signed (+/-). |
Output | distance_ar
ray ,
a Numpy array
(meshgrid)
containing
the distance
from each
point on the
regular 3D
grid to the
Poisson
surface mesh. |
Point Cloud Distance Calculator / Interpolator¶
Aspect | Description |
---|---|
What it does | Estimates a
distance
metric for an
array of 3D
points (e.g.,
a simulated
tree) from
another array
of 3D points
(e.g., a
lidar point
cloud surface
mesh) using
`scipy.inte
rpolate.Regul
arGridInterpo
lator <http
s://docs.scip
y.org/doc/sci
py-0.16.1/ref
erence/genera
ted/scipy.int
erpolate.Regu
larGridInterp
olator.html>`
__. |
Input | query_point
s ,
a Numpy array
with shape
(N, 3) for
which
distances
will be
calculated;
and
distance_ar
ray ,
a Numpy
meshgrid
containing
values of a
distance
metric
estimated at
each point of
a regular 3D
grid. |
Output | distances
,
a Numpy array
with shape
(N, 1)
containing
calculated
distances for
N queried
points. |
Optimization Routine¶
Aspect | Description |
---|---|
What it does | Given a list of trees, simulates a point cloud using 3D modeling parameters, calculates a distance metric, and iteratively modifies the 3D modeling parameters to minimize that distance metric. |
Input | A list of trees as a text file or Pandas DataFrame, optional keyword arguments for optimization settings (e.g., number of steps). |
Output | Optimizatio
nResult
object, with
attributes
including
optimized
parameter
values, the
optimal
distance
metric
achieved, a
trace (array)
for each
simulation
parameter
showing how
that
parameter
evolved
during the
optimization,
and a trace
(array)
showing how
the distance
metric
evolved over
the
optimization.
This object
will also
have a class
method which
generates a
summary
report in
tabular form
describing
the
optimization
results. |
Visualization Components¶
Single Tree Visualizer¶
Aspect | Description |
---|---|
What it does | Produces an interactive visualization of a tree in 3D. Allows the user to modify parameters using widgets. |
Input | A Numpy array
with shape
(N, 3)
containing 3D
points, such
as the output
of a
TreeModel
simulator
method. |
Output | A Plotly Graph Object FigureWidget containing 3D graph objects (e.g., Scatter3D, Scattergl, and/or Mesh3D) representing the point cloud of a single tree and slider widgets for adjusting TreeModel parameters. |
Plot (Multi-Tree) Visualizer¶
Aspect | Description |
---|---|
What it does | Produces an interactive visualization of multiple trees in 3D. Allows users to zoom in/out and shift the angle to see the model. |
Input | A list-like
collection of
Numpy arrays
with shape
(N, 3), such
as a list of
outputs from
multiple
TreeModel
simulations. |
Output | A Plotly Graph Object FigureWidget containing 3D Graph Objects (e.g., Scatter3D, Scattergl, and/or Mesh3D) representing the simulated point clouds from multiple trees. |
Dynamic OptimizationResult Visualizer¶
Aspect | Description |
---|---|
What it does | Visualizes the progression of the optimization routine showing how the 3D points from simulated trees evolve during the optimization. |
Input | An
Optimizatio
nResult
object. |
Output | A Plotly Graph Object FigureWidget which animates or allows the user to use a slider widget to step through optimization steps to visualize how simulated tree point clouds moved during the optimization. |
Interactions to Accomplish Use Cases.¶
Use Case A: Checking format of raw user-provided data¶
Tree List Format Checker
and
Tree List Within Lidar Bounds Checker
will be called to check if the
format of the pre-processed data conform to the formatting requirements
and if the tree list falls within the bounds of the user-provided lidar
data.
Use Case B: Visually Inspecting a 3D Tree Model¶
An instance of the TreeModel
class is initialized with default
values and displayed using the Single Tree Visualizer
component.
Use Case C: Drawing a Forest Plot in 3D¶
The 3D Plot Modeler
reads in a treelist, utilizes the
Tree List Format Checker
to ensure it meets formatting requirements,
instantiates a TreeModel
object for each tree in the treelist and
simulates a 3D point cloud of it, generating a list-like collection of
3D point clouds of simulated trees. The Plot (Multi-Tree) Visualizer
is then called with this list of trees, and an interactive graphic with
several trees is produced.
Use Case D: Co-registering a Tree List with a Lidar Point Cloud¶
Before optimization commences, the Tree List Format Checker
and
Tree List Within Lidar Bounds Checker
will be called to check if the
format of the pre-processed data conform to the formatting requirements
and if the tree list falls within the bounds of the user-provided lidar
data. Also before any optimization begins, the Point Clouder Mesher
will convert the user-provided point cloud file into a 3D surface mesh,
and the Point Cloud Distance Array Generator
will be used to compute
the distance between each points on the regular 3D grid from the points
on the Poisson surface mesh of the lidar point cloud.
The Optimization Routine
is initialized with the user-provided
treelist parameters. The 3D Plot Modeler
will read the tree list and
generate 3D models of all the trees in it. The
Point Cloud Distance Calculator
will be used to calculate the
distance of the simulated trees from the mesh. This distance metric is
the objective function that the Optimization Routine
seeks to
minimize. An OptimizationResult
object is returned which contains
multiple attributes and traces related to the process of optimization.
This object allows the user to execute methods including generation of a
tabular report summarizing the optimization results. The
OptimizationResult
object can also be submitted as input to the
Dynamic OptimizationResult Visualizer
to produce a interactive
Plotly Graph Object to visualize the process of optimization.
Preliminary Plan.¶
- Script for pre-processing field-measured forest inventory text file.
- Script for pre-processing field-measured forest inventory shapefile.
- Implement check format of treelist, check treelist within bounds
- Write unit tests for check_format_treelist and check_treelist_inbounds
- Class for generating a 3D point cloud for a single tree from field-measured attributes
- Function for plotting a single tree, with widgets
- Function for plotting many trees, no widgets
- Process for generating a Poisson Surface mesh from lidar data
- Process for calculating the distance of points on a regular 3D grid from the lidar-derived mesh
- Function for querying this distance array with a set of simulated points, based on interpolation of query points using the regular 3D grid with pre-calculated distances from the lidar mesh.
- Implementation of an optimization algorithm which adjusts tree simulation parameters, calculates the distance of the simulated points from the lidar-derived mesh, and iteratively minimizes this distance function.