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.

@@ -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 _print_progress(self, converged: bool):
266
- """Print convergence progress."""
267
- mean_dscs, sem_dscs = self._calculate_phips_mean_and_sem()
268
-
269
- # Determine which detectors to display
270
- if self.convergable.detector_indices is not None:
271
- check_indices = self.convergable.detector_indices
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
- check_indices = np.where(~np.isnan(mean_dscs))[0]
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
- # Count converged detectors
296
- if self.convergable.tolerance_type == "relative":
297
- converged_mask = relative_sem < self.convergable.tolerance
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
- n_converged = np.sum(converged_mask)
302
- n_total = len(check_indices)
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
- status = "✓" if converged else "..."
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 self.convergable.tolerance_type == "relative":
307
- current_str = f"{worst_rel_sem * 100:.2f}%"
308
- target_str = f"{self.convergable.tolerance * 100:.2f}%"
309
- else:
310
- current_str = f"{worst_sem:.4g}"
311
- target_str = f"{self.convergable.tolerance:.4g}"
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
- print(
314
- f" PHIPS DSCS: {n_converged}/{n_total} detectors converged | "
315
- f"Worst θ={worst_theta:.1f}°: {worst_mean:.4g} | "
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
- print(f"\nStarting PHIPS convergence study:")
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
- while not converged and self.n_orientations < self.max_orientations:
337
- # Create orientations for this batch
338
- orientations = goad.create_uniform_orientation(self.batch_size)
339
- self.settings.orientation = orientations
340
-
341
- # Run MultiProblem
342
- mp = goad.MultiProblem(self.settings)
343
- mp.py_solve()
344
-
345
- # Update statistics
346
- self._update_statistics(mp.results, self.batch_size)
347
-
348
- # Check convergence
349
- converged = self._check_convergence()
350
-
351
- # Print progress
352
- min_required = self.min_batches * self.batch_size
353
- if self.n_orientations < min_required:
354
- print(
355
- f"\nBatch {len(self.batch_data)} ({self.n_orientations}/{min_required} total orientations, min not reached):"
356
- )
357
- else:
358
- print(
359
- f"\nBatch {len(self.batch_data)} ({self.n_orientations} total orientations, min {min_required} reached):"
360
- )
361
- self._print_progress(converged)
362
-
363
- # Store history
364
- mean_dscs, sem_dscs = self._calculate_phips_mean_and_sem()
365
- # Use worst-case SEM for history
366
- valid_mask = ~np.isnan(mean_dscs)
367
- if np.any(valid_mask):
368
- with np.errstate(divide="ignore", invalid="ignore"):
369
- relative_sem = sem_dscs[valid_mask] / np.abs(mean_dscs[valid_mask])
370
- worst_sem = np.max(relative_sem)
371
- self.convergence_history.append(
372
- (self.n_orientations, "phips_dscs", worst_sem)
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" Converged after {self.n_orientations} orientations")
421
+ print(f"\nConverged after {self.n_orientations} orientations.")
396
422
  else:
397
- print(f"✗ Did not converge (reached {self.n_orientations} orientations)")
398
- print(f"{'=' * 60}")
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
- print(f"\nStarting PHIPS Ensemble convergence study:")
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
- while not converged and self.n_orientations < self.max_orientations:
495
- # Randomly select a geometry file for this batch
496
- geom_file = random.choice(self.geom_files)
497
- geom_path = os.path.join(self.geom_dir, geom_file)
498
-
499
- # Create orientations for this batch
500
- orientations = goad.create_uniform_orientation(self.batch_size)
501
-
502
- # Update settings with selected geometry and orientations
503
- self.settings.geom_path = geom_path
504
- self.settings.orientation = orientations
505
-
506
- # Run MultiProblem
507
- mp = goad.MultiProblem(self.settings)
508
- mp.py_solve()
509
-
510
- # Update statistics
511
- self._update_statistics(mp.results, self.batch_size)
512
-
513
- # Check convergence
514
- converged = self._check_convergence()
515
-
516
- # Print progress (with geometry info)
517
- min_required = self.min_batches * self.batch_size
518
- if self.n_orientations < min_required:
519
- print(
520
- f"\nBatch {len(self.batch_data)} ({self.n_orientations}/{min_required} total orientations, min not reached) - Geometry: {geom_file}"
521
- )
522
- else:
523
- print(
524
- f"\nBatch {len(self.batch_data)} ({self.n_orientations} total orientations, min {min_required} reached) - Geometry: {geom_file}"
525
- )
526
- self._print_progress(converged)
527
-
528
- # Store history
529
- mean_dscs, sem_dscs = self._calculate_phips_mean_and_sem()
530
- valid_mask = ~np.isnan(mean_dscs)
531
- if np.any(valid_mask):
532
- with np.errstate(divide="ignore", invalid="ignore"):
533
- relative_sem = sem_dscs[valid_mask] / np.abs(mean_dscs[valid_mask])
534
- worst_sem = np.max(relative_sem)
535
- self.convergence_history.append(
536
- (self.n_orientations, "phips_dscs", worst_sem)
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=None
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" Ensemble Converged after {self.n_orientations} orientations")
596
+ print(f"\nEnsemble converged after {self.n_orientations} orientations.")
560
597
  else:
561
- print(f"✗ Did not converge (reached {self.n_orientations} orientations)")
562
- print(f" Geometries sampled: {len(self.geom_files)}")
563
- print(f"{'=' * 60}")
564
-
565
- # Print detector summary
566
- print(f"\nPHIPS Detector DSCS Summary (Ensemble-Averaged):")
567
- valid_mask = ~np.isnan(mean_dscs)
568
- for i in range(self.NUM_DETECTORS):
569
- theta = self.detector_centers[i]
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
@@ -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.05
221
- beam_area_threshold_fac: float = 4.0
222
- cutoff: float = 0.001
223
- max_rec: int = 100
224
- max_tir: int = 100
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 = False
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.05)
1075
- - beam_area_threshold_fac: Beam area threshold factor (default: 4.0)
1076
- - cutoff: Ray power cutoff (default: 0.001)
1077
- - max_rec: Max recursion depth (default: 100)
1078
- - max_tir: Max TIR bounces (default: 100)
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: False)
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.05),
1140
- beam_area_threshold_fac=kwargs.pop("beam_area_threshold_fac", 4.0),
1141
- cutoff=kwargs.pop("cutoff", 0.001),
1142
- max_rec=kwargs.pop("max_rec", 100),
1143
- max_tir=kwargs.pop("max_tir", 100),
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", False),
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.6.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,,
@@ -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,,