Skip to content

Commit ff1ea25

Browse files
authored
Merge pull request #19 from iosefa/docs/joss-paper-review-2
Docs/joss paper review 2
2 parents 40a4f8a + 8e85a28 commit ff1ea25

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+1746
-761
lines changed

.github/workflows/main.yml

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ jobs:
1212
test:
1313
runs-on: ubuntu-latest
1414

15+
strategy:
16+
matrix:
17+
python-version: ["3.10", "3.11", "3.12"]
18+
1519
steps:
1620
- name: Check out the repository
1721
uses: actions/checkout@v3
@@ -20,12 +24,12 @@ jobs:
2024
uses: conda-incubator/setup-miniconda@v3
2125
with:
2226
auto-update-conda: true
23-
python-version: "3.10"
27+
python-version: ${{ matrix.python-version }}
2428
channels: conda-forge
2529

26-
- name: Create Conda environment with Python 3.10 and PDAL
30+
- name: Create Conda environment with Python and PDAL
2731
run: |
28-
conda create --name pyforestscan_env python=3.10 pdal gdal -c conda-forge -v
32+
conda create --name pyforestscan_env python=${{ matrix.python-version }} pdal gdal -c conda-forge -v
2933
3034
- name: Activate Conda environment and install dependencies
3135
shell: bash -l {0}
@@ -38,4 +42,9 @@ jobs:
3842
shell: bash -l {0}
3943
run: |
4044
conda activate pyforestscan_env
41-
pytest
45+
pytest --cov --cov-report=xml
46+
47+
- name: Upload coverage reports to Codecov
48+
uses: codecov/codecov-action@v5
49+
with:
50+
token: ${{ secrets.CODECOV_TOKEN }}

.github/workflows/publish.yml

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Publish Python Package
1+
name: Publish Python Package and Docker Image
22

