deepSSF 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- deepssf-0.1.1/.github/workflows/ci.yml +26 -0
- deepssf-0.1.1/.github/workflows/publish.yml +20 -0
- deepssf-0.1.1/.gitignore +32 -0
- deepssf-0.1.1/.pre-commit-config.yaml +9 -0
- deepssf-0.1.1/CHANGELOG.md +10 -0
- deepssf-0.1.1/CITATION.cff +13 -0
- deepssf-0.1.1/LICENSE +21 -0
- deepssf-0.1.1/PKG-INFO +145 -0
- deepssf-0.1.1/Package_generation_process.md +302 -0
- deepssf-0.1.1/README.md +106 -0
- deepssf-0.1.1/deepSSF_train_validate_s2.ipynb +3329 -0
- deepssf-0.1.1/environment.yml +33 -0
- deepssf-0.1.1/examples/deepssf_train_validate_example.html +2371 -0
- deepssf-0.1.1/examples/deepssf_train_validate_example.ipynb +2780 -0
- deepssf-0.1.1/examples/deepssf_train_validate_example_files/figure-html/cell-15-output-1.png +0 -0
- deepssf-0.1.1/examples/deepssf_train_validate_example_files/figure-html/cell-19-output-1.png +0 -0
- deepssf-0.1.1/examples/deepssf_train_validate_example_files/figure-html/cell-21-output-1.png +0 -0
- deepssf-0.1.1/examples/deepssf_train_validate_example_files/libs/bootstrap/bootstrap-138a6193a3bd40baf1e627da441a4734.min.css +12 -0
- deepssf-0.1.1/examples/deepssf_train_validate_example_files/libs/bootstrap/bootstrap-icons.css +2106 -0
- deepssf-0.1.1/examples/deepssf_train_validate_example_files/libs/bootstrap/bootstrap-icons.woff +0 -0
- deepssf-0.1.1/examples/deepssf_train_validate_example_files/libs/bootstrap/bootstrap.min.js +7 -0
- deepssf-0.1.1/examples/deepssf_train_validate_example_files/libs/clipboard/clipboard.min.js +7 -0
- deepssf-0.1.1/examples/deepssf_train_validate_example_files/libs/quarto-html/anchor.min.js +9 -0
- deepssf-0.1.1/examples/deepssf_train_validate_example_files/libs/quarto-html/popper.min.js +6 -0
- deepssf-0.1.1/examples/deepssf_train_validate_example_files/libs/quarto-html/quarto-syntax-highlighting-7f8f88aac4f3542376d5c11b86a4c14d.css +236 -0
- deepssf-0.1.1/examples/deepssf_train_validate_example_files/libs/quarto-html/quarto.js +845 -0
- deepssf-0.1.1/examples/deepssf_train_validate_example_files/libs/quarto-html/tabsets/tabsets.js +95 -0
- deepssf-0.1.1/examples/deepssf_train_validate_example_files/libs/quarto-html/tippy.css +1 -0
- deepssf-0.1.1/examples/deepssf_train_validate_example_files/libs/quarto-html/tippy.umd.min.js +2 -0
- deepssf-0.1.1/pyproject.toml +95 -0
- deepssf-0.1.1/src/deepssf/__init__.py +82 -0
- deepssf-0.1.1/src/deepssf/data.py +693 -0
- deepssf-0.1.1/src/deepssf/datasets/data/buffalo_djelk_id2005.csv +10298 -0
- deepssf-0.1.1/src/deepssf/datasets/data/ndvi_2005.tif +0 -0
- deepssf-0.1.1/src/deepssf/datasets/data/slope_2005.tif +0 -0
- deepssf-0.1.1/src/deepssf/model.py +362 -0
- deepssf-0.1.1/src/deepssf/simulate.py +300 -0
- deepssf-0.1.1/src/deepssf/train.py +576 -0
- deepssf-0.1.1/src/deepssf/utils.py +345 -0
- deepssf-0.1.1/src/deepssf/validate.py +172 -0
- deepssf-0.1.1/tests/__init__.py +0 -0
- deepssf-0.1.1/tests/test_deepssf.py +839 -0
- deepssf-0.1.1/tests/test_smoke.py +17 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Runs automatically on every push / pull request to GitHub:
|
|
2
|
+
# lints your code and runs the test suite across Python versions.
|
|
3
|
+
name: CI
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
pull_request:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
test:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: ${{ matrix.python-version }}
|
|
21
|
+
- name: Install package + dev tools
|
|
22
|
+
run: pip install -e ".[dev]"
|
|
23
|
+
- name: Lint
|
|
24
|
+
run: ruff check .
|
|
25
|
+
- name: Test
|
|
26
|
+
run: pytest
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# .github/workflows/publish.yml
|
|
2
|
+
name: Publish to PyPI
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
release:
|
|
6
|
+
types: [published] # fires when you publish a GitHub Release
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
publish:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
environment: pypi
|
|
12
|
+
permissions:
|
|
13
|
+
id-token: write # required for trusted publishing
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.12"
|
|
19
|
+
- run: pip install build && python -m build
|
|
20
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
deepssf-0.1.1/.gitignore
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Byte-compiled / build artifacts
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
*.egg-info/
|
|
7
|
+
|
|
8
|
+
# Virtual environments
|
|
9
|
+
.venv/
|
|
10
|
+
venv/
|
|
11
|
+
env/
|
|
12
|
+
|
|
13
|
+
# Test / tooling caches
|
|
14
|
+
.pytest_cache/
|
|
15
|
+
.ruff_cache/
|
|
16
|
+
.coverage
|
|
17
|
+
|
|
18
|
+
# Notebooks
|
|
19
|
+
.ipynb_checkpoints/
|
|
20
|
+
|
|
21
|
+
# IDE / OS
|
|
22
|
+
.vscode/
|
|
23
|
+
.idea/
|
|
24
|
+
.DS_Store
|
|
25
|
+
|
|
26
|
+
# Models / data (keep large binaries out of git)
|
|
27
|
+
*.pt
|
|
28
|
+
*.pth
|
|
29
|
+
*.ckpt
|
|
30
|
+
|
|
31
|
+
# Example notebook outputs (GIFs, snapshots, saved figures)
|
|
32
|
+
examples/outputs/
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Lets GitHub show a "Cite this repository" button and gives users a clean
|
|
2
|
+
# citation. Fill in DOI/authors to match your MEE paper.
|
|
3
|
+
cff-version: 1.2.0
|
|
4
|
+
title: deepssf
|
|
5
|
+
message: "If you use this software, please cite it as below."
|
|
6
|
+
type: software
|
|
7
|
+
authors:
|
|
8
|
+
- given-names: Scott
|
|
9
|
+
family-names: Forrest
|
|
10
|
+
repository-code: "https://github.com/swforrest/deepssf"
|
|
11
|
+
url: "https://swforrest.github.io/deepSSF/"
|
|
12
|
+
license: MIT
|
|
13
|
+
version: 0.1.0
|
deepssf-0.1.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Scott Forrest
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
deepssf-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: deepSSF
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Deep learning step selection functions for predicting animal movement.
|
|
5
|
+
Project-URL: Homepage, https://swforrest.github.io/deepSSF/
|
|
6
|
+
Project-URL: Repository, https://github.com/swforrest/deepssf
|
|
7
|
+
Project-URL: Paper, https://besjournals.onlinelibrary.wiley.com/doi/full/10.1111/2041-210X.70136
|
|
8
|
+
Author-email: Scott Forrest <scottwforrest@gmail.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: animal-movement,deep-learning,ecology,ssf,step-selection
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: imageio>=2.28
|
|
22
|
+
Requires-Dist: ipykernel>=6.0
|
|
23
|
+
Requires-Dist: jupyterlab>=4.0
|
|
24
|
+
Requires-Dist: matplotlib>=3.7
|
|
25
|
+
Requires-Dist: numpy>=1.24
|
|
26
|
+
Requires-Dist: pandas>=2.0
|
|
27
|
+
Requires-Dist: rasterio>=1.3
|
|
28
|
+
Requires-Dist: torch>=2.0
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
31
|
+
Requires-Dist: pre-commit>=3.7; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
34
|
+
Requires-Dist: twine>=5.0; extra == 'dev'
|
|
35
|
+
Provides-Extra: examples
|
|
36
|
+
Requires-Dist: ipykernel>=6.0; extra == 'examples'
|
|
37
|
+
Requires-Dist: jupyterlab>=4.0; extra == 'examples'
|
|
38
|
+
Description-Content-Type: text/markdown
|
|
39
|
+
|
|
40
|
+
# deepSSF
|
|
41
|
+
|
|
42
|
+
Deep learning step selection functions for predicting animal movement.
|
|
43
|
+
|
|
44
|
+
This package provides the reusable, installable implementation of the deepSSF
|
|
45
|
+
method. The accompanying paper, tutorials, and reproducibility code live at the
|
|
46
|
+
[deepSSF project site](https://swforrest.github.io/deepSSF/).
|
|
47
|
+
|
|
48
|
+
## Installation (pip only)
|
|
49
|
+
|
|
50
|
+
If you manage your own Python environment, install deepSSF with:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install deepssf
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Development install (editable, with linting and testing tools):
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git clone https://github.com/swforrest/deepssf
|
|
60
|
+
cd deepssf
|
|
61
|
+
pip install -e ".[dev]"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Quick start
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
import deepssf
|
|
68
|
+
print(deepssf.__version__)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Setting up (for users new to Python)
|
|
72
|
+
|
|
73
|
+
If you are coming from R, think of a conda environment the way you think of
|
|
74
|
+
an `renv` project library — it is a self-contained Python installation that
|
|
75
|
+
keeps this project's packages separate from everything else on your computer.
|
|
76
|
+
The steps below create one for deepssf and should take about five minutes.
|
|
77
|
+
|
|
78
|
+
### 1. Install Miniconda (once, system-wide)
|
|
79
|
+
|
|
80
|
+
Download and run the installer from the
|
|
81
|
+
[official Miniconda page](https://docs.anaconda.com/miniconda/).
|
|
82
|
+
|
|
83
|
+
- **Windows**: use the **Anaconda Prompt** for all subsequent commands, and
|
|
84
|
+
choose an install path that contains **no spaces** (e.g. `C:\miniconda3`).
|
|
85
|
+
- **macOS / Linux**: a normal terminal works fine.
|
|
86
|
+
|
|
87
|
+
> **Miniforge alternative**: if you prefer to avoid Anaconda's default channel
|
|
88
|
+
> entirely, [Miniforge](https://github.com/conda-forge/miniforge) is a
|
|
89
|
+
> drop-in replacement that ships with `conda-forge` as the only channel.
|
|
90
|
+
|
|
91
|
+
### 2. Create the environment
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
git clone https://github.com/swforrest/deepssf
|
|
95
|
+
cd deepssf
|
|
96
|
+
conda env create -f environment.yml
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
This installs Python 3.11, the geospatial libraries (rasterio / GDAL / PROJ),
|
|
100
|
+
Jupyter Lab, and the deepSSF package itself with all of its dependencies.
|
|
101
|
+
PyTorch is installed via pip with no extra flags — pip automatically picks the
|
|
102
|
+
right build for your hardware: **MPS on Apple Silicon, CUDA on NVIDIA GPUs,
|
|
103
|
+
CPU everywhere else**. No configuration is needed; the package selects the
|
|
104
|
+
correct backend at runtime.
|
|
105
|
+
|
|
106
|
+
### 3. Activate the environment
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
conda activate deepssf
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
You will need to run this once per terminal session before using deepSSF.
|
|
113
|
+
|
|
114
|
+
### 4. (Optional) Register the Jupyter kernel
|
|
115
|
+
|
|
116
|
+
If you use VS Code or another editor that manages its own Jupyter kernel list,
|
|
117
|
+
register the environment so it appears as a kernel option:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
python -m ipykernel install --user --name deepssf --display-name "Python (deepssf)"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### 5. Launch Jupyter Lab
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
jupyter lab
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Then open `examples/deepssf_train_validate_example.ipynb` to get started.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Documentation
|
|
134
|
+
|
|
135
|
+
Tutorials and walkthroughs: https://swforrest.github.io/deepSSF/
|
|
136
|
+
|
|
137
|
+
## Citation
|
|
138
|
+
|
|
139
|
+
If you use deepssf in your research, please cite the paper. See `CITATION.cff` or use the citation and link to paper below.
|
|
140
|
+
|
|
141
|
+
Forrest, S. W., Pagendam, D., Hassan, C., Potts, J. R., Drovandi, C., Bode, M., & Hoskins, A. J. (2026). **Predicting animal movement with deepSSF : A deep learning step selection framework**. Methods in Ecology and Evolution, 17(2), 371–391. https://doi.org/10.1111/2041-210x.70136
|
|
142
|
+
|
|
143
|
+
## License
|
|
144
|
+
|
|
145
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
# Package Generation Process
|
|
2
|
+
|
|
3
|
+
This document records what was done to convert the deepSSF research codebase
|
|
4
|
+
(originally a collection of Jupyter notebooks) into the `deepssf` installable
|
|
5
|
+
Python package.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Starting Point
|
|
10
|
+
|
|
11
|
+
The repo contained:
|
|
12
|
+
|
|
13
|
+
- A number of analysis notebooks from https://swforrest.github.io/deepSSF/ with
|
|
14
|
+
model definitions, data loading, training, simulation, and validation code
|
|
15
|
+
written as a combination of inline and as separate py scripts.
|
|
16
|
+
- No `pyproject.toml`, no `src/` layout, no tests, no installable package.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 2. Package Scaffold
|
|
21
|
+
|
|
22
|
+
### Directory layout
|
|
23
|
+
|
|
24
|
+
The standard `src`-layout was adopted so the package is importable only after
|
|
25
|
+
installation (editable or otherwise), preventing accidental imports from the
|
|
26
|
+
working directory:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
deepSSF_package/
|
|
30
|
+
├── src/
|
|
31
|
+
│ └── deepssf/
|
|
32
|
+
│ ├── __init__.py
|
|
33
|
+
│ ├── data.py
|
|
34
|
+
│ ├── model.py
|
|
35
|
+
│ ├── train.py
|
|
36
|
+
│ ├── simulate.py
|
|
37
|
+
│ ├── validate.py
|
|
38
|
+
│ ├── utils.py
|
|
39
|
+
│ └── datasets/data/ # bundled test dataset (CSV + 2 GeoTIFFs)
|
|
40
|
+
├── tests/
|
|
41
|
+
│ ├── __init__.py
|
|
42
|
+
│ ├── test_deepssf.py
|
|
43
|
+
│ └── test_smoke.py
|
|
44
|
+
├── examples/
|
|
45
|
+
│ └── deepssf_train_validate_example.ipynb
|
|
46
|
+
├── pyproject.toml
|
|
47
|
+
├── environment.yml
|
|
48
|
+
├── README.md
|
|
49
|
+
├── CHANGELOG.md
|
|
50
|
+
├── CITATION.cff
|
|
51
|
+
└── LICENSE
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### `pyproject.toml`
|
|
55
|
+
|
|
56
|
+
A single `pyproject.toml` replaces `setup.py` / `setup.cfg` / `requirements.txt`.
|
|
57
|
+
Key decisions:
|
|
58
|
+
|
|
59
|
+
- Build backend: `hatchling` (version read dynamically from `__init__.py`).
|
|
60
|
+
- Runtime deps declared once: `numpy`, `torch`, `pandas`, `matplotlib`,
|
|
61
|
+
`rasterio`, `imageio`.
|
|
62
|
+
- Optional dep groups:
|
|
63
|
+
- `[dev]` — `pytest`, `ruff`, `pre-commit`, `build`, `twine`.
|
|
64
|
+
- `[examples]` — `jupyterlab`, `ipykernel` (used by `environment.yml`).
|
|
65
|
+
- `requires-python = ">=3.10"`.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## 3. Code Ported from Notebooks
|
|
70
|
+
|
|
71
|
+
Each notebook section was extracted into its own module with type annotations,
|
|
72
|
+
docstrings, and cleaned-up interfaces.
|
|
73
|
+
|
|
74
|
+
### `src/deepssf/model.py`
|
|
75
|
+
|
|
76
|
+
- `ModelParams` — thin wrapper around a config dict; attributes accessible by
|
|
77
|
+
name.
|
|
78
|
+
- `Conv2d_block_spatial` — habitat sub-network (conv stack → log-softmax over
|
|
79
|
+
H×W).
|
|
80
|
+
- `Scalar_to_Grid_Block` — broadcasts scalar covariates into spatial maps.
|
|
81
|
+
- `Conv2d_block_toFC` — movement sub-network (conv stack → flattened dense
|
|
82
|
+
layer).
|
|
83
|
+
- `ConvJointModel` — combines all three blocks; forward pass returns
|
|
84
|
+
`[B, H, W, 2]` (habitat channel + movement channel).
|
|
85
|
+
|
|
86
|
+
### `src/deepssf/train.py`
|
|
87
|
+
|
|
88
|
+
- `negativeLogLikeLoss` — factory returning a loss function that reads the
|
|
89
|
+
observed next-step pixel `(px2, py2)` from the batch; supports `reduction`
|
|
90
|
+
in `{"mean", "sum", "none", "median"}` and a `freeze_movement` flag for
|
|
91
|
+
curriculum training.
|
|
92
|
+
- `EarlyStopping` — patience-based stopping with checkpoint saving.
|
|
93
|
+
- `make_optimisers` — returns two `Adam` optimisers (one per sub-network) with
|
|
94
|
+
`ReduceLROnPlateau` schedulers.
|
|
95
|
+
- `train_loop` / `test_loop` — single-epoch passes.
|
|
96
|
+
- `fit` — full training loop with early stopping, snapshot saving, and loss
|
|
97
|
+
history dict.
|
|
98
|
+
|
|
99
|
+
### `src/deepssf/data.py`
|
|
100
|
+
|
|
101
|
+
- `load_s2_data` — loads all `S2_*.tif` monthly composites from a directory;
|
|
102
|
+
scales DN → surface reflectance.
|
|
103
|
+
- `load_environmental_layers` — dispatches to `load_s2_data` for the S2
|
|
104
|
+
directory; loads other layers from TIFF (scaled to [0, 1]) or `.npy` files.
|
|
105
|
+
- `MovementDataset` — `torch.utils.data.Dataset`; `__getitem__` extracts a
|
|
106
|
+
spatial patch centred on the departure pixel and returns
|
|
107
|
+
`(spatial, scalars, bearing_tm1, next_step_pixel, transform)`.
|
|
108
|
+
- `prepare_movement_df` — converts raw telemetry (one row per fix) to step
|
|
109
|
+
format (one row per consecutive pair). Outputs: `x1_`, `y1_`, `x2_`, `y2_`,
|
|
110
|
+
`t1_`, `dx`, `dy`, `bearing`, `bearing_tm1`, `dt_hour`, `hour_t1`,
|
|
111
|
+
`yday_t1`, and four cyclic encodings.
|
|
112
|
+
- `filter_steps_by_window` *(new)* — drops steps whose displacement `|dx|` or
|
|
113
|
+
`|dy|` exceeds `(window_size - 1) * pixel_size / 2`. Must be called after
|
|
114
|
+
`prepare_movement_df` and before `make_dataloaders` to prevent out-of-bounds
|
|
115
|
+
pixel indices in the loss function (see §6 below).
|
|
116
|
+
- `make_dataloaders` — convenience wrapper that builds `MovementDataset` and
|
|
117
|
+
splits it into train / val / test `DataLoader`s.
|
|
118
|
+
|
|
119
|
+
### `src/deepssf/utils.py`
|
|
120
|
+
|
|
121
|
+
- `get_device` — selects MPS → CUDA → CPU at runtime.
|
|
122
|
+
- `clear_memory` — frees GPU/MPS cache.
|
|
123
|
+
- `subset_raster_with_padding_torch` / `_npy` — crops a raster window with
|
|
124
|
+
−1 padding at boundaries.
|
|
125
|
+
- `subset_raster_all_bands_torch` — multi-band variant.
|
|
126
|
+
- `subset_layer_vectorized` — fast NumPy/Torch crop used inside
|
|
127
|
+
`MovementDataset.__getitem__`.
|
|
128
|
+
- `recover_hour` / `recover_yday` — invert cyclic sine/cosine encodings.
|
|
129
|
+
- `create_gif` — assembles training snapshot PNGs into an animated GIF.
|
|
130
|
+
|
|
131
|
+
### `src/deepssf/simulate.py`
|
|
132
|
+
|
|
133
|
+
Ported from `deepSSF_simulations.ipynb`:
|
|
134
|
+
|
|
135
|
+
- `make_simulation_inputs` — pre-computes cyclic scalar arrays for N steps
|
|
136
|
+
given a starting day-of-year and hour.
|
|
137
|
+
- `simulate_next_step` — runs one forward pass; samples the next location from
|
|
138
|
+
the joint probability map; returns new coordinates and three log-prob tensors.
|
|
139
|
+
- `simulate_trajectory` — loops `simulate_next_step` for N steps and returns a
|
|
140
|
+
DataFrame of `(x, y, hour, yday, month_index)`.
|
|
141
|
+
|
|
142
|
+
### `src/deepssf/validate.py`
|
|
143
|
+
|
|
144
|
+
- `validate_next_step_probs` — iterates over observed steps, runs the model,
|
|
145
|
+
and appends `habitat_prob`, `move_prob`, and `next_step_prob` columns to the
|
|
146
|
+
input DataFrame.
|
|
147
|
+
|
|
148
|
+
### `src/deepssf/__init__.py`
|
|
149
|
+
|
|
150
|
+
Curated public API: re-exports every user-facing name from all five modules,
|
|
151
|
+
plus `__version__ = "0.1.0"`. `__all__` is explicit.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## 4. Example Notebook
|
|
156
|
+
|
|
157
|
+
`examples/deepssf_train_validate_example.ipynb` is a cleaned-up, reproducible
|
|
158
|
+
version of the original analysis notebook. It uses only the public package API:
|
|
159
|
+
no inline model or data-prep code remains. Key changes from the original:
|
|
160
|
+
|
|
161
|
+
- Imports `from deepssf import ...` throughout.
|
|
162
|
+
- Defines `WINDOW_SIZE = 25` and `PIXEL_SIZE = 25` as named constants.
|
|
163
|
+
- Calls `filter_steps_by_window(step_df, window_size=WINDOW_SIZE, pixel_size=PIXEL_SIZE)`
|
|
164
|
+
immediately after `prepare_movement_df`, before `make_dataloaders`.
|
|
165
|
+
- Uses `PIXEL_SIZE` (not a bare literal) in `ModelParams`.
|
|
166
|
+
- Saves all outputs under `examples/outputs/`.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## 5. Test Suite
|
|
171
|
+
|
|
172
|
+
`tests/test_deepssf.py` — 48 tests covering every public function:
|
|
173
|
+
|
|
174
|
+
| Area | Tests |
|
|
175
|
+
|------|-------|
|
|
176
|
+
| `deepssf.utils` | `get_device`, `recover_hour/yday` roundtrips, `subset_raster_*` shapes and padding, `clear_memory` |
|
|
177
|
+
| `deepssf.data` | `extract_year_month_regex`, `day_to_month_index`, `prepare_movement_df` columns / row count / bearing / cyclic range / dx/dy / bearing_tm1, `filter_steps_by_window`, `MovementDataset.__getitem__` shapes, `make_dataloaders` (df= and prepare= variants) |
|
|
178
|
+
| `deepssf.model` | `ModelParams` construction, `Conv2d_block_spatial` output shape, `Scalar_to_Grid_Block` output shape, full forward pass shape, habitat log-normalisation |
|
|
179
|
+
| `deepssf.train` | `negativeLogLikeLoss` (mean, sum, none, median, freeze_movement, invalid reduction), `EarlyStopping` counter / reset, `make_optimisers`, `fit` loss history |
|
|
180
|
+
| `deepssf.simulate` | `make_simulation_inputs` shape / cyclic encoding / hour wrap, `simulate_next_step` return types and shapes, `simulate_trajectory` DataFrame shape and columns |
|
|
181
|
+
| `deepssf.validate` | `validate_next_step_probs` column presence and row-0 == 0 rule, `_day_to_s2_month` range |
|
|
182
|
+
|
|
183
|
+
Ruff (linting + import sorting) is configured in `pyproject.toml` and passes
|
|
184
|
+
clean on all source and test files.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## 6. Issues Encountered and Resolved
|
|
189
|
+
|
|
190
|
+
### OpenMP duplicate-library crash on macOS (MPS)
|
|
191
|
+
|
|
192
|
+
**Symptom**: `OMP Error #15: Initializing libomp.dylib, but found libomp.dylib
|
|
193
|
+
already initialized` — process crashed on the first MPS forward pass.
|
|
194
|
+
|
|
195
|
+
**Root cause**: Two separate copies of libomp were loaded:
|
|
196
|
+
1. pip-installed `torch` bundles its own `libomp.dylib`.
|
|
197
|
+
2. conda-forge's `rasterio` pulled in `libopenblas` (OpenMP build) →
|
|
198
|
+
`llvm-openmp`, a second libomp.
|
|
199
|
+
|
|
200
|
+
Additionally, the system `~/.condarc` had `channel_priority: flexible` plus a
|
|
201
|
+
`defaults` channel entry, which caused conda to pre-install the full
|
|
202
|
+
conda-forge pytorch ecosystem as orphaned packages before pip had a chance to
|
|
203
|
+
install torch.
|
|
204
|
+
|
|
205
|
+
**Fix** (two parts):
|
|
206
|
+
1. Added `- nodefaults` to `environment.yml` channels to prevent the system
|
|
207
|
+
`~/.condarc` channels from being merged into the solve.
|
|
208
|
+
2. Moved `rasterio` from the conda section to the pip section. The macOS ARM64
|
|
209
|
+
pip wheel for rasterio bundles GDAL/PROJ internally, so conda-forge never
|
|
210
|
+
installs libopenblas or llvm-openmp. The conda section now installs only
|
|
211
|
+
pure-Python packages (jupyterlab, ipykernel) with no C extension or BLAS
|
|
212
|
+
dependencies.
|
|
213
|
+
|
|
214
|
+
### torch 2.12 stricter MPS bounds checking
|
|
215
|
+
|
|
216
|
+
**Symptom**: `AcceleratorError: index 25 is out of bounds for dimension 1 with
|
|
217
|
+
size 25` during the first training epoch on MPS.
|
|
218
|
+
|
|
219
|
+
**Root cause**: `MovementDataset.__getitem__` computes the next-step pixel
|
|
220
|
+
index as `px2 - col_start`. For `window_size=25`, valid indices are 0–24. A
|
|
221
|
+
step whose displacement exceeds 12 pixels (i.e. 300 m at 25 m/pixel) produces
|
|
222
|
+
a local index of 25, which is out of bounds. torch 2.5.1 silently allowed
|
|
223
|
+
this; torch 2.12 on MPS correctly raises an error.
|
|
224
|
+
|
|
225
|
+
**Fix**: Rather than clamping the index (which would silently corrupt the loss
|
|
226
|
+
signal), the correct fix is to remove those steps before training. This
|
|
227
|
+
matches the original notebook's pattern. The solution was to:
|
|
228
|
+
- Add `dx` and `dy` columns to `prepare_movement_df` output (the actual x/y
|
|
229
|
+
displacements in CRS units).
|
|
230
|
+
- Add `hour_t1` column (needed by the simulation cell).
|
|
231
|
+
- Add the `filter_steps_by_window(df, window_size, pixel_size)` function.
|
|
232
|
+
- Call it in the example notebook between `prepare_movement_df` and
|
|
233
|
+
`make_dataloaders`.
|
|
234
|
+
|
|
235
|
+
### macOS case-insensitive filesystem collision
|
|
236
|
+
|
|
237
|
+
The original development conda environment was named `deepSSF`. Running
|
|
238
|
+
`conda env remove -n deepssf` (lowercase) on macOS's case-insensitive APFS
|
|
239
|
+
filesystem removed `/opt/miniconda3/envs/deepSSF` — the two names are
|
|
240
|
+
identical to the OS. The new `deepssf` environment (created from
|
|
241
|
+
`environment.yml`) is now the primary development environment.
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## 7. Environment Setup (`environment.yml`)
|
|
246
|
+
|
|
247
|
+
A conda/pip hybrid environment for reproducible setup on any platform:
|
|
248
|
+
|
|
249
|
+
```yaml
|
|
250
|
+
name: deepssf
|
|
251
|
+
|
|
252
|
+
channels:
|
|
253
|
+
- conda-forge
|
|
254
|
+
- nodefaults # prevent system ~/.condarc channels from being merged in
|
|
255
|
+
|
|
256
|
+
dependencies:
|
|
257
|
+
- python=3.11
|
|
258
|
+
- pip
|
|
259
|
+
|
|
260
|
+
# Jupyter — installed via conda for reliable kernel registration
|
|
261
|
+
- jupyterlab>=4.0
|
|
262
|
+
- ipykernel>=6.0
|
|
263
|
+
|
|
264
|
+
- pip:
|
|
265
|
+
# Plain torch — pip selects MPS on macOS, CUDA on NVIDIA, CPU elsewhere
|
|
266
|
+
- torch>=2.0
|
|
267
|
+
|
|
268
|
+
# rasterio via pip — ARM64/Linux wheels bundle GDAL/PROJ internally,
|
|
269
|
+
# avoiding the conda-forge openblas → llvm-openmp conflict with torch's libomp
|
|
270
|
+
- rasterio>=1.3
|
|
271
|
+
|
|
272
|
+
# Install the package + Jupyter extras; all other deps come from pyproject.toml
|
|
273
|
+
- -e ".[examples]"
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Verification (Apple Silicon, MPS)
|
|
277
|
+
|
|
278
|
+
After `conda env create -f environment.yml && conda activate deepssf`:
|
|
279
|
+
|
|
280
|
+
| Check | Result |
|
|
281
|
+
|-------|--------|
|
|
282
|
+
| `torch.backends.mps.is_available()` | `True` |
|
|
283
|
+
| `import deepssf, rasterio` | OK |
|
|
284
|
+
| `pytest` | 48 passed, 1 warning |
|
|
285
|
+
| `ruff check src/ tests/` | All checks passed |
|
|
286
|
+
| Example notebook end-to-end | Completed; produced `best_model.pt`, `loss_history.png`, `simulated_trajectory.png`, `training_progress.gif`, `validation_probs.png` |
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## 8. README
|
|
291
|
+
|
|
292
|
+
A "Setting up (for users new to Python)" section was added as the first major
|
|
293
|
+
section, aimed at R users unfamiliar with Python packaging:
|
|
294
|
+
|
|
295
|
+
- Frames a conda environment as equivalent to an `renv` project library.
|
|
296
|
+
- Links to the official Miniconda page; notes Windows users should use the
|
|
297
|
+
Anaconda Prompt and avoid paths with spaces.
|
|
298
|
+
- Mentions Miniforge as an alternative for those who prefer to avoid
|
|
299
|
+
Anaconda's default channel.
|
|
300
|
+
- Copy-pasteable commands: `conda env create`, `conda activate`, optional
|
|
301
|
+
`ipykernel install`, `jupyter lab`.
|
|
302
|
+
- Notes that PyTorch auto-selects MPS / CUDA / CPU with no manual configuration.
|
deepssf-0.1.1/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# deepSSF
|
|
2
|
+
|
|
3
|
+
Deep learning step selection functions for predicting animal movement.
|
|
4
|
+
|
|
5
|
+
This package provides the reusable, installable implementation of the deepSSF
|
|
6
|
+
method. The accompanying paper, tutorials, and reproducibility code live at the
|
|
7
|
+
[deepSSF project site](https://swforrest.github.io/deepSSF/).
|
|
8
|
+
|
|
9
|
+
## Installation (pip only)
|
|
10
|
+
|
|
11
|
+
If you manage your own Python environment, install deepSSF with:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install deepssf
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Development install (editable, with linting and testing tools):
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
git clone https://github.com/swforrest/deepssf
|
|
21
|
+
cd deepssf
|
|
22
|
+
pip install -e ".[dev]"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick start
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
import deepssf
|
|
29
|
+
print(deepssf.__version__)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Setting up (for users new to Python)
|
|
33
|
+
|
|
34
|
+
If you are coming from R, think of a conda environment the way you think of
|
|
35
|
+
an `renv` project library — it is a self-contained Python installation that
|
|
36
|
+
keeps this project's packages separate from everything else on your computer.
|
|
37
|
+
The steps below create one for deepssf and should take about five minutes.
|
|
38
|
+
|
|
39
|
+
### 1. Install Miniconda (once, system-wide)
|
|
40
|
+
|
|
41
|
+
Download and run the installer from the
|
|
42
|
+
[official Miniconda page](https://docs.anaconda.com/miniconda/).
|
|
43
|
+
|
|
44
|
+
- **Windows**: use the **Anaconda Prompt** for all subsequent commands, and
|
|
45
|
+
choose an install path that contains **no spaces** (e.g. `C:\miniconda3`).
|
|
46
|
+
- **macOS / Linux**: a normal terminal works fine.
|
|
47
|
+
|
|
48
|
+
> **Miniforge alternative**: if you prefer to avoid Anaconda's default channel
|
|
49
|
+
> entirely, [Miniforge](https://github.com/conda-forge/miniforge) is a
|
|
50
|
+
> drop-in replacement that ships with `conda-forge` as the only channel.
|
|
51
|
+
|
|
52
|
+
### 2. Create the environment
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
git clone https://github.com/swforrest/deepssf
|
|
56
|
+
cd deepssf
|
|
57
|
+
conda env create -f environment.yml
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
This installs Python 3.11, the geospatial libraries (rasterio / GDAL / PROJ),
|
|
61
|
+
Jupyter Lab, and the deepSSF package itself with all of its dependencies.
|
|
62
|
+
PyTorch is installed via pip with no extra flags — pip automatically picks the
|
|
63
|
+
right build for your hardware: **MPS on Apple Silicon, CUDA on NVIDIA GPUs,
|
|
64
|
+
CPU everywhere else**. No configuration is needed; the package selects the
|
|
65
|
+
correct backend at runtime.
|
|
66
|
+
|
|
67
|
+
### 3. Activate the environment
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
conda activate deepssf
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
You will need to run this once per terminal session before using deepSSF.
|
|
74
|
+
|
|
75
|
+
### 4. (Optional) Register the Jupyter kernel
|
|
76
|
+
|
|
77
|
+
If you use VS Code or another editor that manages its own Jupyter kernel list,
|
|
78
|
+
register the environment so it appears as a kernel option:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
python -m ipykernel install --user --name deepssf --display-name "Python (deepssf)"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 5. Launch Jupyter Lab
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
jupyter lab
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Then open `examples/deepssf_train_validate_example.ipynb` to get started.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Documentation
|
|
95
|
+
|
|
96
|
+
Tutorials and walkthroughs: https://swforrest.github.io/deepSSF/
|
|
97
|
+
|
|
98
|
+
## Citation
|
|
99
|
+
|
|
100
|
+
If you use deepssf in your research, please cite the paper. See `CITATION.cff` or use the citation and link to paper below.
|
|
101
|
+
|
|
102
|
+
Forrest, S. W., Pagendam, D., Hassan, C., Potts, J. R., Drovandi, C., Bode, M., & Hoskins, A. J. (2026). **Predicting animal movement with deepSSF : A deep learning step selection framework**. Methods in Ecology and Evolution, 17(2), 371–391. https://doi.org/10.1111/2041-210x.70136
|
|
103
|
+
|
|
104
|
+
## License
|
|
105
|
+
|
|
106
|
+
MIT — see [LICENSE](LICENSE).
|