lsurf 1.0.0__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.
Files changed (240) hide show
  1. lsurf-1.0.0/.gitlab/ci-setup.md +95 -0
  2. lsurf-1.0.0/.gitlab-ci.yml +127 -0
  3. lsurf-1.0.0/.python-version +1 -0
  4. lsurf-1.0.0/.ruff.toml +11 -0
  5. lsurf-1.0.0/LICENSE +32 -0
  6. lsurf-1.0.0/MANIFEST.in +37 -0
  7. lsurf-1.0.0/PKG-INFO +381 -0
  8. lsurf-1.0.0/README.md +328 -0
  9. lsurf-1.0.0/__init__.py +0 -0
  10. lsurf-1.0.0/conda-recipe/meta.yaml +69 -0
  11. lsurf-1.0.0/environment.yml +86 -0
  12. lsurf-1.0.0/pyproject.toml +173 -0
  13. lsurf-1.0.0/scripts/00_run_all.py +210 -0
  14. lsurf-1.0.0/scripts/01_basic.py +167 -0
  15. lsurf-1.0.0/scripts/02_sources.py +201 -0
  16. lsurf-1.0.0/scripts/03_visualization.py +326 -0
  17. lsurf-1.0.0/scripts/04_glass_reflection.py +251 -0
  18. lsurf-1.0.0/scripts/05_water_brewster.py +351 -0
  19. lsurf-1.0.0/scripts/06_detector_scan.py +289 -0
  20. lsurf-1.0.0/scripts/07_detector_scan_waves.py +253 -0
  21. lsurf-1.0.0/scripts/08_detector_scan_waves_largescale.py +276 -0
  22. lsurf-1.0.0/scripts/09_full_3d_curved_ocean.py +655 -0
  23. lsurf-1.0.0/scripts/09b_full_3d_curved_ocean_global_sphere.py +628 -0
  24. lsurf-1.0.0/scripts/10_time_spread_estimate.py +206 -0
  25. lsurf-1.0.0/scripts/10b_time_spread_altitude_comparison.py +143 -0
  26. lsurf-1.0.0/scripts/11_atmospheric_refraction.py +640 -0
  27. lsurf-1.0.0/scripts/11b_simple_atmospheric_refraction.py +199 -0
  28. lsurf-1.0.0/scripts/12_absorption_test.py +354 -0
  29. lsurf-1.0.0/scripts/13_time_spread_scaling.py +842 -0
  30. lsurf-1.0.0/scripts/HAHA_refraction_austin.py +225 -0
  31. lsurf-1.0.0/scripts/debug_test2.py +155 -0
  32. lsurf-1.0.0/setup.cfg +4 -0
  33. lsurf-1.0.0/src/lsurf/__init__.py +471 -0
  34. lsurf-1.0.0/src/lsurf/analysis/__init__.py +107 -0
  35. lsurf-1.0.0/src/lsurf/analysis/healpix_utils.py +418 -0
  36. lsurf-1.0.0/src/lsurf/analysis/sphere_viz.py +1280 -0
  37. lsurf-1.0.0/src/lsurf/cli/__init__.py +48 -0
  38. lsurf-1.0.0/src/lsurf/cli/build.py +398 -0
  39. lsurf-1.0.0/src/lsurf/cli/config_schema.py +318 -0
  40. lsurf-1.0.0/src/lsurf/cli/gui_cmd.py +76 -0
  41. lsurf-1.0.0/src/lsurf/cli/interactive.py +850 -0
  42. lsurf-1.0.0/src/lsurf/cli/main.py +81 -0
  43. lsurf-1.0.0/src/lsurf/cli/run.py +806 -0
  44. lsurf-1.0.0/src/lsurf/detectors/__init__.py +266 -0
  45. lsurf-1.0.0/src/lsurf/detectors/analysis.py +289 -0
  46. lsurf-1.0.0/src/lsurf/detectors/base.py +284 -0
  47. lsurf-1.0.0/src/lsurf/detectors/constant_size_rings.py +485 -0
  48. lsurf-1.0.0/src/lsurf/detectors/directional.py +45 -0
  49. lsurf-1.0.0/src/lsurf/detectors/extended/__init__.py +73 -0
  50. lsurf-1.0.0/src/lsurf/detectors/extended/local_sphere.py +353 -0
  51. lsurf-1.0.0/src/lsurf/detectors/extended/recording_sphere.py +368 -0
  52. lsurf-1.0.0/src/lsurf/detectors/planar.py +45 -0
  53. lsurf-1.0.0/src/lsurf/detectors/protocol.py +187 -0
  54. lsurf-1.0.0/src/lsurf/detectors/recording_spheres.py +63 -0
  55. lsurf-1.0.0/src/lsurf/detectors/results.py +1140 -0
  56. lsurf-1.0.0/src/lsurf/detectors/small/__init__.py +79 -0
  57. lsurf-1.0.0/src/lsurf/detectors/small/directional.py +330 -0
  58. lsurf-1.0.0/src/lsurf/detectors/small/planar.py +401 -0
  59. lsurf-1.0.0/src/lsurf/detectors/small/spherical.py +450 -0
  60. lsurf-1.0.0/src/lsurf/detectors/spherical.py +45 -0
  61. lsurf-1.0.0/src/lsurf/geometry/__init__.py +199 -0
  62. lsurf-1.0.0/src/lsurf/geometry/builder.py +478 -0
  63. lsurf-1.0.0/src/lsurf/geometry/cell.py +228 -0
  64. lsurf-1.0.0/src/lsurf/geometry/cell_geometry.py +247 -0
  65. lsurf-1.0.0/src/lsurf/geometry/detector_arrays.py +1785 -0
  66. lsurf-1.0.0/src/lsurf/geometry/geometry.py +222 -0
  67. lsurf-1.0.0/src/lsurf/geometry/surface_analysis.py +375 -0
  68. lsurf-1.0.0/src/lsurf/geometry/validation.py +91 -0
  69. lsurf-1.0.0/src/lsurf/gui/__init__.py +51 -0
  70. lsurf-1.0.0/src/lsurf/gui/app.py +903 -0
  71. lsurf-1.0.0/src/lsurf/gui/core/__init__.py +39 -0
  72. lsurf-1.0.0/src/lsurf/gui/core/scene.py +343 -0
  73. lsurf-1.0.0/src/lsurf/gui/core/simulation.py +264 -0
  74. lsurf-1.0.0/src/lsurf/gui/renderers/__init__.py +40 -0
  75. lsurf-1.0.0/src/lsurf/gui/renderers/ray_renderer.py +353 -0
  76. lsurf-1.0.0/src/lsurf/gui/renderers/source_renderer.py +505 -0
  77. lsurf-1.0.0/src/lsurf/gui/renderers/surface_renderer.py +477 -0
  78. lsurf-1.0.0/src/lsurf/gui/views/__init__.py +48 -0
  79. lsurf-1.0.0/src/lsurf/gui/views/config_editor.py +3199 -0
  80. lsurf-1.0.0/src/lsurf/gui/views/properties.py +257 -0
  81. lsurf-1.0.0/src/lsurf/gui/views/results.py +291 -0
  82. lsurf-1.0.0/src/lsurf/gui/views/scene_tree.py +180 -0
  83. lsurf-1.0.0/src/lsurf/gui/views/viewport_3d.py +555 -0
  84. lsurf-1.0.0/src/lsurf/gui/views/visualizations.py +712 -0
  85. lsurf-1.0.0/src/lsurf/materials/__init__.py +169 -0
  86. lsurf-1.0.0/src/lsurf/materials/base/__init__.py +64 -0
  87. lsurf-1.0.0/src/lsurf/materials/base/full_inhomogeneous.py +208 -0
  88. lsurf-1.0.0/src/lsurf/materials/base/grid_inhomogeneous.py +319 -0
  89. lsurf-1.0.0/src/lsurf/materials/base/homogeneous.py +342 -0
  90. lsurf-1.0.0/src/lsurf/materials/base/material_field.py +527 -0
  91. lsurf-1.0.0/src/lsurf/materials/base/simple_inhomogeneous.py +418 -0
  92. lsurf-1.0.0/src/lsurf/materials/base/spectral_inhomogeneous.py +497 -0
  93. lsurf-1.0.0/src/lsurf/materials/implementations/__init__.py +120 -0
  94. lsurf-1.0.0/src/lsurf/materials/implementations/data/alpha_values_typical_atmosphere_updated.txt +24 -0
  95. lsurf-1.0.0/src/lsurf/materials/implementations/duct_atmosphere.py +390 -0
  96. lsurf-1.0.0/src/lsurf/materials/implementations/exponential_atmosphere.py +435 -0
  97. lsurf-1.0.0/src/lsurf/materials/implementations/gaussian_lens.py +120 -0
  98. lsurf-1.0.0/src/lsurf/materials/implementations/interpolated_data.py +123 -0
  99. lsurf-1.0.0/src/lsurf/materials/implementations/layered_atmosphere.py +134 -0
  100. lsurf-1.0.0/src/lsurf/materials/implementations/linear_gradient.py +109 -0
  101. lsurf-1.0.0/src/lsurf/materials/implementations/linsley_atmosphere.py +764 -0
  102. lsurf-1.0.0/src/lsurf/materials/implementations/standard_materials.py +126 -0
  103. lsurf-1.0.0/src/lsurf/materials/implementations/turbulent_atmosphere.py +135 -0
  104. lsurf-1.0.0/src/lsurf/materials/implementations/us_standard_atmosphere.py +149 -0
  105. lsurf-1.0.0/src/lsurf/materials/utils/__init__.py +77 -0
  106. lsurf-1.0.0/src/lsurf/materials/utils/constants.py +45 -0
  107. lsurf-1.0.0/src/lsurf/materials/utils/device_functions.py +117 -0
  108. lsurf-1.0.0/src/lsurf/materials/utils/dispersion.py +160 -0
  109. lsurf-1.0.0/src/lsurf/materials/utils/factories.py +142 -0
  110. lsurf-1.0.0/src/lsurf/propagation/__init__.py +91 -0
  111. lsurf-1.0.0/src/lsurf/propagation/detector_gpu.py +67 -0
  112. lsurf-1.0.0/src/lsurf/propagation/gpu_device_rays.py +294 -0
  113. lsurf-1.0.0/src/lsurf/propagation/kernels/__init__.py +175 -0
  114. lsurf-1.0.0/src/lsurf/propagation/kernels/absorption/__init__.py +61 -0
  115. lsurf-1.0.0/src/lsurf/propagation/kernels/absorption/grid.py +240 -0
  116. lsurf-1.0.0/src/lsurf/propagation/kernels/absorption/simple.py +232 -0
  117. lsurf-1.0.0/src/lsurf/propagation/kernels/absorption/spectral.py +410 -0
  118. lsurf-1.0.0/src/lsurf/propagation/kernels/detection/__init__.py +64 -0
  119. lsurf-1.0.0/src/lsurf/propagation/kernels/detection/protocol.py +102 -0
  120. lsurf-1.0.0/src/lsurf/propagation/kernels/detection/spherical.py +255 -0
  121. lsurf-1.0.0/src/lsurf/propagation/kernels/device_functions.py +790 -0
  122. lsurf-1.0.0/src/lsurf/propagation/kernels/fresnel/__init__.py +64 -0
  123. lsurf-1.0.0/src/lsurf/propagation/kernels/fresnel/protocol.py +97 -0
  124. lsurf-1.0.0/src/lsurf/propagation/kernels/fresnel/standard.py +258 -0
  125. lsurf-1.0.0/src/lsurf/propagation/kernels/intersection/__init__.py +79 -0
  126. lsurf-1.0.0/src/lsurf/propagation/kernels/intersection/annular_plane.py +207 -0
  127. lsurf-1.0.0/src/lsurf/propagation/kernels/intersection/bounded_plane.py +205 -0
  128. lsurf-1.0.0/src/lsurf/propagation/kernels/intersection/plane.py +166 -0
  129. lsurf-1.0.0/src/lsurf/propagation/kernels/intersection/protocol.py +95 -0
  130. lsurf-1.0.0/src/lsurf/propagation/kernels/intersection/signed_distance.py +742 -0
  131. lsurf-1.0.0/src/lsurf/propagation/kernels/intersection/sphere.py +190 -0
  132. lsurf-1.0.0/src/lsurf/propagation/kernels/propagation/__init__.py +85 -0
  133. lsurf-1.0.0/src/lsurf/propagation/kernels/propagation/grid.py +527 -0
  134. lsurf-1.0.0/src/lsurf/propagation/kernels/propagation/protocol.py +105 -0
  135. lsurf-1.0.0/src/lsurf/propagation/kernels/propagation/simple.py +460 -0
  136. lsurf-1.0.0/src/lsurf/propagation/kernels/propagation/spectral.py +875 -0
  137. lsurf-1.0.0/src/lsurf/propagation/kernels/registry.py +331 -0
  138. lsurf-1.0.0/src/lsurf/propagation/kernels/surface/__init__.py +72 -0
  139. lsurf-1.0.0/src/lsurf/propagation/kernels/surface/bisection.py +232 -0
  140. lsurf-1.0.0/src/lsurf/propagation/kernels/surface/detection.py +402 -0
  141. lsurf-1.0.0/src/lsurf/propagation/kernels/surface/reduction.py +166 -0
  142. lsurf-1.0.0/src/lsurf/propagation/propagator_protocol.py +222 -0
  143. lsurf-1.0.0/src/lsurf/propagation/propagators/__init__.py +101 -0
  144. lsurf-1.0.0/src/lsurf/propagation/propagators/detector_handler.py +354 -0
  145. lsurf-1.0.0/src/lsurf/propagation/propagators/factory.py +200 -0
  146. lsurf-1.0.0/src/lsurf/propagation/propagators/fresnel_handler.py +305 -0
  147. lsurf-1.0.0/src/lsurf/propagation/propagators/gpu_gradient.py +566 -0
  148. lsurf-1.0.0/src/lsurf/propagation/propagators/gpu_surface_propagator.py +707 -0
  149. lsurf-1.0.0/src/lsurf/propagation/propagators/gradient.py +429 -0
  150. lsurf-1.0.0/src/lsurf/propagation/propagators/intersection_handler.py +327 -0
  151. lsurf-1.0.0/src/lsurf/propagation/propagators/material_propagator.py +398 -0
  152. lsurf-1.0.0/src/lsurf/propagation/propagators/signed_distance_handler.py +522 -0
  153. lsurf-1.0.0/src/lsurf/propagation/propagators/spectral_gpu_gradient.py +553 -0
  154. lsurf-1.0.0/src/lsurf/propagation/propagators/surface_interaction.py +616 -0
  155. lsurf-1.0.0/src/lsurf/propagation/propagators/surface_propagator.py +719 -0
  156. lsurf-1.0.0/src/lsurf/py.typed +1 -0
  157. lsurf-1.0.0/src/lsurf/simulation/__init__.py +70 -0
  158. lsurf-1.0.0/src/lsurf/simulation/config.py +164 -0
  159. lsurf-1.0.0/src/lsurf/simulation/orchestrator.py +462 -0
  160. lsurf-1.0.0/src/lsurf/simulation/result.py +299 -0
  161. lsurf-1.0.0/src/lsurf/simulation/simulation.py +262 -0
  162. lsurf-1.0.0/src/lsurf/sources/__init__.py +128 -0
  163. lsurf-1.0.0/src/lsurf/sources/base.py +264 -0
  164. lsurf-1.0.0/src/lsurf/sources/collimated.py +252 -0
  165. lsurf-1.0.0/src/lsurf/sources/custom.py +409 -0
  166. lsurf-1.0.0/src/lsurf/sources/diverging.py +228 -0
  167. lsurf-1.0.0/src/lsurf/sources/gaussian.py +272 -0
  168. lsurf-1.0.0/src/lsurf/sources/parallel_from_positions.py +197 -0
  169. lsurf-1.0.0/src/lsurf/sources/point.py +172 -0
  170. lsurf-1.0.0/src/lsurf/sources/uniform_diverging.py +258 -0
  171. lsurf-1.0.0/src/lsurf/surfaces/__init__.py +184 -0
  172. lsurf-1.0.0/src/lsurf/surfaces/cpu/__init__.py +50 -0
  173. lsurf-1.0.0/src/lsurf/surfaces/cpu/curved_wave.py +463 -0
  174. lsurf-1.0.0/src/lsurf/surfaces/cpu/gerstner_wave.py +381 -0
  175. lsurf-1.0.0/src/lsurf/surfaces/cpu/wave_params.py +118 -0
  176. lsurf-1.0.0/src/lsurf/surfaces/gpu/__init__.py +72 -0
  177. lsurf-1.0.0/src/lsurf/surfaces/gpu/annular_plane.py +453 -0
  178. lsurf-1.0.0/src/lsurf/surfaces/gpu/bounded_plane.py +390 -0
  179. lsurf-1.0.0/src/lsurf/surfaces/gpu/curved_wave.py +483 -0
  180. lsurf-1.0.0/src/lsurf/surfaces/gpu/gerstner_wave.py +377 -0
  181. lsurf-1.0.0/src/lsurf/surfaces/gpu/multi_curved_wave.py +520 -0
  182. lsurf-1.0.0/src/lsurf/surfaces/gpu/plane.py +299 -0
  183. lsurf-1.0.0/src/lsurf/surfaces/gpu/recording_sphere.py +587 -0
  184. lsurf-1.0.0/src/lsurf/surfaces/gpu/sphere.py +311 -0
  185. lsurf-1.0.0/src/lsurf/surfaces/protocol.py +336 -0
  186. lsurf-1.0.0/src/lsurf/surfaces/registry.py +373 -0
  187. lsurf-1.0.0/src/lsurf/utilities/__init__.py +175 -0
  188. lsurf-1.0.0/src/lsurf/utilities/detector_analysis.py +814 -0
  189. lsurf-1.0.0/src/lsurf/utilities/fresnel.py +628 -0
  190. lsurf-1.0.0/src/lsurf/utilities/interactions.py +1215 -0
  191. lsurf-1.0.0/src/lsurf/utilities/propagation.py +602 -0
  192. lsurf-1.0.0/src/lsurf/utilities/ray_data.py +532 -0
  193. lsurf-1.0.0/src/lsurf/utilities/recording_sphere.py +745 -0
  194. lsurf-1.0.0/src/lsurf/utilities/time_spread.py +463 -0
  195. lsurf-1.0.0/src/lsurf/visualization/__init__.py +329 -0
  196. lsurf-1.0.0/src/lsurf/visualization/absorption_plots.py +334 -0
  197. lsurf-1.0.0/src/lsurf/visualization/atmospheric_plots.py +754 -0
  198. lsurf-1.0.0/src/lsurf/visualization/common.py +348 -0
  199. lsurf-1.0.0/src/lsurf/visualization/detector_plots.py +1350 -0
  200. lsurf-1.0.0/src/lsurf/visualization/detector_sphere_plots.py +1173 -0
  201. lsurf-1.0.0/src/lsurf/visualization/fresnel_plots.py +1061 -0
  202. lsurf-1.0.0/src/lsurf/visualization/ocean_simulation_plots.py +999 -0
  203. lsurf-1.0.0/src/lsurf/visualization/polarization_plots.py +916 -0
  204. lsurf-1.0.0/src/lsurf/visualization/raytracing_plots.py +1521 -0
  205. lsurf-1.0.0/src/lsurf/visualization/ring_detector_plots.py +1867 -0
  206. lsurf-1.0.0/src/lsurf/visualization/time_spread_plots.py +531 -0
  207. lsurf-1.0.0/src/lsurf.egg-info/PKG-INFO +381 -0
  208. lsurf-1.0.0/src/lsurf.egg-info/SOURCES.txt +238 -0
  209. lsurf-1.0.0/src/lsurf.egg-info/dependency_links.txt +1 -0
  210. lsurf-1.0.0/src/lsurf.egg-info/entry_points.txt +2 -0
  211. lsurf-1.0.0/src/lsurf.egg-info/requires.txt +28 -0
  212. lsurf-1.0.0/src/lsurf.egg-info/top_level.txt +1 -0
  213. lsurf-1.0.0/tests/__init__.py +18 -0
  214. lsurf-1.0.0/tests/conftest.py +72 -0
  215. lsurf-1.0.0/tests/test_absorption.py +882 -0
  216. lsurf-1.0.0/tests/test_atmosphere_templates.py +554 -0
  217. lsurf-1.0.0/tests/test_bounding_sphere.py +342 -0
  218. lsurf-1.0.0/tests/test_cell_geometry.py +547 -0
  219. lsurf-1.0.0/tests/test_detectors.py +430 -0
  220. lsurf-1.0.0/tests/test_example_scripts.py +249 -0
  221. lsurf-1.0.0/tests/test_flat_ocean_travel_time.py +305 -0
  222. lsurf-1.0.0/tests/test_geometry_validation.py +410 -0
  223. lsurf-1.0.0/tests/test_gpu_modules.py +1820 -0
  224. lsurf-1.0.0/tests/test_intersection_precision.py +623 -0
  225. lsurf-1.0.0/tests/test_kernel_compatibility.py +243 -0
  226. lsurf-1.0.0/tests/test_materials.py +299 -0
  227. lsurf-1.0.0/tests/test_optional_numba.py +134 -0
  228. lsurf-1.0.0/tests/test_physics_constraints.py +534 -0
  229. lsurf-1.0.0/tests/test_polarization_preservation.py +469 -0
  230. lsurf-1.0.0/tests/test_propagation.py +371 -0
  231. lsurf-1.0.0/tests/test_ray_data.py +353 -0
  232. lsurf-1.0.0/tests/test_reflection.py +981 -0
  233. lsurf-1.0.0/tests/test_sources.py +1423 -0
  234. lsurf-1.0.0/tests/test_spectral_atmosphere.py +1423 -0
  235. lsurf-1.0.0/tests/test_specular_time_spread.py +530 -0
  236. lsurf-1.0.0/tests/test_surfaces.py +2094 -0
  237. lsurf-1.0.0/tests/test_time_spread_scaling.py +659 -0
  238. lsurf-1.0.0/tests/test_timing.py +256 -0
  239. lsurf-1.0.0/tests/test_travel_time_physics.py +1432 -0
  240. lsurf-1.0.0/tox.ini +24 -0
