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
@@ -0,0 +1,190 @@
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
+ GPU-Accelerated Sphere Intersection
36
+
37
+ Analytical ray-sphere intersection using quadratic formula.
38
+
39
+ This module contains ONLY pure CUDA kernels - no GPU memory management.
40
+ The propagator layer is responsible for cuda.to_device() and copy_to_host().
41
+ """
42
+
43
+ import math
44
+
45
+ from ..registry import IntersectionKernelID, register_kernel
46
+
47
+ # GPU support is optional
48
+ try:
49
+ from numba import cuda
50
+
51
+ HAS_CUDA = True
52
+ except ImportError:
53
+
54
+ class _FakeCuda:
55
+ """Fake cuda module for when numba is not installed."""
56
+
57
+ @staticmethod
58
+ def jit(*args, **kwargs):
59
+ """Return a no-op decorator."""
60
+
61
+ def decorator(func):
62
+ return func
63
+
64
+ if args and callable(args[0]):
65
+ return args[0]
66
+ return decorator
67
+
68
+ @staticmethod
69
+ def is_available():
70
+ return False
71
+
72
+ @staticmethod
73
+ def grid(n):
74
+ return 0
75
+
76
+ @staticmethod
77
+ def synchronize():
78
+ pass
79
+
80
+ cuda = _FakeCuda() # type: ignore[assignment]
81
+ HAS_CUDA = False
82
+
83
+
84
+ # =============================================================================
85
+ # CUDA Kernels
86
+ # =============================================================================
87
+
88
+
89
+ @register_kernel(IntersectionKernelID.SPHERE_ANALYTICAL)
90
+ @cuda.jit
91
+ def kernel_sphere_intersect(
92
+ origins, # (N, 3) ray origins
93
+ directions, # (N, 3) ray directions
94
+ distances_out, # (N,) output distances
95
+ hit_mask_out, # (N,) output hit mask
96
+ normals_out, # (N, 3) output normals at intersection
97
+ center_x, # Sphere center X
98
+ center_y, # Sphere center Y
99
+ center_z, # Sphere center Z
100
+ radius, # Sphere radius
101
+ ):
102
+ """
103
+ CUDA kernel for ray-sphere intersection.
104
+
105
+ Uses analytical solution via quadratic formula:
106
+ |o + t*d - c|² = r²
107
+ Expands to: t²(d·d) + 2t(d·(o-c)) + (o-c)·(o-c) - r² = 0
108
+
109
+ Returns the nearest positive intersection distance.
110
+ """
111
+ idx = cuda.grid(1)
112
+ if idx >= origins.shape[0]:
113
+ return
114
+
115
+ # Load ray data
116
+ ox = origins[idx, 0]
117
+ oy = origins[idx, 1]
118
+ oz = origins[idx, 2]
119
+ dx = directions[idx, 0]
120
+ dy = directions[idx, 1]
121
+ dz = directions[idx, 2]
122
+
123
+ # Normalize direction
124
+ d_len = math.sqrt(dx * dx + dy * dy + dz * dz)
125
+ if d_len < 1e-10:
126
+ hit_mask_out[idx] = False
127
+ distances_out[idx] = math.inf
128
+ return
129
+ dx /= d_len
130
+ dy /= d_len
131
+ dz /= d_len
132
+
133
+ # Vector from origin to sphere center
134
+ ocx = ox - center_x
135
+ ocy = oy - center_y
136
+ ocz = oz - center_z
137
+
138
+ # Quadratic coefficients
139
+ # a = d·d = 1 (normalized direction)
140
+ b = 2.0 * (dx * ocx + dy * ocy + dz * ocz)
141
+ c = ocx * ocx + ocy * ocy + ocz * ocz - radius * radius
142
+
143
+ # Discriminant
144
+ discriminant = b * b - 4.0 * c
145
+
146
+ if discriminant < 0:
147
+ hit_mask_out[idx] = False
148
+ distances_out[idx] = math.inf
149
+ return
150
+
151
+ sqrt_disc = math.sqrt(discriminant)
152
+
153
+ # Two solutions
154
+ t1 = (-b - sqrt_disc) / 2.0
155
+ t2 = (-b + sqrt_disc) / 2.0
156
+
157
+ # Find nearest positive intersection
158
+ if t1 > 1e-6:
159
+ t = t1
160
+ elif t2 > 1e-6:
161
+ t = t2
162
+ else:
163
+ hit_mask_out[idx] = False
164
+ distances_out[idx] = math.inf
165
+ return
166
+
167
+ # Store results
168
+ hit_mask_out[idx] = True
169
+ distances_out[idx] = t
170
+
171
+ # Compute intersection point and normal
172
+ px = ox + t * dx
173
+ py = oy + t * dy
174
+ pz = oz + t * dz
175
+
176
+ # Normal points outward from sphere center
177
+ nx = px - center_x
178
+ ny = py - center_y
179
+ nz = pz - center_z
180
+
181
+ # Normalize
182
+ n_len = math.sqrt(nx * nx + ny * ny + nz * nz)
183
+ if n_len > 1e-10:
184
+ normals_out[idx, 0] = nx / n_len
185
+ normals_out[idx, 1] = ny / n_len
186
+ normals_out[idx, 2] = nz / n_len
187
+ else:
188
+ normals_out[idx, 0] = 0.0
189
+ normals_out[idx, 1] = 0.0
190
+ normals_out[idx, 2] = 1.0
@@ -0,0 +1,85 @@
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
+ Propagation Kernels for GPU Ray Tracing
36
+
37
+ CUDA kernels for GPU-accelerated ray propagation through
38
+ various inhomogeneous material models:
39
+
40
+ - simple: 1D LUT interpolation for radially-symmetric materials
41
+ - spectral: 2D LUT interpolation for wavelength-dependent materials
42
+ - grid: 3D trilinear interpolation for arbitrary 3D fields
43
+
44
+ Kernel Types
45
+ ------------
46
+ - SIMPLE_EULER, SIMPLE_RK4: Simple 1D LUT kernels
47
+ - SPECTRAL_EULER, SPECTRAL_RK4: Spectral 2D LUT kernels
48
+ - SPECTRAL_EULER_PERRAY, SPECTRAL_RK4_PERRAY: Per-ray wavelength kernels
49
+ - GRID_EULER, GRID_RK4: 3D grid-based kernels
50
+
51
+ Note: Surface intersection during propagation is handled by the propagator
52
+ layer, which calls intersection kernels separately after each propagation step.
53
+ """
54
+
55
+ from .protocol import PropagationKernelProtocol
56
+ from .simple import (
57
+ _kernel_simple_inhomogeneous_euler,
58
+ _kernel_simple_inhomogeneous_rk4,
59
+ )
60
+ from .spectral import (
61
+ _kernel_spectral_inhomogeneous_euler,
62
+ _kernel_spectral_inhomogeneous_rk4,
63
+ _kernel_spectral_inhomogeneous_euler_perray,
64
+ _kernel_spectral_inhomogeneous_rk4_perray,
65
+ )
66
+ from .grid import (
67
+ _kernel_grid_inhomogeneous_euler,
68
+ _kernel_grid_inhomogeneous_rk4,
69
+ )
70
+
71
+ __all__ = [
72
+ # Protocol
73
+ "PropagationKernelProtocol",
74
+ # Simple kernels
75
+ "_kernel_simple_inhomogeneous_euler",
76
+ "_kernel_simple_inhomogeneous_rk4",
77
+ # Spectral kernels
78
+ "_kernel_spectral_inhomogeneous_euler",
79
+ "_kernel_spectral_inhomogeneous_rk4",
80
+ "_kernel_spectral_inhomogeneous_euler_perray",
81
+ "_kernel_spectral_inhomogeneous_rk4_perray",
82
+ # Grid kernels
83
+ "_kernel_grid_inhomogeneous_euler",
84
+ "_kernel_grid_inhomogeneous_rk4",
85
+ ]