goad-py 0.6.0__cp38-abi3-musllinux_1_2_aarch64.whl → 0.7.0__cp38-abi3-musllinux_1_2_aarch64.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.
Potentially problematic release.
This version of goad-py might be problematic. Click here for more details.
- goad_py/_goad_py.abi3.so +0 -0
- goad_py/convergence.py +233 -285
- goad_py/convergence_display.py +499 -0
- goad_py/phips_convergence.py +220 -192
- goad_py/unified_convergence.py +18 -18
- {goad_py-0.6.0.dist-info → goad_py-0.7.0.dist-info}/METADATA +2 -1
- goad_py-0.7.0.dist-info/RECORD +12 -0
- goad_py-0.6.0.dist-info/RECORD +0 -11
- {goad_py-0.6.0.dist-info → goad_py-0.7.0.dist-info}/WHEEL +0 -0
goad_py/phips_convergence.py
CHANGED
|
@@ -6,14 +6,21 @@ which requires Custom binning with PHIPS detector geometry and post-processing
|
|
|
6
6
|
to compute mean DSCS at each of the 20 PHIPS detectors.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
from dataclasses import dataclass
|
|
10
|
-
from typing import List, Dict, Optional, Tuple
|
|
11
|
-
import numpy as np
|
|
12
9
|
import os
|
|
13
10
|
import random
|
|
11
|
+
from dataclasses import dataclass
|
|
14
12
|
from pathlib import Path
|
|
13
|
+
from typing import Dict, List, Optional, Tuple
|
|
14
|
+
|
|
15
|
+
import numpy as np
|
|
16
|
+
from rich.console import Console
|
|
17
|
+
|
|
15
18
|
from . import _goad_py as goad
|
|
16
19
|
from .convergence import ConvergenceResults
|
|
20
|
+
from .convergence_display import (
|
|
21
|
+
ArrayConvergenceVariable,
|
|
22
|
+
ConvergenceDisplay,
|
|
23
|
+
)
|
|
17
24
|
|
|
18
25
|
|
|
19
26
|
@dataclass
|
|
@@ -76,6 +83,8 @@ class PHIPSConvergence:
|
|
|
76
83
|
min_batches: Minimum number of batches before allowing convergence
|
|
77
84
|
"""
|
|
78
85
|
self.settings = settings
|
|
86
|
+
# Enable quiet mode to suppress Rust progress bars
|
|
87
|
+
self.settings.quiet = True
|
|
79
88
|
self.convergable = convergable
|
|
80
89
|
self.batch_size = batch_size
|
|
81
90
|
self.max_orientations = max_orientations
|
|
@@ -109,6 +118,26 @@ class PHIPSConvergence:
|
|
|
109
118
|
# Accumulated PHIPS DSCS for final average
|
|
110
119
|
self.phips_dscs_sum = None
|
|
111
120
|
|
|
121
|
+
# Rich console
|
|
122
|
+
self._console = Console()
|
|
123
|
+
|
|
124
|
+
# Create display variable for PHIPS DSCS
|
|
125
|
+
display_variable = ArrayConvergenceVariable(
|
|
126
|
+
name="phips_dscs",
|
|
127
|
+
tolerance=convergable.tolerance,
|
|
128
|
+
tolerance_type=convergable.tolerance_type,
|
|
129
|
+
indices=convergable.detector_indices,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# Initialize display system
|
|
133
|
+
self._display = ConvergenceDisplay(
|
|
134
|
+
variables=[display_variable],
|
|
135
|
+
batch_size=self.batch_size,
|
|
136
|
+
min_batches=self.min_batches,
|
|
137
|
+
convergence_type=self._get_convergence_type(),
|
|
138
|
+
console=self._console,
|
|
139
|
+
)
|
|
140
|
+
|
|
112
141
|
def _compute_phips_dscs_from_mueller2d(self, results: goad.Results) -> np.ndarray:
|
|
113
142
|
"""
|
|
114
143
|
Compute mean DSCS at each of 20 PHIPS detectors from Custom binning results.
|
|
@@ -262,59 +291,43 @@ class PHIPSConvergence:
|
|
|
262
291
|
|
|
263
292
|
return converged
|
|
264
293
|
|
|
265
|
-
def
|
|
266
|
-
"""
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
294
|
+
def _get_convergence_type(self) -> str:
|
|
295
|
+
"""Get the convergence type name for display."""
|
|
296
|
+
class_name = self.__class__.__name__
|
|
297
|
+
if class_name == "PHIPSEnsembleConvergence":
|
|
298
|
+
return "PHIPS Ensemble"
|
|
299
|
+
elif class_name == "PHIPSConvergence":
|
|
300
|
+
return "PHIPS"
|
|
272
301
|
else:
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
if len(check_indices) == 0:
|
|
276
|
-
print(f" PHIPS DSCS: No valid detectors")
|
|
277
|
-
return
|
|
278
|
-
|
|
279
|
-
# Find worst-case detector (highest relative SEM)
|
|
280
|
-
mean_subset = mean_dscs[check_indices]
|
|
281
|
-
sem_subset = sem_dscs[check_indices]
|
|
282
|
-
|
|
283
|
-
with np.errstate(divide="ignore", invalid="ignore"):
|
|
284
|
-
relative_sem = np.where(
|
|
285
|
-
mean_subset != 0, sem_subset / np.abs(mean_subset), np.inf
|
|
286
|
-
)
|
|
287
|
-
|
|
288
|
-
worst_idx_in_subset = np.argmax(relative_sem)
|
|
289
|
-
worst_detector_idx = check_indices[worst_idx_in_subset]
|
|
290
|
-
worst_theta = self.detector_centers[worst_detector_idx]
|
|
291
|
-
worst_mean = mean_subset[worst_idx_in_subset]
|
|
292
|
-
worst_sem = sem_subset[worst_idx_in_subset]
|
|
293
|
-
worst_rel_sem = relative_sem[worst_idx_in_subset]
|
|
302
|
+
return class_name
|
|
294
303
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
else:
|
|
299
|
-
converged_mask = sem_subset < self.convergable.tolerance
|
|
304
|
+
def _get_detector_angles(self, variable: str) -> np.ndarray:
|
|
305
|
+
"""Get detector angles for PHIPS detectors."""
|
|
306
|
+
return self.detector_centers
|
|
300
307
|
|
|
301
|
-
|
|
302
|
-
|
|
308
|
+
def _get_phips_stats(self, variable: str) -> Tuple[float, float]:
|
|
309
|
+
"""Get mean and SEM for a single PHIPS detector (not used for array display)."""
|
|
310
|
+
# This is not used since PHIPS uses array display, but required by interface
|
|
311
|
+
return 0.0, 0.0
|
|
303
312
|
|
|
304
|
-
|
|
313
|
+
def _update_convergence_history(self):
|
|
314
|
+
"""Update convergence history with current worst-case SEM."""
|
|
315
|
+
mean_dscs, sem_dscs = self._calculate_phips_mean_and_sem()
|
|
305
316
|
|
|
306
|
-
if
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
317
|
+
if len(mean_dscs) > 0:
|
|
318
|
+
# Find worst-case detector
|
|
319
|
+
if self.convergable.tolerance_type == "relative":
|
|
320
|
+
with np.errstate(divide="ignore", invalid="ignore"):
|
|
321
|
+
relative_sem = np.where(
|
|
322
|
+
mean_dscs != 0, sem_dscs / np.abs(mean_dscs), np.inf
|
|
323
|
+
)
|
|
324
|
+
worst_sem = np.max(relative_sem)
|
|
325
|
+
else:
|
|
326
|
+
worst_sem = np.max(sem_dscs)
|
|
312
327
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
f"SEM: {current_str} (target: {target_str}) {status}"
|
|
317
|
-
)
|
|
328
|
+
self.convergence_history.append(
|
|
329
|
+
(self.n_orientations, "phips_dscs", worst_sem)
|
|
330
|
+
)
|
|
318
331
|
|
|
319
332
|
def run(self) -> ConvergenceResults:
|
|
320
333
|
"""
|
|
@@ -323,54 +336,68 @@ class PHIPSConvergence:
|
|
|
323
336
|
Returns:
|
|
324
337
|
ConvergenceResults with PHIPS DSCS values
|
|
325
338
|
"""
|
|
326
|
-
|
|
327
|
-
print(f" Batch size: {self.batch_size}")
|
|
328
|
-
print(f" Max orientations: {self.max_orientations}")
|
|
329
|
-
print(
|
|
330
|
-
f" Tolerance: {self.convergable.tolerance * 100:.1f}% ({self.convergable.tolerance_type})"
|
|
331
|
-
)
|
|
332
|
-
print(f" Min batches: {self.min_batches}")
|
|
333
|
-
|
|
339
|
+
iteration = 0
|
|
334
340
|
converged = False
|
|
335
341
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
self.
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
342
|
+
# Create Live context for smooth updating display
|
|
343
|
+
with self._display.create_live_context() as live:
|
|
344
|
+
# Show initial display before first batch
|
|
345
|
+
initial_display = self._display.build_display(
|
|
346
|
+
iteration=0,
|
|
347
|
+
n_orientations=self.n_orientations,
|
|
348
|
+
get_stats=self._get_phips_stats,
|
|
349
|
+
get_array_stats=lambda var: self._calculate_phips_mean_and_sem(),
|
|
350
|
+
get_bin_labels=self._get_detector_angles,
|
|
351
|
+
power_ratio=None,
|
|
352
|
+
geom_info=None,
|
|
353
|
+
)
|
|
354
|
+
live.update(initial_display)
|
|
355
|
+
|
|
356
|
+
while not converged and self.n_orientations < self.max_orientations:
|
|
357
|
+
iteration += 1
|
|
358
|
+
|
|
359
|
+
# Create orientations for this batch
|
|
360
|
+
orientations = goad.create_uniform_orientation(self.batch_size)
|
|
361
|
+
self.settings.orientation = orientations
|
|
362
|
+
|
|
363
|
+
# Run MultiProblem with error handling for bad geometries
|
|
364
|
+
try:
|
|
365
|
+
mp = goad.MultiProblem(self.settings)
|
|
366
|
+
mp.py_solve()
|
|
367
|
+
except Exception as e:
|
|
368
|
+
# Geometry loading failed (bad faces, degenerate geometry, etc.)
|
|
369
|
+
# For single-geometry convergence, we can't skip - must raise error
|
|
370
|
+
error_msg = (
|
|
371
|
+
f"Failed to initialize MultiProblem with geometry '{self.settings.geom_path}': {e}\n"
|
|
372
|
+
f"Please check geometry file for:\n"
|
|
373
|
+
f" - Degenerate faces (area = 0)\n"
|
|
374
|
+
f" - Non-planar geometry\n"
|
|
375
|
+
f" - Faces that are too small\n"
|
|
376
|
+
f" - Invalid mesh topology\n"
|
|
377
|
+
f" - Geometry file corruption"
|
|
378
|
+
)
|
|
379
|
+
raise type(e)(error_msg) from e
|
|
380
|
+
|
|
381
|
+
# Update statistics
|
|
382
|
+
self._update_statistics(mp.results, self.batch_size)
|
|
383
|
+
|
|
384
|
+
# Update convergence history
|
|
385
|
+
self._update_convergence_history()
|
|
386
|
+
|
|
387
|
+
# Check convergence
|
|
388
|
+
converged = self._check_convergence()
|
|
389
|
+
|
|
390
|
+
# Update live display
|
|
391
|
+
display = self._display.build_display(
|
|
392
|
+
iteration=iteration,
|
|
393
|
+
n_orientations=self.n_orientations,
|
|
394
|
+
get_stats=self._get_phips_stats,
|
|
395
|
+
get_array_stats=lambda var: self._calculate_phips_mean_and_sem(),
|
|
396
|
+
get_bin_labels=self._get_detector_angles,
|
|
397
|
+
power_ratio=None,
|
|
398
|
+
geom_info=None,
|
|
373
399
|
)
|
|
400
|
+
live.update(display)
|
|
374
401
|
|
|
375
402
|
# Compute final results
|
|
376
403
|
mean_dscs, sem_dscs = self._calculate_phips_mean_and_sem()
|
|
@@ -389,28 +416,13 @@ class PHIPSConvergence:
|
|
|
389
416
|
else f"Did not converge within {self.max_orientations} orientations",
|
|
390
417
|
)
|
|
391
418
|
|
|
392
|
-
# Print summary
|
|
393
|
-
print(f"\n{'=' * 60}")
|
|
419
|
+
# Print final summary
|
|
394
420
|
if converged:
|
|
395
|
-
print(f"
|
|
421
|
+
print(f"\nConverged after {self.n_orientations} orientations.")
|
|
396
422
|
else:
|
|
397
|
-
print(
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
# Print detector summary
|
|
401
|
-
print(f"\nPHIPS Detector DSCS Summary:")
|
|
402
|
-
valid_mask = ~np.isnan(mean_dscs)
|
|
403
|
-
for i in range(self.NUM_DETECTORS):
|
|
404
|
-
theta = self.detector_centers[i]
|
|
405
|
-
if valid_mask[i]:
|
|
406
|
-
mean_val = mean_dscs[i]
|
|
407
|
-
sem_val = sem_dscs[i]
|
|
408
|
-
rel_sem = sem_val / abs(mean_val) * 100
|
|
409
|
-
print(
|
|
410
|
-
f" Detector {i:2d} (θ={theta:6.1f}°): {mean_val:.6e} ± {sem_val:.6e} ({rel_sem:.2f}%)"
|
|
411
|
-
)
|
|
412
|
-
else:
|
|
413
|
-
print(f" Detector {i:2d} (θ={theta:6.1f}°): No data")
|
|
423
|
+
print(
|
|
424
|
+
f"\nWarning: Did not converge within {self.max_orientations} orientations"
|
|
425
|
+
)
|
|
414
426
|
|
|
415
427
|
return results
|
|
416
428
|
|
|
@@ -480,65 +492,93 @@ class PHIPSEnsembleConvergence(PHIPSConvergence):
|
|
|
480
492
|
Returns:
|
|
481
493
|
ConvergenceResults with ensemble-averaged PHIPS DSCS values
|
|
482
494
|
"""
|
|
483
|
-
|
|
484
|
-
print(f" Geometry files: {len(self.geom_files)}")
|
|
485
|
-
print(f" Batch size: {self.batch_size}")
|
|
486
|
-
print(f" Max orientations: {self.max_orientations}")
|
|
487
|
-
print(
|
|
488
|
-
f" Tolerance: {self.convergable.tolerance * 100:.1f}% ({self.convergable.tolerance_type})"
|
|
489
|
-
)
|
|
490
|
-
print(f" Min batches: {self.min_batches}")
|
|
491
|
-
|
|
495
|
+
iteration = 0
|
|
492
496
|
converged = False
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
497
|
+
skipped_geometries = [] # Track skipped geometry files
|
|
498
|
+
|
|
499
|
+
# Create Live context for smooth updating display
|
|
500
|
+
with self._display.create_live_context() as live:
|
|
501
|
+
# Show initial display before first batch
|
|
502
|
+
initial_display = self._display.build_display(
|
|
503
|
+
iteration=0,
|
|
504
|
+
n_orientations=self.n_orientations,
|
|
505
|
+
get_stats=self._get_phips_stats,
|
|
506
|
+
get_array_stats=lambda var: self._calculate_phips_mean_and_sem(),
|
|
507
|
+
get_bin_labels=self._get_detector_angles,
|
|
508
|
+
power_ratio=None,
|
|
509
|
+
geom_info=None,
|
|
510
|
+
)
|
|
511
|
+
live.update(initial_display)
|
|
512
|
+
|
|
513
|
+
while not converged and self.n_orientations < self.max_orientations:
|
|
514
|
+
iteration += 1
|
|
515
|
+
|
|
516
|
+
# Randomly select a geometry file for this batch
|
|
517
|
+
geom_file = random.choice(self.geom_files)
|
|
518
|
+
geom_path = os.path.join(self.geom_dir, geom_file)
|
|
519
|
+
|
|
520
|
+
# Create orientations for this batch
|
|
521
|
+
orientations = goad.create_uniform_orientation(self.batch_size)
|
|
522
|
+
|
|
523
|
+
# Update settings with selected geometry and orientations
|
|
524
|
+
self.settings.geom_path = geom_path
|
|
525
|
+
self.settings.orientation = orientations
|
|
526
|
+
|
|
527
|
+
# Run MultiProblem
|
|
528
|
+
try:
|
|
529
|
+
mp = goad.MultiProblem(self.settings)
|
|
530
|
+
mp.py_solve()
|
|
531
|
+
except Exception as e:
|
|
532
|
+
# Geometry loading failed (bad faces, degenerate geometry, etc.)
|
|
533
|
+
print(f"\nWarning: Skipping geometry '{geom_file}': {e}")
|
|
534
|
+
skipped_geometries.append(geom_file)
|
|
535
|
+
|
|
536
|
+
# Check if all geometries have been skipped
|
|
537
|
+
if len(skipped_geometries) >= len(self.geom_files):
|
|
538
|
+
raise ValueError(
|
|
539
|
+
f"All {len(self.geom_files)} geometry files failed to load. "
|
|
540
|
+
"Please check geometry files for degenerate faces, non-planar geometry, "
|
|
541
|
+
"or faces that are too small."
|
|
542
|
+
)
|
|
543
|
+
|
|
544
|
+
# Skip this iteration without updating statistics
|
|
545
|
+
continue
|
|
546
|
+
|
|
547
|
+
# Update statistics
|
|
548
|
+
self._update_statistics(mp.results, self.batch_size)
|
|
549
|
+
|
|
550
|
+
# Update convergence history
|
|
551
|
+
self._update_convergence_history()
|
|
552
|
+
|
|
553
|
+
# Check convergence
|
|
554
|
+
converged = self._check_convergence()
|
|
555
|
+
|
|
556
|
+
# Update live display with geometry info
|
|
557
|
+
geom_info = f"Geom: {geom_file}"
|
|
558
|
+
display = self._display.build_display(
|
|
559
|
+
iteration=iteration,
|
|
560
|
+
n_orientations=self.n_orientations,
|
|
561
|
+
get_stats=self._get_phips_stats,
|
|
562
|
+
get_array_stats=lambda var: self._calculate_phips_mean_and_sem(),
|
|
563
|
+
get_bin_labels=self._get_detector_angles,
|
|
564
|
+
power_ratio=None,
|
|
565
|
+
geom_info=geom_info,
|
|
537
566
|
)
|
|
567
|
+
live.update(display)
|
|
538
568
|
|
|
539
569
|
# Compute final results
|
|
540
570
|
mean_dscs, sem_dscs = self._calculate_phips_mean_and_sem()
|
|
541
571
|
|
|
572
|
+
# Prepare warning message
|
|
573
|
+
warning = None
|
|
574
|
+
if not converged:
|
|
575
|
+
warning = f"Did not converge within {self.max_orientations} orientations"
|
|
576
|
+
|
|
577
|
+
# Add skipped geometries info to warning
|
|
578
|
+
if skipped_geometries:
|
|
579
|
+
skipped_msg = f"Skipped {len(skipped_geometries)} bad geometries"
|
|
580
|
+
warning = f"{warning} | {skipped_msg}" if warning else skipped_msg
|
|
581
|
+
|
|
542
582
|
# Create results
|
|
543
583
|
results = ConvergenceResults(
|
|
544
584
|
converged=converged,
|
|
@@ -548,33 +588,21 @@ class PHIPSEnsembleConvergence(PHIPSConvergence):
|
|
|
548
588
|
mueller_1d=None,
|
|
549
589
|
mueller_2d=None,
|
|
550
590
|
convergence_history=self.convergence_history,
|
|
551
|
-
warning=
|
|
552
|
-
if converged
|
|
553
|
-
else f"Did not converge within {self.max_orientations} orientations",
|
|
591
|
+
warning=warning,
|
|
554
592
|
)
|
|
555
593
|
|
|
556
|
-
# Print summary
|
|
557
|
-
print(f"\n{'=' * 60}")
|
|
594
|
+
# Print final summary
|
|
558
595
|
if converged:
|
|
559
|
-
print(f"
|
|
596
|
+
print(f"\nEnsemble converged after {self.n_orientations} orientations.")
|
|
560
597
|
else:
|
|
561
|
-
print(
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
#
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
if valid_mask[i]:
|
|
571
|
-
mean_val = mean_dscs[i]
|
|
572
|
-
sem_val = sem_dscs[i]
|
|
573
|
-
rel_sem = sem_val / abs(mean_val) * 100
|
|
574
|
-
print(
|
|
575
|
-
f" Detector {i:2d} (θ={theta:6.1f}°): {mean_val:.6e} ± {sem_val:.6e} ({rel_sem:.2f}%)"
|
|
576
|
-
)
|
|
577
|
-
else:
|
|
578
|
-
print(f" Detector {i:2d} (θ={theta:6.1f}°): No data")
|
|
598
|
+
print(
|
|
599
|
+
f"\nWarning: Did not converge within {self.max_orientations} orientations"
|
|
600
|
+
)
|
|
601
|
+
|
|
602
|
+
# Report skipped geometries if any
|
|
603
|
+
if skipped_geometries:
|
|
604
|
+
print(
|
|
605
|
+
f"Note: Skipped {len(skipped_geometries)} geometry file(s) due to errors"
|
|
606
|
+
)
|
|
579
607
|
|
|
580
608
|
return results
|
goad_py/unified_convergence.py
CHANGED
|
@@ -217,11 +217,11 @@ class PHIPSMode(ConvergenceMode):
|
|
|
217
217
|
class BeamTracingConfig:
|
|
218
218
|
"""Beam tracing performance and accuracy parameters."""
|
|
219
219
|
|
|
220
|
-
beam_power_threshold: float = 0.
|
|
221
|
-
beam_area_threshold_fac: float =
|
|
222
|
-
cutoff: float = 0.
|
|
223
|
-
max_rec: int =
|
|
224
|
-
max_tir: int =
|
|
220
|
+
beam_power_threshold: float = 0.005
|
|
221
|
+
beam_area_threshold_fac: float = 0.001
|
|
222
|
+
cutoff: float = 0.999
|
|
223
|
+
max_rec: int = 10
|
|
224
|
+
max_tir: int = 10
|
|
225
225
|
|
|
226
226
|
def __post_init__(self):
|
|
227
227
|
"""Validate beam tracing parameters."""
|
|
@@ -283,7 +283,7 @@ class AdvancedConfig:
|
|
|
283
283
|
mapping: Optional[Any] = (
|
|
284
284
|
"ApertureDiffraction" # String that will be converted to enum in __post_init__
|
|
285
285
|
)
|
|
286
|
-
coherence: bool =
|
|
286
|
+
coherence: bool = True
|
|
287
287
|
fov_factor: Optional[float] = None
|
|
288
288
|
|
|
289
289
|
def __post_init__(self):
|
|
@@ -1071,11 +1071,11 @@ def run_convergence(
|
|
|
1071
1071
|
- n_phi: Number of phi bins for standard mode (default: 181)
|
|
1072
1072
|
|
|
1073
1073
|
# Beam tracing parameters
|
|
1074
|
-
- beam_power_threshold: Beam power threshold (default: 0.
|
|
1075
|
-
- beam_area_threshold_fac: Beam area threshold factor (default:
|
|
1076
|
-
- cutoff: Ray power cutoff (default: 0.
|
|
1077
|
-
- max_rec: Max recursion depth (default:
|
|
1078
|
-
- max_tir: Max TIR bounces (default:
|
|
1074
|
+
- beam_power_threshold: Beam power threshold (default: 0.005)
|
|
1075
|
+
- beam_area_threshold_fac: Beam area threshold factor (default: 0.001)
|
|
1076
|
+
- cutoff: Ray power cutoff (default: 0.999)
|
|
1077
|
+
- max_rec: Max recursion depth (default: 10)
|
|
1078
|
+
- max_tir: Max TIR bounces (default: 10)
|
|
1079
1079
|
|
|
1080
1080
|
# Geometry transformations
|
|
1081
1081
|
- scale: Problem scaling factor - scales entire problem including geometry,
|
|
@@ -1086,7 +1086,7 @@ def run_convergence(
|
|
|
1086
1086
|
|
|
1087
1087
|
# Advanced configuration
|
|
1088
1088
|
- mapping: DSCS mapping scheme (default: goad.Mapping.ApertureDiffraction)
|
|
1089
|
-
- coherence: Enable coherent scattering (default:
|
|
1089
|
+
- coherence: Enable coherent scattering (default: True)
|
|
1090
1090
|
- fov_factor: Field of view factor (optional)
|
|
1091
1091
|
|
|
1092
1092
|
# Reproducibility
|
|
@@ -1136,11 +1136,11 @@ def run_convergence(
|
|
|
1136
1136
|
"""
|
|
1137
1137
|
# Extract beam tracing parameters from kwargs
|
|
1138
1138
|
beam_tracing = BeamTracingConfig(
|
|
1139
|
-
beam_power_threshold=kwargs.pop("beam_power_threshold", 0.
|
|
1140
|
-
beam_area_threshold_fac=kwargs.pop("beam_area_threshold_fac",
|
|
1141
|
-
cutoff=kwargs.pop("cutoff", 0.
|
|
1142
|
-
max_rec=kwargs.pop("max_rec",
|
|
1143
|
-
max_tir=kwargs.pop("max_tir",
|
|
1139
|
+
beam_power_threshold=kwargs.pop("beam_power_threshold", 0.005),
|
|
1140
|
+
beam_area_threshold_fac=kwargs.pop("beam_area_threshold_fac", 0.001),
|
|
1141
|
+
cutoff=kwargs.pop("cutoff", 0.999),
|
|
1142
|
+
max_rec=kwargs.pop("max_rec", 10),
|
|
1143
|
+
max_tir=kwargs.pop("max_tir", 10),
|
|
1144
1144
|
)
|
|
1145
1145
|
|
|
1146
1146
|
# Extract geometry transform parameters
|
|
@@ -1153,7 +1153,7 @@ def run_convergence(
|
|
|
1153
1153
|
# Extract advanced configuration parameters
|
|
1154
1154
|
advanced_config = AdvancedConfig(
|
|
1155
1155
|
mapping=kwargs.pop("mapping", "ApertureDiffraction"),
|
|
1156
|
-
coherence=kwargs.pop("coherence",
|
|
1156
|
+
coherence=kwargs.pop("coherence", True),
|
|
1157
1157
|
fov_factor=kwargs.pop("fov_factor", None),
|
|
1158
1158
|
)
|
|
1159
1159
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: goad-py
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Intended Audience :: Science/Research
|
|
6
6
|
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
@@ -17,6 +17,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
17
17
|
Classifier: Operating System :: OS Independent
|
|
18
18
|
Requires-Dist: numpy>=1.20.0
|
|
19
19
|
Requires-Dist: toml>=0.10.0
|
|
20
|
+
Requires-Dist: rich>=13.0.0
|
|
20
21
|
Summary: Physical optics light scattering computation
|
|
21
22
|
Keywords: light-scattering,optics,simulation,scientific-computing,physics
|
|
22
23
|
Home-Page: https://github.com/hballington12/goad
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
goad_py-0.7.0.dist-info/METADATA,sha256=0_d3FTncDZ9MrOT3XWx-LpLlVW_kRzyVm8D3Bd2PH1Q,3266
|
|
2
|
+
goad_py-0.7.0.dist-info/WHEEL,sha256=bITaocPl86jMm-S2cO-6dnFV3lXGZ1OL6ueZKGDGDMY,106
|
|
3
|
+
goad_py.libs/libgcc_s-39080030.so.1,sha256=fIO6GHOh8Ft9CR0Geu7wSUb9Xnl122iTtrxQQ9TAkTQ,789673
|
|
4
|
+
goad_py.libs/libstdc++-cedf4250.so.6,sha256=ahluTdjW3ViH_6W4-dRp01QgMtKg6f8XkwQdWeci4q8,22443689
|
|
5
|
+
goad_py/__init__.py,sha256=iGJg-Oj9btk4I4GITkE7olNRm38uFRjENMJqXaDJmpM,1083
|
|
6
|
+
goad_py/_goad_py.abi3.so,sha256=kJF-rqUjrRf1_UPBDCXHU5PJzQT9rzXhBEBJ4XEEGlQ,2297769
|
|
7
|
+
goad_py/convergence.py,sha256=gbf8-uQTpCltCO3MrhVckobSP-uM2lxOiYocB6YSBTs,32682
|
|
8
|
+
goad_py/convergence_display.py,sha256=2V_kyARZ504-pJNjiWO-Zqd5S1z8leTJ-A86c4r382w,16672
|
|
9
|
+
goad_py/goad_py.pyi,sha256=7Y79-TV-NjEN8DWPEqSRGQ7alCrkylL6y1ZK8d6FYSg,14502
|
|
10
|
+
goad_py/phips_convergence.py,sha256=U_2r40lDza6FO0VDo-FD6KxaKjo9gDdVfm01StqYKMU,22765
|
|
11
|
+
goad_py/unified_convergence.py,sha256=3R4D_bVD-u-XbkaZ4R_BcVGZpwKoq8S0OZ-My-Nlxm0,49212
|
|
12
|
+
goad_py-0.7.0.dist-info/RECORD,,
|
goad_py-0.6.0.dist-info/RECORD
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
goad_py-0.6.0.dist-info/METADATA,sha256=CtiEjICRynM820bMQscUyTLqIUx3XHtPhH-PE3_4kek,3238
|
|
2
|
-
goad_py-0.6.0.dist-info/WHEEL,sha256=bITaocPl86jMm-S2cO-6dnFV3lXGZ1OL6ueZKGDGDMY,106
|
|
3
|
-
goad_py.libs/libgcc_s-39080030.so.1,sha256=fIO6GHOh8Ft9CR0Geu7wSUb9Xnl122iTtrxQQ9TAkTQ,789673
|
|
4
|
-
goad_py.libs/libstdc++-cedf4250.so.6,sha256=ahluTdjW3ViH_6W4-dRp01QgMtKg6f8XkwQdWeci4q8,22443689
|
|
5
|
-
goad_py/__init__.py,sha256=iGJg-Oj9btk4I4GITkE7olNRm38uFRjENMJqXaDJmpM,1083
|
|
6
|
-
goad_py/_goad_py.abi3.so,sha256=DYPrCyfGW4eulvzkbBcxecbDbA4Nezj7NbV2LYyaw3Q,2297745
|
|
7
|
-
goad_py/convergence.py,sha256=hXVvlfjVEKpOlxoiJ_NGDzDlCoSqyo6V7g3OxNp2xUA,35209
|
|
8
|
-
goad_py/goad_py.pyi,sha256=7Y79-TV-NjEN8DWPEqSRGQ7alCrkylL6y1ZK8d6FYSg,14502
|
|
9
|
-
goad_py/phips_convergence.py,sha256=sA7XIjKRLaRTIDCTjgq0i6xFxYhTD1rcu6ZMYAetDPE,21803
|
|
10
|
-
goad_py/unified_convergence.py,sha256=jC9z_YXX3za-nL5jdYxfw6G13moOCZT9Bp7bI9FIzCg,49212
|
|
11
|
-
goad_py-0.6.0.dist-info/RECORD,,
|
|
File without changes
|