Skip to main content

pypi actions codecov downloads clinicedc

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 an entry in the Eye Exam Register on the server, uploads each file, and moves the completed folder to an archive.

Prerequisites

  1. A running clinicedc server with edc-retinopathy installed and an API token created.

  2. 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 DICOM and 1 HTML file.

  • Per-eye: at least 2 DICOM and 2 HTML files.

By default only DICOM files are uploaded. JPEG files are ignored unless --include-jpgs is set. HTML reports can be made optional with --no-require-html.

Quick start

  1. 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.

  2. Edit the config to fill in api_url, subject_folder_pattern, and optionally filename_eye_pattern, device_id, etc.

  3. Set the API token as an environment variable (recommended):

    REM Windows (persists across reboots)
    setx FUNDUS_CAMERA_WATCHDOG_TOKEN "YOUR_DRF_TOKEN"
  4. Start the watchdog:

    cd C:\RetCamOutput
    uvx fundus-camera-watchdog

Configuration

Settings are resolved in the following order (highest priority first):

  1. CLI flags (e.g. --api-url)

  2. JSON config file

  3. FUNDUS_CAMERA_WATCHDOG_TOKEN environment variable (token only)

  4. 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

include_jpgs

Include JPEG files in uploads and readiness checks. By default only DICOM files are uploaded. Set to true or use --include-jpgs to also upload JPEGs. Default: false.

require_html

Whether HTML report files are required before triggering uploads. Set to false or use --no-require-html to upload as soon as enough DICOM (or JPEG) files are present. Default: true.

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:

  1. Detect – watches for new files in subject subfolders using filesystem events (watchdog), plus a periodic sweep every 60 seconds as a safety net.

  2. Wait – each file is given up to 30 seconds to stabilise (stop growing) before being registered.

  3. Classify – extracts eye laterality from each filename using the configured pattern. Maps files to API types:

    • *.dcm + OD -> right_dicom

    • *.dcm + OS -> left_dicom

    • *.jpg + OD -> right (only with --include-jpgs)

    • *.jpg + OS -> left (only with --include-jpgs)

    • *.html (combined) -> report

    • *.html + OD (per_eye) -> right_report

    • *.html + OS (per_eye) -> left_report

  4. Resolve – POST /api/retinopathy/resolve/ confirms an EyeExamRegister exists on the server for this subject. If the server answers no_eligible_session, every register for the subject is complete or contraindicated and no upload can succeed until someone creates a new one in the EDC, so the subject folder is set aside (see Rejected subjects below) rather than retried.

  5. Upload – sends each file to the server. Original filenames are preserved. Each upload includes a SHA-256 checksum. Multiple files per eye are supported. By default only DICOM and HTML files are uploaded; use --include-jpgs to also upload JPEG images.

  6. Verify – GET .../status/ confirms the session received the expected files.

  7. 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.

  • Rejected subjects – if the server reports that no register can accept the upload (no_eligible_session), retrying cannot help. The subject folder is moved to <watch-dir>/rejected/<subject_id>_<timestamp>/ and an error is logged naming the subject. Create a new entry in the Eye Exam Register in the EDC, then move the folder back under the watch directory to upload it.

  • 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.

Metadata

Release files for fundus-camera-watchdog 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fundus-camera-watchdog 1.0.0
File Size Uploaded
fundus_camera_watchdog-1.0.0.tar.gz 15.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fundus-camera-watchdog 1.0.0
File Interpreter ABI Platform
fundus_camera_watchdog-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 32.1 kB

Release files / fundus_camera_watchdog-1.0.0.tar.gz

Download URL fundus_camera_watchdog-1.0.0.tar.gz
Size 15.5 kB
Tags Source
SHA-256 checksum
How to use checksums
e7bc4295f1e0f596b4e01d0f8921e6a86762712f52b1e651c371a68a828a7711
BLAKE2b-256 checksum
How to use checksums
d38e7b543f778ffca283d149e4ba3dcb1f605b1b5ff4c09efdcd652837241928
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.11 {"installer":{"name":"uv","version":"0.12.11","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}

Release files / fundus_camera_watchdog-1.0.0-py3-none-any.whl

Download URL fundus_camera_watchdog-1.0.0-py3-none-any.whl
Size 16.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f65fed4a32c69a1ac248a8519d6434a5780f293d3ee0b662dc55d0e22264bd53
BLAKE2b-256 checksum
How to use checksums
55e32845c4c0782053ae40706e13eb6e3f24057dcca027000a15b1b5143e814e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.11 {"installer":{"name":"uv","version":"0.12.11","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}

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page