radphen-iadpython 0.7.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.
Files changed (98) hide show
  1. radphen_iadpython-0.7.0/CHANGELOG.rst +124 -0
  2. radphen_iadpython-0.7.0/CITATION.cff +13 -0
  3. radphen_iadpython-0.7.0/LICENSE.txt +18 -0
  4. radphen_iadpython-0.7.0/MANIFEST.in +15 -0
  5. radphen_iadpython-0.7.0/PKG-INFO +264 -0
  6. radphen_iadpython-0.7.0/PROVENANCE.md +90 -0
  7. radphen_iadpython-0.7.0/README.rst +207 -0
  8. radphen_iadpython-0.7.0/iadpython/__init__.py +59 -0
  9. radphen_iadpython-0.7.0/iadpython/ad.py +1377 -0
  10. radphen_iadpython-0.7.0/iadpython/agrid.py +306 -0
  11. radphen_iadpython-0.7.0/iadpython/cache.py +133 -0
  12. radphen_iadpython-0.7.0/iadpython/combine.py +620 -0
  13. radphen_iadpython-0.7.0/iadpython/constants.py +3 -0
  14. radphen_iadpython-0.7.0/iadpython/data/M38597.csv +759 -0
  15. radphen_iadpython-0.7.0/iadpython/double.py +376 -0
  16. radphen_iadpython-0.7.0/iadpython/fresnel.py +642 -0
  17. radphen_iadpython-0.7.0/iadpython/grid.py +125 -0
  18. radphen_iadpython-0.7.0/iadpython/iad.py +615 -0
  19. radphen_iadpython-0.7.0/iadpython/iadc.py +1003 -0
  20. radphen_iadpython-0.7.0/iadpython/iadcommand.py +712 -0
  21. radphen_iadpython-0.7.0/iadpython/layer.py +241 -0
  22. radphen_iadpython-0.7.0/iadpython/nist.py +114 -0
  23. radphen_iadpython-0.7.0/iadpython/port.py +242 -0
  24. radphen_iadpython-0.7.0/iadpython/quadrature.py +172 -0
  25. radphen_iadpython-0.7.0/iadpython/redistribution.py +318 -0
  26. radphen_iadpython-0.7.0/iadpython/rxt.py +201 -0
  27. radphen_iadpython-0.7.0/iadpython/sphere.py +582 -0
  28. radphen_iadpython-0.7.0/iadpython/start.py +377 -0
  29. radphen_iadpython-0.7.0/iadpython/txt.py +147 -0
  30. radphen_iadpython-0.7.0/pyproject.toml +140 -0
  31. radphen_iadpython-0.7.0/radphen_iadpython.egg-info/PKG-INFO +264 -0
  32. radphen_iadpython-0.7.0/radphen_iadpython.egg-info/SOURCES.txt +96 -0
  33. radphen_iadpython-0.7.0/radphen_iadpython.egg-info/dependency_links.txt +1 -0
  34. radphen_iadpython-0.7.0/radphen_iadpython.egg-info/entry_points.txt +2 -0
  35. radphen_iadpython-0.7.0/radphen_iadpython.egg-info/requires.txt +33 -0
  36. radphen_iadpython-0.7.0/radphen_iadpython.egg-info/top_level.txt +1 -0
  37. radphen_iadpython-0.7.0/setup.cfg +4 -0
  38. radphen_iadpython-0.7.0/tests/data/basic-A.rxt +37 -0
  39. radphen_iadpython-0.7.0/tests/data/basic-A.txt +49 -0
  40. radphen_iadpython-0.7.0/tests/data/basic-B.rxt +57 -0
  41. radphen_iadpython-0.7.0/tests/data/basic-B.txt +69 -0
  42. radphen_iadpython-0.7.0/tests/data/basic-C.rxt +56 -0
  43. radphen_iadpython-0.7.0/tests/data/basic-C.txt +68 -0
  44. radphen_iadpython-0.7.0/tests/data/basic-D.rxt +42 -0
  45. radphen_iadpython-0.7.0/tests/data/basic-D.txt +55 -0
  46. radphen_iadpython-0.7.0/tests/data/basic-E.rxt +56 -0
  47. radphen_iadpython-0.7.0/tests/data/basic-E.txt +68 -0
  48. radphen_iadpython-0.7.0/tests/data/sample-A.rxt +56 -0
  49. radphen_iadpython-0.7.0/tests/data/sample-A.txt +65 -0
  50. radphen_iadpython-0.7.0/tests/data/sample-B.rxt +56 -0
  51. radphen_iadpython-0.7.0/tests/data/sample-B.txt +65 -0
  52. radphen_iadpython-0.7.0/tests/data/sample-C.rxt +54 -0
  53. radphen_iadpython-0.7.0/tests/data/sample-C.txt +65 -0
  54. radphen_iadpython-0.7.0/tests/data/sample-D.rxt +35 -0
  55. radphen_iadpython-0.7.0/tests/data/sample-D.txt +47 -0
  56. radphen_iadpython-0.7.0/tests/data/sample-E.rxt +31 -0
  57. radphen_iadpython-0.7.0/tests/data/sample-E.txt +47 -0
  58. radphen_iadpython-0.7.0/tests/data/sample-F.rxt +49 -0
  59. radphen_iadpython-0.7.0/tests/data/sample-F.txt +65 -0
  60. radphen_iadpython-0.7.0/tests/data/sample-G.rxt +35 -0
  61. radphen_iadpython-0.7.0/tests/data/sample-G.txt +47 -0
  62. radphen_iadpython-0.7.0/tests/test_agrid.py +45 -0
  63. radphen_iadpython-0.7.0/tests/test_all_notebooks.py +60 -0
  64. radphen_iadpython-0.7.0/tests/test_boundary.py +88 -0
  65. radphen_iadpython-0.7.0/tests/test_combo.py +513 -0
  66. radphen_iadpython-0.7.0/tests/test_double.py +267 -0
  67. radphen_iadpython-0.7.0/tests/test_fresnel.py +541 -0
  68. radphen_iadpython-0.7.0/tests/test_grid.py +148 -0
  69. radphen_iadpython-0.7.0/tests/test_iad.py +539 -0
  70. radphen_iadpython-0.7.0/tests/test_iadcommand.py +464 -0
  71. radphen_iadpython-0.7.0/tests/test_interface_matched.py +62 -0
  72. radphen_iadpython-0.7.0/tests/test_inverse_boundaries.py +57 -0
  73. radphen_iadpython-0.7.0/tests/test_layer.py +170 -0
  74. radphen_iadpython-0.7.0/tests/test_layer_api.py +362 -0
  75. radphen_iadpython-0.7.0/tests/test_layers.py +165 -0
  76. radphen_iadpython-0.7.0/tests/test_mismatched_layers.py +205 -0
  77. radphen_iadpython-0.7.0/tests/test_nist.py +106 -0
  78. radphen_iadpython-0.7.0/tests/test_one_sphere.py +430 -0
  79. radphen_iadpython-0.7.0/tests/test_outer_media.py +104 -0
  80. radphen_iadpython-0.7.0/tests/test_port.py +68 -0
  81. radphen_iadpython-0.7.0/tests/test_python310_random.py +28 -0
  82. radphen_iadpython-0.7.0/tests/test_quadrature.py +192 -0
  83. radphen_iadpython-0.7.0/tests/test_redistribution.py +141 -0
  84. radphen_iadpython-0.7.0/tests/test_roundtrip_0_spheres.py +168 -0
  85. radphen_iadpython-0.7.0/tests/test_roundtrip_1_sphere.py +173 -0
  86. radphen_iadpython-0.7.0/tests/test_roundtrip_2_spheres.py +101 -0
  87. radphen_iadpython-0.7.0/tests/test_rxt.py +76 -0
  88. radphen_iadpython-0.7.0/tests/test_specular_incidence.py +89 -0
  89. radphen_iadpython-0.7.0/tests/test_sphere.py +125 -0
  90. radphen_iadpython-0.7.0/tests/test_start.py +205 -0
  91. radphen_iadpython-0.7.0/tests/test_txt.py +116 -0
  92. radphen_iadpython-0.7.0/tests/test_ur1_uru.py +80 -0
  93. radphen_iadpython-0.7.0/tools/PUBLISHING.md +56 -0
  94. radphen_iadpython-0.7.0/tools/README.md +37 -0
  95. radphen_iadpython-0.7.0/tools/VALIDATION.md +58 -0
  96. radphen_iadpython-0.7.0/tools/compare_backend.py +217 -0
  97. radphen_iadpython-0.7.0/tools/original.json +830 -0
  98. radphen_iadpython-0.7.0/tools/renamed.json +830 -0
