Tool for generating and utilizing 3D meshes for simulated canopies
Project description
canopy_factory
First attempt at a procedurally generated 3D canopy architecture model including a maize model based on field measurements provided by Matthew Runyun for the rdla field trials. The L-System used to generate the geometry is based on the system described in Cieslak et al. 2022. Where parameters were missing from the data, values & profiles from Cieslak et al. 2022 were used.
Installation
Conda environment
It is highly recommended that dependencies be installed via the conda
package manager. Two conda environment YAML files are provided that
enumerate all of the required dependencies and conda channels. These
files can be used to create
(conda env create --file environment.yml) or update
(conda env update -n canopy --file environment.yml)
conda environments with those requirements.
environment.ymldependencies necessary if binaries are available for LPy your system (see note below about Macs w/ Apple Silicon)environment_build_lpy.ymldependencies necessary if LPy needs to be built from source for your OS
Dependencies installed from source or outside PyPI
There are several packages that may need to be install via source or from a package manager other than python's pip/conda. Where possible, scripts are provided to aid in completing these steps if they are necessary.
- hothouse for using the embree ray tracer to calculate the light intercepted by generated geometries. Must be installed from PyPI via pip until a release is available on conda-forge (ETA summer 2026).
- OpenAlea PlantGL for creating virtual plant geometry meshes (required by LPy). Must be built from source if conda not used.
- OpenAlea LPy for procedural generation of 3D plant geometries. Must be built from source if conda not used.
- ffmpeg for creating animations. Must be installed via a package manager for your OS (e.g. homebrew, apt, vcpkg) if conda is not used.
Installing hothouse
pip install hothouse
These commands are provided by the build_hothouse.sh script.
Install PlantGL
if [ ! -d plantgl ]; then
git clone git@github.com:openalea/plantgl.git
fi
cd plantgl
if [ ! -d build ]; then
mkdir build
fi
cd build
cmake -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX} \
-DCMAKE_PREFIX_PATH=${CONDA_PREFIX} \
-DCMAKE_BUILD_TYPE=Release \
-DBISON_ROOT=${CONDA_PREFIX} \
-DPython3_ROOT_DIR=${CONDA_PREFIX} \
-DPython3_FIND_STRATEGY=LOCATION \
..
make -j 8
make install
cd ..
pip install .
cd ..
These commands are provided by the build_plantgl.sh script.
Install LPy
export PLANTGL_ROOT="${CONDA_PREFIX}"
if [ ! -d lpy ]; then
git clone git@github.com:openalea/lpy.git
fi
cd lpy
if [ ! -d build ]; then
mkdir build
fi
cd build
cmake -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX} \
-DCMAKE_PREFIX_PATH=${CONDA_PREFIX} \
-DCMAKE_BUILD_TYPE=Release \
-DPython3_ROOT_DIR=${CONDA_PREFIX} \
-DPython3_FIND_STRATEGY=LOCATION \
..
make -j 8
make install
cd ..
pip install .
cd ..
These commands are provided by the build_lpy.sh script.
Install canopy_factory
After installing the non-PyPI dependencies via one of the methods above, canopy_factory can be installed in development mode via:
python -m pip install -e '.[dev]'
Possible installation errors
If you are using Python >= 3.12 and you get an error along the lines of AttributeError: module 'pkgutil' has no attribute 'ImpImporter'. Did you mean: 'zipimporter'? during the installation process, you will need to
manually upgrade pip and setuptools via:
python -m ensurepip --upgrade
python -m pip install --upgrade setuptools
Running
The canopy_factory Python CLI can be used to generate and/or analyze 3D meshes for
single plants, plots with multiple rows of plants, or
side-by-side plots with different genetic lines. If no arguments are
provided defaults will be assumed (e.g. id defaults to "B73_WT" for maize).
For more information about the allowed parameters, run:
python -m canopy_factory -h
Examples
Single maize plant using data collected in 2024 for B73 rdla
python -m canopy_factory generate maize --id=B73_rdla
Single maize plant using data collected in 2024 for B73 WT & rdla side-by-side
python -m canopy_factory generate maize --id=all_combined
500cm x 500cm plot of uniquely generated B73 WT maize plants with 100 cm plant spacing between rows & 20 cm plant spacing between plants within rows
python -m canopy_factory generate maize --id=B73_WT --canopy=unique --plot-length=500 --plot-width=500 --row-spacing=100 --plant-spacing=20
Plot light totals for all IDs in the maize data file for 2025 using periodic boundary conditions
python -m canopy_factory totals maize --canopy=unique --periodic-canopy --output-totals-plot --id=all --data-year=2025
Plot the layout for a field with periodic boundary conditions
python -m canopy_factory layout --periodic-canopy
Movie over one day for plot of raytraced unique B73 WT maize plants generated using data from 2025
python -m canopy_factory animate maize --canopy=unique --id=B73_WT --data-year=2025
Movie over growing season for plot of raytraced unique B73 WT maize plants generated using data from 2025
python -m canopy_factory animate maize --canopy=unique --id=B73_WT --data-year=2025 --start-date=planting --stop-date=maturity
Find the row spacing the makes the light intercepted by a plot of B73_rdla match the light intercepted by plot of B73_WT with a row spacing of 76.2
python -m canopy_factory match_query maize --id=B73_rdla --vary=row_spacing
Documentation
Additional documentation on the Python APIs can be found here.
Repository contents
LICENSE- License for using this modelREADME.md- This filepyproject.toml- Python package configuration filebuild_embree.sh- Bash script for building embree from sourcebuild_hothouse.sh- Bash script for building hothouse from sourcebuild_lpy.sh- Bash script for building LPy from sourcebuild_plantgl.sh- Bash script for building PlantGL from sourcebuild_pyembree.sh- Bash script for building pyembree/embreex from sourcecanopy_factory- Python package containing model interface, I/O tools, & utilities for generating model componentsenvironment.yml- Conda environment file containing required dependenciesenvironment_build_lpy.yml- Conda environment file containing dependencies required for building OpenAlea dependencies (LPy & PlantGL from source)environment_raytrace.yml- Conda environment file containing required dependencies for building embree, pyembree/embreex & hothousetests- Package testsyamls- YAML specification files for yggdrasildocs- Package documentation
Funding
This work is supported by funding from the CROPPS NSF STC (Grant No. DBI-2019674).
Citations
- Mikolaj Cieslak, Nazifa Khan, Pascal Ferraro, Raju Soolanayakanahally, Stephen J Robinson, Isobel Parkin, Ian McQuillan, Przemyslaw Prusinkiewicz, L-system models for image-based phenomics: case studies of maize and canola, in silico Plants, Volume 4, Issue 1, 2022, diab039, https://doi.org/10.1093/insilicoplants/diab039
- F. Boudon, C. Pradal, T. Cokelaer, P. Prusinkiewicz, C. Godin. L-Py: an L-system simulation framework for modeling plant architecture development based on a dynamic language. Frontiers in Plant Science, Frontiers, 2012, 3 (76), doi: 10.3389/fpls.2012.00076
Parameters
| Name | Description | Phenotyping methods |
|---|---|---|
| BranchAngle | Angle between shoot and stem | Protractor or Image Segmentation |
| RotationAngle | Angle between consecutive leaves | Unsure |
| InternodeLength | Distance between nodes | Ruler or Image segmentation |
| InternodeWidth | Width of stem between nodes | Can be estimated from InternodeLength |
| LeafCurve | Profile of leaf cross-section | Image segmentation |
| LeafBend | Profile of how leaf curves due to gravity along their length | Image segmentation |
| LeafTwist | Profile of how leaves twist along their length | Image segmentation |
Most important:
- InternodeLength (or leaf height)
- BranchAngle
Need multiple time points for age dependence, probably 3 or more. Movies along the row (e.g. by rover) could be segmented to get parameters if manual measurements would not be possible. Drone images probably would not help with these parameters, but would be good for validating the canopy coverage predicted by the model.
To do
- Confirm width of mesh leaves (radius vs. diameter)
- Describe profiles in README
- More generic way of specifying profiles (e.g. using PlantGL editor to generate profile and then saving it to a file that can be loaded in the future)
- More realistic age dependency for internode length
- Validate simulated distribution against observations
- Profile to determine if anything can be optimized
- Parallelize ray tracing
- Fix leaf unfurling
- Debug InternodeWidthExp taken from Cieslak et al. 2022 seems to be off by a factor of 10
- Connect to yggdrasil
- Add to model repo
- Add mass dependency for limiting growth
- integrate with BioCro
- gravitropism
- phototropism
- publish to PyPI
- publish to conda_forge
- build docs
- Allow leaf reflectance/transmittance to be provided as spectra
- More realistic age dependency for color change & senesence
- Only include green leaves in LAI calculation
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file canopy_factory-0.2.0.tar.gz.
File metadata
- Download URL: canopy_factory-0.2.0.tar.gz
- Upload date:
- Size: 64.8 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a0054fa776333c1d013841da1ae28124e7b9f7cfaf92e9c83f89d23dea3b6d16
|
|
| MD5 |
6899815aefe3d97097644a96a1ea9d69
|
|
| BLAKE2b-256 |
67139b989a595a1e3a4bd1fdd7e41c75263f4b5b4319607a2851f2eb08b5cc8c
|
Provenance
The following attestation bundles were made for canopy_factory-0.2.0.tar.gz:
Publisher:
publish-to-pypi.yml on langmm/canopy_factory
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
canopy_factory-0.2.0.tar.gz -
Subject digest:
a0054fa776333c1d013841da1ae28124e7b9f7cfaf92e9c83f89d23dea3b6d16 - Sigstore transparency entry: 1770639827
- Sigstore integration time:
-
Permalink:
langmm/canopy_factory@e633732351d3ac973797b55d93e8deadf2be9170 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/langmm
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@e633732351d3ac973797b55d93e8deadf2be9170 -
Trigger Event:
release
-
Statement type:
File details
Details for the file canopy_factory-0.2.0-py3-none-any.whl.
File metadata
- Download URL: canopy_factory-0.2.0-py3-none-any.whl
- Upload date:
- Size: 230.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
289b7174ddd763673c315e44868bc73191ec27a5d904d00210e5708dabe1a063
|
|
| MD5 |
ac90990bee77362166e28ce986c4f429
|
|
| BLAKE2b-256 |
e512f1d7c128b77b45330eeba2d755273e2adf66620e2fa48dadd304c75e246a
|
Provenance
The following attestation bundles were made for canopy_factory-0.2.0-py3-none-any.whl:
Publisher:
publish-to-pypi.yml on langmm/canopy_factory
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
canopy_factory-0.2.0-py3-none-any.whl -
Subject digest:
289b7174ddd763673c315e44868bc73191ec27a5d904d00210e5708dabe1a063 - Sigstore transparency entry: 1770639990
- Sigstore integration time:
-
Permalink:
langmm/canopy_factory@e633732351d3ac973797b55d93e8deadf2be9170 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/langmm
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@e633732351d3ac973797b55d93e8deadf2be9170 -
Trigger Event:
release
-
Statement type: