lsurf 1.0.0__py3-none-any.whl

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 (180) hide show
  1. lsurf/__init__.py +471 -0
  2. lsurf/analysis/__init__.py +107 -0
  3. lsurf/analysis/healpix_utils.py +418 -0
  4. lsurf/analysis/sphere_viz.py +1280 -0
  5. lsurf/cli/__init__.py +48 -0
  6. lsurf/cli/build.py +398 -0
  7. lsurf/cli/config_schema.py +318 -0
  8. lsurf/cli/gui_cmd.py +76 -0
  9. lsurf/cli/interactive.py +850 -0
  10. lsurf/cli/main.py +81 -0
  11. lsurf/cli/run.py +806 -0
  12. lsurf/detectors/__init__.py +266 -0
  13. lsurf/detectors/analysis.py +289 -0
  14. lsurf/detectors/base.py +284 -0
  15. lsurf/detectors/constant_size_rings.py +485 -0
  16. lsurf/detectors/directional.py +45 -0
  17. lsurf/detectors/extended/__init__.py +73 -0
  18. lsurf/detectors/extended/local_sphere.py +353 -0
  19. lsurf/detectors/extended/recording_sphere.py +368 -0
  20. lsurf/detectors/planar.py +45 -0
  21. lsurf/detectors/protocol.py +187 -0
  22. lsurf/detectors/recording_spheres.py +63 -0
  23. lsurf/detectors/results.py +1140 -0
  24. lsurf/detectors/small/__init__.py +79 -0
  25. lsurf/detectors/small/directional.py +330 -0
  26. lsurf/detectors/small/planar.py +401 -0
  27. lsurf/detectors/small/spherical.py +450 -0
  28. lsurf/detectors/spherical.py +45 -0
  29. lsurf/geometry/__init__.py +199 -0
  30. lsurf/geometry/builder.py +478 -0
  31. lsurf/geometry/cell.py +228 -0
  32. lsurf/geometry/cell_geometry.py +247 -0
  33. lsurf/geometry/detector_arrays.py +1785 -0
  34. lsurf/geometry/geometry.py +222 -0
  35. lsurf/geometry/surface_analysis.py +375 -0
  36. lsurf/geometry/validation.py +91 -0
  37. lsurf/gui/__init__.py +51 -0
  38. lsurf/gui/app.py +903 -0
  39. lsurf/gui/core/__init__.py +39 -0
  40. lsurf/gui/core/scene.py +343 -0
  41. lsurf/gui/core/simulation.py +264 -0
  42. lsurf/gui/renderers/__init__.py +40 -0
  43. lsurf/gui/renderers/ray_renderer.py +353 -0
  44. lsurf/gui/renderers/source_renderer.py +505 -0
  45. lsurf/gui/renderers/surface_renderer.py +477 -0
  46. lsurf/gui/views/__init__.py +48 -0
  47. lsurf/gui/views/config_editor.py +3199 -0
  48. lsurf/gui/views/properties.py +257 -0
  49. lsurf/gui/views/results.py +291 -0
  50. lsurf/gui/views/scene_tree.py +180 -0
  51. lsurf/gui/views/viewport_3d.py +555 -0
  52. lsurf/gui/views/visualizations.py +712 -0
  53. lsurf/materials/__init__.py +169 -0
  54. lsurf/materials/base/__init__.py +64 -0
  55. lsurf/materials/base/full_inhomogeneous.py +208 -0
  56. lsurf/materials/base/grid_inhomogeneous.py +319 -0
  57. lsurf/materials/base/homogeneous.py +342 -0
  58. lsurf/materials/base/material_field.py +527 -0
  59. lsurf/materials/base/simple_inhomogeneous.py +418 -0
  60. lsurf/materials/base/spectral_inhomogeneous.py +497 -0
  61. lsurf/materials/implementations/__init__.py +120 -0
  62. lsurf/materials/implementations/data/alpha_values_typical_atmosphere_updated.txt +24 -0
  63. lsurf/materials/implementations/duct_atmosphere.py +390 -0
  64. lsurf/materials/implementations/exponential_atmosphere.py +435 -0
  65. lsurf/materials/implementations/gaussian_lens.py +120 -0
  66. lsurf/materials/implementations/interpolated_data.py +123 -0
  67. lsurf/materials/implementations/layered_atmosphere.py +134 -0
  68. lsurf/materials/implementations/linear_gradient.py +109 -0
  69. lsurf/materials/implementations/linsley_atmosphere.py +764 -0
  70. lsurf/materials/implementations/standard_materials.py +126 -0
  71. lsurf/materials/implementations/turbulent_atmosphere.py +135 -0
  72. lsurf/materials/implementations/us_standard_atmosphere.py +149 -0
  73. lsurf/materials/utils/__init__.py +77 -0
  74. lsurf/materials/utils/constants.py +45 -0
  75. lsurf/materials/utils/device_functions.py +117 -0
  76. lsurf/materials/utils/dispersion.py +160 -0
  77. lsurf/materials/utils/factories.py +142 -0
  78. lsurf/propagation/__init__.py +91 -0
  79. lsurf/propagation/detector_gpu.py +67 -0
  80. lsurf/propagation/gpu_device_rays.py +294 -0
  81. lsurf/propagation/kernels/__init__.py +175 -0
  82. lsurf/propagation/kernels/absorption/__init__.py +61 -0
  83. lsurf/propagation/kernels/absorption/grid.py +240 -0
  84. lsurf/propagation/kernels/absorption/simple.py +232 -0
  85. lsurf/propagation/kernels/absorption/spectral.py +410 -0
  86. lsurf/propagation/kernels/detection/__init__.py +64 -0
  87. lsurf/propagation/kernels/detection/protocol.py +102 -0
  88. lsurf/propagation/kernels/detection/spherical.py +255 -0
  89. lsurf/propagation/kernels/device_functions.py +790 -0
  90. lsurf/propagation/kernels/fresnel/__init__.py +64 -0
  91. lsurf/propagation/kernels/fresnel/protocol.py +97 -0
  92. lsurf/propagation/kernels/fresnel/standard.py +258 -0
  93. lsurf/propagation/kernels/intersection/__init__.py +79 -0
  94. lsurf/propagation/kernels/intersection/annular_plane.py +207 -0
  95. lsurf/propagation/kernels/intersection/bounded_plane.py +205 -0
  96. lsurf/propagation/kernels/intersection/plane.py +166 -0
  97. lsurf/propagation/kernels/intersection/protocol.py +95 -0
  98. lsurf/propagation/kernels/intersection/signed_distance.py +742 -0
  99. lsurf/propagation/kernels/intersection/sphere.py +190 -0
  100. lsurf/propagation/kernels/propagation/__init__.py +85 -0
  101. lsurf/propagation/kernels/propagation/grid.py +527 -0
  102. lsurf/propagation/kernels/propagation/protocol.py +105 -0
  103. lsurf/propagation/kernels/propagation/simple.py +460 -0
  104. lsurf/propagation/kernels/propagation/spectral.py +875 -0
  105. lsurf/propagation/kernels/registry.py +331 -0
  106. lsurf/propagation/kernels/surface/__init__.py +72 -0
  107. lsurf/propagation/kernels/surface/bisection.py +232 -0
  108. lsurf/propagation/kernels/surface/detection.py +402 -0
  109. lsurf/propagation/kernels/surface/reduction.py +166 -0
  110. lsurf/propagation/propagator_protocol.py +222 -0
  111. lsurf/propagation/propagators/__init__.py +101 -0
  112. lsurf/propagation/propagators/detector_handler.py +354 -0
  113. lsurf/propagation/propagators/factory.py +200 -0
  114. lsurf/propagation/propagators/fresnel_handler.py +305 -0
  115. lsurf/propagation/propagators/gpu_gradient.py +566 -0
  116. lsurf/propagation/propagators/gpu_surface_propagator.py +707 -0
  117. lsurf/propagation/propagators/gradient.py +429 -0
  118. lsurf/propagation/propagators/intersection_handler.py +327 -0
  119. lsurf/propagation/propagators/material_propagator.py +398 -0
  120. lsurf/propagation/propagators/signed_distance_handler.py +522 -0
  121. lsurf/propagation/propagators/spectral_gpu_gradient.py +553 -0
  122. lsurf/propagation/propagators/surface_interaction.py +616 -0
  123. lsurf/propagation/propagators/surface_propagator.py +719 -0
  124. lsurf/py.typed +1 -0
  125. lsurf/simulation/__init__.py +70 -0
  126. lsurf/simulation/config.py +164 -0
  127. lsurf/simulation/orchestrator.py +462 -0
  128. lsurf/simulation/result.py +299 -0
  129. lsurf/simulation/simulation.py +262 -0
  130. lsurf/sources/__init__.py +128 -0
  131. lsurf/sources/base.py +264 -0
  132. lsurf/sources/collimated.py +252 -0
  133. lsurf/sources/custom.py +409 -0
  134. lsurf/sources/diverging.py +228 -0
  135. lsurf/sources/gaussian.py +272 -0
  136. lsurf/sources/parallel_from_positions.py +197 -0
  137. lsurf/sources/point.py +172 -0
  138. lsurf/sources/uniform_diverging.py +258 -0
  139. lsurf/surfaces/__init__.py +184 -0
  140. lsurf/surfaces/cpu/__init__.py +50 -0
  141. lsurf/surfaces/cpu/curved_wave.py +463 -0
  142. lsurf/surfaces/cpu/gerstner_wave.py +381 -0
  143. lsurf/surfaces/cpu/wave_params.py +118 -0
  144. lsurf/surfaces/gpu/__init__.py +72 -0
  145. lsurf/surfaces/gpu/annular_plane.py +453 -0
  146. lsurf/surfaces/gpu/bounded_plane.py +390 -0
  147. lsurf/surfaces/gpu/curved_wave.py +483 -0
  148. lsurf/surfaces/gpu/gerstner_wave.py +377 -0
  149. lsurf/surfaces/gpu/multi_curved_wave.py +520 -0
  150. lsurf/surfaces/gpu/plane.py +299 -0
  151. lsurf/surfaces/gpu/recording_sphere.py +587 -0
  152. lsurf/surfaces/gpu/sphere.py +311 -0
  153. lsurf/surfaces/protocol.py +336 -0
  154. lsurf/surfaces/registry.py +373 -0
  155. lsurf/utilities/__init__.py +175 -0
  156. lsurf/utilities/detector_analysis.py +814 -0
  157. lsurf/utilities/fresnel.py +628 -0
  158. lsurf/utilities/interactions.py +1215 -0
  159. lsurf/utilities/propagation.py +602 -0
  160. lsurf/utilities/ray_data.py +532 -0
  161. lsurf/utilities/recording_sphere.py +745 -0
  162. lsurf/utilities/time_spread.py +463 -0
  163. lsurf/visualization/__init__.py +329 -0
  164. lsurf/visualization/absorption_plots.py +334 -0
  165. lsurf/visualization/atmospheric_plots.py +754 -0
  166. lsurf/visualization/common.py +348 -0
  167. lsurf/visualization/detector_plots.py +1350 -0
  168. lsurf/visualization/detector_sphere_plots.py +1173 -0
  169. lsurf/visualization/fresnel_plots.py +1061 -0
  170. lsurf/visualization/ocean_simulation_plots.py +999 -0
  171. lsurf/visualization/polarization_plots.py +916 -0
  172. lsurf/visualization/raytracing_plots.py +1521 -0
  173. lsurf/visualization/ring_detector_plots.py +1867 -0
  174. lsurf/visualization/time_spread_plots.py +531 -0
  175. lsurf-1.0.0.dist-info/METADATA +381 -0
  176. lsurf-1.0.0.dist-info/RECORD +180 -0
  177. lsurf-1.0.0.dist-info/WHEEL +5 -0
  178. lsurf-1.0.0.dist-info/entry_points.txt +2 -0
  179. lsurf-1.0.0.dist-info/licenses/LICENSE +32 -0
  180. lsurf-1.0.0.dist-info/top_level.txt +1 -0
