Metadata-Version: 2.4
Name: shelterbelts
Version: 0.0.3
Summary: Using satellite imagery to identify shelterbelts and measure their impacts on agricultural productivity
Author-email: Christopher Bradley <christopher.bradley@anu.edu.au>
License-Expression: MIT
Project-URL: Homepage, https://github.com/ChristopherBradley/shelterbelts
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: rioxarray
Requires-Dist: pandas
Requires-Dist: scipy
Requires-Dist: requests
Requires-Dist: pysheds
Requires-Dist: owslib
Requires-Dist: pyproj
Requires-Dist: matplotlib
Requires-Dist: netcdf4
Requires-Dist: odc-stac
Requires-Dist: pystac_client
Requires-Dist: planetary_computer
Requires-Dist: geopandas
Requires-Dist: windrose
Requires-Dist: seaborn
Requires-Dist: scikit-learn
Requires-Dist: fiona
Requires-Dist: openpyxl
Requires-Dist: DAESIM_preprocess
Requires-Dist: osmnx
Requires-Dist: xlsxwriter
Requires-Dist: pyarrow
Requires-Dist: tensorflow
Requires-Dist: dask[distributed]
Requires-Dist: cql2
Requires-Dist: earthengine-api
Requires-Dist: geemap
Requires-Dist: tqdm
Requires-Dist: awscli
Requires-Dist: numba
Provides-Extra: dev
Requires-Dist: jupyter; extra == "dev"
Requires-Dist: jupytext; extra == "dev"
Requires-Dist: pytest; extra == "dev"
Requires-Dist: twine; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: jupyterlab-lsp; extra == "dev"
Requires-Dist: python-lsp-server[all]; extra == "dev"
Requires-Dist: ghp-import; extra == "dev"
Requires-Dist: sphinx; extra == "dev"
Requires-Dist: sphinx-argparse; extra == "dev"
Dynamic: license-file

# shelterbelts
This repo is for using satellite imagery to map and categorise shelterbelts across Australia, in preparation for measuring impacts on agricultural productivity at scale.

## Google Earth Engine App
You can visualise some results from the repo in this Earth Engine App:  
https://christopher-bradley-phd.projects.earthengine.app/view/shelterbelts  

Or a mobile friendly version at:  
https://christopher-bradley-phd.projects.earthengine.app/view/shelterbelts-mobile  

## Notebook Examples
There are jupyter notebooks to demo the functionality of this repo in [examples](examples). 

## Documentation
View the published docs at:  
https://christopherbradley.github.io/shelterbelts/index.html

## Installation
`pip install shelterbelts`  
View the pypi package at: https://pypi.org/project/shelterbelts


### Current Methods
The tree predictions come from annual Sentinel-2 imagery largely following a method by Stewart et al. (2025), using a tree/no-tree training dataset provided by Nicolas Pucino.

After the predictions, pixels were categorised using the following method:
- Assign trees from model confidence (50% threshold)
- Assign scattered trees to small groups (< 20 pixels)
- Assign core & buffers to big groups (> 3 pixels thick)
- Assign sheltered vs unsheltered pixels based on percent cover within 100m (5% threshold)
, or wind direction (20 pixels leeward, 10 pixels upwind)
- Assign grassland, cropland, urban and water categories from WorldCover 2021
- Assign riparian and roads trees (3 pixel buffer)
- Assign linear vs non-linear patches by fitting an ellipse and skeleton to each group and applying length and width thresholds.

### Upcoming Plans
- Calculate summary statistics for different regions (IBRA, LGAs, GRDC agricultural zones)
- Include 1m shelter categories for all of ACT & NSW
- Analyse effects on productivity & potential future benefits
- Add layers with opportunities for more trees.

## Parameter Reference

The main parameters for categorising shelterbelts are below:

