goad-py 0.5.5__tar.gz → 0.6.0__tar.gz

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.

Files changed (137) hide show
  1. {goad_py-0.5.5 → goad_py-0.6.0}/PKG-INFO +1 -1
  2. goad_py-0.6.0/goad-py/examples/direct/multiproblem_phips_example.py +163 -0
  3. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/examples/unified/09_phips_convergence.py +0 -3
  4. goad_py-0.6.0/goad-py/examples/unified/10_advanced_parameters.py +216 -0
  5. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/python/goad_py/unified_convergence.py +245 -3
  6. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/src/lib.rs +4 -0
  7. {goad_py-0.5.5 → goad_py-0.6.0}/pyproject.toml +1 -1
  8. {goad_py-0.5.5 → goad_py-0.6.0}/python/goad_py/unified_convergence.py +245 -3
  9. {goad_py-0.5.5 → goad_py-0.6.0}/src/settings.rs +50 -0
  10. goad_py-0.5.5/goad-py/examples/unified/09_phips_convergence_results.json +0 -220
  11. {goad_py-0.5.5 → goad_py-0.6.0}/.github/workflows/python.yml +0 -0
  12. {goad_py-0.5.5 → goad_py-0.6.0}/.github/workflows/rust.yml +0 -0
  13. {goad_py-0.5.5 → goad_py-0.6.0}/.gitignore +0 -0
  14. {goad_py-0.5.5 → goad_py-0.6.0}/Cargo.lock +0 -0
  15. {goad_py-0.5.5 → goad_py-0.6.0}/Cargo.toml +0 -0
  16. {goad_py-0.5.5 → goad_py-0.6.0}/LICENSE +0 -0
  17. {goad_py-0.5.5 → goad_py-0.6.0}/README-python.md +0 -0
  18. {goad_py-0.5.5 → goad_py-0.6.0}/README.md +0 -0
  19. {goad_py-0.5.5 → goad_py-0.6.0}/blender/addon/__init__.py +0 -0
  20. {goad_py-0.5.5 → goad_py-0.6.0}/blender/addon/goad_py/__init__.py +0 -0
  21. {goad_py-0.5.5 → goad_py-0.6.0}/blender/addon.zip +0 -0
  22. {goad_py-0.5.5 → goad_py-0.6.0}/blender/build.sh +0 -0
  23. {goad_py-0.5.5 → goad_py-0.6.0}/blender/dev.blend +0 -0
  24. {goad_py-0.5.5 → goad_py-0.6.0}/config/default.toml +0 -0
  25. {goad_py-0.5.5 → goad_py-0.6.0}/config_editor.sh +0 -0
  26. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/8col.obj +0 -0
  27. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/clip_test.obj +0 -0
  28. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/concave1.obj +0 -0
  29. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/concave2.obj +0 -0
  30. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/cone.obj +0 -0
  31. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/cube.obj +0 -0
  32. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/cube2.obj +0 -0
  33. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/cube_inside_cube.obj +0 -0
  34. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/cube_inside_hex.obj +0 -0
  35. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/cube_inside_ico.obj +0 -0
  36. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/cubes.obj +0 -0
  37. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/hex.obj +0 -0
  38. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/hex2.obj +0 -0
  39. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/hex3.obj +0 -0
  40. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/hex4.obj +0 -0
  41. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/hex5.obj +0 -0
  42. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/hex6.obj +0 -0
  43. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/hex7.obj +0 -0
  44. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/hex_20_30_30.obj +0 -0
  45. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/hex_distort.obj +0 -0
  46. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/hex_hollow.obj +0 -0
  47. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/hex_indented.obj +0 -0
  48. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/icosphere1.obj +0 -0
  49. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/multiple.obj +0 -0
  50. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/multiple2.obj +0 -0
  51. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/multiple3.obj +0 -0
  52. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/octo.obj +0 -0
  53. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/octo2.obj +0 -0
  54. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/para.obj +0 -0
  55. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/para_rough1.obj +0 -0
  56. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/plane_xy.obj +0 -0
  57. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/plane_yz.obj +0 -0
  58. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/plate.obj +0 -0
  59. {goad_py-0.5.5 → goad_py-0.6.0}/examples/data/plate_distort.obj +0 -0
  60. {goad_py-0.5.5 → goad_py-0.6.0}/examples/multi-problem.rs +0 -0
  61. {goad_py-0.5.5 → goad_py-0.6.0}/examples/problem-diff.rs +0 -0
  62. {goad_py-0.5.5 → goad_py-0.6.0}/examples/problem1.rs +0 -0
  63. {goad_py-0.5.5 → goad_py-0.6.0}/examples/simplify.rs +0 -0
  64. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/.gitignore +0 -0
  65. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/CLAUDE.md +0 -0
  66. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/Cargo.toml +0 -0
  67. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/DISTRIBUTION.md +0 -0
  68. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/README-python.md +0 -0
  69. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/UNIFIED_API.md +0 -0
  70. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/UNIFIED_API_SUMMARY.md +0 -0
  71. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/build_and_test.sh +0 -0
  72. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/build_wheels_local.sh +0 -0
  73. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/convergence.py +0 -0
  74. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/examples/README.md +0 -0
  75. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/examples/direct/README.md +0 -0
  76. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/examples/direct/backscatter_convergence_example.py +0 -0
  77. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/examples/direct/convergence_example.py +0 -0
  78. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/examples/direct/ensemble_example.py +0 -0
  79. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/examples/direct/multiproblem_example.py +0 -0
  80. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/examples/direct/phips_convergence_example.py +0 -0
  81. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/examples/direct/phips_ensemble_convergence_example.py +0 -0
  82. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/examples/direct/s11_convergence_example.py +0 -0
  83. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/examples/direct/simple_example.py +0 -0
  84. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/examples/unified/01_simple_asymmetry.py +0 -0
  85. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/examples/unified/02_interval_binning.py +0 -0
  86. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/examples/unified/03_multiple_targets.py +0 -0
  87. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/examples/unified/04_mueller_element.py +0 -0
  88. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/examples/unified/05_backscatter_specific_bin.py +0 -0
  89. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/examples/unified/06_ensemble_convergence.py +0 -0
  90. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/examples/unified/07_advanced_config.py +0 -0
  91. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/examples/unified/08_parameter_sweep.py +0 -0
  92. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/examples/unified/README.md +0 -0
  93. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/goad_py.pyi +0 -0
  94. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/plot.ipynb +0 -0
  95. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/publish_test.sh +0 -0
  96. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/python/goad_py/__init__.py +0 -0
  97. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/python/goad_py/convergence.py +0 -0
  98. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/python/goad_py/goad_py.pyi +0 -0
  99. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/python/goad_py/phips_convergence.py +0 -0
  100. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/release.sh +0 -0
  101. {goad_py-0.5.5 → goad_py-0.6.0}/goad-py/test_wheels.sh +0 -0
  102. {goad_py-0.5.5 → goad_py-0.6.0}/python/goad_py/__init__.py +0 -0
  103. {goad_py-0.5.5 → goad_py-0.6.0}/python/goad_py/convergence.py +0 -0
  104. {goad_py-0.5.5 → goad_py-0.6.0}/python/goad_py/goad_py.pyi +0 -0
  105. {goad_py-0.5.5 → goad_py-0.6.0}/python/goad_py/phips_convergence.py +0 -0
  106. {goad_py-0.5.5 → goad_py-0.6.0}/setup.sh +0 -0
  107. {goad_py-0.5.5 → goad_py-0.6.0}/src/_quickstart.rs +0 -0
  108. {goad_py-0.5.5 → goad_py-0.6.0}/src/beam.rs +0 -0
  109. {goad_py-0.5.5 → goad_py-0.6.0}/src/bins.rs +0 -0
  110. {goad_py-0.5.5 → goad_py-0.6.0}/src/clip.rs +0 -0
  111. {goad_py-0.5.5 → goad_py-0.6.0}/src/containment.rs +0 -0
  112. {goad_py-0.5.5 → goad_py-0.6.0}/src/diff.rs +0 -0
  113. {goad_py-0.5.5 → goad_py-0.6.0}/src/distortion.rs +0 -0
  114. {goad_py-0.5.5 → goad_py-0.6.0}/src/field.rs +0 -0
  115. {goad_py-0.5.5 → goad_py-0.6.0}/src/fresnel.rs +0 -0
  116. {goad_py-0.5.5 → goad_py-0.6.0}/src/geom.rs +0 -0
  117. {goad_py-0.5.5 → goad_py-0.6.0}/src/lib.rs +0 -0
  118. {goad_py-0.5.5 → goad_py-0.6.0}/src/main.rs +0 -0
  119. {goad_py-0.5.5 → goad_py-0.6.0}/src/multiproblem.rs +0 -0
  120. {goad_py-0.5.5 → goad_py-0.6.0}/src/orientation.rs +0 -0
  121. {goad_py-0.5.5 → goad_py-0.6.0}/src/output.rs +0 -0
  122. {goad_py-0.5.5 → goad_py-0.6.0}/src/params.rs +0 -0
  123. {goad_py-0.5.5 → goad_py-0.6.0}/src/powers.rs +0 -0
  124. {goad_py-0.5.5 → goad_py-0.6.0}/src/problem.rs +0 -0
  125. {goad_py-0.5.5 → goad_py-0.6.0}/src/result.rs +0 -0
  126. {goad_py-0.5.5 → goad_py-0.6.0}/src/settings/cli.rs +0 -0
  127. {goad_py-0.5.5 → goad_py-0.6.0}/src/settings/constants.rs +0 -0
  128. {goad_py-0.5.5 → goad_py-0.6.0}/src/settings/loading.rs +0 -0
  129. {goad_py-0.5.5 → goad_py-0.6.0}/src/settings/validation.rs +0 -0
  130. {goad_py-0.5.5 → goad_py-0.6.0}/src/snell.rs +0 -0
  131. {goad_py-0.5.5 → goad_py-0.6.0}/template/custom_bins.toml +0 -0
  132. {goad_py-0.5.5 → goad_py-0.6.0}/template/goad_pbs.sh +0 -0
  133. {goad_py-0.5.5 → goad_py-0.6.0}/tests/fixed_orientation_tests.rs +0 -0
  134. {goad_py-0.5.5 → goad_py-0.6.0}/tests/helpers.rs +0 -0
  135. {goad_py-0.5.5 → goad_py-0.6.0}/tests/test_data/fixed_hex_30_20_20_mueller_scatgrid +0 -0
  136. {goad_py-0.5.5 → goad_py-0.6.0}/tests/test_data/fixed_hex_30_30_30_mueller_scatgrid +0 -0
  137. {goad_py-0.5.5 → goad_py-0.6.0}/tests/test_data/hex.obj +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: goad-py
