Example 06: Detector Scan (Planar Surface)
Location: scripts/06_detector_scan.py
This example demonstrates scanning a detector through angular positions to measure ray distributions from a planar water surface.
Overview
Features demonstrated:
Detector position scanning
Time-of-arrival measurements
Angular distribution analysis
Specular reflection peak detection
Multi-panel visualization
Geometry
Detector arc (0-90°)
○ ○ ○ ○ ○ ○ ○
○ ○
○ ○
○ ○
Beam → ○ ═════════════════ ← Water surface (z=0)
45°
Water surface: Horizontal plane at z=0
Beam: 45° grazing angle, 5 mm radius, 5000 rays
Detector: 2 cm radius sphere, scans 0-90° in 1° steps
Key Code Sections
Detector Scanning Loop
detector_angles_deg = np.arange(0, 91, 1)
detection_counts = np.zeros(len(detector_angles_deg))
for idx, angle_deg in enumerate(detector_angles_deg):
angle_rad = np.radians(angle_deg)
detector_pos = (
detector_distance * np.cos(angle_rad),
0,
detector_distance * np.sin(angle_rad),
)
detector = sr.SphericalDetector(
center=detector_pos,
radius=detector_radius,
)
events = detector.detect(reflected_rays)
detection_counts[idx] = len(events)
Timing Analysis
For each detection, record arrival time and angle:
if num_detected > 0:
times = np.array([e.time for e in events])
mean_arrival_times[idx] = np.mean(times)
std_arrival_times[idx] = np.std(times)
# Angles to detector normal
detector_normal = -np.array(detector_pos) / np.linalg.norm(detector_pos)
angles = []
for e in events:
ray_dir = e.direction / np.linalg.norm(e.direction)
cos_angle = np.clip(np.dot(ray_dir, detector_normal), -1, 1)
angles.append(np.degrees(np.arccos(cos_angle)))
Visualization
Two plots are generated:
Ray paths (
06_detector_scan_rays.png): - Incident and reflected ray paths - Surface geometry - Intersection pointsDetector scan results (
06_detector_scan.png): - Detection count vs. angle - Intensity vs. angle - Mean arrival time vs. angle - Timing spread vs. angle - Angular distribution histograms - Time distribution histograms
Expected Output
Console output:
======================================================================
Detector Position Scan - Planar Water Surface
======================================================================
Planar Surface:
Material: Water (n ≈ 1.33)
Position: z = 0
Beam:
Rays: 5000
Grazing angle: 45°
Radius: 5.0 mm
Height: 5.0 cm
Detector:
Distance: 100 cm
Radius: 2.0 cm
Scanning 91 detector positions...
Results:
Expected specular angle: 45°
Peak detection: 5000 rays at 43°
Total detections: 12,876
Detection efficiency: 7.2%
Physics
Specular Reflection
For a planar surface, the law of reflection predicts:
where \(\theta_i\) is the incident angle and \(\theta_r\) is the reflection angle.
For a 45° grazing angle:
Incident angle to normal: 45°
Reflection angle to normal: 45°
Expected detector peak: 45° above horizon
Detection Efficiency
Only rays within the detector solid angle are recorded:
For the parameters in this example:
\(r_{detector} = 0.02\) m
\(d_{detector} = 1.0\) m
\(\Omega \approx 0.0013\) sr (0.01% of sphere)
Time Spread
The timing spread arises from:
Beam geometry: Rays start at different positions
Path length variation: Different distances to detector
Multiple reflections: (negligible for planar surface)
Running the Example
From the scripts/ directory:
python 06_detector_scan.py
Execution time: ~5 seconds (GPU) or ~20 seconds (CPU)
Generated plots:
plots/06_detector_scan_rays.pngplots/06_detector_scan.png
Exercises
Vary beam angle: Change
grazing_angle_degto 30° or 60°Detector resolution: Reduce
detector_stepto 0.5° for finer samplingLarger detector: Increase
detector_radiusto 0.05 mDifferent materials: Replace water with
BK7_GLASS
See Also
07_detector_scan_waves - Same scan with wave surface
lsurf.detectors.SphericalDetector- Detector APIlsurf.visualization.plot_detector_scan_results()- Visualization function