Skip to main content

obdeect

obdeect is a C++20 optical ray tracing prototype for imaging atmospheric Cherenkov telescopes. The C++ core uses only the standard library. Python provides plotting, PSF analysis, and model import tools.

Installation and Build

For a released platform wheel, Python 3.10+ is sufficient. The wheel contains the C++20 ray-tracing executables and headers. A source checkout additionally needs a C++20 compiler and CMake 3.20+.

Install the current development distribution from PyPI and run the packaged tracer without a source checkout:

python -m pip install obdeect-dev
obdeect-simtools-raytrace --telescope MST --photons 10000 --output trace.csv

Installation and build steps are as follows:

python -m venv .venv
source .venv/bin/activate
python -m pip install -e '.[dev]'
cmake --preset debug
cmake --build --preset debug

Test your installation with:

ctest --test-dir build/debug --output-on-failure
python -m unittest discover -s python/tests

Simple Telescope Simulation

Trace the simple spherical telescope and make three plots:

./build/debug/obdeect_reference --photons 10000 --output  reference.csv
obdeect-plot-reference --telescope reference-mst --view structure --output structure.png
obdeect-plot-reference  reference.csv --telescope reference-mst --view rays --output rays.png
obdeect-plot-reference  reference.csv --telescope reference-mst --view focal-plane --output focal.png

The structure plot shows the reference mirror, camera, and four supports in two side projections. The ray plot uses actual CSV vertices. The focal plot shows detected weight per bin and x/y projections. --max-paths limits displayed rays; --bins controls the focal histogram. Coordinates are telescope frame metres. The older --focal-plane flag remains supported.

Artificial calibration sources

The baseline executable uses 400-nm photons and supports three deterministic source models over the same entrance pupil:

# Plane wave from an on/off-axis star; angles are telescope-frame degrees.
./build/obdeect_reference --source star --field-x-deg 0.5 --field-y-deg 0.0

# Finite-distance point flasher, with per-photon inverse-square weights.
./build/obdeect_reference --source illuminator --distance-m 50

# Collimated or finite-divergence calibration laser.
./build/obdeect_reference --source laser --distance-m 50 --divergence-deg 0.1

CSV output stores every traced path vertex plus wavelength, emission time, source weight and the trace's wavelength-independent throughput. The latter is currently one for a detector-surface hit and zero for every loss; a compiled coating/material scene will replace it with wavelength-dependent transport.

CTAO reference models

obdeect_ctao --telescope LST|MST|SST|SCT writes ragged photon paths for the same Python plotter. The analytic catalogue uses public simulation-models 6.3.0 identifiers as a tested baseline; the production importer accepts an explicitly selected version from the supplied checkout and records provenance. It contains optical prescriptions only: it does not load model JSON, facet positions, detector conversion, alignment, structures, throughput, or the SCT coordinate transform. LST ideal-paraboloid and MST central-sphere baselines are executable and tested; SST/SCT are two-mirror prescription scaffolding awaiting their model-specific geometry validation.

The core now also has a finite-facet and tabulated-coating kernel for use by a future model importer. A facet list is not currently embedded in any reference model, so this must not be interpreted as segmented CTAO telescope support. The explicit status, remaining work, and evidence required before claiming sim_telarray/ROBAST-level coverage are in docs/STATUS.md. Reference manifest and comparison schemas are described in docs/REFERENCE_MANIFEST.md and docs/COMPARISON_CONTRACT.md.

Import a selected simulation-models production

The standard-library importer records every selected parameter record and all declared model-file assets with SHA-256 hashes. It neither downloads nor copies external model data.

obdeect-import-simulation-models /path/to/simulation-models LSTN-design \
  --version 6.3.0 --output lstn-design.ir.json

This command selects and hashes the source parameter records and their declared assets. It is provenance input for scene compilation, not a ray-tracing command and does not download, copy, or silently interpret model files.

The emitted obdeect.simulation-models-ir.v1 JSON is the auditable hand-off from model selection to the future C++ scene compiler. An unresolved parameter file, missing declared asset, identity mismatch, or unsafe path fails the import; no field is silently discarded.

Coordinate and model convention

The mirror vertex is at z=0 m; incoming artificial Cherenkov photons begin at z=20 m and travel in -z. The spherical centre is at z=9.75 m, making the paraxial screen location z=4.875 m. The simple structure is four finite-cylinder support legs plus a circular camera face evaluated before the primary reflection. CSV records source, termination/mirror, and focal-screen vertices so the plot displays the actual traced path.