3
- Version: 0.5.5
3
+ Version: 0.6.0
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Science/Research
6
6
  Classifier: Topic :: Scientific/Engineering :: Physics
@@ -0,0 +1,163 @@
1
+ """
2
+ Example script demonstrating MultiProblem Python API without config file dependencies.
3
+
4
+ This script shows how to:
5
+ 1. Create binning schemes explicitly
6
+ 2. Create orientation schemes explicitly
7
+ 3. Use Settings with absolute geometry paths
8
+ 4. Use MultiProblem for multi-orientation averaging with no external dependencies
9
+ """
10
+
11
+ import goad_py as goad
12
+ import os
13
+ from pathlib import Path
14
+ import sys
15
+ import toml
16
+
17
+ PHIPS_BINS_FILE = "../../../phips_bins_edges.toml"
18
+
19
+ # Check that PHIPS bins file exists
20
+ phips_bins_path = Path(PHIPS_BINS_FILE)
21
+ if not phips_bins_path.exists():
22
+ print(f"\nError: PHIPS bins file not found at {phips_bins_path}")
23
+ print("Please run phips_detector_angles_edges.py first to generate the file.")
24
+ sys.exit(1)
25
+
26
+ with open(phips_bins_path, "r") as f:
27
+ bins_data = toml.load(f)
28
+
29
+ # Convert to format expected by BinningScheme.custom()
30
+ custom_bins = bins_data["bins"]
31
+ print(f"Loaded {len(custom_bins)} custom bins")
32
+
33
+ # Create binning scheme
34
+ binning = goad.BinningScheme.custom(custom_bins)
35
+
36
+ print("MultiProblem Example - Config-Free API")
37
+ print("=" * 50)
38
+
39
+ # Get absolute path to geometry file
40
+ current_dir = os.path.dirname(os.path.abspath(__file__))
41
+ geom_path = os.path.join(current_dir, "..", "..", "..", "examples", "data", "hex.obj")
42
+ geom_path = os.path.abspath(geom_path)
43
+
44
+ print(f"Using geometry file: {geom_path}")
45
+
46
+ # Example 1: Uniform orientation scheme with custom settings
47
+ print("\n1. Creating MultiProblem with uniform orientations...")
48
+
49
+ # # Create custom binning scheme
50
+ # binning = goad.BinningScheme.simple(181, 181) # 181x181 angular grid
51
+ # print("Created binning scheme: Simple 181x181")
52
+
53
+ # Create uniform orientation (100 random orientations)
54
+ uniform_orientation = goad.create_uniform_orientation(100)
55
+ print("Created uniform orientation: 100 random orientations")
56
+
57
+ # Create settings with all parameters explicit (no config file dependencies)
58
+ settings = goad.Settings(
59
+ geom_path=geom_path,
60
+ wavelength=0.532, # 532nm green laser
61
+ particle_refr_index_re=1.31, # glass refractive index
62
+ particle_refr_index_im=0.0, # no absorption
63
+ medium_refr_index_re=1.0, # air/vacuum
64
+ medium_refr_index_im=0.0,
65
+ orientation=uniform_orientation,
66
+ binning=binning,
67
+ beam_power_threshold=0.005,
68
+ cutoff=0.99,
69
+ max_rec=10,
70
+ max_tir=10,
71
+ )
72
+
73
+ # Create and solve MultiProblem
74
+ print("Creating MultiProblem with uniform orientations...")
75
+ multi_problem = goad.MultiProblem(settings)
76
+ print(f"Number of orientations: {multi_problem.num_orientations}")
77
+
78
+ print("Solving MultiProblem (this averages over all orientations)...")
79
+ multi_problem.py_solve()
80
+
81
+ # Access averaged results
82
+ results = multi_problem.results
83
+ print(
84
+ f"Averaged Mueller matrix shape: {len(results.mueller)}x{len(results.mueller[0])}"
85
+ )
86
+ print(f"Averaged asymmetry parameter: {results.asymmetry}")
87
+
88
+ # Example 2: Discrete orientation scheme with custom binning
89
+ print("\n2. Creating MultiProblem with discrete orientations...")
90
+
91
+ # Create custom binning scheme with higher resolution in forward direction
92
+ interval_binning = goad.BinningScheme.interval(
93
+ thetas=[0.0, 30.0, 180.0], # Split at 30 degrees
94
+ theta_spacings=[1.0, 5.0], # Fine resolution near forward, coarse elsewhere
95
+ phis=[0.0, 360.0], # Full phi range
96
+ phi_spacings=[5.0], # 5 degree phi spacing
97
+ )
98
+ print("Created interval binning scheme")
99
+
100
+ # Create specific Euler angles
101
+ euler1 = goad.Euler(0.0, 0.0, 0.0) # No rotation
102
+ euler2 = goad.Euler(30.0, 30.0, 30.0) # 30 degree rotations
103
+ euler3 = goad.Euler(45.0, 60.0, 90.0) # Mixed rotations
104
+
105
+ # Create discrete orientation scheme
106
+ discrete_orientation = goad.create_discrete_orientation([euler1, euler2, euler3])
107
+ print("Created discrete orientation: 3 specific orientations")
108
+
109
+ # Create settings with discrete orientation and custom binning
110
+ settings2 = goad.Settings(
111
+ geom_path=geom_path,
112
+ wavelength=0.633, # 633nm red laser
113
+ particle_refr_index_re=1.5, # different material
114
+ particle_refr_index_im=0.01, # slight absorption
115
+ orientation=discrete_orientation,
116
+ binning=interval_binning,
117
+ )
118
+
119
+ # Create and solve MultiProblem
120
+ print("Creating MultiProblem with discrete orientations...")
121
+ multi_problem2 = goad.MultiProblem(settings2)
122
+ print(f"Number of orientations: {multi_problem2.num_orientations}")
123
+
124
+ print("Solving MultiProblem with specific orientations...")
125
+ multi_problem2.py_solve()
126
+
127
+ # Access averaged results
128
+ results2 = multi_problem2.results
129
+ print(
130
+ f"Averaged Mueller matrix shape: {len(results2.mueller)}x{len(results2.mueller[0])}"
131
+ )
132
+ print(f"Averaged asymmetry parameter: {results2.asymmetry}")
133
+
134
+ # Example 3: Custom binning with specific angles
135
+ print("\n3. Creating MultiProblem with custom binning...")
136
+
137
+ # Create custom binning scheme with specific angle pairs
138
+ custom_bins = [
139
+ (0.0, 0.0), # Forward scattering
140
+ (10.0, 0.0), # Near-forward
141
+ (30.0, 0.0), # Small angle
142
+ (90.0, 0.0), # Side scattering
143
+ (150.0, 0.0), # Backscattering region
144
+ (180.0, 0.0), # Exact backscattering
145
+ ]
146
+ custom_binning = goad.BinningScheme.custom(custom_bins)
147
+ print(f"Created custom binning with {len(custom_bins)} specific angles")
148
+
149
+ # Simple settings with default values
150
+ settings3 = goad.Settings(
151
+ geom_path=geom_path,
152
+ binning=custom_binning,
153
+ # All other parameters use defaults
154
+ )
155
+
156
+ multi_problem3 = goad.MultiProblem(settings3)
157
+ print(f"Number of orientations: {multi_problem3.num_orientations}")
158
+
159
+ print("Solving MultiProblem with custom binning...")
160
+ multi_problem3.py_solve()
161
+
162
+ results3 = multi_problem3.results
163
+ print(f"Custom binned results: {len(results3.mueller)} angle pairs")
@@ -6,10 +6,7 @@ Demonstrates converging on PHIPS detector bins (all except the first one).
6
6
  PHIPS detectors measure scattering at 20 specific angles from 18° to 170°.