@@ -0,0 +1,95 @@
1
+ # GitLab CI Setup
2
+
3
+ ## Overview
4
+
5
+ This repository uses GitLab CI/CD for automated testing, building, and deployment.
6
+
7
+ ## Pipeline Stages
8
+
9
+ ### 1. Check Stage
10
+ - **check:pre-commit**: Runs all pre-commit hooks to ensure code quality
11
+ - Code formatting (Black)
12
+ - Linting (Ruff)
13
+ - File checks (trailing whitespace, EOF, merge conflicts, etc.)
14
+
15
+ ### 2. Test Stage
16
+ - **test:py313**: Main test suite on Python 3.13
17
+ - Runs full test suite with pytest
18
+ - Generates coverage reports
19
+ - Creates JUnit XML for GitLab integration
20
+ - **test:py314**: Test suite on Python 3.14-rc (allow_failure: true)
21
+ - Early testing for upcoming Python version
22
+
23
+ ### 3. Build Stage
24
+ - **build:package**: Builds distribution packages
25
+ - Only runs on `main` branch and tags
26
+ - Creates wheel and source distribution
27
+ - Validates with twine
28
+ - Artifacts stored for 1 week
29
+
30
+ ### 4. Deploy Stage
31
+ - **pages**: Builds and deploys Sphinx documentation
32
+ - Only runs on `main` branch and tags
33
+ - Generates HTML documentation
34
+ - Deploys to GitLab Pages
35
+ - **deploy:pypi**: Deploys to PyPI
36
+ - Only runs on tags
37
+ - Uses `PYPI_TOKEN` secret variable
38
+ - Uploads built packages from build stage
39
+
40
+ ## Required Variables
41
+
42
+ Set these in GitLab CI/CD Settings → Variables:
43
+
44
+ - `PYPI_TOKEN`: PyPI API token for package deployment
45
+ - Type: Variable
46
+ - Protected: Yes
47
+ - Masked: Yes
48
+
49
+ ## Local Testing
50
+
51
+ Test the pipeline locally before pushing:
52
+
53
+ ```bash
54
+ # Install dependencies
55
+ pip install -e ".[dev,test]"
56
+
57
+ # Run pre-commit checks
58
+ pre-commit run --all-files
59
+
60
+ # Run tests
61
+ pytest -v tests/
62
+
63
+ # Build package
64
+ python -m build
65
+ python -m twine check dist/*
66
+
67
+ # Build documentation
68
+ sphinx-build -b html docs public
69
+ ```
70
+
71
+ ## Python Version Support
72
+
73
+ - **Minimum**: Python 3.13
74
+ - **Tested**: Python 3.13, 3.14-rc
75
+ - **Recommended**: Python 3.13
76
+
77
+ ## Cache Configuration
78
+
79
+ The pipeline caches pip packages to speed up builds:
80
+ - Cache directory: `$CI_PROJECT_DIR/.cache/pip`
81
+ - Separate cache for pre-commit hooks
82
+
83
+ ## Coverage Reports
84
+
85
+ Coverage reports are:
86
+ - Displayed in pipeline output
87
+ - Stored as HTML artifacts (1 week)
88
+ - Integrated with GitLab's coverage visualization
89
+
90
+ ## Artifacts
91
+
92
+ Build artifacts are stored for:
93
+ - Test reports: 1 week
94
+ - Built packages: 1 week
95
+ - Documentation: 1 week
@@ -0,0 +1,127 @@
1
+ image: python:3.14
2
+
3
+ variables:
4
+ PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
5
+
6
+ cache:
7
+ paths:
8
+ - .cache/pip
9
+
10
+ stages:
11
+ - check
12
+ - test
13
+ - build
14
+ - deploy
15
+
16
+ # =============================================================================
17
+ # Pre-commit checks
18
+ # =============================================================================
19
+
20
+ check:pre-commit:
21
+ stage: check
22
+ allow_failure: false
23
+ before_script:
24
+ - pip install pre-commit
25
+ script:
26
+ - pre-commit run --all-files --verbose --show-diff-on-failure
27
+ cache:
28
+ key: pre-commit
29
+ paths:
30
+ - ~/.cache/pre-commit
31
+
32
+ # =============================================================================
33
+ # Tests
34
+ # =============================================================================
35
+
36
+ test:py314:
37
+ stage: test
38
+ image: python:3.14
39
+ before_script:
40
+ - pip install -e ".[test]"
41
+ script:
42
+ # Run non-slow tests only (~5 min) - use `pytest` for full suite
43
+ - pytest -v -m "not slow" tests/
44
+ coverage: '/(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/'
45
+ artifacts:
46
+ when: always
47
+ reports:
48
+ junit: junit.xml
49
+ paths:
50
+ - htmlcov/
51
+ expire_in: 1 week
52
+
53
+ # =============================================================================
54
+ # Build
55
+ # =============================================================================
56
+
57
+ build:package:
58
+ stage: build
59
+ only:
60
+ - tags
61
+ - master
62
+ before_script:
63
+ - pip install build twine
64
+ script:
65
+ - python -m build
66
+ - python -m twine check dist/*
67
+ artifacts:
68
+ paths:
69
+ - dist/
70
+ expire_in: 1 week
71
+
72
+ # =============================================================================
73
+ # Documentation
74
+ # =============================================================================
75
+
76
+ pages:
77
+ stage: deploy
78
+ only:
79
+ - master
80
+ - tags
81
+ before_script:
82
+ - pip install -e ".[dev]"
83
+ - pip install sphinx sphinx-rtd-theme sphinx-autodoc-typehints
84
+ script:
85
+ - sphinx-build -b html docs public
86
+ artifacts:
87
+ paths:
88
+ - public
89
+ expire_in: 1 week
90
+
91
+ # =============================================================================
92
+ # Publish to TestPyPI (manual trigger)
93
+ # =============================================================================
94
+
95
+ publish:testpypi:
96
+ stage: deploy
97
+ rules:
98
+ - if: $CI_COMMIT_TAG =~ /^v.*/
99
+ when: manual
100
+ dependencies:
101
+ - build:package
102
+ before_script:
103
+ - pip install twine
104
+ script:
105
+ - python -m twine upload --repository testpypi dist/*
106
+ variables:
107
+ TWINE_USERNAME: __token__
108
+ TWINE_PASSWORD: $TESTPYPI_TOKEN
109
+
110
+ # =============================================================================
111
+ # Publish to PyPI (manual trigger)
112
+ # =============================================================================
113
+
114
+ publish:pypi:
115
+ stage: deploy
116
+ rules:
117
+ - if: $CI_COMMIT_TAG =~ /^v.*/
118
+ when: manual
119
+ dependencies:
120
+ - build:package
121
+ before_script:
122
+ - pip install twine
123
+ script:
124
+ - python -m twine upload dist/*
125
+ variables:
126
+ TWINE_USERNAME: __token__
127
+ TWINE_PASSWORD: $PYPI_TOKEN
@@ -0,0 +1 @@
1
+ 3.13
lsurf-1.0.0/.ruff.toml ADDED
@@ -0,0 +1,11 @@
1
+ # Ruff configuration
2
+ [lint.per-file-ignores]
3
+ "__init__.py" = [
4
+ "E402",
5
+ "F401",
6
+ ] # Allow module-level imports not at top, unused imports
7
+ "tests/*.py" = ["E722"] # Allow bare except in tests for CUDA checks
8
+ "scripts/*.py" = [
9
+ "E402",
10
+ "F841",
11
+ ] # Allow imports after code, unused variables in scripts
lsurf-1.0.0/LICENSE ADDED
@@ -0,0 +1,32 @@
1
+ # The Clear BSD License
2
+ #
3
+ # Copyright (c) 2026 Tobias Heibges
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted (subject to the limitations in the disclaimer
8
+ # below) provided that the following conditions are met:
9
+ #
10
+ # * Redistributions of source code must retain the above copyright notice,
11
+ # this list of conditions and the following disclaimer.
12
+ #
13
+ # * Redistributions in binary form must reproduce the above copyright
14
+ # notice, this list of conditions and the following disclaimer in the
15
+ # documentation and/or other materials provided with the distribution.
16
+ #
17
+ # * Neither the name of the copyright holder nor the names of its
18
+ # contributors may be used to endorse or promote products derived from this
19
+ # software without specific prior written permission.
20
+ #
21
+ # NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
22
+ # THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
23
+ # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25
+ # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
26
+ # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28
+ # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29
+ # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
30
+ # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
+ # POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,37 @@
1
+ # Include documentation
2
+ include README.md
3
+ include LICENSE
4
+ include CHANGELOG.md
5
+
6
+ # Include package data
7
+ include src/surface_reflections/py.typed
8
+
9
+ # Include configuration files
10
+ include pyproject.toml
11
+ include setup.cfg
12
+ include environment.yml
13
+
14
+ # Include conda recipe
15
+ recursive-include conda-recipe *
16
+
17
+ # Exclude development files
18
+ exclude .gitignore
19
+ exclude .pre-commit-config.yaml
20
+
21
+ # Exclude test cache
22
+ global-exclude __pycache__
23
+ global-exclude *.py[cod]
24
+ global-exclude .pytest_cache
25
+ global-exclude .mypy_cache
26
+ global-exclude .ruff_cache
27
+
28
+ # Exclude data and plots directories
29
+ prune data
30
+ prune plots
31
+ prune old
32
+ prune info
33
+ prune docs
34
+
35
+ # Exclude large binary files
36
+ global-exclude numba
37
+ global-exclude sys
lsurf-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,381 @@
1
+ Metadata-Version: 2.4
2
+ Name: lsurf
3
+ Version: 1.0.0
4
+ Summary: L-SURF: GPU-accelerated physically-accurate raytracing framework for simulating light-surface interactions
5
+ Author: Tobias Heibges
6
+ Maintainer: Tobias Heibges
7
+ License: BSD-3-Clause-Clear
8
+ Project-URL: Homepage, https://github.com/tobi-h/lsurf
9
+ Project-URL: Documentation, https://github.com/tobi-h/lsurf#readme
10
+ Project-URL: Repository, https://github.com/tobi-h/lsurf.git
11
+ Project-URL: Issues, https://github.com/tobi-h/lsurf/issues
12
+ Keywords: raytracing,gpu,cuda,numba,optics,fresnel,reflection,refraction,waves,ocean,simulation,physics
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: BSD License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Topic :: Scientific/Engineering :: Physics
21
+ Classifier: Topic :: Scientific/Engineering :: Visualization
22
+ Requires-Python: >=3.13
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: numpy>=1.24.0
26
+ Requires-Dist: matplotlib>=3.7.0
27
+ Requires-Dist: pydantic>=2.0.0
28
+ Requires-Dist: numba>=0.58.0
29
+ Requires-Dist: h5py>=3.8.0
30
+ Requires-Dist: astropy-healpix>=1.0.0
31
+ Requires-Dist: matplotlib-label-lines>=0.7.0
32
+ Requires-Dist: click>=8.0.0
33
+ Requires-Dist: rich>=13.0.0
34
+ Requires-Dist: questionary>=2.0.0
35
+ Requires-Dist: pyyaml>=6.0.0
36
+ Requires-Dist: tomli>=2.0.0
37
+ Requires-Dist: tomli-w>=1.0.0
38
+ Requires-Dist: dearpygui>=2.0.0
39
+ Requires-Dist: pytest>=7.0.0
40
+ Requires-Dist: pytest-cov>=4.0.0
41
+ Requires-Dist: scipy>=1.11.0
42
+ Requires-Dist: black>=23.0.0
43
+ Requires-Dist: ruff>=0.1.0
44
+ Requires-Dist: mypy>=1.0.0
45
+ Requires-Dist: pre-commit>=3.0.0
46
+ Requires-Dist: build>=1.0.0
47
+ Requires-Dist: twine>=4.0.0
48
+ Provides-Extra: docs
49
+ Requires-Dist: sphinx>=7.0.0; extra == "docs"
50
+ Requires-Dist: sphinx-rtd-theme>=2.0.0; extra == "docs"
51
+ Requires-Dist: sphinx-autodoc-typehints>=1.24.0; extra == "docs"
52
+ Dynamic: license-file
53
+
54
+ # L-SURF
55
+
56
+ <p align="center">
57
+ <img src="lsurf_logo.jpg" alt="L-SURF Logo" width="400">
58
+ </p>
59
+
60
+ <p align="center">
61
+ <a href="https://pypi.org/project/lsurf/"><img src="https://badge.fury.io/py/lsurf.svg" alt="PyPI version"></a>
62
+ <a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.13+-blue.svg" alt="Python 3.13+"></a>
63
+ <a href="https://spdx.org/licenses/BSD-3-Clause-Clear.html"><img src="https://img.shields.io/badge/License-BSD--3--Clause--Clear-blue.svg" alt="License"></a>
64
+ <a href="https://l-surf-b86f2d.gitlab.io/"><img src="https://img.shields.io/badge/docs-GitLab%20Pages-orange.svg" alt="Documentation"></a>
65
+ </p>
66
+
67
+ **L**ight **SURF**ace Reflections - GPU-accelerated physically-accurate raytracing framework for simulating light-surface interactions.
68
+
69
+ **Documentation:** https://l-surf-b86f2d.gitlab.io
70
+
71
+ ## Features
72
+
73
+ - **Fresnel reflection and refraction** - Physically accurate polarization-dependent coefficients
74
+ - **Multiple scattering** - Multi-bounce ray tracing with intensity splitting
75
+ - **Ocean wave surfaces** - Gerstner wave modeling with curved Earth geometry
76
+ - **GPU acceleration** - CUDA-accelerated via Numba for high-performance simulations
77
+ - **Wavelength-dependent materials** - Sellmeier and Cauchy dispersion models
78
+ - **Polarization tracking** - s and p polarization component handling
79
+
80
+ ## Installation
81
+
82
+ ### Prerequisites
83
+
84
+ #### NVIDIA GPU Support (Recommended)
85
+
86
+ For GPU-accelerated ray tracing, you need:
87
+
88
+ 1. **NVIDIA GPU** with CUDA Compute Capability 3.5+ (most GPUs from 2012 onwards)
89
+ 2. **NVIDIA Driver** (version 450+ recommended)
90
+ 3. **CUDA Toolkit** (version 11.0+ recommended)
91
+
92
+ **Check your system:**
93
+ ```bash
94
+ # Check NVIDIA driver
95
+ nvidia-smi
96
+
97
+ # Check CUDA version (if installed)
98
+ nvcc --version
99
+ ```
100
+
101
+ **Installing NVIDIA drivers (if needed):**
102
+ ```bash
103
+ # Ubuntu/Debian
104
+ sudo apt update
105
+ sudo apt install nvidia-driver-535 # or latest version
106
+
107
+ # Fedora
108
+ sudo dnf install akmod-nvidia
109
+ ```
110
+
111
+ **Installing CUDA Toolkit:**
112
+ - Download from [NVIDIA CUDA Downloads](https://developer.nvidia.com/cuda-downloads)
113
+ - Or use your distribution's package manager
114
+
115
+ > **Note:** The package works without a GPU (CPU fallback), but simulations will be significantly slower.
116
+
117
+ #### Python Environment
118
+
119
+ - Python >= 3.13
120
+ - pip, conda, or mamba
121
+
122
+ ### Install from PyPI
123
+
124
+ ```bash
125
+ pip install lsurf
126
+ ```
127
+
128
+ ### Development Installation
129
+
130
+ ```bash
131
+ git clone https://github.com/tobi-h/lsurf.git
132
+ cd lsurf
133
+ pip install -e .
134
+ ```
135
+
136
+ ### Verifying GPU Setup
137
+
138
+ After installation, verify everything works:
139
+
140
+ ```python
141
+ from numba import cuda
142
+
143
+ # Check CUDA availability
144
+ print(f"CUDA available: {cuda.is_available()}")
145
+
146
+ if cuda.is_available():
147
+ gpu = cuda.get_current_device()
148
+ print(f"GPU: {gpu.name}")
149
+ print(f"Compute Capability: {gpu.compute_capability}")
150
+ print(f"Memory: {gpu.total_memory / 1e9:.1f} GB")
151
+ ```
152
+
153
+ ### Troubleshooting
154
+
155
+ | Issue | Solution |
156
+ |-------|----------|
157
+ | `CUDA not available` | Install NVIDIA drivers and CUDA toolkit |
158
+ | `conda: PackagesNotFoundError` | Update conda: `conda update -n base conda` |
159
+ | `numba.cuda import error` | Ensure CUDA_HOME is set and nvcc is in PATH |
160
+ | `Out of memory` | Reduce `num_rays` or use batched processing |
161
+
162
+ ## Quick Start
163
+
164
+ ### Using the CLI (Recommended)
165
+
166
+ The **command-line interface** is the recommended way to run simulations:
167
+
168
+ ```bash
169
+ # Build a configuration interactively
170
+ lsurf build -o my_simulation.yaml
171
+
172
+ # Or use a built-in template
173
+ lsurf build --template ocean -o ocean_sim.yaml
174
+
175
+ # Validate the configuration
176
+ lsurf run my_simulation.yaml --dry-run
177
+
178
+ # Run the simulation
179
+ lsurf run my_simulation.yaml --progress
180
+
181
+ # Run with custom parameters
182
+ lsurf run my_simulation.yaml --num-rays 100000 --output-dir ./results
183
+ ```
184
+
185
+ ### Using the GUI
186
+
187
+ For interactive exploration and visualization, use the **graphical interface**:
188
+
189
+ ```bash
190
+ # Launch the GUI
191
+ lsurf gui
192
+
193
+ # Or load an existing configuration
194
+ lsurf gui my_simulation.yaml
195
+ ```
196
+
197
+ The GUI provides:
198
+ - Interactive 3D visualization of geometry
199
+ - Configuration editor with live preview
200
+ - One-click simulation execution
201
+ - Built-in result visualization and analysis
202
+
203
+ ### Python API
204
+
205
+ For custom workflows and advanced use cases, use the Python API with `GeometryBuilder`:
206
+
207
+ ```python
208
+ import lsurf as sr
209
+ from lsurf.geometry import GeometryBuilder
210
+ from lsurf.simulation import Simulation, SimulationConfig
211
+ from lsurf.surfaces import SphereSurface, PlaneSurface, SurfaceRole
212
+
213
+ # Define constants
214
+ EARTH_RADIUS = 6.371e6 # meters
215
+
216
+ # Create materials
217
+ atmosphere = sr.ExponentialAtmosphere(n_sea_level=1.000293)
218
+
219
+ # Create surfaces
220
+ ocean = SphereSurface(
221
+ center=(0, 0, -EARTH_RADIUS),
222
+ radius=EARTH_RADIUS,
223
+ role=SurfaceRole.OPTICAL,
224
+ name="ocean",
225
+ )
226
+
227
+ detector = PlaneSurface(
228
+ point=(0, 0, 35000),
229
+ normal=(0, 0, 1),
230
+ role=SurfaceRole.DETECTOR,
231
+ name="detector_35km",
232
+ )
233
+
234
+ # Build geometry with named media
235
+ geometry = (
236
+ GeometryBuilder()
237
+ .register_medium("atmosphere", atmosphere)
238
+ .register_medium("ocean", sr.WATER)
239
+ .set_background("atmosphere") # Ray propagation medium
240
+ .add_surface(ocean, front="atmosphere", back="ocean")
241
+ .add_detector(detector)
242
+ .build()
243
+ )
244
+
245
+ # Configure simulation
246
+ config = SimulationConfig(
247
+ step_size=100.0, # Max step size in meters
248
+ max_bounces=5, # Maximum surface interactions
249
+ adaptive_stepping=True, # Use smaller steps near surfaces
250
+ min_step_size=3e-4, # 0.3mm for ~1ps time resolution
251
+ )
252
+
253
+ # Create simulation and run
254
+ sim = Simulation(geometry, config)
255
+
256
+ # Generate rays from a source
257
+ source = sr.CollimatedBeam(
258
+ center=(0, 0, 1000),
259
+ direction=(0.17, 0, -0.98), # ~10° grazing angle
260
+ radius=10.0,
261
+ num_rays=10000,
262
+ wavelength=532e-9,
263
+ )
264
+ rays = source.generate()
265
+
266
+ # Run simulation
267
+ result = sim.run(rays)
268
+ print(f"Detected: {result.statistics.rays_detected}")
269
+ print(f"Absorbed: {result.statistics.rays_absorbed}")
270
+ ```
271
+
272
+ ### Simple Surface Interaction
273
+
274
+ For quick tests without the full simulation framework:
275
+
276
+ ```python
277
+ import lsurf as sr
278
+
279
+ # Create a water surface
280
+ surface = sr.PlaneSurface(
281
+ point=(0, 0, 0),
282
+ normal=(0, 0, 1),
283
+ material_front=sr.AIR_STP,
284
+ material_back=sr.WATER,
285
+ role=sr.SurfaceRole.OPTICAL,
286
+ name="water_surface",
287
+ )
288
+
289
+ # Create a collimated beam
290
+ source = sr.CollimatedBeam(
291
+ center=(0, 0, 0.1),
292
+ direction=(0.707, 0, -0.707), # 45° incidence
293
+ radius=0.01,
294
+ num_rays=1000,
295
+ wavelength=532e-9,
296
+ )
297
+ rays = source.generate()
298
+
299
+ # Process reflection/refraction
300
+ reflected, refracted = sr.process_surface_interaction(
301
+ rays, surface,
302
+ wavelength=532e-9,
303
+ generate_reflected=True,
304
+ generate_refracted=True,
305
+ )
306
+
307
+ print(f"Reflected rays: {reflected.num_rays}")
308
+ print(f"Refracted rays: {refracted.num_rays}")
309
+ ```
310
+
311
+ ## Example Scripts
312
+
313
+ The `scripts/` directory contains **educational example scripts** that demonstrate specific features and techniques. These are provided as learning resources and references for custom workflows.
314
+
315
+ > **Note:** For standard simulations, use the CLI (`lsurf run`) or GUI (`lsurf gui`) instead of writing custom scripts. The CLI/GUI handle configuration management, validation, and output automatically.
316
+
317
+ | Script | Description |
318
+ | -------------------------------------- | ---------------------------------------------- |
319
+ | `01_basic.py` | Basic raytracing setup |
320
+ | `02_sources.py` | Different ray source types |
321
+ | `03_visualization.py` | Visualization capabilities |
322
+ | `04_glass_reflection.py` | Fresnel reflection at glass interface |
323
+ | `05_water_brewster.py` | Brewster angle validation |
324
+ | `06_detector_scan.py` | Detector position scanning (planar) |
325
+ | `07_detector_scan_waves.py` | Detector scanning with wave surface |
326
+ | `08_detector_scan_waves_largescale.py` | Large-scale ocean simulation |
327
+ | `09_full_3d_curved_ocean.py` | Full 3D ray tracing with curved ocean surface |
328
+ | `10_time_spread_estimate.py` | Geometric time spread estimation |
329
+
330
+ Run an example:
331
+
332
+ ```bash
333
+ cd scripts
334
+ python 01_basic.py
335
+ ```
336
+
337
+ ## Dependencies
338
+
339
+ | Category | Packages |
340
+ |----------|----------|
341
+ | **Core** | numpy >= 1.24, matplotlib >= 3.7, pydantic >= 2.0 |
342
+ | **GPU** | numba >= 0.58, CUDA toolkit >= 11.0 |
343
+ | **Optional** | h5py >= 3.8 (HDF5 support), astropy-healpix (spherical analysis) |
344
+ | **Dev** | pytest, black, ruff, mypy, pre-commit |
345
+
346
+ All dependencies are automatically installed via `environment.yml` or `pip install -e ".[dev]"`.
347
+
348
+ ## Project Structure
349
+
350
+ ```
351
+ lsurf/
352
+ ├── src/
353
+ │ └── lsurf/ # Main package
354
+ │ ├── geometry/ # GeometryBuilder and Geometry
355
+ │ ├── simulation/ # Simulation, SimulationConfig, results
356
+ │ ├── propagation/ # Ray propagation engines and GPU kernels
357
+ │ ├── materials/ # Material definitions (homogeneous, atmosphere)
358
+ │ ├── sources/ # Ray source generators
359
+ │ ├── surfaces/ # Surface geometries (cpu/ and gpu/)
360
+ │ ├── detectors/ # Detection and analysis
361
+ │ ├── utilities/ # Ray data, fresnel, recording
362
+ │ ├── visualization/ # Plotting functions
363
+ │ └── interactions.py # Surface interaction processing
364
+ ├── scripts/ # Example scripts
365
+ ├── tests/ # Test suite
366
+ ├── docs/ # Sphinx documentation
367
+ ├── pyproject.toml # Python packaging config
368
+ └── environment.yml # Development environment
369
+ ```
370
+
371
+ ## Testing
372
+
373
+ ```bash
374
+ pytest tests/ -v
375
+ ```
376
+
377
+ ## License
378
+
379
+ Clear BSD License - see [LICENSE](LICENSE) for details.
380
+
381
+ Copyright (c) 2026 Tobias Heibges. All rights reserved.