CamTrapTools 0.6.0__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.
- camtraptools-0.6.0/.github/workflows/ci.yml +35 -0
- camtraptools-0.6.0/.github/workflows/publish.yml +23 -0
- camtraptools-0.6.0/.gitignore +11 -0
- camtraptools-0.6.0/CHANGELOG.md +270 -0
- camtraptools-0.6.0/CITATION.cff +19 -0
- camtraptools-0.6.0/LICENSE +21 -0
- camtraptools-0.6.0/PKG-INFO +302 -0
- camtraptools-0.6.0/README.md +265 -0
- camtraptools-0.6.0/docs/adapted-examples.jpg +0 -0
- camtraptools-0.6.0/docs/case-study-kgalagadi.md +285 -0
- camtraptools-0.6.0/docs/report.png +0 -0
- camtraptools-0.6.0/docs/review.jpg +0 -0
- camtraptools-0.6.0/docs/user-guide.md +819 -0
- camtraptools-0.6.0/examples/kgalagadi/prepare.py +129 -0
- camtraptools-0.6.0/examples/kgalagadi/sensitivity.py +173 -0
- camtraptools-0.6.0/pyproject.toml +60 -0
- camtraptools-0.6.0/src/camtraptools/__init__.py +3 -0
- camtraptools-0.6.0/src/camtraptools/activity.py +255 -0
- camtraptools-0.6.0/src/camtraptools/adapt.py +453 -0
- camtraptools-0.6.0/src/camtraptools/check.py +232 -0
- camtraptools-0.6.0/src/camtraptools/cli.py +887 -0
- camtraptools-0.6.0/src/camtraptools/compare.py +189 -0
- camtraptools-0.6.0/src/camtraptools/crops.py +191 -0
- camtraptools-0.6.0/src/camtraptools/detect.py +319 -0
- camtraptools-0.6.0/src/camtraptools/ecology.py +372 -0
- camtraptools-0.6.0/src/camtraptools/evaluate.py +267 -0
- camtraptools-0.6.0/src/camtraptools/events.py +104 -0
- camtraptools-0.6.0/src/camtraptools/export.py +159 -0
- camtraptools-0.6.0/src/camtraptools/importer.py +116 -0
- camtraptools-0.6.0/src/camtraptools/ingest.py +376 -0
- camtraptools-0.6.0/src/camtraptools/labels.py +297 -0
- camtraptools-0.6.0/src/camtraptools/report.py +315 -0
- camtraptools-0.6.0/src/camtraptools/review.py +155 -0
- camtraptools-0.6.0/src/camtraptools/reviews.py +192 -0
- camtraptools-0.6.0/src/camtraptools/templates/evaluation.html +115 -0
- camtraptools-0.6.0/src/camtraptools/templates/event.html +148 -0
- camtraptools-0.6.0/src/camtraptools/templates/events.html +48 -0
- camtraptools-0.6.0/tests/conftest.py +31 -0
- camtraptools-0.6.0/tests/test_activity.py +125 -0
- camtraptools-0.6.0/tests/test_adapt.py +301 -0
- camtraptools-0.6.0/tests/test_check.py +233 -0
- camtraptools-0.6.0/tests/test_cli.py +754 -0
- camtraptools-0.6.0/tests/test_compare.py +113 -0
- camtraptools-0.6.0/tests/test_crops.py +152 -0
- camtraptools-0.6.0/tests/test_deployments.py +42 -0
- camtraptools-0.6.0/tests/test_detect.py +275 -0
- camtraptools-0.6.0/tests/test_ecology.py +229 -0
- camtraptools-0.6.0/tests/test_evaluate.py +255 -0
- camtraptools-0.6.0/tests/test_events.py +169 -0
- camtraptools-0.6.0/tests/test_export.py +208 -0
- camtraptools-0.6.0/tests/test_field_sheet.py +183 -0
- camtraptools-0.6.0/tests/test_importer.py +146 -0
- camtraptools-0.6.0/tests/test_ingest.py +38 -0
- camtraptools-0.6.0/tests/test_labels.py +187 -0
- camtraptools-0.6.0/tests/test_media.py +99 -0
- camtraptools-0.6.0/tests/test_recorded_periods.py +152 -0
- camtraptools-0.6.0/tests/test_report.py +108 -0
- camtraptools-0.6.0/tests/test_review.py +250 -0
- camtraptools-0.6.0/tests/test_reviews.py +163 -0
- camtraptools-0.6.0/uv.lock +3936 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
name: Python ${{ matrix.python }} on ${{ matrix.os }}
|
|
14
|
+
runs-on: ${{ matrix.os }}
|
|
15
|
+
strategy:
|
|
16
|
+
fail-fast: false
|
|
17
|
+
matrix:
|
|
18
|
+
os: [ubuntu-latest]
|
|
19
|
+
python: ["3.11", "3.12", "3.13", "3.14"]
|
|
20
|
+
include:
|
|
21
|
+
- os: windows-latest
|
|
22
|
+
python: "3.14"
|
|
23
|
+
- os: macos-latest
|
|
24
|
+
python: "3.14"
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
27
|
+
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
28
|
+
with:
|
|
29
|
+
python-version: ${{ matrix.python }}
|
|
30
|
+
- name: Install dependencies
|
|
31
|
+
run: uv sync --locked
|
|
32
|
+
- name: Lint
|
|
33
|
+
run: uv run ruff check src tests
|
|
34
|
+
- name: Test
|
|
35
|
+
run: uv run pytest
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
publish:
|
|
12
|
+
name: Build and publish
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
environment: pypi
|
|
15
|
+
permissions:
|
|
16
|
+
id-token: write
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
19
|
+
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
20
|
+
- name: Build
|
|
21
|
+
run: uv build
|
|
22
|
+
- name: Publish
|
|
23
|
+
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project uses
|
|
5
|
+
[Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.6.0] - 2026-10-20
|
|
10
|
+
|
|
11
|
+
Ready for real surveys: large surveys and interrupted runs, other folder layouts,
|
|
12
|
+
camera clock correction, importing existing labels, the relative abundance index, a
|
|
13
|
+
user guide, and packaging for PyPI.
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- `labels` command: imports existing image labels from a Camtrap DP package (human
|
|
18
|
+
classifications first; event-level observations label every image in the event), a
|
|
19
|
+
Wildlife Insights `images.csv` export (with its taxonomy), a Timelapse CSV export or
|
|
20
|
+
any CSV (`--species-column`, `--path-column`, `--file-column`, `--folder-column`), and
|
|
21
|
+
writes a truth file for `evaluate`, `crops` and `compare`. Images are matched by path,
|
|
22
|
+
without leading folders, then by unique file name; common names are turned into
|
|
23
|
+
scientific names with SpeciesNet's taxonomy when its model is downloaded, or with a
|
|
24
|
+
`--names` mapping; blank labels are recognised, and unmatched, ambiguous and
|
|
25
|
+
unrecognised labels are reported.
|
|
26
|
+
- Clock correction: optional `cameraTime` and `actualTime` field-sheet columns (what a
|
|
27
|
+
camera's clock showed and the real time at that moment) make `ingest` shift all of
|
|
28
|
+
that deployment's image times by the difference before deployment periods are
|
|
29
|
+
derived, keep each image's original camera time in `mediaComments`, and report the
|
|
30
|
+
correction. `check` suggests these columns when it finds a wrong clock.
|
|
31
|
+
- Relative abundance index in `ecology`: independent events per 100 camera-days for
|
|
32
|
+
each species, in `occupancy.csv` and the printed table, and per site and species in
|
|
33
|
+
`rai.csv`.
|
|
34
|
+
- `detect` saves SpeciesNet's progress every 10 minutes and continues an interrupted
|
|
35
|
+
run when the same command is run again, discarding saved progress from a run with
|
|
36
|
+
other settings; it shows SpeciesNet's progress bars.
|
|
37
|
+
- `ingest --folder-depth` reads deployments from deeper folder levels, such as
|
|
38
|
+
`site/camera/` (deployment `site_camera`).
|
|
39
|
+
- `ingest` reports the files it skipped by type, such as videos, and JPEG images
|
|
40
|
+
outside any deployment folder.
|
|
41
|
+
- User guide (`docs/user-guide.md`): installation, preparing images and field sheets,
|
|
42
|
+
every step from `ingest` to `export` with example output and how to read it, choosing
|
|
43
|
+
a workflow, the files in a package, troubleshooting and a command reference.
|
|
44
|
+
|
|
45
|
+
- Packaging for PyPI: project links, keywords and classifiers, a workflow that
|
|
46
|
+
publishes to PyPI with trusted publishing when a GitHub release is published, and a
|
|
47
|
+
`CITATION.cff` file for citing the toolkit.
|
|
48
|
+
|
|
49
|
+
### Changed
|
|
50
|
+
|
|
51
|
+
- The README's images and links are absolute, so they also work on PyPI.
|
|
52
|
+
- The message for a missing `detect` extra gives the `pip` command as well.
|
|
53
|
+
- `events` summarises all events at once: 100,000 images now take about a second
|
|
54
|
+
instead of more than ten minutes, with identical results.
|
|
55
|
+
- Activity curves of species with many events are computed from one-minute bins with
|
|
56
|
+
a fast Fourier transform, so `ecology` handles thousands of events per species in
|
|
57
|
+
seconds; smaller samples are computed exactly as before.
|
|
58
|
+
|
|
59
|
+
### Fixed
|
|
60
|
+
|
|
61
|
+
- An event whose images all had a classifier probability of 0 got no confidence; its
|
|
62
|
+
species is now chosen by the number of images.
|
|
63
|
+
|
|
64
|
+
## [0.5.0] - 2026-10-20
|
|
65
|
+
|
|
66
|
+
Ecology: detection histories, occupancy corrected for imperfect detection, daily
|
|
67
|
+
activity and overlap between species, and a comparison of how AI mistakes, review and
|
|
68
|
+
adaptation change these results.
|
|
69
|
+
|
|
70
|
+
### Added
|
|
71
|
+
|
|
72
|
+
- `ecology` command: writes a detection history per species (sites by sampling
|
|
73
|
+
occasions of `--occasion-days`, default 7, with 1 for recorded, 0 for not recorded and
|
|
74
|
+
empty when no camera was running), the camera days per site and occasion
|
|
75
|
+
(`effort.csv`) and naive occupancy per species (`occupancy.csv`): events, sites
|
|
76
|
+
recorded out of sites surveyed, and the share of surveyed occasions with a record at
|
|
77
|
+
those sites. Sites are camera locations, reviewed decisions replace the AI's, and
|
|
78
|
+
events identified only to a higher taxon are left out and listed unless `--all-taxa`
|
|
79
|
+
or `--taxon` is given.
|
|
80
|
+
- Occupancy model in `ecology`: for each species recorded at three or more sites, the
|
|
81
|
+
single-season occupancy model (MacKenzie et al. 2002) estimates the probability that
|
|
82
|
+
a site is occupied, with a 95% profile-likelihood interval, from a daily detection
|
|
83
|
+
probability applied to each occasion's camera days. `occupancy.csv` and the printed
|
|
84
|
+
table add the chance of recording the species in a full occasion and of missing it
|
|
85
|
+
over the whole survey at an occupied site, with a warning when detection is too rare
|
|
86
|
+
to estimate occupancy or the interval is wider than 0.5.
|
|
87
|
+
- Activity patterns in `ecology`: for each species with at least
|
|
88
|
+
`--min-activity-events` events (default 20), a daily activity curve from the start
|
|
89
|
+
times of its independent events, as a von Mises kernel density with the bandwidth of
|
|
90
|
+
Taylor (2008) estimated from trigonometric moments up to order 3, and its busiest
|
|
91
|
+
time of day. The overlap coefficient between every pair of species (Δ₁, or Δ₄ when
|
|
92
|
+
both have 75 or more events; Ridout & Linkie 2009) comes with a 95% percentile
|
|
93
|
+
bootstrap interval from 999 resamples. Writes `activity.csv`, `overlap.csv` and an
|
|
94
|
+
`activity.svg` chart of the six most recorded species.
|
|
95
|
+
- `compare` command: runs the ecology analyses on every labelling of a survey (the
|
|
96
|
+
machine's labels alone, with reviews, ground truth from `--truth`, and other packages
|
|
97
|
+
with `--other NAME=FOLDER`) and compares them with the reference (truth if given,
|
|
98
|
+
otherwise the reviews): species and species-at-site records missed or added, mean
|
|
99
|
+
naive and modelled occupancy error, the difference between each species' activity
|
|
100
|
+
curves (1 − Δ) and the error in overlaps between species. Writes each source's
|
|
101
|
+
ecology results, `scores.csv`, `comparison.csv` and `overlap_comparison.csv`.
|
|
102
|
+
- Ecological consequences in the case study, with `examples/kgalagadi/sensitivity.py`,
|
|
103
|
+
which builds labellings with cross-fitted adapted layers and with simulated review of
|
|
104
|
+
the least confident 5% to 50% of events, and compares them with the volunteer labels.
|
|
105
|
+
- `examples/kgalagadi/prepare.py` also writes a field sheet with each camera's season,
|
|
106
|
+
from its first and last capture including blank ones.
|
|
107
|
+
|
|
108
|
+
## [0.4.0] - 2026-10-19
|
|
109
|
+
|
|
110
|
+
Evaluation and regional adaptation: measure the AI against ground truth, build crop
|
|
111
|
+
datasets split by camera, adapt SpeciesNet to a region and use the adapted layer in
|
|
112
|
+
`detect`, with a case study on Snapshot Kgalagadi.
|
|
113
|
+
|
|
114
|
+
### Added
|
|
115
|
+
|
|
116
|
+
- `evaluate` command: compares the AI's event-level decisions with ground truth, either
|
|
117
|
+
the package's reviews or a CSV of image labels (`--truth`, with `filePath` and
|
|
118
|
+
`scientificName` and optional `genus`, `family`, `order` and `class` columns). Each
|
|
119
|
+
event is correct, correct only above species level (verified against the true
|
|
120
|
+
taxon's ancestry), unverified, or wrong. The command prints per-label precision and
|
|
121
|
+
recall and every event that was not correct, and writes `evaluation.csv`.
|
|
122
|
+
- Confidence thresholds: `evaluate` prints, for each label the AI used, the lowest event
|
|
123
|
+
confidence at which its answers reach a target precision (`--target-precision`,
|
|
124
|
+
default 0.95) and how many answers that keeps. Labels with fewer than ten answers are
|
|
125
|
+
flagged as unreliable, and `evaluation.csv` includes each event's confidence.
|
|
126
|
+
- Failure report: `evaluate --report report.html --images DIR` writes a self-contained
|
|
127
|
+
HTML page with the outcomes, precision and recall, thresholds and every event the AI
|
|
128
|
+
did not get exactly right, with its images and bounding boxes.
|
|
129
|
+
- `crops` command: saves a JPEG crop of every animal detection with a known true label
|
|
130
|
+
(from `--truth` or the reviews) in `train/`, `val/` and `test/` folders with one
|
|
131
|
+
subfolder per label, and lists them in `crops.csv`. Each camera location (its
|
|
132
|
+
`locationID`, `locationName` or deployment) goes to a single split, so evaluation uses
|
|
133
|
+
unseen backgrounds; target shares are set with `--val` and `--test`. Boxes are padded
|
|
134
|
+
(`--padding`), crops under 32 pixels and detections whose true label is blank are
|
|
135
|
+
skipped, the padding is recorded, and the command warns about labels with no or few
|
|
136
|
+
training crops.
|
|
137
|
+
- `adapt` command: trains a new final layer for SpeciesNet on the crops from `crops`,
|
|
138
|
+
for only the labels in the training split, on frozen SpeciesNet features. Labels
|
|
139
|
+
SpeciesNet knows start from its own weights, the layer from the epoch with the lowest
|
|
140
|
+
validation loss is kept (`--epochs`, `--learning-rate`, `--seed`, `--device`), and
|
|
141
|
+
`--balanced` weights classes by their number of crops. The command saves the layer as `adapted.pt`, every crop's prediction
|
|
142
|
+
in `predictions.csv` and the crops' SpeciesNet features in `features.npz`, which later
|
|
143
|
+
runs reuse. It prints accuracy per split and per label for SpeciesNet as run by
|
|
144
|
+
`detect`, SpeciesNet limited to the training labels and the adapted layer, and the
|
|
145
|
+
held-out labels it cannot name. Requires the optional `detect` extra.
|
|
146
|
+
- `adapt` chooses a confidence threshold on the validation crops: the lowest at which
|
|
147
|
+
the adapted layer is as precise as SpeciesNet's species-level answers. It is saved in
|
|
148
|
+
`adapted.pt` with the crop padding.
|
|
149
|
+
- `detect --adapted MODEL_DIR` classifies every animal detection with an adapted layer,
|
|
150
|
+
cropped like the training crops, and uses its answer at or above the layer's threshold
|
|
151
|
+
(or `--adapted-threshold`), except where SpeciesNet named a species the layer was not
|
|
152
|
+
trained on. Answers are saved in `adapted.csv`, observations record the adapted layer
|
|
153
|
+
in `classifiedBy`, and the command prints how many of SpeciesNet's answers changed.
|
|
154
|
+
- `evaluate --deployment` compares only events from the given deployments, such as
|
|
155
|
+
cameras held out from training.
|
|
156
|
+
- Case study (`docs/case-study-kgalagadi.md`): adapting SpeciesNet on Snapshot
|
|
157
|
+
Kgalagadi Season 1 raised correct events on seven held-out cameras from 72 to 92 of
|
|
158
|
+
104. `examples/kgalagadi/prepare.py` downloads the data and writes the truth file to
|
|
159
|
+
reproduce it.
|
|
160
|
+
|
|
161
|
+
### Changed
|
|
162
|
+
|
|
163
|
+
- Per-label precision counts answers that are correct above species level (such as
|
|
164
|
+
*Bovidae* for a gemsbok) as right; recall still requires the exact taxon.
|
|
165
|
+
|
|
166
|
+
### Fixed
|
|
167
|
+
|
|
168
|
+
- The review app screenshot in the README was missing from the repository.
|
|
169
|
+
|
|
170
|
+
## [0.3.0] - 2026-10-19
|
|
171
|
+
|
|
172
|
+
Human review: a local web app that shows the AI's least confident decisions first and
|
|
173
|
+
records corrections as human observations.
|
|
174
|
+
|
|
175
|
+
### Added
|
|
176
|
+
|
|
177
|
+
- `review` command: a local web app (on 127.0.0.1 only) that shows each event's images
|
|
178
|
+
with the AI's bounding boxes, labels and confidences, the event-level decision with its
|
|
179
|
+
vote share and common name, and previous/next navigation with the arrow keys. Only
|
|
180
|
+
images listed in the package can be served.
|
|
181
|
+
- Review decisions: each event page has a form, pre-filled with the AI's decision, to
|
|
182
|
+
accept or correct the type, scientific name and count. Decisions are stored in
|
|
183
|
+
`reviews.csv` with the reviewer's name (`--reviewer`) and time, and written to
|
|
184
|
+
`observations.csv` as event-level observations with `classificationMethod` `human`,
|
|
185
|
+
next to the machine's. Saving moves to the next event. `events` re-applies reviews,
|
|
186
|
+
`export` uses the human decision for reviewed events, and forms are protected by a
|
|
187
|
+
per-session token.
|
|
188
|
+
- The review app shows events least confident first (`--order uncertainty`, the default,
|
|
189
|
+
or `--order time`), scoring each event by its vote share and best classifier
|
|
190
|
+
probability, with animals not identified to species capped at 0.5. It starts at the
|
|
191
|
+
least confident unreviewed event and, after saving, moves to the next unreviewed one.
|
|
192
|
+
- Review progress on every page, an "all events" page with confidence and review status,
|
|
193
|
+
and keyboard shortcuts: Enter or A to save, B for blank, 1–9 for the count, S for the
|
|
194
|
+
species field and the arrow keys to move between events.
|
|
195
|
+
- `review` uses another port when the requested one is in use, and says so.
|
|
196
|
+
- `review-stats` command: reviewed events, agreement with the AI, each correction (AI →
|
|
197
|
+
reviewer), changes per AI confidence band and review speed (pauses over ten minutes
|
|
198
|
+
count as breaks).
|
|
199
|
+
|
|
200
|
+
## [0.2.0] - 2026-10-19
|
|
201
|
+
|
|
202
|
+
AI detection and species identification, independent events, importing other tools'
|
|
203
|
+
results and validated Camtrap DP export.
|
|
204
|
+
|
|
205
|
+
### Added
|
|
206
|
+
|
|
207
|
+
- `detect` command: runs SpeciesNet on every ingested image. SpeciesNet uses
|
|
208
|
+
MegaDetector v5a to find animals, people and vehicles, classifies each animal and
|
|
209
|
+
applies geofencing (`--country`, `--admin1-region`) and taxonomic rollup. Results are
|
|
210
|
+
saved as `speciesnet.json`, and the command prints the images per category and per
|
|
211
|
+
species for each deployment. Requires the optional `detect` extra; SpeciesNet is
|
|
212
|
+
Apache-2.0 and its MegaDetector inference code is GPL-licensed.
|
|
213
|
+
- `detect` writes `observations.csv` with Camtrap DP media-level observations: one per
|
|
214
|
+
detection at or above `--threshold` (default 0.2) with bounding box, `scientificName`
|
|
215
|
+
(species, or a higher taxon such as *Bovidae* when SpeciesNet rolls up), classifier
|
|
216
|
+
probability and model version; `blank` for empty images, `unknown` when SpeciesNet
|
|
217
|
+
cannot tell, and `unclassified` for images it could not process.
|
|
218
|
+
- `detect` reuses existing results for the same model and country, so trying another
|
|
219
|
+
`--threshold` is instant; `--rerun` runs SpeciesNet again, and `--images` is only
|
|
220
|
+
needed when it runs.
|
|
221
|
+
- `events` command: groups consecutive images at each deployment into independent
|
|
222
|
+
events (a new event after more than `--gap` minutes without images, default 30),
|
|
223
|
+
fills in `eventID` on media-level observations and adds one event-level observation
|
|
224
|
+
per event. The event's species is chosen by summed classifier probability across its
|
|
225
|
+
images, its count is the largest number of individuals in any single image, and the
|
|
226
|
+
command prints independent animal events per taxon and deployment. Rerunning
|
|
227
|
+
replaces earlier event-level observations.
|
|
228
|
+
- `import` command: reads results in the MegaDetector batch format (MegaDetector,
|
|
229
|
+
AddaxAI, Timelapse, run_md_and_speciesnet) or SpeciesNet's format, matches their
|
|
230
|
+
image paths to the package even when they are relative to another folder, and writes
|
|
231
|
+
them as `speciesnet.json` and `observations.csv`, so `events` and later steps work
|
|
232
|
+
unchanged. Classification taxonomy is kept when it is in SpeciesNet's format; the
|
|
233
|
+
command reports how many images matched, were ignored or have no results, and
|
|
234
|
+
images without results are recorded as `unclassified`.
|
|
235
|
+
- `export` command: writes a complete Camtrap DP 1.0.2 data package (`datapackage.json`,
|
|
236
|
+
`deployments.csv`, `media.csv`, `observations.csv`) to a separate folder, with every
|
|
237
|
+
standard column, time zones on all timestamps (`--timezone`, e.g.
|
|
238
|
+
`Africa/Johannesburg`, including daylight saving), spatial, temporal and taxonomic
|
|
239
|
+
coverage, contributors, project details (`--sampling-design`) and data and media
|
|
240
|
+
licenses. Images without a timestamp and non-standard deployment columns are left out
|
|
241
|
+
and reported. Exported packages pass Frictionless validation against the Camtrap DP
|
|
242
|
+
profile, which is checked in the test suite.
|
|
243
|
+
- `detect` records when SpeciesNet ran with the computer's UTC offset.
|
|
244
|
+
|
|
245
|
+
## [0.1.0] - 2026-10-15
|
|
246
|
+
|
|
247
|
+
First release: ingest, quality checks and an HTML health report.
|
|
248
|
+
|
|
249
|
+
### Added
|
|
250
|
+
|
|
251
|
+
- `ingest` command: scans one folder per camera deployment, reads capture times from
|
|
252
|
+
EXIF and writes `media.csv` and `deployments.csv` in Camtrap DP format.
|
|
253
|
+
- Optional CSV or Excel field sheets with coordinates, camera details and recorded
|
|
254
|
+
deployment periods, which take priority over image dates.
|
|
255
|
+
- Field-sheet validation: duplicate IDs, impossible coordinates, unreadable or reversed
|
|
256
|
+
dates, images outside the recorded period, and deployment IDs that do not match image
|
|
257
|
+
folders, with suggestions for near matches.
|
|
258
|
+
- `check` command: missing timestamps, reset or wrongly set clocks, time going
|
|
259
|
+
backwards, long gaps (`--max-gap-days`), days with excessive triggers and cameras
|
|
260
|
+
without night or day images, with key numbers for each deployment.
|
|
261
|
+
- `report` command: a self-contained HTML report with an interactive timeline, a
|
|
262
|
+
summary table and all issues, in light and dark mode.
|
|
263
|
+
- Continuous integration on Python 3.11–3.14 (Linux) and on Windows and macOS.
|
|
264
|
+
|
|
265
|
+
[0.6.0]: https://github.com/ivanposavecwildlife/CamTrapTools/releases/tag/v0.6.0
|
|
266
|
+
[0.5.0]: https://github.com/ivanposavecwildlife/CamTrapTools/releases/tag/v0.5.0
|
|
267
|
+
[0.4.0]: https://github.com/ivanposavecwildlife/CamTrapTools/releases/tag/v0.4.0
|
|
268
|
+
[0.3.0]: https://github.com/ivanposavecwildlife/CamTrapTools/releases/tag/v0.3.0
|
|
269
|
+
[0.2.0]: https://github.com/ivanposavecwildlife/CamTrapTools/releases/tag/v0.2.0
|
|
270
|
+
[0.1.0]: https://github.com/ivanposavecwildlife/CamTrapTools/releases/tag/v0.1.0
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use CamTrapTools in your work, please cite it as below."
|
|
3
|
+
title: "CamTrapTools: open-source toolkit for camera-trap projects, from SD card to ecological answers"
|
|
4
|
+
type: software
|
|
5
|
+
authors:
|
|
6
|
+
- family-names: Posavec
|
|
7
|
+
given-names: Ivan
|
|
8
|
+
repository-code: "https://github.com/ivanposavecwildlife/CamTrapTools"
|
|
9
|
+
url: "https://github.com/ivanposavecwildlife/CamTrapTools"
|
|
10
|
+
license: MIT
|
|
11
|
+
version: "0.6.0"
|
|
12
|
+
date-released: "2026-10-20"
|
|
13
|
+
keywords:
|
|
14
|
+
- camera traps
|
|
15
|
+
- wildlife monitoring
|
|
16
|
+
- ecology
|
|
17
|
+
- Camtrap DP
|
|
18
|
+
- SpeciesNet
|
|
19
|
+
- occupancy
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ivan Posavec
|
|
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.
|