7
7
  """
8
8
 
9
- import sys
10
9
  from pathlib import Path
11
-
12
- sys.path.insert(0, "../../python")
13
10
  import goad_py as goad
14
11
 
15
12
  print("=" * 80)
@@ -0,0 +1,216 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Example 10: Advanced Parameters - Comprehensive Demonstration
4
+
5
+ Demonstrates ALL modifiable parameters in run_convergence():
6
+ - Optical parameters (wavelength, refractive indices)
7
+ - Convergence parameters (batch size, max orientations, min batches)
8
+ - Beam tracing parameters (thresholds, recursion limits, cutoff)
9
+ - Geometry transformations (problem scale, per-axis scaling, distortion)
10
+ - Advanced configuration (mapping, coherence, field of view)
11
+ - Reproducibility (random seed)
12
+
13
+ This example showcases the full flexibility of the unified convergence API.
14
+ """
15
+
16
+ from pathlib import Path
17
+ import goad_py as goad
18
+
19
+ print("=" * 80)
20
+ print("Example 10: Advanced Parameters - ALL Modifiable Parameters")
21
+ print("=" * 80)
22
+
23
+ # Get paths relative to this script's location
24
+ script_dir = Path(__file__).parent
25
+ geom_file = script_dir / "../../../examples/data/hex.obj"
26
+ phips_bins_file = script_dir / "../../../phips_bins_edges.toml"
27
+
28
+ # Resolve to absolute paths
29
+ geom_file = str(geom_file.resolve())
30
+ phips_bins_file = str(phips_bins_file.resolve())
31
+
32
+ # Configuration summary
33
+ print("\n" + "=" * 80)
34
+ print("Configuration Summary:")
35
+ print("=" * 80)
36
+ print("OPTICAL PARAMETERS:")
37
+ print(" Wavelength: 0.633 μm (HeNe laser)")
38
+ print(" Particle refractive index: 1.5 + 0.01i (absorbing particle)")
39
+ print(" Medium refractive index: 1.33 + 0.0i (water)")
40
+ print()
41
+ print("CONVERGENCE PARAMETERS:")
42
+ print(" Batch size: 12 orientations per batch")
43
+ print(" Max orientations: 500")
44
+ print(" Min batches: 3")
45
+ print()
46
+ print("BEAM TRACING PARAMETERS:")
47
+ print(" Beam power threshold: 0.01 (stricter than default 0.05)")
48
+ print(" Beam area threshold factor: 2.0 (half of default 4.0)")
49
+ print(" Cutoff: 0.0005 (stricter than default 0.001)")
50
+ print(" Max recursion depth: 6 (limited for demonstration)")
51
+ print(" Max TIR bounces: 50 (half of default 100)")
52
+ print()
53
+ print("GEOMETRY TRANSFORMATIONS:")
54
+ print(" Problem scale: 2.0 (scales entire problem by 2x)")
55
+ print(" Per-axis geometry scale: [1.0, 1.0, 1.5] (stretch z-axis by 1.5x)")
56
+ print(" Distortion: 0.1 (adds 10% geometric distortion)")
57
+ print()
58
+ print("ADVANCED CONFIGURATION:")
59
+ print(" Mapping: GeometricOptics (instead of default ApertureDiffraction)")
60
+ print(" Coherence: True (enable coherent scattering calculations)")
61
+ print(" Field of view factor: 2.0 (doubled FOV)")
62
+ print()
63
+ print("REPRODUCIBILITY:")
64
+ print(" Random seed: 42 (for reproducible results)")
65
+ print()
66
+ print("CONVERGENCE TARGET:")
67
+ print(" Mode: PHIPS detector convergence")
68
+ print(" Detectors: Indices 1-19 (26° to 170°, skipping 18° forward scatter)")
69
+ print(" Tolerance: 50% relative SEM (relaxed for demo)")
70
+ print("=" * 80 + "\n")
71
+
72
+ # Converge on all PHIPS detectors except the first one (indices 1-19)
73
+ detector_indices = list(range(1, 20)) # [1, 2, 3, ..., 19]
74
+
75
+ print(f"Starting convergence on {len(detector_indices)} PHIPS detectors...\n")
76
+
77
+ # Run PHIPS convergence with ALL MODIFIABLE PARAMETERS
78
+ results = goad.run_convergence(
79
+ # Required parameters
80
+ geometry=geom_file,
81
+ targets=[
82
+ {
83
+ "tolerance": 0.25, # 50% relative SEM (relaxed for demo)
84
+ "tolerance_type": "relative",
85
+ "detector_indices": detector_indices,
86
+ }
87
+ ],
88
+ mode=goad.PHIPSMode(bins_file=phips_bins_file),
89
+ # ========================================================================
90
+ # OPTICAL PARAMETERS
91
+ # ========================================================================
92
+ wavelength=0.633, # HeNe laser wavelength in microns
93
+ particle_refr_index_re=1.5, # Real part of particle refractive index
94
+ particle_refr_index_im=0.01, # Imaginary part (absorption)
95
+ medium_refr_index_re=1.33, # Real part of medium refractive index (water)
96
+ medium_refr_index_im=0.0, # Imaginary part (no absorption in medium)
97
+ # ========================================================================
98
+ # CONVERGENCE PARAMETERS
99
+ # ========================================================================
100
+ batch_size=12, # Orientations per batch (smaller batches for finer control)
101
+ max_orientations=500, # Maximum total orientations
102
+ min_batches=10, # Minimum batches before checking convergence
103
+ mueller_1d=False, # Mueller matrix output (N/A for PHIPS mode)
104
+ # ========================================================================
105
+ # BEAM TRACING PARAMETERS
106
+ # ========================================================================
107
+ beam_power_threshold=0.01, # Beam power threshold (stricter than default)
108
+ beam_area_threshold_fac=0.001, # Beam area threshold factor (tighter threshold)
109
+ cutoff=0.0005, # Ray power cutoff (more accurate but slower)
110
+ max_rec=6, # Maximum recursion depth (limited for demo)
111
+ max_tir=20, # Maximum total internal reflection bounces
112
+ # ========================================================================
113
+ # GEOMETRY TRANSFORMATIONS
114
+ # ========================================================================
115
+ scale=1.0, # Problem scaling factor (numerical changes only)
116
+ geom_scale=[3.0, 3.0, 6.0], # Per-axis geometry scaling
117
+ distortion=0.0, # Geometry distortion factor
118
+ # ========================================================================
119
+ # ADVANCED CONFIGURATION
120
+ # ========================================================================
121
+ mapping=goad.Mapping.ApertureDiffraction, # or GeometricOptics
122
+ coherence=True, # Enable coherent scattering calculations
123
+ fov_factor=2.0, # Field of view factor (doubled)
124
+ )
125
+
126
+ # Print summary
127
+ print(results.summary())
128
+
129
+ # Save results
130
+ results.save("10_advanced_parameters_results.json")
131
+
132
+ # Show detailed PHIPS output
133
+ print("\n" + "=" * 80)
134
+ print("PHIPS Detector DSCS Values (all 20 detectors)")
135
+ print("=" * 80)
136
+
137
+ import json
138
+
139
+ with open("10_advanced_parameters_results.json", "r") as f:
140
+ data = json.load(f)
141
+
142
+ phips_dscs = data.get("phips_dscs")
143
+ detector_angles = data.get("detector_angles")
144
+
145
+ if phips_dscs and detector_angles:
146
+ print(
147
+ f"\n{'Detector':<10} {'Angle':<10} {'DSCS Mean':<15} {'DSCS SEM':<15} {'Rel. SEM':<10}"
148
+ )
149
+ print("-" * 70)
150
+
151
+ for i, (dscs_data, angle) in enumerate(zip(phips_dscs, detector_angles)):
152
+ mean, sem = dscs_data[0], dscs_data[1]
153
+ rel_sem = (sem / abs(mean) * 100) if mean != 0 else float("inf")
154
+
155
+ # Mark which detectors were converged on
156
+ marker = "✓" if i in detector_indices else "○"
157
+
158
+ print(
159
+ f"{marker} {i:<8} {angle:<10.1f} {mean:<15.4e} {sem:<15.4e} {rel_sem:<10.2f}%"
160
+ )
161
+
162
+ print("\n" + "=" * 80)
163
+ print("Legend:")
164
+ print(" ✓ = Converged on this detector")
165
+ print(" ○ = Not a convergence target (but still computed)")
166
+ print("=" * 80)
167
+
168
+ # Show configuration that was used
169
+ print("\n" + "=" * 80)
170
+ print("Configuration Used (from saved results):")
171
+ print("=" * 80)
172
+
173
+ config = data.get("config", {})
174
+ if config:
175
+ print(f"\nOptical parameters:")
176
+ print(f" Wavelength: {config.get('wavelength')} μm")
177
+ print(
178
+ f" Particle refractive index: {config.get('particle_refr_index_re')} + {config.get('particle_refr_index_im')}i"
179
+ )
180
+ print(
181
+ f" Medium refractive index: {config.get('medium_refr_index_re')} + {config.get('medium_refr_index_im')}i"
182
+ )
183
+
184
+ beam_tracing = config.get("beam_tracing", {})
185
+ if beam_tracing:
186
+ print(f"\nBeam tracing parameters:")
187
+ print(f" Max recursion depth: {beam_tracing.get('max_rec')}")
188
+ print(f" Max TIR bounces: {beam_tracing.get('max_tir')}")
189
+ print(f" Cutoff: {beam_tracing.get('cutoff')}")
190
+ print(f" Beam power threshold: {beam_tracing.get('beam_power_threshold')}")
191
+ print(
192
+ f" Beam area threshold factor: {beam_tracing.get('beam_area_threshold_fac')}"
193
+ )
194
+
195
+ geom_transform = config.get("geometry_transform", {})
196
+ if geom_transform:
197
+ print(f"\nGeometry transformations:")
198
+ print(f" Problem scale: {geom_transform.get('scale')}")
199
+ if geom_transform.get("distortion"):
200
+ print(f" Distortion: {geom_transform.get('distortion')}")
201
+ if geom_transform.get("geom_scale"):
202
+ print(f" Per-axis geometry scale: {geom_transform.get('geom_scale')}")
203
+
204
+ advanced = config.get("advanced_config", {})
205
+ if advanced:
206
+ print(f"\nAdvanced configuration:")
207
+ print(f" Mapping: {advanced.get('mapping')}")
208
+ print(f" Coherence: {advanced.get('coherence')}")
209
+ if advanced.get("fov_factor"):
210
+ print(f" Field of view factor: {advanced.get('fov_factor')}")
211
+
212
+ if config.get("seed"):
213
+ print(f"\nReproducibility:")
214
+ print(f" Random seed: {config.get('seed')}")
215
+
216
+ print("\n✓ Example completed successfully!")