lsurf/__init__.py ADDED
@@ -0,0 +1,471 @@
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.
33
+
34
+ """
35
+ L-SURF: Light Surface Reflections
36
+
37
+ A GPU-accelerated physically-accurate raytracing framework for simulating
38
+ light-surface interactions with spatially-varying material properties.
39
+
40
+ Note: Numba performance warnings about GPU under-utilization are suppressed
41
+ by default. These warnings occur with small ray counts during testing but
42
+ are not relevant for production simulations with larger ray counts.
43
+
44
+ This module supports:
45
+ - Inhomogeneous media with gradient refractive indices
46
+ - Multiple scattering and subsurface propagation
47
+ - Fresnel reflection and refraction
48
+ - Wavelength-dependent material properties
49
+ - Polarization tracking (optional)
50
+
51
+ Main Components
52
+ ---------------
53
+ - materials: Material property definitions (refractive index, absorption, etc.)
54
+ - surfaces: Surface geometry and intersection (planar, spherical, waves)
55
+ - sources: Ray generation (point, collimated, diverging, gaussian)
56
+ - detectors: Detection and analysis (spherical, planar, directional)
57
+ - ray_data: Ray batch data structures for GPU processing
58
+ - propagation: Ray propagation engine (straight-line and curved paths)
59
+ - gpu: GPU-accelerated kernels and algorithms
60
+
61
+ Example Usage
62
+ -------------
63
+ >>> from surface_roughness import materials, ray_data, propagation
64
+ >>>
65
+ >>> # Create material
66
+ >>> material = materials.AIR_STP
67
+ >>>
68
+ >>> # Create ray batch
69
+ >>> rays = ray_data.create_ray_batch(num_rays=10000)
70
+ >>>
71
+ >>> # Initialize rays (would come from source module)
72
+ >>> rays.positions[:] = ...
73
+ >>> rays.directions[:] = ...
74
+ >>> rays.active[:] = True
75
+ >>>
76
+ >>> # Propagate
77
+ >>> propagator = propagation.StraightLinePropagator()
78
+ >>> propagator.propagate_step(rays, step_size=1e-3, material=material)
79
+
80
+ Refactored Modules (New Structure)
81
+ ----------------------------------
82
+ The codebase has been refactored into single-responsibility modules:
83
+
84
+ >>> # Modular surfaces
85
+ >>> from lsurf.surfaces import CurvedWaveSurface, PlaneSurface
86
+ >>>
87
+ >>> # Modular sources
88
+ >>> from surface_roughness.sources import CollimatedBeam, PointSource
89
+ >>>
90
+ >>> # Modular detectors
91
+ >>> from surface_roughness.detectors import SphericalDetector
92
+ >>>
93
+ >>> # Modular materials
94
+ >>> from surface_roughness.materials import WATER, create_sellmeier_material
95
+
96
+ References
97
+ ----------
98
+ .. [1] Born, M., & Wolf, E. (1999). Principles of Optics (7th ed.).
99
+ Cambridge University Press.
100
+ .. [2] Ishimaru, A. (1978). Wave Propagation and Scattering in Random Media.
101
+ Academic Press.
102
+ """
103
+
104
+ # =============================================================================
105
+ # Suppress Numba Performance Warnings
106
+ # =============================================================================
107
+ # These warnings about GPU under-utilization are expected for small test cases
108
+ # and are not relevant for production simulations with larger ray counts.
109
+ import warnings
110
+
111
+ try:
112
+ from numba.core.errors import NumbaPerformanceWarning
113
+
114
+ warnings.filterwarnings("ignore", category=NumbaPerformanceWarning)
115
+ except ImportError:
116
+ # Numba not installed, no warnings to suppress
117
+ pass
118
+
119
+ # =============================================================================
120
+ # Module Imports (Refactored Structure)
121
+ # =============================================================================
122
+ # Refactored modules (new single-responsibility structure)
123
+ from . import detectors, materials, sources, surfaces, utilities
124
+
125
+ # Backward compatibility aliases for moved modules
126
+ ray_data = utilities.ray_data
127
+ propagation = utilities.propagation
128
+ fresnel = utilities.fresnel
129
+ recording_sphere = utilities.recording_sphere
130
+
131
+ # Supporting modules
132
+ from . import visualization
133
+
134
+ # Backward compatibility alias for moved interactions module
135
+ interactions = utilities.interactions
136
+
137
+ # Key visualization functions
138
+ from .visualization import (
139
+ create_beam_profile_figure,
140
+ create_detector_scan_figure,
141
+ create_ray_overview_figure,
142
+ create_wavelength_figure,
143
+ # Detector visualization
144
+ plot_beam_slice,
145
+ plot_bounce_points,
146
+ plot_detection_counts,
147
+ plot_detection_efficiency,
148
+ plot_mean_arrival_time,
149
+ plot_ray_endpoints_histogram,
150
+ plot_ray_endpoints_scatter,
151
+ # Ray tracing visualization
152
+ plot_ray_paths_projection,
153
+ plot_surface_profile,
154
+ plot_wavelength_histogram,
155
+ )
156
+
157
+ # Version info
158
+ __version__ = "0.2.0" # Refactored modular architecture
159
+ __author__ = "L-SURF Development Team"
160
+
161
+ # =============================================================================
162
+ # Expose key classes from refactored modules
163
+ # =============================================================================
164
+
165
+ # Materials module
166
+ # Analysis module
167
+ from . import analysis
168
+
169
+ # Detectors module
170
+ from .detectors import (
171
+ DetectionEvent,
172
+ Detector,
173
+ DirectionalDetector,
174
+ LocalRecordingSphere,
175
+ LocalRecordingSphereDetector,
176
+ PlanarDetector,
177
+ RecordingSphere,
178
+ # Recording sphere detectors
179
+ RecordingSphereBase,
180
+ RecordingSphereDetector,
181
+ SphericalDetector,
182
+ compute_angular_distribution,
183
+ compute_intensity_distribution,
184
+ compute_time_distribution,
185
+ compute_wavelength_distribution,
186
+ )
187
+ from .detectors import (
188
+ compute_statistics as compute_detector_statistics,
189
+ )
190
+
191
+ # Interactions
192
+ from .utilities.interactions import (
193
+ process_surface_interaction,
194
+ reflect_rays,
195
+ refract_rays,
196
+ trace_rays_multi_bounce,
197
+ trace_rays_with_splitting,
198
+ )
199
+ from .materials import (
200
+ AIR_STP,
201
+ BK7_GLASS,
202
+ VACUUM,
203
+ WATER,
204
+ HomogeneousMaterial,
205
+ MaterialField,
206
+ cauchy_refractive_index,
207
+ create_cauchy_material,
208
+ create_sellmeier_material,
209
+ sellmeier_refractive_index,
210
+ # Atmosphere materials
211
+ ExponentialAtmosphere,
212
+ STANDARD_ATMOSPHERE,
213
+ create_exponential_atmosphere,
214
+ )
215
+
216
+ # Sources module
217
+ from .sources import (
218
+ CollimatedBeam,
219
+ DivergingBeam,
220
+ GaussianBeam,
221
+ ParallelBeamFromPositions,
222
+ PointSource,
223
+ RaySource,
224
+ )
225
+
226
+ # Surfaces module
227
+ from .surfaces import (
228
+ EARTH_RADIUS,
229
+ CurvedWaveSurface,
230
+ GerstnerWaveParams,
231
+ GerstnerWaveSurface,
232
+ PlaneSurface,
233
+ SphereSurface,
234
+ RecordingSphereSurface,
235
+ LocalRecordingSphereSurface,
236
+ Surface,
237
+ SurfaceRole,
238
+ # Surface type registry
239
+ SurfaceTypeInfo,
240
+ register_surface_type,
241
+ get_surface_type,
242
+ get_surface_type_id,
243
+ is_gpu_capable,
244
+ list_surface_types,
245
+ # Backwards compatibility
246
+ GeometryInfo,
247
+ register_geometry,
248
+ get_geometry_id,
249
+ )
250
+
251
+ # Backwards compatibility alias
252
+ PlanarSurface = PlaneSurface
253
+
254
+ # Propagation
255
+ from .utilities.propagation import (
256
+ PropagationConfig,
257
+ PropagationMode,
258
+ StraightLinePropagator,
259
+ )
260
+ from .propagation import (
261
+ GPUGradientPropagator,
262
+ GPUInhomogeneousPropagator,
263
+ GPUMaterialID,
264
+ GradientPropagator,
265
+ create_propagator,
266
+ )
267
+
268
+ # Ray data structures
269
+ from .utilities.ray_data import (
270
+ RayBatch,
271
+ RayStatistics,
272
+ compute_statistics,
273
+ create_ray_batch,
274
+ merge_ray_batches,
275
+ )
276
+
277
+ # Recording data and I/O from utilities
278
+ from .utilities.recording_sphere import (
279
+ RecordedRays,
280
+ load_recorded_rays_hdf5,
281
+ load_recorded_rays_numpy,
282
+ save_recorded_rays_hdf5,
283
+ save_recorded_rays_numpy,
284
+ )
285
+
286
+ __all__: list[str] = [
287
+ # ==========================================================================
288
+ # Refactored Modules
289
+ # ==========================================================================
290
+ "materials",
291
+ "ray_data",
292
+ "propagation",
293
+ "sources",
294
+ "surfaces",
295
+ "fresnel",
296
+ "interactions",
297
+ "visualization",
298
+ "detectors",
299
+ "recording_sphere",
300
+ "analysis",
301
+ # Material classes
302
+ "MaterialField",
303
+ "HomogeneousMaterial",
304
+ "VACUUM",
305
+ "AIR_STP",
306
+ "WATER",
307
+ "BK7_GLASS",
308
+ "sellmeier_refractive_index",
309
+ "cauchy_refractive_index",
310
+ "create_sellmeier_material",
311
+ "create_cauchy_material",
312
+ # Ray data structures
313
+ "RayBatch",
314
+ "RayStatistics",
315
+ "create_ray_batch",
316
+ "compute_statistics",
317
+ "merge_ray_batches",
318
+ # Propagation
319
+ "PropagationMode",
320
+ "PropagationConfig",
321
+ "StraightLinePropagator",
322
+ "GradientPropagator",
323
+ "GPUGradientPropagator",
324
+ "GPUInhomogeneousPropagator",
325
+ "GPUMaterialID",
326
+ "create_propagator",
327
+ # Sources
328
+ "RaySource",
329
+ "PointSource",
330
+ "CollimatedBeam",
331
+ "DivergingBeam",
332
+ "GaussianBeam",
333
+ "ParallelBeamFromPositions",
334
+ # Surfaces
335
+ "Surface",
336
+ "SurfaceRole",
337
+ "SurfaceTypeInfo",
338
+ "register_surface_type",
339
+ "get_surface_type",
340
+ "get_surface_type_id",
341
+ "is_gpu_capable",
342
+ "list_surface_types",
343
+ # Backwards compatibility
344
+ "GeometryInfo",
345
+ "register_geometry",
346
+ "get_geometry_id",
347
+ "PlaneSurface",
348
+ "PlanarSurface", # Backwards compatibility alias
349
+ "SphereSurface",
350
+ "RecordingSphereSurface",
351
+ "LocalRecordingSphereSurface",
352
+ "GerstnerWaveSurface",
353
+ "GerstnerWaveParams",
354
+ "CurvedWaveSurface",
355
+ "EARTH_RADIUS",
356
+ # Interactions
357
+ "process_surface_interaction",
358
+ "reflect_rays",
359
+ "refract_rays",
360
+ "trace_rays_multi_bounce",
361
+ "trace_rays_with_splitting",
362
+ # Detectors
363
+ "Detector",
364
+ "SphericalDetector",
365
+ "PlanarDetector",
366
+ "DirectionalDetector",
367
+ "DetectionEvent",
368
+ "compute_angular_distribution",
369
+ "compute_time_distribution",
370
+ "compute_intensity_distribution",
371
+ "compute_wavelength_distribution",
372
+ "compute_detector_statistics",
373
+ # Recording sphere detectors
374
+ "RecordingSphereBase",
375
+ "RecordingSphereDetector",
376
+ "LocalRecordingSphereDetector",
377
+ "RecordingSphere",
378
+ "LocalRecordingSphere",
379
+ "RecordedRays",
380
+ "save_recorded_rays_hdf5",
381
+ "load_recorded_rays_hdf5",
382
+ "save_recorded_rays_numpy",
383
+ "load_recorded_rays_numpy",
384
+ # Visualization
385
+ "plot_ray_paths_projection",
386
+ "plot_ray_endpoints_scatter",
387
+ "plot_ray_endpoints_histogram",
388
+ "plot_surface_profile",
389
+ "plot_bounce_points",
390
+ "create_ray_overview_figure",
391
+ "plot_beam_slice",
392
+ "plot_wavelength_histogram",
393
+ "plot_detection_counts",
394
+ "plot_detection_efficiency",
395
+ "plot_mean_arrival_time",
396
+ "create_wavelength_figure",
397
+ "create_beam_profile_figure",
398
+ "create_detector_scan_figure",
399
+ # Logging
400
+ "configure_logging",
401
+ ]
402
+
403
+
404
+ # =============================================================================
405
+ # Logging Configuration
406
+ # =============================================================================
407
+
408
+
409
+ def configure_logging(
410
+ level: str = "INFO",
411
+ format: str = "%(levelname)s - %(message)s",
412
+ suppress_numba: bool = True,
413
+ ) -> None:
414
+ """
415
+ Configure logging for lsurf simulations.
416
+
417
+ Parameters
418
+ ----------
419
+ level : str
420
+ Logging level: "DEBUG", "INFO", "WARNING", "ERROR".
421
+ DEBUG shows per-bounce details, INFO shows simulation summaries.
422
+ format : str
423
+ Log message format string.
424
+ suppress_numba : bool
425
+ If True, suppress verbose numba/CUDA logging and performance warnings
426
+ (default True). Set to False to see GPU under-utilization warnings
427
+ which can help optimize ray counts.
428
+
429
+ Examples
430
+ --------
431
+ >>> import lsurf as sr
432
+ >>> sr.configure_logging("INFO") # Show simulation progress
433
+ >>> sr.configure_logging("DEBUG") # Show detailed per-bounce info
434
+ >>> sr.configure_logging("INFO", suppress_numba=False) # Show GPU warnings
435
+ """
436
+ import logging
437
+ import warnings
438
+
439
+ # Configure lsurf logger
440
+ lsurf_logger = logging.getLogger("lsurf")
441
+ lsurf_logger.setLevel(getattr(logging, level.upper()))
442
+
443
+ # Add handler if none exists
444
+ if not lsurf_logger.handlers:
445
+ handler = logging.StreamHandler()
446
+ handler.setFormatter(logging.Formatter(format))
447
+ lsurf_logger.addHandler(handler)
448
+ else:
449
+ # Update existing handler format
450
+ for handler in lsurf_logger.handlers:
451
+ handler.setFormatter(logging.Formatter(format))
452
+
453
+ # Handle numba loggers and warnings
454
+ if suppress_numba:
455
+ for name in ["numba", "numba.cuda"]:
456
+ logging.getLogger(name).setLevel(logging.WARNING)
457
+ # Suppress numba performance warnings (already done at import, but ensure)
458
+ try:
459
+ from numba.core.errors import NumbaPerformanceWarning
460
+
461
+ warnings.filterwarnings("ignore", category=NumbaPerformanceWarning)
462
+ except ImportError:
463
+ pass
464
+ else:
465
+ # Re-enable numba performance warnings if user wants them
466
+ try:
467
+ from numba.core.errors import NumbaPerformanceWarning
468
+
469
+ warnings.filterwarnings("default", category=NumbaPerformanceWarning)
470
+ except ImportError:
471
+ pass
@@ -0,0 +1,107 @@
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.
33
+
34
+ """
35
+ Analysis Module - Sphere Pattern Analysis and Visualization
36
+
37
+ This module provides tools for analyzing ray patterns on spherical detection surfaces,
38
+ including HEALPix mapping, intensity distribution analysis, and arrival time statistics.
39
+
40
+ Available Functions
41
+ -------------------
42
+ rays_to_healpix
43
+ Convert recorded rays to HEALPix pixel representation
44
+ aggregate_healpix_data
45
+ Aggregate ray properties per HEALPix pixel
46
+ identify_peak_region
47
+ Find pixels with highest intensity
48
+ compute_time_statistics
49
+ Compute arrival time statistics in peak region
50
+
51
+ plot_mollweide_intensity
52
+ Visualize intensity distribution on Mollweide projection
53
+ plot_mollweide_time
54
+ Visualize arrival time distribution on Mollweide projection
55
+ plot_time_distributions
56
+ Plot arrival time histograms and statistics
57
+ plot_combined_analysis
58
+ Create comprehensive multi-panel figure
59
+
60
+ Examples
61
+ --------
62
+ >>> from lsurf import load_recorded_rays_hdf5
63
+ >>> from lsurf.analysis import rays_to_healpix, plot_mollweide_intensity
64
+ >>>
65
+ >>> # Load simulation data
66
+ >>> rays, metadata = load_recorded_rays_hdf5('simulation.h5')
67
+ >>>
68
+ >>> # Convert to HEALPix
69
+ >>> healpix_data = rays_to_healpix(rays, nside=128)
70
+ >>>
71
+ >>> # Visualize
72
+ >>> plot_mollweide_intensity(healpix_data, output='intensity_map.png')
73
+ """
74
+
75
+ from .healpix_utils import (
76
+ aggregate_healpix_data,
77
+ compute_time_statistics,
78
+ identify_peak_region,
79
+ rays_to_healpix,
80
+ )
81
+ from .sphere_viz import (
82
+ plot_2d_combined,
83
+ plot_2d_intensity,
84
+ plot_2d_time,
85
+ plot_combined_analysis,
86
+ plot_mollweide_intensity,
87
+ plot_mollweide_time,
88
+ plot_ray_direction_intensity,
89
+ plot_time_distributions,
90
+ plot_viewing_angle_intensity,
91
+ )
92
+
93
+ __all__ = [
94
+ "rays_to_healpix",
95
+ "aggregate_healpix_data",
96
+ "identify_peak_region",
97
+ "compute_time_statistics",
98
+ "plot_mollweide_intensity",
99
+ "plot_mollweide_time",
100
+ "plot_time_distributions",
101
+ "plot_combined_analysis",
102
+ "plot_2d_intensity",
103
+ "plot_2d_time",
104
+ "plot_2d_combined",
105
+ "plot_viewing_angle_intensity",
106
+ "plot_ray_direction_intensity",
107
+ ]