obdeect 0.7.0__tar.gz → 0.7.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.
- {obdeect-0.7.0 → obdeect-0.7.1}/AGENTS.md +2 -3
- {obdeect-0.7.0 → obdeect-0.7.1}/PKG-INFO +3 -1
- {obdeect-0.7.0 → obdeect-0.7.1}/README.md +2 -0
- obdeect-0.7.1/docs/changes/31.bugfix.md +1 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/optical-models.md +5 -6
- {obdeect-0.7.0 → obdeect-0.7.1}/python/obdeect/compiler.py +8 -15
- {obdeect-0.7.0 → obdeect-0.7.1}/python/tests/test_axes_offset.py +29 -3
- {obdeect-0.7.0 → obdeect-0.7.1}/.clang-format +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/.clang-tidy +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/.editorconfig +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/.gitattributes +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/.github/workflows/ci.yml +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/.github/workflows/docs.yml +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/.github/workflows/pypi.yml +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/.github/workflows/tests.yml +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/.gitignore +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/.pre-commit-config.yaml +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/CHANGELOG.md +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/CITATION.cff +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/CMakeLists.txt +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/CMakePresets.json +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/LICENSE +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/bench/bench_trace.cpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/bench/replay.cpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/bench/replay_compare.hpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/bindings/README.md +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/bindings/core.cpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/include/obdeect/bounds.hpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/include/obdeect/bunches.hpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/include/obdeect/json.hpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/include/obdeect/model.hpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/include/obdeect/model_json.hpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/include/obdeect/obscurers.hpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/include/obdeect/random.hpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/include/obdeect/source.hpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/include/obdeect/surfaces.hpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/include/obdeect/table.hpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/include/obdeect/trace.hpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/include/obdeect/vec.hpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/tests/check.hpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/tests/data/make_polynomial_reference.py +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/tests/legacy_asphere.hpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/tests/test_asphere_steps.cpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/tests/test_bounds.cpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/tests/test_kernels.cpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/tests/test_model_json.cpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/tests/test_replay_compare.cpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/cpp/tests/test_trace.cpp +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/VALIDATION.md +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/_static/figures/baffle_area.png +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/_static/figures/mst_shadowing.png +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/_static/figures/telescope_lst.png +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/_static/figures/telescope_mst_flashcam.png +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/_static/figures/telescope_mst_nectarcam.png +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/_static/figures/telescope_sct.png +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/_static/figures/telescope_sst.png +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/_static/figures/telescopes-provenance.json +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/_static/figures/validation_psf_area.png +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/_static/images/obdeect_21ratio_large.jpg +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/_static/images/obdeect_21ratio_small.jpg +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/_static/images/obdeect_large.jpg +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/_static/images/obdeect_logo.jpg +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/_static/images/obdeect_small.jpg +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/_static/obdeect.css +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/air-shower-photons.md +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/api.md +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/batch-tracing.md +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/build_versions.py +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/changelog.md +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/changes/.gitkeep +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/changes/27.feature.md +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/changes/28.maintenance.md +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/conf.py +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/figures/make_figures.py +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/figures/telescopes.yml +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/index.md +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/installation.md +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/light-sources.md +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/limitations.md +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/optical-elements.md +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/optics.md +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/python-guide.md +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/shadowing.md +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/telescopes.md +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/usage.md +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/docs/user-guide.md +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/pyproject.toml +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/python/obdeect/__init__.py +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/python/obdeect/cli.py +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/python/obdeect/formats.py +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/python/obdeect/model.py +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/python/obdeect/plot.py +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/python/obdeect/propagation.py +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/python/obdeect/psf.py +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/python/obdeect/repository.py +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/python/obdeect/simtel_tables.py +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/python/tests/telescopes.py +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/python/tests/test_bunches.py +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/python/tests/test_compiler.py +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/python/tests/test_docs_versions.py +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/python/tests/test_formats.py +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/python/tests/test_model.py +0 -0
- {obdeect-0.7.0 → obdeect-0.7.1}/python/tests/test_propagation.py +0 -0
|
@@ -51,9 +51,8 @@ scope. Read the relevant code and tests first; use `docs/VALIDATION.md` and
|
|
|
51
51
|
## Changes and validation
|
|
52
52
|
|
|
53
53
|
- Make the narrowest complete change and preserve unrelated work.
|
|
54
|
-
-
|
|
55
|
-
|
|
56
|
-
release-note change.
|
|
54
|
+
- Add an appropriate Towncrier fragment under `docs/changes/` for changes
|
|
55
|
+
that should appear in the release notes.
|
|
57
56
|
- Add or update a focused test for every behavioural change. Establish analytic
|
|
58
57
|
kernel and primitive tests before optical-model, cross-tool, or performance tests.
|
|
59
58
|
- Preserve results across photon ordering, blocks, and thread counts. Record
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: obdeect
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: Ray tracing for imaging atmospheric Cherenkov telescopes
|
|
5
5
|
Author: obdeect contributors
|
|
6
6
|
License: BSD 3-Clause License
|
|
@@ -64,6 +64,8 @@ Description-Content-Type: text/markdown
|
|
|
64
64
|
<img src="docs/_static/images/obdeect_21ratio_small.jpg" alt="Obdeect optical ray tracing for imaging atmospheric Cherenkov telescopes" width="800">
|
|
65
65
|
</p>
|
|
66
66
|
|
|
67
|
+
[](https://doi.org/10.5281/zenodo.23942573)
|
|
68
|
+
|
|
67
69
|
`obdeect` is a C++20 optical ray tracer for imaging atmospheric Cherenkov
|
|
68
70
|
telescopes. The C++ core uses only the standard library. Python compiles
|
|
69
71
|
optical models from the simulation models, traces photons, and plots results;
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
<img src="docs/_static/images/obdeect_21ratio_small.jpg" alt="Obdeect optical ray tracing for imaging atmospheric Cherenkov telescopes" width="800">
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
|
+
[](https://doi.org/10.5281/zenodo.23942573)
|
|
8
|
+
|
|
7
9
|
`obdeect` is a C++20 optical ray tracer for imaging atmospheric Cherenkov
|
|
8
10
|
telescopes. The C++ core uses only the standard library. Python compiles
|
|
9
11
|
optical models from the simulation models, traces photons, and plots results;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Accept two components for axes offsets (as expected by the simulation models).
|
|
@@ -31,15 +31,14 @@ path of the first error. Surface and obscurer ids are unique.
|
|
|
31
31
|
|
|
32
32
|
Some telescopes have the optical origin displaced from the rotation axes. The
|
|
33
33
|
sim_telarray `axes_offsets` record gives the horizontal offset between the
|
|
34
|
-
azimuth and altitude axes,
|
|
35
|
-
|
|
36
|
-
perpendicular to the optical axis) is rejected at compile time.
|
|
34
|
+
azimuth and altitude axes, followed by the altitude-to-optical-axis offset,
|
|
35
|
+
in the record's units (cm in sim_telarray).
|
|
37
36
|
|
|
38
37
|
The compiler stores the offset in the telescope frame, in metres, as
|
|
39
38
|
`optics.axes_offset_m` = [x, y, z]. The key is written only when the offset is
|
|
40
|
-
non-zero, and it needs the zenith angle of the compilation.
|
|
41
|
-
`(O
|
|
42
|
-
`theta`. The loader requires three numbers.
|
|
39
|
+
non-zero, and it needs the zenith angle of the compilation. For components
|
|
40
|
+
`(O, T)` and zenith `theta`, the offset is
|
|
41
|
+
`(O cos(theta) - T, 0, O sin(theta))`. The loader requires three numbers.
|
|
43
42
|
|
|
44
43
|
The offset is applied only by `trace_bunches`, which subtracts it from its frame
|
|
45
44
|
offset (see [Batch tracing](batch-tracing.md)). `trace`, `star_photons` and the
|
|
@@ -170,13 +170,11 @@ def compile_model(
|
|
|
170
170
|
def _axes_offset_m(p: _Parameters, zenith_deg: float | None) -> list[float]:
|
|
171
171
|
"""Offset of the optical origin from the telescope sphere centre, telescope frame [m].
|
|
172
172
|
|
|
173
|
-
The ``axes_offsets`` record (sim_telarray ``axes_offset
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
telescope frame at the compiled zenith angle: (O cos(theta), 0, O sin(theta)). Zero when the
|
|
179
|
-
record is absent or zero; a non-zero offset needs the zenith angle.
|
|
173
|
+
The ``axes_offsets`` record (sim_telarray ``axes_offset``) holds the horizontal offset
|
|
174
|
+
between the azimuth and altitude axes followed by the altitude-to-optical-axis offset.
|
|
175
|
+
The first component transforms to (along*cos(theta), 0, along*sin(theta)); the second is
|
|
176
|
+
subtracted along telescope-frame x. Zero when the record is absent or zero; a non-zero
|
|
177
|
+
offset needs the zenith angle.
|
|
180
178
|
"""
|
|
181
179
|
if "axes_offsets" not in p:
|
|
182
180
|
return [0.0, 0.0, 0.0]
|
|
@@ -184,22 +182,17 @@ def _axes_offset_m(p: _Parameters, zenith_deg: float | None) -> list[float]:
|
|
|
184
182
|
if len(values) > 2:
|
|
185
183
|
raise ModelError("axes_offsets has more than two components")
|
|
186
184
|
along = number(values[0], "axes_offsets") * length_unit_m(units[0], "axes_offsets")
|
|
187
|
-
|
|
185
|
+
transverse = (
|
|
188
186
|
number(values[1], "axes_offsets") * length_unit_m(units[1], "axes_offsets")
|
|
189
187
|
if len(values) == 2
|
|
190
188
|
else 0.0
|
|
191
189
|
)
|
|
192
|
-
if
|
|
193
|
-
raise NotImplementedError(
|
|
194
|
-
"a non-zero second axes_offsets component (displacement perpendicular to the optical "
|
|
195
|
-
"axis) is not supported"
|
|
196
|
-
)
|
|
197
|
-
if along == 0.0:
|
|
190
|
+
if along == 0.0 and transverse == 0.0:
|
|
198
191
|
return [0.0, 0.0, 0.0]
|
|
199
192
|
if zenith_deg is None:
|
|
200
193
|
raise ModelError("axes_offsets needs the telescope zenith angle")
|
|
201
194
|
theta = math.radians(zenith_deg)
|
|
202
|
-
return [along * math.cos(theta), 0.0, along * math.sin(theta)]
|
|
195
|
+
return [along * math.cos(theta) - transverse, 0.0, along * math.sin(theta)]
|
|
203
196
|
|
|
204
197
|
|
|
205
198
|
def _sampling(p: _Parameters, optics: dict[str, Any]) -> dict[str, float]:
|
|
@@ -116,9 +116,35 @@ def test_axes_offset_follows_the_zenith_angle():
|
|
|
116
116
|
assert model.axes_offset_m == pytest.approx((1.6, 0.0, 0.0))
|
|
117
117
|
|
|
118
118
|
|
|
119
|
-
def
|
|
120
|
-
|
|
121
|
-
|
|
119
|
+
def test_second_axes_offset_component_is_transverse_to_the_optical_axis():
|
|
120
|
+
model = compiled([OFFSET_CM, 10.0])
|
|
121
|
+
assert model.axes_offset_m == pytest.approx((
|
|
122
|
+
OFFSET_CM / 100 * COS - 0.1,
|
|
123
|
+
0.0,
|
|
124
|
+
OFFSET_CM / 100 * SIN,
|
|
125
|
+
))
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def test_equal_offsets_align_optical_and_azimuth_axes_at_zenith():
|
|
129
|
+
model = compiled([OFFSET_CM, OFFSET_CM], zenith_deg=0.0)
|
|
130
|
+
assert model.axes_offset_m == pytest.approx(ORIGIN)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def test_transverse_offset_matches_explicit_frame_transform(reference):
|
|
134
|
+
model = compiled([OFFSET_CM, 10.0])
|
|
135
|
+
bunches = ground_bunches(3000)
|
|
136
|
+
# sim_telarray translates by -O before rotation and +T in telescope x.
|
|
137
|
+
frame_offset = -ROTATION @ GROUND_OFFSET_M + np.array([0.1, 0.0, 0.0])
|
|
138
|
+
expected = trace_ground(reference, bunches, 30.0, offset_m=frame_offset)
|
|
139
|
+
actual = trace_ground(model, bunches, 30.0)
|
|
140
|
+
assert len(actual["weight"]) > 0
|
|
141
|
+
for name in ("bunch_index", "position_m", "direction", "time_ns", "weight"):
|
|
142
|
+
np.testing.assert_allclose(actual[name], expected[name], atol=1e-9)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def test_second_axes_offset_component_needs_the_zenith_angle():
|
|
146
|
+
with pytest.raises(ModelError, match="zenith"):
|
|
147
|
+
compiled([0.0, 10.0], zenith_deg=None)
|
|
122
148
|
|
|
123
149
|
|
|
124
150
|
def test_axes_offset_needs_the_zenith_angle():
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|