File watchdog for fundus camera
Project description
Fundus Camera Watchdog
fundus-camera-watchdog monitors a folder on the fundus camera workstation and uploads files to a clinicedc project using the edc-retinopathy API.
It runs on the camera’s workstation. When the camera finishes an examination and writes files to disk, the watchdog detects them, confirms the subject has a camera session on the server, uploads each file, and moves the completed folder to an archive.
Prerequisites
A running clinicedc server with edc-retinopathy installed and an API token created.
The camera software must write its output into the watched folder using the expected layout (see Folder layout below).
Folder layout
The camera creates one subfolder per subject. Folder names follow a configurable pattern (see subject_folder_pattern). Filenames contain the eye laterality (OD for right, OS for left), extracted via filename_eye_pattern.
Combined report (default):
C:\RetCamOutput\
105-10-0989-3_\
105-10-0989-3_Retina_OD_20260602_121802.jpg
105-10-0989-3_Retina_OS_20260602_121803.jpg
105-10-0989-3_Retina_OD_20260602_121802.dcm
105-10-0989-3_Retina_OS_20260602_121803.dcm
105-10-0989-3_Report_20260602.html
105-10-0001-2_\
...
Per-eye report:
C:\RetCamOutput\
105-10-0989-3_\
105-10-0989-3_Retina_OD_20260602_121802.jpg
105-10-0989-3_Retina_OS_20260602_121803.jpg
105-10-0989-3_Report_OD_20260602.html
105-10-0989-3_Report_OS_20260602.html
Processing is triggered once a subject folder contains the expected number of files:
Combined (default): at least 2 JPEG and 1 HTML file.
Per-eye: at least 2 JPEG and 2 HTML files.
DICOM (.dcm) files are uploaded when present but are not required for triggering.
Quick start
Generate a sample config in the camera output folder:
cd C:\RetCamOutput uvx fundus-camera-watchdog --create-config
This creates fundus_camera_watchdog.json with sensible defaults.
Edit the config to fill in api_url, subject_folder_pattern, and optionally filename_eye_pattern, device_id, etc.
Set the API token as an environment variable (recommended):
REM Windows (persists across reboots) setx FUNDUS_CAMERA_WATCHDOG_TOKEN "YOUR_DRF_TOKEN"
Start the watchdog:
cd C:\RetCamOutput uvx fundus-camera-watchdog
Configuration
Settings are resolved in the following order (highest priority first):
CLI flags (e.g. --api-url)
JSON config file
FUNDUS_CAMERA_WATCHDOG_TOKEN environment variable (token only)
Built-in defaults
Config file discovery
If --config is not provided, the watchdog looks for fundus_camera_watchdog.json in the watch directory (or the current directory if --watch-dir is also omitted). Use --create-config to generate a sample.
Example fundus_camera_watchdog.json:
{
"watch_dir": "C:\\RetCamOutput",
"api_url": "https://edc.example.com",
"device_id": "RET-CAM-001",
"site_id": "40",
"report_type": "combined",
"subject_folder_pattern": "^(?P<subject_identifier>\\d{3}-\\d{2}-\\d{4}-\\d)_$",
"filename_eye_pattern": "(?P<eye>OD|OS)"
}
Required settings
- watch_dir
Folder the camera writes subject subfolders to. Defaults to the current directory if not provided.
- api_url
Base URL of the EDC server (e.g. https://edc.example.com).
- token
DRF authentication token. Can be provided via --token, the config file, or FUNDUS_CAMERA_WATCHDOG_TOKEN env var (recommended).
Optional settings
- device_id
Identifier for this camera (sent to the server on resolve).
- site_id
Study site identifier.
- report_type
How the camera produces report files. combined (default) means a single HTML file covers both eyes; per_eye means one HTML per eye.
- subject_folder_pattern
Regex to match subject folder names in the watch directory. Use a named group subject_identifier to extract the ID from the folder name. Default: ^(?P<subject_identifier>.+)$ (matches everything, folder name used as-is).
Example for folders like 105-40-1232-0_:
"subject_folder_pattern": "^(?P<subject_identifier>\\d{3}-\\d{2}-\\d{4}-\\d)_$"This matches the folder and extracts 105-40-1232-0 as the subject identifier (stripping the trailing underscore).
- filename_eye_pattern
Regex to extract eye laterality from filenames. Use a named group eye. Default: (?P<eye>OD|OS).
The extracted value is normalised automatically. All of the following are recognised:
Left eye: L, LE, OS, LEFT
Right eye: R, RE, OD, RIGHT
- log_level
One of DEBUG, INFO (default), WARNING, ERROR.
Usage
Run from the camera output folder:
cd C:\RetCamOutput uvx fundus-camera-watchdog
With an explicit config file:
uvx fundus-camera-watchdog --config C:\path\to\fundus_camera_watchdog.json
CLI flags override any value from the config file:
uvx fundus-camera-watchdog --log-level DEBUG --report-type per_eye
Without a config file:
uvx fundus-camera-watchdog ^
--watch-dir C:\RetCamOutput ^
--api-url https://edc.example.com ^
--token YOUR_TOKEN ^
--device-id RET-CAM-001 ^
--subject-folder-pattern "^(?P<subject_identifier>\d{3}-\d{2}-\d{4}-\d)_$"
Stop with Ctrl+C.
What it does
The watchdog runs continuously and performs the following for each subject:
Detect – watches for new files in subject subfolders using filesystem events (watchdog), plus a periodic sweep every 60 seconds as a safety net.
Wait – each file is given up to 30 seconds to stabilise (stop growing) before being registered.
Classify – extracts eye laterality from each filename using the configured pattern. Maps files to API types:
*.jpg + OD -> right
*.jpg + OS -> left
*.dcm + OD -> right_dicom
*.dcm + OS -> left_dicom
*.html (combined) -> report
*.html + OD (per_eye) -> right_report
*.html + OS (per_eye) -> left_report
Resolve – POST /api/retinopathy/resolve/ confirms a CameraSession exists on the server for this subject.
Upload – sends each file to the server. Original filenames are preserved. Each upload includes a SHA-256 checksum. Multiple files per eye are supported.
Verify – GET .../status/ confirms the session received the expected files.
Archive – the subject folder is moved to <watch-dir>/processed/<subject_id>_<timestamp>/.
Error handling
Retries – every API call is retried up to 3 times with a 5-second delay.
Failed subjects – if any step fails, the subject is left in place and retried on the next 60-second sweep.
Startup scan – on (re)start the watchdog scans all existing subject folders, picking up where it left off.
Thread safety – file detection and upload run on separate threads with proper locking.
Project details
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 fundus_camera_watchdog-0.5.0.tar.gz.
File metadata
- Download URL: fundus_camera_watchdog-0.5.0.tar.gz
- Upload date:
- Size: 13.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d5078659b7b9039dbd956b402cf89116836533762a0555636a7391bf2b94dc1b
|
|
| MD5 |
72440c487e6807af8ca3bfc532c02cd5
|
|
| BLAKE2b-256 |
107fa1df80761841351a52b78d9fa97a2d571824a1052818c1be23608b6de3cb
|
File details
Details for the file fundus_camera_watchdog-0.5.0-py3-none-any.whl.
File metadata
- Download URL: fundus_camera_watchdog-0.5.0-py3-none-any.whl
- Upload date:
- Size: 14.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19f78ceed4d8af1373dff8affc90cf0bb1faaf65117e9854c3640b33f90b943c
|
|
| MD5 |
35cd1a9afeb0fc0552f86c527d82dfaf
|
|
| BLAKE2b-256 |
d209b89d1c4cf5d0ccaf38cf6049936d9874d47ed120f86d12d2a0ad59804afb
|