Core architecture status

The C++20 core is split by responsibility so a photon kernel never needs Python, YAML, EventIO or a plotting dependency.

CORSIKA 7 EventIO input

The optional C++ EventIO adapter reads CORSIKA IACT TELFIL files directly. In this workspace it builds against the adjacent EventIO C source checkout; an installed library can instead be selected with -DEventio_ROOT=/path/to/install.

cmake -S . -B build/eventio -DOBDEECT_BUILD_EVENTIO_INPUT=ON
cmake --build build/eventio --target obdeect_eventio_summary
./build/eventio/obdeect_eventio_summary /path/to/CORSIKA_TELFIL

EventioPhotonReader yields one weighted OpticalPhoton per CORSIKA bunch, with a PhotonBatchContext for run, event, reused array and telescope. It supports full, compact and 3D records in both array layouts. A zero wavelength stays unresolved; CEFFIC photoelectron-like bunches are rejected. Use resolve_eventio_spectrum() to create deterministic spectral children before any wavelength-dependent response. AtmosphereTransmissionTable reads the simulation transmission table and attenuate_eventio_direct_beam() applies direct-beam extinction between emission and telescope arrival. Check that the table's observation altitude and CORSIKA production configuration match before using it. These stages are separate from the file decoder and optical kernel. The reader's CORSIKA-local arrival rays must be transformed into the selected telescope scene frame before tracing. See the input and atmosphere plan for conventions and remaining production-file validation.

Component Current implementation
math.hpp Vec3, dot/cross/norm and checked direction normalisation.
photon_buffer.hpp, abi.hpp SoA input contract, result buffers, status values and validation.
source.hpp Deterministic 400-nm star, point illuminator and laser sources.
tables.hpp Immutable no-extrapolation 1-D response interpolation.
intersections.hpp, geometry.hpp Plane, sphere/cap, disk, finite cylinder and axisymmetric-surface dispatch.
interactions.hpp Checked specular reflection.
axisymmetric_optics.hpp Paraboloid/even-polynomial SC surfaces and forward Newton intersection.
facets.hpp Finite circular facet intersection, nearest-hit selection and tabulated coating response.
scene.hpp, trace.hpp Immutable directed reference-scene compilation and scalar SoA block tracing.
diagnostics.hpp Status/weight closure summary.
model_import.hpp Canonical CTAO model provenance/import target.

Linting

Install CMake, Ninja, a C++20 compiler, Python 3.10+, and the development tools:

python -m pip install --upgrade pip ruff
python -m pip install .

Examples and tutorials

Tutorials cover sources, optical reference models, field-angle scans, and model provenance. Run the examples with:

python examples/run_examples.py --build build/debug --output out/examples --photons 1000

Each case writes a CSV, structure/ray/focal plots where applicable, and status counts. See examples/README.md for the case list.

Scope

The reference scene is MST inspired; it is not a CTAO production telescope. The obdeect_ctao command traces analytic LST/MST optical baselines and contains SST/SCT polynomial prescriptions. Model-derived nominal LST/MST surface tables are traceable through obdeect-simtools-raytrace --scene-file; run-specific alignment, secondary structures, obscurers, and wavelength-dependent bindings remain gated. Current limitations and validation evidence are in status. The current code review records fixes and remaining duplication.

PSF scan

obdeect-psf scan --executable ./build/debug/obdeect_reference --photons 10000 \
  --field-x-deg 0 0.5 1.0 --output-dir out/reference_psf --plot out/reference_psf.png

A scan writes one trace CSV per offset and psf_scan.csv/psf_scan.json. These metrics describe the selected deterministic reference configuration; they are not validation of a production telescope model.

The production 7.0.0 sim_telarray reference includes focal-plane PSFs, integration radii, cumulative distributions, and archived photon lists for LST, both MST configurations, and SST across their selected North/South sites. These remain the comparison fixtures for native scene traces.

Model provenance and scene compilation

The Python adapters can select a simulation-models record, hash its declared assets, and compile a provenance-checked scene hand-off. Compilation retains mirror-list geometry, derives nominal single-reflector panel normals, and reports run-specific alignment, structures, and materials as trace blockers. For nominal LST and MST records it can also emit the strict native surface table consumed directly by the C++ tracer:

