dlufd 0.0.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.
@@ -0,0 +1 @@
1
+ ../../../.skills/skills/gm-pr-workflow
@@ -0,0 +1,5 @@
1
+ ---
2
+ BasedOnStyle: LLVM
3
+ ColumnLimit: 100
4
+ IndentWidth: 2
5
+ SortIncludes: CaseSensitive
@@ -0,0 +1,17 @@
1
+ ---
2
+ Checks: >
3
+ -*,
4
+ bugprone-argument-comment,
5
+ bugprone-branch-clone,
6
+ bugprone-empty-catch,
7
+ bugprone-exception-escape,
8
+ bugprone-infinite-loop,
9
+ bugprone-macro-parentheses,
10
+ bugprone-suspicious-memset-usage,
11
+ bugprone-undefined-memory-manipulation,
12
+ performance-for-range-copy
13
+ WarningsAsErrors: '*'
14
+ HeaderFilterRegex: 'cpp/include/dlufd/.*'
15
+ CheckOptions:
16
+ - key: readability-identifier-length.MinimumVariableNameLength
17
+ value: '2'
@@ -0,0 +1 @@
1
+ ../../../.skills/skills/gm-pr-workflow
@@ -0,0 +1,12 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ insert_final_newline = true
7
+ indent_style = space
8
+ indent_size = 2
9
+ trim_trailing_whitespace = true
10
+
11
+ [*.py]
12
+ indent_size = 4
@@ -0,0 +1,7 @@
1
+ * text=auto eol=lf
2
+
3
+ *.cpp text diff=cpp
4
+ *.hpp text diff=cpp
5
+ *.py text diff=python
6
+ *.yml text
7
+ *.yaml text
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: Changelog
3
+ # Require a changelog entry for each pull request
4
+ # from: https://github.com/cta-observatory/ctapipe/blob/main/.github/workflows/changelog.yml
5
+
6
+ on:
7
+ pull_request:
8
+ types: [opened, reopened, synchronize, labeled, unlabeled, ready_for_review]
9
+ branches:
10
+ - 'main'
11
+
12
+ env:
13
+ FRAGMENT_NAME_PREFIX: "docs/changes/${{ github.event.number }}"
14
+
15
+ permissions:
16
+ contents: read
17
+
18
+ jobs:
19
+ changelog:
20
+ runs-on: ubuntu-slim
21
+ if: >-
22
+ github.event.pull_request.draft == false &&
23
+ !contains(github.event.pull_request.labels.*.name, 'no-changelog-needed') &&
24
+ !contains(github.event.pull_request.labels.*.name, 'dependencies')
25
+ steps:
26
+ - name: Checkout code
27
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
28
+
29
+ - name: Check for at least one changelog fragment
30
+ run: |
31
+ find docs/changes -type f | \
32
+ grep -E "^${FRAGMENT_NAME_PREFIX}\.(feature|bugfix|maintenance)\.md$"
@@ -0,0 +1,31 @@
1
+ ---
2
+ name: CI-linter
3
+
4
+ on:
5
+ push:
6
+ branches:
7
+ - main
8
+ pull_request:
9
+
10
+ concurrency:
11
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
12
+ cancel-in-progress: true
13
+
14
+ jobs:
15
+ lint:
16
+ runs-on: ubuntu-slim
17
+ steps:
18
+ - uses: actions/checkout@v7
19
+ with:
20
+ fetch-depth: 0
21
+ - uses: actions/setup-python@v7
22
+ with:
23
+ python-version: '3.14'
24
+ - name: Install linters
25
+ run: python -m pip install --upgrade pip pre-commit clang-format
26
+ - name: Run repository hooks
27
+ run: pre-commit run --all-files
28
+ - name: Check C++ formatting
29
+ run: >-
30
+ find cpp -type f \( -name '*.cpp' -o -name '*.hpp' \) -print0
31
+ | xargs -0 clang-format --dry-run --Werror
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: CI-docs
3
+
4
+ on:
5
+ pull_request:
6
+ push:
7
+ branches:
8
+ - main
9
+ tags:
10
+ - "v*"
11
+ workflow_dispatch:
12
+
13
+ concurrency:
14
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || 'pages' }}
15
+ cancel-in-progress: true
16
+
17
+ jobs:
18
+ build:
19
+ runs-on: ubuntu-slim
20
+ permissions:
21
+ contents: read
22
+ steps:
23
+ - uses: actions/checkout@v7
24
+ with:
25
+ fetch-depth: 0
26
+ - uses: actions/setup-python@v7
27
+ with:
28
+ python-version: "3.14"
29
+ - name: Install dlufd with the documentation tools
30
+ run: python -m pip install --upgrade pip && python -m pip install ".[docs]"
31
+ - name: Build documentation
32
+ run: sphinx-build -W --keep-going -b html docs docs/_build/html
33
+ - uses: actions/upload-pages-artifact@v5
34
+ with:
35
+ path: docs/_build/html
36
+
37
+ deploy:
38
+ if: github.event_name != 'pull_request' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
39
+ needs: build
40
+ runs-on: ubuntu-slim
41
+ permissions:
42
+ pages: write
43
+ id-token: write
44
+ environment:
45
+ name: github-pages
46
+ url: ${{ steps.deployment.outputs.page_url }}
47
+ steps:
48
+ - id: deployment
49
+ uses: actions/deploy-pages@v5
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: Build and publish dlufd
3
+
4
+ on:
5
+ pull_request:
6
+ paths:
7
+ - "cpp/**"
8
+ - "python/**"
9
+ - "CMakeLists.txt"
10
+ - "pyproject.toml"
11
+ - ".github/workflows/pypi.yml"
12
+ push:
13
+ tags:
14
+ - "v*"
15
+ workflow_dispatch:
16
+ inputs:
17
+ publish_testpypi:
18
+ description: Publish the built distributions to TestPyPI
19
+ required: false
20
+ type: boolean
21
+ default: false
22
+
23
+ concurrency:
24
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
25
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
26
+
27
+ permissions:
28
+ contents: read
29
+
30
+ jobs:
31
+ wheels:
32
+ strategy:
33
+ fail-fast: false
34
+ matrix:
35
+ os: [ubuntu-24.04, ubuntu-24.04-arm, macos-15]
36
+ runs-on: ${{ matrix.os }}
37
+ steps:
38
+ - uses: actions/checkout@v7
39
+ with:
40
+ ref: ${{ github.ref }}
41
+ - uses: actions/setup-python@v7
42
+ with:
43
+ python-version: "3.14"
44
+ - name: Install wheel tooling
45
+ run: python -m pip install --upgrade cibuildwheel
46
+ - name: Build and smoke-test wheels
47
+ env:
48
+ CIBW_BUILD: "cp314-* cp315-*"
49
+ CIBW_TEST_REQUIRES: "pytest matplotlib"
50
+ CIBW_TEST_COMMAND: python -m pytest {project}/python/tests -q
51
+ run: python -m cibuildwheel --output-dir wheelhouse
52
+ - uses: actions/upload-artifact@v7
53
+ with:
54
+ name: wheels-${{ matrix.os }}
55
+ path: wheelhouse/*.whl
56
+
57
+ sdist:
58
+ runs-on: ubuntu-24.04
59
+ steps:
60
+ - uses: actions/checkout@v7
61
+ with:
62
+ ref: ${{ github.ref }}
63
+ - uses: actions/setup-python@v7
64
+ with:
65
+ python-version: "3.14"
66
+ - name: Build source distribution
67
+ run: |
68
+ python -m pip install --upgrade build
69
+ python -m build --sdist --outdir dist
70
+ - uses: actions/upload-artifact@v7
71
+ with:
72
+ name: sdist
73
+ path: dist/*.tar.gz
74
+
75
+ publish:
76
+ if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
77
+ needs: [wheels, sdist]
78
+ runs-on: ubuntu-24.04
79
+ environment: pypi
80
+ permissions:
81
+ id-token: write
82
+ steps:
83
+ - uses: actions/download-artifact@v8
84
+ with:
85
+ path: dist
86
+ merge-multiple: true
87
+ - name: Publish distributions to PyPI
88
+ uses: pypa/gh-action-pypi-publish@release/v1
89
+
90
+ publish-testpypi:
91
+ if: >-
92
+ ${{
93
+ github.event_name == 'workflow_dispatch' && inputs.publish_testpypi
94
+ }}
95
+ needs: [wheels, sdist]
96
+ runs-on: ubuntu-24.04
97
+ environment: testpypi
98
+ permissions:
99
+ id-token: write
100
+ steps:
101
+ - uses: actions/download-artifact@v8
102
+ with:
103
+ path: dist
104
+ merge-multiple: true
105
+ - name: Publish distributions to TestPyPI
106
+ uses: pypa/gh-action-pypi-publish@release/v1
107
+ with:
108
+ repository-url: https://test.pypi.org/legacy/
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: CI-tests
3
+
4
+ on:
5
+ push:
6
+ branches:
7
+ - main
8
+ pull_request:
9
+
10
+ concurrency:
11
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
12
+ cancel-in-progress: true
13
+
14
+ permissions:
15
+ contents: read
16
+
17
+ jobs:
18
+ build-and-test:
19
+ strategy:
20
+ fail-fast: false
21
+ matrix:
22
+ runner: [ubuntu-24.04, ubuntu-24.04-arm, macos-15]
23
+ python-version: ['3.14', '3.15']
24
+ runs-on: ${{ matrix.runner }}
25
+ steps:
26
+ - uses: actions/checkout@v7
27
+ - uses: actions/setup-python@v7
28
+ with:
29
+ python-version: ${{ matrix.python-version }}
30
+ allow-prereleases: true
31
+ - name: Install Python package and test dependencies
32
+ run: python -m pip install --upgrade pip && python -m pip install ".[plot]" pytest
33
+ - name: Configure and build
34
+ run: >-
35
+ cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
36
+ && cmake --build build --parallel
37
+ - name: Run native and Python tests
38
+ run: ctest --test-dir build --output-on-failure && pytest python/tests
39
+ sanitizers:
40
+ runs-on: ubuntu-24.04
41
+ steps:
42
+ - uses: actions/checkout@v7
43
+ - name: Configure, build, and test with sanitizers
44
+ run: >-
45
+ cmake -S . -B build-sanitize -DCMAKE_BUILD_TYPE=Debug
46
+ -DCMAKE_CXX_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer"
47
+ -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address,undefined"
48
+ && cmake --build build-sanitize --parallel
49
+ && ctest --test-dir build-sanitize --output-on-failure
dlufd-0.0.1/.gitignore ADDED
@@ -0,0 +1,32 @@
1
+ # CMake and native build products
2
+ /build/
3
+ /out/
4
+ /compile_commands.json
5
+ /tmp_planning/
6
+ *.o
7
+ *.obj
8
+ *.a
9
+ *.so
10
+ *.dylib
11
+ *.dll
12
+
13
+ # Generated trace and visualisation products
14
+ *.npz
15
+ *.html
16
+
17
+ # Python
18
+ __pycache__/
19
+ *.py[cod]
20
+ .pytest_cache/
21
+ .ruff_cache/
22
+ .venv/
23
+ *.egg-info/
24
+ /dist/
25
+
26
+ # IDE and operating-system files
27
+ .DS_Store
28
+ .vscode/
29
+ .idea/
30
+
31
+ # Documentation build
32
+ /docs/_build/
@@ -0,0 +1 @@
1
+ ../../../.skills/skills/gm-pr-workflow
@@ -0,0 +1,64 @@
1
+ ---
2
+ default_language_version:
3
+ python: python3.14
4
+
5
+ repos:
6
+ - repo: https://github.com/pre-commit/pre-commit-hooks
7
+ rev: v5.0.0
8
+ hooks:
9
+ - id: check-yaml
10
+ - id: check-json
11
+ - id: end-of-file-fixer
12
+ - id: trailing-whitespace
13
+ - repo: https://github.com/astral-sh/ruff-pre-commit
14
+ rev: v0.12.7
15
+ hooks:
16
+ - id: ruff-check
17
+ args: [--fix]
18
+ - id: ruff-format
19
+ # Github action
20
+ - repo: https://github.com/rhysd/actionlint
21
+ rev: v1.7.12
22
+ hooks:
23
+ - id: actionlint
24
+ # https://pyproject-fmt.readthedocs.io/en/latest/
25
+ - repo: https://github.com/tox-dev/pyproject-fmt
26
+ rev: "v2.29.2"
27
+ hooks:
28
+ - id: pyproject-fmt
29
+ # codespell
30
+ - repo: https://github.com/codespell-project/codespell
31
+ rev: v2.4.3
32
+ hooks:
33
+ - id: codespell
34
+ args: [
35
+ "--ignore-words-list=als,hel",
36
+ ]
37
+ # markdownlint
38
+ - repo: https://github.com/igorshubovych/markdownlint-cli
39
+ rev: v0.49.1
40
+ hooks:
41
+ - id: markdownlint
42
+ args: ["--disable", "MD041"]
43
+ # yamllint
44
+ - repo: https://github.com/adrienverge/yamllint.git
45
+ rev: v1.38.0
46
+ hooks:
47
+ - id: yamllint
48
+ args:
49
+ [
50
+ "--strict",
51
+ "-d",
52
+ '{extends: default, rules: {line-length: {max: 300}, indentation: {spaces: 2, indent-sequences: consistent}, truthy: {allowed-values: ["true", "false", "on", "off"]}}}'
53
+ ]
54
+ # towncrier
55
+ - repo: https://github.com/twisted/towncrier
56
+ rev: 25.8.0
57
+ hooks:
58
+ - id: towncrier-check
59
+ files: ^docs/changes/
60
+ # shellcheck
61
+ - repo: https://github.com/shellcheck-py/shellcheck-py
62
+ rev: v0.11.0.1-1
63
+ hooks:
64
+ - id: shellcheck
dlufd-0.0.1/AGENTS.md ADDED
@@ -0,0 +1,66 @@
1
+ # dlufd Agent Guide
2
+
3
+ ## Scope
4
+
5
+ `dlufd` propagates photons through the atmosphere, from an emission point or the
6
+ CORSIKA telescope-sphere plane to the telescope-sphere plane: extinction, refraction
7
+ and group-index timing from n(h), optional single scattering, wavelength assignment,
8
+ and early thinning with the efficiency envelope. Photon generation, optics and camera
9
+ simulation are out of scope.
10
+
11
+ ## Layout
12
+
13
+ - `cpp/include/dlufd/`: C++ core headers.
14
+ - `cpp/bindings/core.cpp`: nanobind extension; the only C++ file that may
15
+ depend on Python.
16
+ - `cpp/tests/`: native tests (`test_*.cpp`) and shared helpers (`check.hpp`).
17
+ - `python/dlufd/`: Python boundary (API, CLI, optional plotting).
18
+ - `python/tests/`: pytest suite.
19
+ - `docs/`: Sphinx sources. `docs/changes/` is towncrier input.
20
+
21
+ ## Design rules
22
+
23
+ - Never ever modify the main README.md. Suggest instead changes, don't apply them.
24
+ - Keep the core C++20 standard-library-only. Python, plotting and file formats of
25
+ other programs belong at the boundary, never in a per-photon kernel.
26
+ - Per-photon kernels are pure functions of (chunk, parameters): no allocation, I/O,
27
+ Python calls or virtual dispatch per photon. Float32 SoA photon columns,
28
+ counter-based random numbers (Philox) keyed on (seed, stage id, event, telescope,
29
+ photon index). The scalar version is the reference for any SIMD or GPU version.
30
+ - Write kernels as templates on the scalar type (later differentiability).
31
+ - Make units, frames, random seeds and applied efficiencies explicit. Reject invalid
32
+ input; never silently discard fields.
33
+ - Do not hardwire CTAO names, telescope geometry, model versions or physics
34
+ parameters. Configuration comes from validated input written by simtools.
35
+ - Plotting is optional (`.[plot]`); matplotlib is never a core dependency.
36
+ - Use Python >=3.14 (as in `pyproject.toml`).
37
+ - Atmospheric effects are an ordered list of independent effects. Each is recorded
38
+ in the efficiency ledger of the stream.
39
+ - Extinction must stay identical to sim_telarray's `atmospheric_transmission2`.
40
+
41
+ ## Changes and validation
42
+
43
+ - Make the narrowest complete change and preserve unrelated work.
44
+ - Add a Towncrier fragment under `docs/changes/` for changes that should appear in
45
+ the release notes.
46
+ - Add or update a focused test for every behavioural change. Analytic kernel tests
47
+ come before cross-tool or performance tests.
48
+ - Results must not depend on photon ordering, chunk size or thread count.
49
+ - Do not weaken tolerances or replace reference data to hide a discrepancy.
50
+
51
+ ## Build, test, and lint
52
+
53
+ ```bash
54
+ python -m pip install -e '.[dev]'
55
+ cmake --preset debug
56
+ cmake --build --preset debug
57
+ ctest --test-dir build/debug --output-on-failure
58
+ python -m pytest python/tests
59
+ ruff format --check python
60
+ ruff check python
61
+ find cpp -type f \( -name '*.cpp' -o -name '*.hpp' \) -print0 | \
62
+ xargs -0 clang-format --dry-run --Werror
63
+ pre-commit run --all-files
64
+ ```
65
+
66
+ Docs build with warnings as errors: `sphinx-build -W --keep-going -b html docs docs/_build/html`.
@@ -0,0 +1,12 @@
1
+ # Changelog
2
+
3
+ This project follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
4
+ and uses semantic versioning after the first stable release.
5
+
6
+ <!-- towncrier release notes start -->
7
+
8
+ ## [v0.0.1] - 2026-11-07
9
+
10
+ ### Added
11
+
12
+ - Initial repository skeleton (build, packaging, CI, documentation); no functionality yet.
@@ -0,0 +1,14 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use dlufd, please cite it using the metadata below."
3
+ title: "dlufd: Atmospheric propagation of Cherenkov and artificial-source photons"
4
+ version: 0.0.1
5
+ date-released: 2026-11-07
6
+ license: BSD-3-Clause
7
+ type: software
8
+ repository-code: "https://github.com/GernotMaier/dlufd"
9
+ authors:
10
+ - given-names: Gernot
11
+ family-names: Maier
12
+ affiliation: DESY
13
+ orcid: 'https://orcid.org/0000-0001-9868-4700'
14
+ abstract: "Atmospheric propagation for Cherenkov-telescope simulations: extinction, refraction and timing from the refractive-index profile, optional single scattering, and early photon thinning, as a standard-library-only C++20 core with a Python API, working on gstrickd photon streams."
dlufd-0.0.1/CLAUDE.md ADDED
@@ -0,0 +1,2 @@
1
+ @../AGENTS.md
2
+ @AGENTS.md
@@ -0,0 +1,50 @@
1
+ cmake_minimum_required(VERSION 3.20)
2
+ project(dlufd VERSION 0.1.0 LANGUAGES CXX)
3
+
4
+ option(DLUFD_BUILD_TESTING "Build the C++ tests" ON)
5
+ if(DEFINED SKBUILD_PLATLIB_DIR)
6
+ set(DLUFD_BUILD_PYTHON_API_DEFAULT ON)
7
+ else()
8
+ set(DLUFD_BUILD_PYTHON_API_DEFAULT OFF)
9
+ endif()
10
+ option(DLUFD_BUILD_PYTHON_API "Build the Python extension" ${DLUFD_BUILD_PYTHON_API_DEFAULT})
11
+
12
+ # Header-only, standard-library-only core.
13
+ add_library(dlufd_core INTERFACE)
14
+ target_include_directories(dlufd_core INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/cpp/include)
15
+ target_compile_features(dlufd_core INTERFACE cxx_std_20)
16
+ # Identical floating-point results for any thread count and chunk size on one
17
+ # platform: no implicit fused multiply-add contraction.
18
+ if(NOT MSVC)
19
+ target_compile_options(dlufd_core INTERFACE -ffp-contract=off)
20
+ endif()
21
+
22
+ function(dlufd_enable_warnings target)
23
+ if(MSVC)
24
+ target_compile_options(${target} PRIVATE /W4 /WX)
25
+ else()
26
+ target_compile_options(${target} PRIVATE -Wall -Wextra -Wpedantic -Werror)
27
+ endif()
28
+ endfunction()
29
+
30
+ if(DLUFD_BUILD_PYTHON_API)
31
+ find_package(Python 3.14 COMPONENTS Interpreter Development.Module REQUIRED)
32
+ execute_process(COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir
33
+ OUTPUT_VARIABLE nanobind_DIR OUTPUT_STRIP_TRAILING_WHITESPACE
34
+ COMMAND_ERROR_IS_FATAL ANY)
35
+ find_package(nanobind CONFIG REQUIRED)
36
+ nanobind_add_module(_core NB_STATIC cpp/bindings/core.cpp)
37
+ target_link_libraries(_core PRIVATE dlufd_core)
38
+ dlufd_enable_warnings(_core)
39
+ install(TARGETS _core LIBRARY DESTINATION dlufd)
40
+ endif()
41
+
42
+ if(DLUFD_BUILD_TESTING)
43
+ enable_testing()
44
+ foreach(test_name version)
45
+ add_executable(test_${test_name} cpp/tests/test_${test_name}.cpp)
46
+ target_link_libraries(test_${test_name} PRIVATE dlufd_core)
47
+ dlufd_enable_warnings(test_${test_name})
48
+ add_test(NAME ${test_name} COMMAND test_${test_name})
49
+ endforeach()
50
+ endif()
@@ -0,0 +1,55 @@
1
+ {
2
+ "version": 3,
3
+ "cmakeMinimumRequired": {
4
+ "major": 3,
5
+ "minor": 20,
6
+ "patch": 0
7
+ },
8
+ "configurePresets": [
9
+ {
10
+ "name": "base",
11
+ "hidden": true,
12
+ "generator": "Ninja",
13
+ "binaryDir": "${sourceDir}/build/${presetName}",
14
+ "cacheVariables": {
15
+ "CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
16
+ "DLUFD_BUILD_TESTING": "ON"
17
+ }
18
+ },
19
+ {
20
+ "name": "debug",
21
+ "displayName": "Debug",
22
+ "inherits": "base",
23
+ "cacheVariables": {
24
+ "CMAKE_BUILD_TYPE": "Debug"
25
+ }
26
+ },
27
+ {
28
+ "name": "release",
29
+ "displayName": "Release",
30
+ "inherits": "base",
31
+ "cacheVariables": {
32
+ "CMAKE_BUILD_TYPE": "Release"
33
+ }
34
+ }
35
+ ],
36
+ "buildPresets": [
37
+ {
38
+ "name": "debug",
39
+ "configurePreset": "debug"
40
+ },
41
+ {
42
+ "name": "release",
43
+ "configurePreset": "release"
44
+ }
45
+ ],
46
+ "testPresets": [
47
+ {
48
+ "name": "debug",
49
+ "configurePreset": "debug",
50
+ "output": {
51
+ "outputOnFailure": true
52
+ }
53
+ }
54
+ ]
55
+ }
dlufd-0.0.1/LICENSE ADDED
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, dlufd contributors, Gernot Maier (DESY)
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
dlufd-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,101 @@
1
+ Metadata-Version: 2.2
2
+ Name: dlufd
3
+ Version: 0.0.1
4
+ Summary: Atmospheric propagation of Cherenkov and artificial-source photons
5
+ Author: dlufd contributors
6
+ License: BSD 3-Clause License
7
+
8
+ Copyright (c) 2026, dlufd contributors, Gernot Maier (DESY)
9
+ All rights reserved.
10
+
11
+ Redistribution and use in source and binary forms, with or without
12
+ modification, are permitted provided that the following conditions are met:
13
+
14
+ 1. Redistributions of source code must retain the above copyright notice, this
15
+ list of conditions and the following disclaimer.
16
+
17
+ 2. Redistributions in binary form must reproduce the above copyright notice,
18
+ this list of conditions and the following disclaimer in the documentation
19
+ and/or other materials provided with the distribution.
20
+
21
+ 3. Neither the name of the copyright holder nor the names of its
22
+ contributors may be used to endorse or promote products derived from
23
+ this software without specific prior written permission.
24
+
25
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
29
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
+
36
+ Classifier: Development Status :: 2 - Pre-Alpha
37
+ Classifier: License :: OSI Approved :: BSD License
38
+ Classifier: Programming Language :: C++
39
+ Classifier: Programming Language :: Python :: 3 :: Only
40
+ Classifier: Programming Language :: Python :: 3.14
41
+ Classifier: Programming Language :: Python :: 3.15
42
+ Requires-Python: >=3.14
43
+ Requires-Dist: numpy>=2.3
44
+ Provides-Extra: dev
45
+ Requires-Dist: nanobind>=3.1; extra == "dev"
46
+ Requires-Dist: pre-commit; extra == "dev"
47
+ Requires-Dist: pytest; extra == "dev"
48
+ Requires-Dist: ruff; extra == "dev"
49
+ Provides-Extra: docs
50
+ Requires-Dist: myst-parser; extra == "docs"
51
+ Requires-Dist: pydata-sphinx-theme; extra == "docs"
52
+ Requires-Dist: pyyaml; extra == "docs"
53
+ Requires-Dist: sphinx; extra == "docs"
54
+ Provides-Extra: plot
55
+ Requires-Dist: matplotlib>=3.8; extra == "plot"
56
+ Description-Content-Type: text/markdown
57
+
58
+ # dlufd
59
+
60
+ Atmospheric propagation of Cherenkov and artificial-source photons.
61
+
62
+ Atmospheric propagation for Cherenkov-telescope simulations: extinction, refraction and timing from the refractive-index profile, optional single scattering, and early photon thinning, as a standard-library-only C++20 core with a Python API, working on gstrickd photon streams.
63
+
64
+ `dlufd` is one module of a modular Cherenkov-telescope simulation chain
65
+ (CORSIKA7 or light sources, atmosphere, optics, camera). Modules exchange photons as
66
+ [gstrickd](https://github.com/gammasim/gstrickd) photon streams;
67
+ [simtools](https://github.com/gammasim/simtools) configures and runs the chain.
68
+
69
+ Status: pre-alpha, no functionality yet.
70
+
71
+ ## User Installation
72
+
73
+ ```sh
74
+ python -m venv .venv
75
+ source .venv/bin/activate
76
+ python -m pip install dlufd
77
+ ```
78
+
79
+ (requires python 3.14 or higher)
80
+
81
+ ## Developer Installation
82
+
83
+ ```sh
84
+ python -m venv .venv
85
+ source .venv/bin/activate
86
+ python -m pip install -e '.[dev]'
87
+ cmake --preset debug
88
+ cmake --build --preset debug
89
+ ```
90
+
91
+ Test your installation with:
92
+
93
+ ```sh
94
+ ctest --test-dir build/debug --output-on-failure
95
+ python -m pytest python/tests
96
+ ```
97
+
98
+ ## License and Citation
99
+
100
+ BSD 3-Clause License, see [LICENSE](LICENSE). Please cite `dlufd` using the
101
+ metadata in [CITATION.cff](CITATION.cff).
dlufd-0.0.1/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # dlufd
2
+
3
+ Atmospheric propagation of Cherenkov and artificial-source photons.
4
+
5
+ Atmospheric propagation for Cherenkov-telescope simulations: extinction, refraction and timing from the refractive-index profile, optional single scattering, and early photon thinning, as a standard-library-only C++20 core with a Python API, working on gstrickd photon streams.
6
+
7
+ `dlufd` is one module of a modular Cherenkov-telescope simulation chain
8
+ (CORSIKA7 or light sources, atmosphere, optics, camera). Modules exchange photons as
9
+ [gstrickd](https://github.com/gammasim/gstrickd) photon streams;
10
+ [simtools](https://github.com/gammasim/simtools) configures and runs the chain.
11
+
12
+ Status: pre-alpha, no functionality yet.
13
+
14
+ ## User Installation
15
+
16
+ ```sh
17
+ python -m venv .venv
18
+ source .venv/bin/activate
19
+ python -m pip install dlufd
20
+ ```
21
+
22
+ (requires python 3.14 or higher)
23
+
24
+ ## Developer Installation
25
+
26
+ ```sh
27
+ python -m venv .venv
28
+ source .venv/bin/activate
29
+ python -m pip install -e '.[dev]'
30
+ cmake --preset debug
31
+ cmake --build --preset debug
32
+ ```
33
+
34
+ Test your installation with:
35
+
36
+ ```sh
37
+ ctest --test-dir build/debug --output-on-failure
38
+ python -m pytest python/tests
39
+ ```
40
+
41
+ ## License and Citation
42
+
43
+ BSD 3-Clause License, see [LICENSE](LICENSE). Please cite `dlufd` using the
44
+ metadata in [CITATION.cff](CITATION.cff).
@@ -0,0 +1,17 @@
1
+ // Python.h must precede all standard headers (it sets feature-test macros such as
2
+ // _POSIX_C_SOURCE), so the nanobind headers come first.
3
+ #include <nanobind/nanobind.h>
4
+ #include <nanobind/stl/tuple.h>
5
+
6
+ #include "dlufd/version.hpp"
7
+
8
+ #include <tuple>
9
+
10
+ namespace nb = nanobind;
11
+
12
+ NB_MODULE(_core, module) {
13
+ module.doc() = "dlufd native core";
14
+ module.def("core_version", [] {
15
+ return std::make_tuple(dlufd::version_major, dlufd::version_minor, dlufd::version_patch);
16
+ });
17
+ }
@@ -0,0 +1,10 @@
1
+ #pragma once
2
+
3
+ namespace dlufd {
4
+
5
+ // Version of the C++ core; the Python package version comes from the git tag.
6
+ inline constexpr int version_major = 0;
7
+ inline constexpr int version_minor = 1;
8
+ inline constexpr int version_patch = 0;
9
+
10
+ } // namespace dlufd
@@ -0,0 +1,43 @@
1
+ #pragma once
2
+
3
+ #include <cmath>
4
+ #include <cstdio>
5
+ #include <cstdlib>
6
+ #include <exception>
7
+
8
+ // Assertions that stay active in Release builds.
9
+ inline int check_failures = 0;
10
+
11
+ #define CHECK(condition) \
12
+ do { \
13
+ if (!(condition)) { \
14
+ std::fprintf(stderr, "%s:%d: CHECK failed: %s\n", __FILE__, __LINE__, #condition); \
15
+ ++check_failures; \
16
+ } \
17
+ } while (false)
18
+
19
+ #define CHECK_NEAR(value, expected, tolerance) \
20
+ do { \
21
+ const double check_v = (value), check_e = (expected); \
22
+ if (!(std::abs(check_v - check_e) <= (tolerance))) { \
23
+ std::fprintf(stderr, "%s:%d: CHECK_NEAR failed: %s = %.17g, expected %.17g +- %g\n", \
24
+ __FILE__, __LINE__, #value, check_v, check_e, static_cast<double>(tolerance)); \
25
+ ++check_failures; \
26
+ } \
27
+ } while (false)
28
+
29
+ // Run the tests; an escaping exception counts as a failure.
30
+ template <class Tests> int run_checks(Tests tests) noexcept {
31
+ try {
32
+ tests();
33
+ } catch (const std::exception &error) {
34
+ std::fprintf(stderr, "unexpected exception: %s\n", error.what());
35
+ ++check_failures;
36
+ } catch (...) {
37
+ std::fprintf(stderr, "unexpected exception\n");
38
+ ++check_failures;
39
+ }
40
+ if (check_failures)
41
+ std::fprintf(stderr, "%d check(s) failed\n", check_failures);
42
+ return check_failures ? EXIT_FAILURE : EXIT_SUCCESS;
43
+ }
@@ -0,0 +1,11 @@
1
+ #include "check.hpp"
2
+
3
+ #include "dlufd/version.hpp"
4
+
5
+ int main() {
6
+ return run_checks([] {
7
+ CHECK(dlufd::version_major >= 0);
8
+ CHECK(dlufd::version_minor >= 0);
9
+ CHECK(dlufd::version_patch >= 0);
10
+ });
11
+ }
@@ -0,0 +1,2 @@
1
+ ```{include} ../CHANGELOG.md
2
+ ```
File without changes
@@ -0,0 +1,42 @@
1
+ """Sphinx configuration of the dlufd documentation."""
2
+
3
+ import tomllib
4
+ from importlib.metadata import PackageNotFoundError, version
5
+ from pathlib import Path
6
+
7
+ import yaml
8
+
9
+ ROOT = Path(__file__).resolve().parents[1]
10
+
11
+ project = "dlufd"
12
+ copyright = "2026, dlufd developers" # noqa: A001
13
+ with open(ROOT / "CITATION.cff", encoding="utf-8") as file:
14
+ author = ", ".join(
15
+ f"{a['given-names']} {a['family-names']}" for a in yaml.safe_load(file)["authors"]
16
+ )
17
+ with open(ROOT / "pyproject.toml", "rb") as file:
18
+ distribution = tomllib.load(file)["project"]["name"]
19
+ try:
20
+ release = version(distribution)
21
+ except PackageNotFoundError:
22
+ release = "unknown"
23
+ version = release
24
+
25
+ extensions = ["myst_parser", "sphinx.ext.autodoc", "sphinx.ext.mathjax", "sphinx.ext.githubpages"]
26
+ source_suffix = {".md": "markdown"}
27
+ root_doc = "index"
28
+ exclude_patterns = ["_build", "changes"]
29
+ myst_heading_anchors = 3
30
+ myst_enable_extensions = ["colon_fence", "dollarmath"]
31
+
32
+ html_theme = "pydata_sphinx_theme"
33
+ html_title = project
34
+ html_theme_options = {
35
+ "icon_links": [
36
+ {
37
+ "name": "GitHub",
38
+ "url": "https://github.com/gammasim/dlufd",
39
+ "icon": "fa-brands fa-github",
40
+ },
41
+ ],
42
+ }
@@ -0,0 +1,11 @@
1
+ # dlufd
2
+
3
+ Atmospheric propagation for Cherenkov-telescope simulations: extinction, refraction and timing from the refractive-index profile, optional single scattering, and early photon thinning, as a standard-library-only C++20 core with a Python API, working on gstrickd photon streams.
4
+
5
+ Status: pre-alpha, no functionality yet.
6
+
7
+ ```{toctree}
8
+ :maxdepth: 1
9
+
10
+ changelog
11
+ ```
@@ -0,0 +1,71 @@
1
+ [build-system]
2
+ build-backend = "scikit_build_core.build"
3
+ requires = [ "nanobind>=3.1", "scikit-build-core>=0.10", "setuptools-scm>=8" ]
4
+
5
+ [project]
6
+ name = "dlufd"
7
+ description = "Atmospheric propagation of Cherenkov and artificial-source photons"
8
+ readme = "README.md"
9
+ license = { file = "LICENSE" }
10
+ authors = [ { name = "dlufd contributors" } ]
11
+ requires-python = ">=3.14"
12
+ classifiers = [
13
+ "Development Status :: 2 - Pre-Alpha",
14
+ "License :: OSI Approved :: BSD License",
15
+ "Programming Language :: C++",
16
+ "Programming Language :: Python :: 3 :: Only",
17
+ "Programming Language :: Python :: 3.14",
18
+ "Programming Language :: Python :: 3.15",
19
+ ]
20
+ dynamic = [ "version" ]
21
+ dependencies = [
22
+ "numpy>=2.3",
23
+ ]
24
+ optional-dependencies.dev = [ "nanobind>=3.1", "pre-commit", "pytest", "ruff" ]
25
+ optional-dependencies.docs = [ "myst-parser", "pydata-sphinx-theme", "pyyaml", "sphinx" ]
26
+ optional-dependencies.plot = [ "matplotlib>=3.8" ]
27
+
28
+ [tool.setuptools_scm]
29
+ fallback_version = "0.1.0"
30
+
31
+ [tool.scikit-build]
32
+ build-dir = "build/{wheel_tag}"
33
+ cmake.args = [ "-DDLUFD_BUILD_TESTING=OFF" ]
34
+ cmake.build-type = "Release"
35
+ sdist.include = [ "cpp/**", "CMakeLists.txt", "python/**", "README.md", "LICENSE" ]
36
+ wheel.packages = [ "python/dlufd" ]
37
+ wheel.platlib = true
38
+ # Editable installs rebuild the extension when the C++ sources change.
39
+ editable.rebuild = true
40
+ editable.verbose = false
41
+
42
+ [tool.cibuildwheel]
43
+ # Oldest macOS release supported by the binary wheels.
44
+ macos.environment = { MACOSX_DEPLOYMENT_TARGET = "13.3" }
45
+
46
+ [tool.ruff]
47
+ target-version = "py314"
48
+ line-length = 100
49
+ preview = true
50
+ lint.select = [ "E", "F", "I", "UP" ]
51
+
52
+ [tool.pyproject-fmt]
53
+ max_supported_python = "3.15"
54
+
55
+ [tool.towncrier]
56
+ package = "dlufd"
57
+ package_dir = "python"
58
+ directory = "docs/changes"
59
+ filename = "CHANGELOG.md"
60
+ start_string = "<!-- towncrier release notes start -->\n"
61
+ title_format = "## [{version}] - {project_date}"
62
+ issue_format = "#{issue}"
63
+ underlines = [ "", "", "" ]
64
+ type = [
65
+ { directory = "feature", name = "Added", showcontent = true },
66
+ { directory = "bugfix", name = "Fixed", showcontent = true },
67
+ { directory = "maintenance", name = "Maintenance", showcontent = true },
68
+ ]
69
+
70
+ [[tool.dynamic-metadata]]
71
+ provider = "scikit_build_core.metadata.setuptools_scm"
@@ -0,0 +1,8 @@
1
+ """dlufd: atmospheric propagation of Cherenkov and artificial-source photons."""
2
+
3
+ from importlib.metadata import PackageNotFoundError, version
4
+
5
+ try:
6
+ __version__ = version("dlufd")
7
+ except PackageNotFoundError:
8
+ __version__ = "0.0.0"
@@ -0,0 +1,9 @@
1
+ """The package and its native extension import."""
2
+
3
+ import dlufd
4
+ from dlufd import _core
5
+
6
+
7
+ def test_version():
8
+ assert isinstance(dlufd.__version__, str)
9
+ assert len(_core.core_version()) == 3