33
on:
44
push:
@@ -28,4 +28,27 @@ jobs:
2828
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
2929
run: |
3030
python setup.py sdist bdist_wheel
31-
twine upload dist/* -u __token__ -p $PYPI_TOKEN
31+
twine upload dist/* -u __token__ -p $PYPI_TOKEN
32+
33+
docker:
34+
runs-on: ubuntu-latest
35+
needs: release
36+
37+
steps:
38+
- name: Check out the repository
39+
uses: actions/checkout@v3
40+
41+
- name: Log in to Docker Hub
42+
uses: docker/login-action@v2
43+
with:
44+
username: ${{ secrets.DOCKER_USERNAME }}
45+
password: ${{ secrets.DOCKER_PASSWORD }}
46+
47+
- name: Build Docker image
48+
run: docker build -t pyforestscan .
49+
50+
- name: Tag Docker image
51+
run: docker tag pyforestscan iosefa/pyforestscan:latest
52+
53+
- name: Push Docker image
54+
run: docker push iosefa/pyforestscan:latest

.gitignore

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,6 @@ instance/
6868
# Scrapy stuff:
6969
.scrapy
7070

71-
# Sphinx documentation
72-
docs/_build/
73-
7471
# PyBuilder
7572
.pybuilder/
7673
target/
@@ -174,3 +171,11 @@ data/
174171

175172
# tests
176173
test_data/output.tif
174+
175+
# tifs created from tests
176+
*.tif
177+
178+
docs/example_data/ept
179+
180+
*.pdf
181+
*.jats

.idea/PyForestScan.iml

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.readthedocs.yml

Lines changed: 0 additions & 13 deletions
This file was deleted.

Dockerfile

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
FROM jupyter/base-notebook:latest
2+
LABEL maintainer="Iosefa Percival"
3+
LABEL repo="https://github.com/iosefa/PyForestScan"
4+
5+
USER root
6+
RUN apt-get update -y && apt-get install -y \
7+
gcc g++ make \
8+
libgdal-dev libgl1 sqlite3 && \
9+
apt-get clean && rm -rf /var/lib/apt/lists/*
10+
11+
RUN fix-permissions "${CONDA_DIR}" && \
12+
fix-permissions "/home/${NB_USER}"
13+
14+
USER 1000
15+
RUN mamba install -c conda-forge sqlite gdal pdal -y && \
16+
pip install --no-cache-dir pyforestscan jupyter-server-proxy && \
17+
mamba update -c conda-forge -y && \
18+
jupyter server extension enable --sys-prefix jupyter_server_proxy
19+
20+
RUN mkdir ./examples
21+
COPY /docs/examples ./examples
22+
23+
ENV PROJ_LIB='/opt/conda/share/proj'
24+
ENV JUPYTER_ENABLE_LAB=yes
25+
26+
USER root
27+
RUN chown -R ${NB_UID} ${HOME}
28+
USER ${NB_USER}

README.md

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,25 @@
11
# PyForestScan: Airborne Point Cloud Analysis for Forest Structure
22

3+
[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/iosefa/PyForestScan/HEAD?labpath=docs%2Fexamples%2Fgetting-started-importing-preprocessing-dtm-chm.ipynb)
4+
[![PyPI](https://img.shields.io/pypi/v/PyForestScan.svg)](https://pypi.org/project/PyForestScan/)
5+
[![Docker Pulls](https://img.shields.io/docker/pulls/iosefa/pyforestscan?logo=docker&label=pulls)](https://hub.docker.com/r/iosefa/pyforestscan)
6+
[![Contributors](https://img.shields.io/github/contributors/iosefa/PyForestScan.svg?label=contributors)](https://github.com/iosefa/PyForestScan/graphs/contributors)
7+
[![Tests](https://img.shields.io/github/actions/workflow/status/iosefa/PyForestScan/main.yml?branch=main)](https://github.com/iosefa/PyForestScan/actions/workflows/main.yml)
8+
[![Coverage](https://img.shields.io/codecov/c/github/iosefa/PyForestScan/main)](https://codecov.io/gh/iosefa/PyForestScan)
9+
10+
**Calculate Forest Structural Metrics from lidar point clouds in Python**
11+
312
![Height Above Ground](./screenshots/hag.png)
413

514
## Overview
615

7-
PyForestScan is a Python library designed for analyzing and visualizing forest structure using airborne
8-
3D point cloud data. The library helps derive important forest metrics such as Canopy Height,
9-
Plant Area Index (PAI), Canopy Cover, Plant Area Density (PAD), and Foliage Height Diversity (FHD).
16+
PyForestScan is a Python library designed for analyzing and visualizing forest structure using airborne 3D point cloud data. The library helps derive important forest metrics such as Canopy Height, Plant Area Index (PAI), Canopy Cover, Plant Area Density (PAD), and Foliage Height Diversity (FHD).
1017

1118
## Features
1219

1320
- **Forest Metrics**: Calculate and visualize key metrics like Canopy Height, PAI, PAD, and FHD.
14-
- **Airborne Data Compatibility**: Supports LiDAR and Structure from Motion (SfM) data from drones and UAVs.
15-
- **Visualization**: Create 2D and 3D visualizations of forest structures.
21+
- **Large Point Cloud Support**: Utilizes efficient data formats such as EPT for large point cloud processing.
22+
- **Visualization**: Create 2D and 3D visualizations of forest structure and structural metrics
1623
- **Extensibility**: Easily add custom filters and visualization techniques to suit your needs.
1724

1825
## Installation
@@ -26,27 +33,34 @@ pip install pyforestscan
2633
### Dependencies
2734

2835
> [!IMPORTANT]
29-
> You MUST have installed PDAL to use PyForestScan. If you use conda to install PDAL, make sure you install pyforestscan in the conda environment with PDAL. See https://pdal.io/en/latest/ for more information.
36+
> You MUST have installed both PDAL and GDAL to use PyForestScan. If you use conda to install PDAL, make sure you install pyforestscan in the conda environment with PDAL (and GDAL if using conda). See https://pdal.io/en/latest/ for more information on PDAL and https://gdal.org/en/stable/.
3037
3138
- PDAL >= 2.7
39+
- GDAL >= 3.5
3240
- Python >= 3.10
3341

3442
## Quick Start
3543

36-
### Derive Forest Metrics from Airborne Data
44+
### Calculate, Export, and Plot Plant Area Index
45+
46+
The following snippet shows how you can load a las file, create 5m by 5m by 1m voxels with points assigned to them, and generate plant area density at 1m layers and plant area index for each 5m grid cell before writing the resulting PAI layer to a geotiff and plotting.
3747

38-
The following snipped shows how you can load a las file, create 25m by 25m by 5m voxels with points assigned to them, and generate plant area density at 5m layers and plant area index for each 25m grid cell before writing the resulting PAI layer to a geotiff.
3948
```python
4049
from pyforestscan.handlers import read_lidar, create_geotiff
4150
from pyforestscan.calculate import assign_voxels, calculate_pad, calculate_pai
51+
from pyforestscan.visualize import plot_metric
4252

43-
arrays = read_lidar("path/to/lidar/file.las", "EPSG:32605", hag=True)
44-
voxels, extent = assign_voxels(arrays[0], (25, 25, 5))
45-
pad = calculate_pad(voxels, 5)
53+
arrays = read_lidar("example_data/20191210_5QKB020880.laz", "EPSG:32605", hag=True)
54+
voxel_resolution = (5, 5, 1)
55+
voxels, extent = assign_voxels(arrays[0], voxel_resolution)
56+
pad = calculate_pad(voxels, voxel_resolution[-1])
4657
pai = calculate_pai(pad)
4758
create_geotiff(pai, "output_pai.tiff", "EPSG:32605", extent)
59+
plot_metric('Plant Area Index', pai, extent, metric_name='PAI', cmap='viridis', fig_size=None)
4860
```
4961

62+
![Plant Area Index](./screenshots/pai.png)
63+
5064
## Documentation
5165

5266
For detailed instructions and examples, visit our [documentation](https://pyforestscan.readthedocs.io/).
@@ -85,7 +99,7 @@ pytest tests/test_calculate.py
8599

86100
## Contributing
87101

88-
We welcome contributions! Please check our [Contributing Guidelines](CONTRIBUTING.md) to get started.
102+
We welcome contributions! Please check our [Contributing Guidelines](docs/contributing.md) to get started.
89103

90104
## License
91105

docs/CNAME

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pyforestscan.sefa.ai

docs/Makefile

Lines changed: 0 additions & 20 deletions
This file was deleted.

docs/api/calculate.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Calculate Module
2+
3+
::: pyforestscan.calculate

0 commit comments

Comments
 (0)