obdeect-import-simulation-models /path/to/simulation-models LSTN-design \
  --version 7.0.0 --output lstn.ir.json
obdeect-compile-scene lstn.ir.json --source-root /path/to/simulation-models \
  --simtel-root /path/to/sim_telarray --output lstn.scene.json \
  --native-output lstn.scene.csv
obdeect-simtools-raytrace --scene-file lstn.scene.csv --source star \
  --photons 10000 --output lstn-arrivals.csv

--simtel-root is needed when a camera response table is found in sim_telarray's cfg/CTA search path rather than simulation-models Files. The selected file path and SHA-256 hash are recorded in the scene provenance.

CSV trace output includes source weight, wavelength, emission time, terminal status, path length, path vertices, and primary/focal incidence angles. The current executable-level throughput is one for a detector-surface hit and zero for a loss; material and coating kernels remain separately tested primitives until their model bindings are selected.

Project map

Path Purpose
cpp/include/obdeect/ Geometry, optics, sources, and tracing
cpp/tests/ Native tests
python/obdeect/ Import, plotting, and PSF commands
python/tests/ Python tests
examples/ Runnable end to end examples
docs/ Tutorials, status, and comparison contracts

License and Citation

BSD-3-Clause license. Citation metadata is in CITATION.cff.

Generative AI disclosure

Generative AI tools were used to write much of this project; outputs were reviewed and validated by the authors.

Generative AI tools (mostly ChatGPT 5.6) were used to write the entire code of this project. All AI-assisted outputs were reviewed, validated, and, where necessary, modified by the authors to ensure accuracy and reliability.

Release files for obdeect-dev 0.1.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 obdeect-dev 0.1.0
File Size Uploaded
obdeect_dev-0.1.0.tar.gz 6.8 MB Details

Built distributions (wheels)

Table of built distributions (wheels) for obdeect-dev 0.1.0
File Interpreter ABI Platform
obdeect_dev-0.1.0-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details
obdeect_dev-0.1.0-py3-none-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl Python 3 none Linux glibc 2.28+ x86-64, Linux glibc 2.24+ x86-64 Details
obdeect_dev-0.1.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details

Total release size: 8.3 MB

Release files / obdeect_dev-0.1.0.tar.gz

Download URL obdeect_dev-0.1.0.tar.gz
Size 6.8 MB
Tags Source
SHA-256 checksum
How to use checksums
6accdd8452d3117d3b33bb7009fe09e942adccd97a430c00f99c0acb43003abb
BLAKE2b-256 checksum
How to use checksums
e458488d060ca20641ee3778b5f6d44e6a390d11053ce240ab53b17e95c049f1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.

Transparency log

Release files / obdeect_dev-0.1.0-py3-none-musllinux_1_2_x86_64.whl

Download URL obdeect_dev-0.1.0-py3-none-musllinux_1_2_x86_64.whl
Size 1.2 MB
Tags Linux musl 1.2+ x86-64 Python 3
SHA-256 checksum
How to use checksums
4ebde24795b17c726a2de2b9883875a158446d49a80a08e54ab8163ad0d0bd51
BLAKE2b-256 checksum
How to use checksums
a4a8e5ff260b6811b347a05ba0a81aa2db874f5871a5eae6e6291fbe62d06bc6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.

Transparency log

Release files / obdeect_dev-0.1.0-py3-none-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl

Download URL obdeect_dev-0.1.0-py3-none-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Size 152.9 kB
Tags Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64 Python 3
SHA-256 checksum
How to use checksums
1e34b2e4e36158ffd89063364ed590f59085acc82ccd1537cbcc849d699c57cc
BLAKE2b-256 checksum
How to use checksums
6eeeffa9060805b4c73c701da09a763e49e25d1bfb88e61a9700e4d214128a32
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.

Transparency log

Release files / obdeect_dev-0.1.0-py3-none-macosx_11_0_arm64.whl

Download URL obdeect_dev-0.1.0-py3-none-macosx_11_0_arm64.whl
Size 150.2 kB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
00c7f3d439f0ae71827e4be38224600ec56888a460f9da4ae2d0523a35f21945
BLAKE2b-256 checksum
How to use checksums
dbc0397e6797928af574d4939520869113871f5a94432076e7fa79cb55aa8626
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

4 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