@@ -0,0 +1,124 @@
1
+ Changelog for `iadpython` package
2
+ =================================
3
+
4
+ 0.8.0 (unreleased, fork)
5
+ ------------------------
6
+ * add ``Layer`` class and ``Sample(layers=[...])`` API for explicit multilayer
7
+ structure; each layer carries its own a, b, g, n, d, and phase function
8
+ * support refractive-index mismatched layers exactly (Snell-invariant master
9
+ grid with per-channel total internal reflection at internal interfaces)
10
+ * support per-layer phase functions, mixing Henyey-Greenstein and TABULATED
11
+ layers freely within one stack
12
+ * support wavelength-dependent layer properties (arrays inside Layer
13
+ attributes; one ``pf_data`` column per wavelength); scalar layers broadcast
14
+ across the sweep
15
+ * exact analytic unscattered (ballistic) reflection/transmission for
16
+ multilayer stacks, including mismatched indices and absorbing slides
17
+ * BREAKING: flat arrays on ``a``/``b``/``g`` now always mean wavelengths;
18
+ the old form where arrays passed to ``rt_matrices()`` meant layers was
19
+ removed (use ``Sample(layers=...)``); array-valued ``n`` on a flat sample
20
+ now raises
21
+ * make ``mu_a()``/``mu_s()``/``mu_sp()`` and zero-thickness collapse handling
22
+ array-safe
23
+
24
+ 0.7.0
25
+ -----
26
+ * align build, packaging, CI, and docs infrastructure with miepython patterns
27
+ * move JupyterLite configuration into package-managed location
28
+ * integrate adaptive AGrid warm starts for inverse-search acceleration
29
+ * align `iadcommand` behavior more closely with legacy `iad` CLI
30
+ * improve wavelength handling to match legacy `iad` behavior
31
+ * add and expand round-trip coverage (including one-sphere workflows)
32
+ * increase minimum supported Python version to 3.10
33
+ * improve linting quality and add/expand pylint checks
34
+ * port two-sphere integrating-sphere gain and normalization equations from CWEB/C into `DoubleSphere`
35
+ * wire two-sphere forward measurement path into `Experiment.measured_rt()` for `num_spheres == 2`
36
+ * fix `DoubleSphere.do_one_photon()` return contract to return two values by default
37
+ * expand two-sphere tests to cover CWEB-equation parity, normalization anchors, and experiment wiring
38
+
39
+ 0.6.0
40
+ ------
41
+ * fully support single integrating spheres
42
+ * add command-line support
43
+ * add Monte Carlo sphere simulations
44
+ * add Port class for Sphere class
45
+ * change entrance port to empty port
46
+ * improve sphere-single.ipynb
47
+ * add sphere-random.ipynb
48
+ * improve single sphere testing
49
+ * add port testing
50
+ * add notebook on measurements
51
+ * rearrange documentation
52
+
53
+
54
+ 0.5.3
55
+ ------
56
+ * add github actions
57
+ * add citation with zenodo DOI
58
+ * add copyright to docs
59
+ * add conda support
60
+ * improve badges
61
+ * add github auto testing
62
+ * lint files
63
+ * start fixing math in docstrings
64
+ * remove tox
65
+
66
+ v0.5.2
67
+ ------
68
+ * fix search, one-sphere round-trips now
69
+ * fix packaging
70
+ * fix html generation
71
+ * linting
72
+
73
+ v0.5.1
74
+ ------
75
+ * inverse calculation works for 0 spheres
76
+ * much more testing
77
+ * basic multiple layers support
78
+ * single location for version number
79
+ * revert to sphinx_rtd_theme
80
+
81
+ v0.4.0
82
+ ------
83
+ * forward adding-doubling calculation is pure python now
84
+ * create pure python packages
85
+ * include wheel file
86
+ * package as python3 only
87
+ * use sphinx_book_theme for docs
88
+
89
+ v0.3.0
90
+ ------
91
+ * improve packaging
92
+ * improve documentation with Sphinx
93
+ * use tox
94
+ * add better diagnostics for finding libiad library
95
+
96
+ v0.2.5
97
+ ------
98
+ * add doc files to distribution
99
+ * promise only python 3 and non-zip
100
+ * improve long description
101
+
102
+ v0.2.4
103
+ * fix bugs found by C Regan
104
+ * (unreleased??)
105
+
106
+ v0.2.3
107
+ ------
108
+ * fix __init__.py so "import iadpython" works
109
+
110
+ v0.2.2
111
+ ------
112
+ * necessary because setup.py version did not get updated
113
+
114
+ v0.2.1
115
+ ------
116
+ * remove ctypes as a requirement
117
+
118
+ v0.2.0
119
+ ------
120
+ * initial checkin
121
+ * Convert to markdown format
122
+ * update to correct contents
123
+ * add ctypes as dependancy, fix test path
124
+ * update my notes on how to cut a release
@@ -0,0 +1,13 @@
1
+ authors:
2
+ - family-names: Prahl
3
+ given-names: Scott
4
+ orcid: https://orcid.org/0000-0003-1468-6851
5
+ cff-version: 1.2.0
6
+ date-released: '2023-09-19'
7
+ doi: 10.5281/zenodo.8361415
8
+ message: If you use this software, please cite it as below.
9
+ title: 'iadpython: a python module implementation of adding-doubling.'
10
+ url: https://zenodo.org/badge/latestdoi/102148844
11
+ version: 0.5.3
12
+
13
+
@@ -0,0 +1,18 @@
1
+ Copyright 2017-2021 Scott Prahl
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,15 @@
1
+ # Core package files
2
+ include LICENSE.txt
3
+ include README.rst
4
+ include CHANGELOG.rst
5
+ include CITATION.cff
6
+
7
+ # Package data needed at runtime
8
+ include iadpython/data/*.csv
9
+
10
+ # Test suite + fixtures for reproducible sdist testing
11
+ recursive-include tests *.py
12
+ recursive-include tests/data *.rxt *.txt
13
+
14
+ include PROVENANCE.md
15
+ recursive-include tools *.py *.md *.json
@@ -0,0 +1,264 @@
1
+ Metadata-Version: 2.4
2
+ Name: radphen-iadpython
3
+ Version: 0.7.0
4
+ Summary: Forward and inverse radiative transport using adding-doubling
5
+ Author-email: Scott Prahl <scott.prahl@oit.edu>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/PanxoPanza/iadpython
8
+ Project-URL: Documentation, https://iadpython.readthedocs.io
9
+ Project-URL: Source, https://github.com/PanxoPanza/iadpython
10
+ Project-URL: Tracker, https://github.com/PanxoPanza/iadpython/issues
11
+ Project-URL: Changelog, https://github.com/PanxoPanza/iadpython/blob/main/docs/CHANGELOG.rst
12
+ Keywords: absorption,scattering,reflection,transmission,optical properties,radiative transport,scattering coefficient,scattering anisotropy
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Topic :: Scientific/Engineering
16
+ Classifier: Programming Language :: Python
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Requires-Python: <3.15,>=3.10
24
+ Description-Content-Type: text/x-rst
25
+ License-File: LICENSE.txt
26
+ Requires-Dist: scipy>=1.10
27
+ Requires-Dist: numpy>=1.24
28
+ Requires-Dist: pandas>=1.5
29
+ Requires-Dist: matplotlib
30
+ Provides-Extra: docs
31
+ Requires-Dist: Sphinx==8.1.3; extra == "docs"
32
+ Requires-Dist: nbsphinx==0.9.7; extra == "docs"
33
+ Requires-Dist: sphinx_automodapi; extra == "docs"
34
+ Requires-Dist: sphinx_rtd_theme; extra == "docs"
35
+ Provides-Extra: dev
36
+ Requires-Dist: pytest; extra == "dev"
37
+ Requires-Dist: imageio; extra == "dev"
38
+ Requires-Dist: requests; extra == "dev"
39
+ Requires-Dist: ruff; extra == "dev"
40
+ Requires-Dist: yamllint; extra == "dev"
41
+ Requires-Dist: rstcheck; extra == "dev"
42
+ Requires-Dist: pylint; extra == "dev"
43
+ Requires-Dist: pyroma; extra == "dev"
44
+ Requires-Dist: black[jupyter]; extra == "dev"
45
+ Requires-Dist: build; extra == "dev"
46
+ Requires-Dist: check-manifest; extra == "dev"
47
+ Requires-Dist: libarchive-c; extra == "dev"
48
+ Requires-Dist: pyyaml; extra == "dev"
49
+ Requires-Dist: setuptools; extra == "dev"
50
+ Requires-Dist: jupyterlab; extra == "dev"
51
+ Requires-Dist: nbconvert; extra == "dev"
52
+ Requires-Dist: nbformat; extra == "dev"
53
+ Provides-Extra: lite
54
+ Requires-Dist: jupyterlite-core==0.6.4; extra == "lite"
55
+ Requires-Dist: jupyterlite-pyodide-kernel==0.6.1; extra == "lite"
56
+ Dynamic: license-file
57
+
58
+ radphen-iadpython
59
+ =================
60
+
61
+ This is the MIT-licensed RadPhen fork of Scott Prahl's iadpython, maintained
62
+ at https://github.com/PanxoPanza/iadpython for empylib. Distribution version
63
+ 0.7.0 retains the original ``iadpython`` import namespace and ``iadp``
64
+ command. The distribution name alone is ``radphen-iadpython``.
65
+
66
+ Install with ``python -m pip install radphen-iadpython``. For example::
67
+
68
+ import iadpython as iad
69
+ sample = iad.Sample(a=0.9, b=1.0, g=0.5)
70
+ print(sample.rt())
71
+
72
+ The fork preserves HG, TABULATED and MOMENTS phase functions, complex sample
73
+ and exterior boundary indices, and diffuse-cone transport from the audited
74
+ source. See PROVENANCE.md for the exact source and release procedure.
75
+ Both distributions provide ``iadpython`` and ``iadp``; install this fork in a
76
+ fresh environment without the upstream ``iadpython`` distribution. They cannot
77
+ coexist safely in one environment because their package paths overlap.
78
+
79
+ Original upstream README (historical attribution)
80
+ =================================================
81
+
82
+ .. |pypi| image:: https://img.shields.io/pypi/v/iadpython?color=68CA66
83
+ :target: https://pypi.org/project/iadpython/
84
+ :alt: pypi
85
+
86
+ .. |github| image:: https://img.shields.io/github/v/tag/scottprahl/iadpython?label=github&color=68CA66
87
+ :target: https://github.com/scottprahl/iadpython
88
+ :alt: github
89
+
90
+ .. |conda| image:: https://img.shields.io/conda/vn/conda-forge/iadpython?label=conda&color=68CA66
91
+ :target: https://github.com/conda-forge/iadpython-feedstock
92
+ :alt: conda
93
+
94
+ .. |doi| image:: https://zenodo.org/badge/102148844.svg
95
+ :target: https://zenodo.org/badge/latestdoi/102148844
96
+ :alt: doi
97
+
98
+ .. |license| image:: https://img.shields.io/github/license/scottprahl/iadpython?color=68CA66
99
+ :target: https://github.com/scottprahl/iadpython/blob/main/LICENSE.txt
100
+ :alt: License
101
+
102
+ .. |test| image:: https://github.com/scottprahl/iadpython/actions/workflows/test.yaml/badge.svg
103
+ :target: https://github.com/scottprahl/iadpython/actions/workflows/test.yaml
104
+ :alt: Testing
105
+
106
+ .. |docs| image:: https://readthedocs.org/projects/iadpython/badge
107
+ :target: https://iadpython.readthedocs.io
108
+ :alt: Docs
109
+
110
+ .. |downloads| image:: https://img.shields.io/pypi/dm/iadpython?color=68CA66
111
+ :target: https://pypi.org/project/iadpython/
112
+ :alt: Downloads
113
+
114
+ iadpython
115
+ =========
116
+
117
+ by Scott Prahl
118
+
119
+ |pypi| |github| |conda| |doi|
120
+
121
+ |license| |test| |docs| |downloads|
122
+
123
+ `iadpython` will be a pure Python module to do forward and inverse multiple light
124
+ scattering (radiative transport) in layered materials. Calculations are done using
125
+ van de Hulst's adding-doubling technique.
126
+
127
+ The original adding-doubling algorithm was developed by van de Hulst to model light
128
+ propagation through layered media. I extended it to handle Fresnel
129
+ reflection at boundaries as well as interactions with integrating spheres.
130
+
131
+ Finally, the code was further extended to handle lost light using
132
+ Monte Carlo techniques for inverse calculations.
133
+
134
+ Version v0.4.0 started the migration to a pure-python implementation. This
135
+ version includes the ability to do forward calculations of light transport through
136
+ layered 1D structures.
137
+
138
+ The long-term goal is rewrite the integrating sphere, inverse algorithm, and
139
+ lost light calculations in pure python so that one can do
140
+ inverse calculations (i.e., reflection and transmission measurements to
141
+ intrinsic absorption and scattering properties).
142
+
143
+ Both inverse and forward calculations are currently possible using the `iadc` framework.
144
+ This is a python interface to the inverse
145
+ adding-doubling package written in C by Scott Prahl
146
+ <https://github.com/scottprahl/iad>. This works now
147
+ but is a nuisance to install and maintain because of its dependence on compiling
148
+ and installing a C library.
149
+
150
+ See <https://iadpython.readthedocs.io> for full documentation of `iadpython`.
151
+
152
+ Differences from upstream iadpython (this fork)
153
+ -----------------------------------------------
154
+
155
+ This fork adds first-class multilayer support and **changes how arrays are
156
+ interpreted** relative to upstream. If you are migrating code, read this
157
+ section.
158
+
159
+ **Layer API.** A multilayer sample is built from explicit ``Layer`` objects;
160
+ each layer may have its own refractive index (large index mismatches between
161
+ layers are handled exactly, including total internal reflection), its own
162
+ Henyey-Greenstein anisotropy *or* tabulated phase function, and its own
163
+ wavelength dependence::
164
+
165
+ import numpy as np
166
+ import iadpython as iad
167
+
168
+ l0 = iad.Layer(a=0.95, b=0.84, g=0.20, n=1.35, d=0.10)
169
+ l1 = iad.Layer(a=0.81, b=0.31, g=0.85, n=2.00, d=0.05)
170
+ l2 = iad.Layer(a=0.90, b=1.00, n=1.45, pf_type='TABULATED', pf_data=df)
171
+
172
+ s = iad.Sample(layers=[l0, l1, l2], n_above=1.5, quad_pts=16)
173
+ ur1, ut1, uru, utu = s.rt()
174
+
175
+ **Axis rule.** The two axes of a simulation are now structurally distinct
176
+ and cannot be confused:
177
+
178
+ * *layer axis* = position in the ``layers`` list;
179
+ * *wavelength axis* = arrays **inside** each attribute (``a``/``b``/``g``/``n``
180
+ of a ``Layer`` may each be a scalar or a wavelength array; a ``TABULATED``
181
+ phase function holds one ``pf_data`` column per wavelength). Scalar-valued
182
+ layers are automatically held constant across the sweep.
183
+
184
+ **Breaking change.** Upstream allowed ``sample.a = np.array([...])`` followed
185
+ by ``rt_matrices()`` to mean *layers* while the same array passed to ``rt()``
186
+ meant *wavelengths*. That ambiguity is removed: flat arrays on ``a``/``b``/``g``
187
+ now **always mean wavelengths**, and array-valued ``n`` on a flat sample is an
188
+ error. Code using the old flat-arrays-as-layers form fails with::
189
+
190
+ RuntimeError: array-valued a/b/g now mean wavelengths, not layers; build a
191
+ multilayer sample with iadpython.Sample(layers=[iadpython.Layer(...), ...])
192
+
193
+ Classic single-layer usage (scalars, or wavelength arrays with ``rt()``) is
194
+ unchanged, as are all inverse-calculation entry points.
195
+
196
+ Usage
197
+ -----
198
+
199
+ The following will do a forward calculation::
200
+
201
+ import iadpython as iad
202
+
203
+ mu_s = 10 # scattering coefficient [1/mm]
204
+ mu_a = 0.1 # absorption coefficient [1/mm]
205
+ g = 0.9 # scattering anisotropy
206
+ d = 1 # thickness mm
207
+
208
+ a = mu_s/(mu_a+mu_s)
209
+ b = (mu_a+mu_s) * d
210
+
211
+ # air / glass / sample / glass / air
212
+ s = iadpython.Sample(a=a, b=b, g=g, n=1.4, n_above=1.5, n_below=1.5)
213
+ ur1, ut1, uru, utu = s.rt()
214
+
215
+ print('Collimated light incident perpendicular to sample')
216
+ print(' total reflection = %.5f' % ur1)
217
+ print(' total transmission = %.5f' % ut1)
218
+
219
+ print('Diffuse light incident on sample')
220
+ print(' total reflection = %.5f' % uru)
221
+ print(' total transmission = %.5f' % utu)
222
+
223
+ `Sample` also accepts tabulated phase-function data via the ``pf_data``
224
+ keyword. When ``pf_type`` is ``'TABULATED'``, ``pf_data`` may hold one column per
225
+ wavelength and must have the same length as other wavelength-dependent inputs.
226
+
227
+
228
+ Installation
229
+ ------------
230
+
231
+ Use ``pip``::
232
+
233
+ pip install iadpython
234
+
235
+ or ``conda``::
236
+
237
+ conda install -c conda-forge iadpython
238
+
239
+ or use immediately by clicking the Google Colaboratory button below
240
+
241
+ .. image:: https://colab.research.google.com/assets/colab-badge.svg
242
+ :target: https://colab.research.google.com/github/scottprahl/iadpython/blob/main
243
+ :alt: Colab
244
+
245
+ Inverse Calculations
246
+ ---------------------
247
+
248
+ As of version 0.5.3, the forward and inverse calculations work fine as long as you do not need to
249
+ include integrating sphere effects or lost-light calculations.
250
+
251
+ If you want to do these, then you're probably best served by downloading and compiling
252
+ the C-code (on unix or macos) or the `.exe` file for Windows. <https://omlc.org/software/iad/>
253
+
254
+
255
+ Dependencies
256
+ ------------
257
+
258
+ Required Python modules: numpy, matplotlib, ctypes, scipy
259
+
260
+
261
+ License
262
+ -------
263
+
264
+ `iadpython` is licensed under the terms of the MIT license.
@@ -0,0 +1,90 @@
1
+ # RadPhen adding-doubling backend
2
+
3
+ Distribution: **radphen-iadpython 0.7.0**. Import: `iadpython`.
4
+ CLI: `iadp`. This is a maintained fork, not the upstream distribution.
5
+
6
+ Exact audited source: https://github.com/PanxoPanza/iadpython/tree/687a1b803594075d7f4f8feba9e1f7468827e7f9
7
+ (commit `687a1b803594075d7f4f8feba9e1f7468827e7f9`). That fork derives from
8
+ Scott Prahl's https://github.com/scottprahl/iadpython .
9
+ The original MIT copyright and license remain verbatim in LICENSE.txt and
10
+ are included in wheels and source distributions. Package author and numerical
11
+ code attribution remain Scott Prahl; RadPhen maintains this distribution.
12
+
13
+ This release changes distribution metadata and release tooling and includes
14
+ three narrowly reviewed source corrections, each audited explicitly against
15
+ the source commit by tools/compare_backend.py:
16
+
17
+ - `interface_rt` returns analytic R=0, T=1 for identical finite positive-real-part
18
+ scalar media, including exact grazing incidence.
19
+ - `Sphere.uniform` passes explicit `(0.0, 1.0)` to three `random.gauss` calls,
20
+ retaining the standard-normal sampling while supporting Python 3.10.
21
+ - Three two-parameter inverse searches retain their Nelder-Mead objectives,
22
+ then recompute the selected point's L1 residual. Only when it exceeds the
23
+ existing tolerance does a bounded least-squares residual-vector fit run.
24
+ A candidate is accepted only for finite parameters and a finite, strictly
25
+ smaller L1 residual. Selected parameters are explicitly restored after trials.
26
+ This escapes flat L1 plateaus near conservative albedo; scalar searches,
27
+ initialization, measurement physics and acceptance tolerance are unchanged.
28
+
29
+ The remaining 18 executable module ASTs match the source commit. Function
30
+ docstrings clarify the external incident-cosine convention. HG, TABULATED,
31
+ MOMENTS and complex-boundary forward fixtures remain unchanged.
32
+ See tools/README.md for reproducible source and fixture checks.
33
+
34
+ The original import and CLI are retained. Do not install upstream `iadpython`
35
+ and `radphen-iadpython` together: both own the same `iadpython` package and
36
+ `iadp` command. Use separate clean environments for baseline comparisons.
37
+
38
+ ## Release procedure
39
+
40
+ 1. Recheck the proposed name radphen-iadpython on PyPI immediately before
41
+ publishing; the repository does not reserve it.
42
+ 2. Configure a PyPI Trusted Publisher for the actual GitHub owner/repository,
43
+ workflow pypi.yaml, environment pypi. Protect the environment with owner
44
+ approval. No API token is stored in this repository.
45
+ 3. Review the source diff and validation, push the fork, and create reviewed
46
+ tag v0.7.0. Only owner-initiated manual dispatch on that tag can publish.
47
+ If transferring to an organization, replace the actor ownership condition
48
+ with the explicitly authorized release owner.
49
+ 4. Dispatch the publish workflow. It builds and checks both artifacts before
50
+ the protected job requests a short-lived PyPI OIDC credential.
51
+ 5. Verify installed wheel and iadp --version from PyPI before
52
+ releasing empylib 0.2.0.
53
+
54
+ Local build/test commands do not publish packages.
55
+
56
+ ## Resolution of the seven initial baseline failures
57
+
58
+ The initial audited baseline had seven failing tests. Review separated one
59
+ physical edge-case defect from stale test calls and inputs:
60
+
61
+ - Three matched-interface Fresnel/glass failures shared the identical-media
62
+ precision/grazing defect. The new exact matched-media guard fixes that limit.
63
+ Nearby unequal indices retain the original Fresnel path.
64
+ - Two specular tests converted the incident cosine into the slab, then passed
65
+ it to an API that takes the cosine in the illuminated external medium.
66
+ Their inputs now use the original external cosine; expectations are retained.
67
+ The production specular algorithm is unchanged and its docstrings clarified.
68
+ - Two redistribution tests called the removed `hg_legendre` name. They now
69
+ call the existing `phase_legendre` API with the same expected matrices.
70
+
71
+ The reviewed Fresnel/redistribution and new interface/incidence regression
72
+ selection passes 71 tests. No test exclusions or xfails were added. Numerical
73
+ fixtures remain exactly equal for all six cases and 816 recorded values.
74
+ The full inherited suite is a separate required CI gate; the earlier bounded,
75
+ incomplete run is not a passing result. Publication requires that gate to pass.
76
+
77
+ ## Additional findings from the first full GitHub CI
78
+
79
+ Full CI for initial packaging commit 78d24 found five failing tests on Python
80
+ 3.10 (four sphere tests reached zero-argument random.gauss and one inverse
81
+ roundtrip stalled), and one inverse-roundtrip failure on Python 3.14. These
82
+ were additional inherited issues beyond the initial seven targeted failures.
83
+ They motivated the explicit Gaussian-default compatibility correction and
84
+ bounded inverse-fit refinement above, rather than relaxed tolerances or skips.
85
+ The sphere selection passes 13 tests on both Python 3.10 and 3.14. Five new
86
+ inverse boundary/control regressions pass, checking real measured transport at
87
+ g=-0.9, 0 and 0.9, rejection/restoration of a worse candidate, and no fallback
88
+ for an already adequate fit. The unchanged full zero-sphere inverse-roundtrip file also passes all six tests.
89
+ Full CI after these corrections remains required;
90
+ the first failing CI is not evidence of a complete passing release.