| Parameter | Default | Low Threshold | High Threshold | Description |
|-----------|---------|---------------|----------------|-------------|
| `min_patch_size` | 20 | 15 | 25 | Minimum area (pixels) to classify as a patch rather than scattered trees |
| `min_core_size` | 1000 | 100 | 10000 | Minimum patch size (pixels) to classify as a core area |
| `edge_size` | 3 | 2 | 5 | Distance (pixels) defining the edge region around patch cores |
| `buffer_width` | 4 | 3 | 5 | Number of pixels away from the feature that still counts as within the buffer |
| `distance_threshold` | 20 | 10 | 30 | Distance from trees that counts as sheltered |
| `density_threshold` | 5 | 3 | 10 | Percentage tree cover within distance_threshold that counts as sheltered |
| `wind_threshold` | 20 | 15 | 25 | Wind speed threshold in km/h |
| `wind_method` | WINDWARD | MOST_COMMON | ANY | Method to determine primary wind direction |
| `min_shelterbelt_length` | 20 | 15 | 25 | Minimum skeleton length (in pixels) to classify a cluster as linear |
| `max_shelterbelt_width` | 6 | 5 | 7 | Maximum skeleton width (in pixels) to classify a cluster as linear |

Parameters can be modified when calling functions directly in Python or via command-line arguments. For example:

```bash
python -m shelterbelts.indices.tree_categories input.tif --min_patch_size 30 --edge_size 5
```

# Setup

## Local Setup
1. Download and install Miniconda from https://www.anaconda.com/download/success
2. Add the miniconda filepath to your ~/.zhrc, e.g. export PATH="/opt/miniconda3/bin:$PATH"
3. `git clone https://github.com/ChristopherBradley/shelterbelts.git`
4. `cd shelterbelts`
5. `conda env create -f environment.yml`
6. `conda activate shelterbelts`

## Setup on gadi at the National Computing Infrastructure (NCI)
1. [Create an account](https://my.nci.org.au/mancini/login) and request access to the projects xe2 (Borevitz Lab), v10 (Digital Earth Australia modules), ka08 (Sentinel-2 Imagery), ob53 (BARRA Wind).
2. `ssh {username}@nci.org.au` and enter the password used to create your account.
3. `git clone https://github.com/ChristopherBradley/shelterbelts.git`
4. There are examples usage of the environments in pbs_scripts
5. (optional) I like to have git ignore the .ipynb files, so that images don't clog up the git history `git ls-files "*.ipynb" | xargs git update-index --skip-worktree`

## Usage on NCI ARE (National Computing Infrastructure's Australian Research Environment)
1. Login here: https://are.nci.org.au/
2. Go to JupyterLab and create a session with 1 hour, queue normalbw, compute size small, project xe2, storage gdata/+gdata/xe2+gdata/v10+gdata/ka08+gdata/ob53, python environment base /g/data/xe2/cb8590/miniconda, conda environment /g/data/xe2/cb8590/miniconda/envs/shelterbelts. Except for demo_sentinel_nci.py, use Module Directories /g/data/v10/public/modules/modulefiles and Modules: dea/20231204.
3. Right click any .py file and open as a jupyter notebook.

# Testing
If on gadi:
`qsub -I -P xe2 -q copyq -l ncpus=1 -l mem=8GB -l walltime=02:00:00 -l storage=gdata/xe2+scratch/xe2+gdata/v10+gdata/ka08 -l wd`

Then:
`conda activate shelterbelts`
`pytest tests`  # everything should pass except test_sentinel_nci.py

Finally:
`module use /g/data/v10/public/modules/modulefiles`
`module load dea/20231204`
`pytest tests/test_classifications/test_sentinel_nci.py`

# Generating the Documentation
Generate the html: 
`make clean && make html`

You can view the documenation locally in a browser by opening `docs/build/index.html`

Run the doctests: 
`make doctest`

Upload the html to github pages: 
`ghp-import -n -p -f docs/build/html`


# Uploading to PyPI

1. rm dist/* 
2. Update the version in pyproject.toml
3. python3 -m build
4. twine upload dist/*
5. Enter the API token
6. Check it out at https://pypi.org/project/shelterbelts
