pyshs-optics 4.0.2__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.
- pyshs_optics-4.0.2/LICENSE +21 -0
- pyshs_optics-4.0.2/PKG-INFO +457 -0
- pyshs_optics-4.0.2/README.md +433 -0
- pyshs_optics-4.0.2/pyproject.toml +44 -0
- pyshs_optics-4.0.2/setup.cfg +4 -0
- pyshs_optics-4.0.2/src/py_shs/HRS.py +521 -0
- pyshs_optics-4.0.2/src/py_shs/SHS.py +666 -0
- pyshs_optics-4.0.2/src/py_shs/__init__.py +7 -0
- pyshs_optics-4.0.2/src/py_shs/__main__.py +5 -0
- pyshs_optics-4.0.2/src/py_shs/cli.py +50 -0
- pyshs_optics-4.0.2/src/py_shs/cube_SHS.py +658 -0
- pyshs_optics-4.0.2/src/py_shs/cylinder_SHS.py +571 -0
- pyshs_optics-4.0.2/src/py_shs/ellipsoid_SHS.py +612 -0
- pyshs_optics-4.0.2/src/py_shs/graph_angle.py +60 -0
- pyshs_optics-4.0.2/src/py_shs/graph_assembly.py +74 -0
- pyshs_optics-4.0.2/src/py_shs/pyshs_gui.py +1911 -0
- pyshs_optics-4.0.2/src/py_shs/script_cylinder_random.py +60 -0
- pyshs_optics-4.0.2/src/py_shs/script_gauss2PySHS.py +108 -0
- pyshs_optics-4.0.2/src/py_shs/script_sphere.py +61 -0
- pyshs_optics-4.0.2/src/py_shs/script_sphere_random.py +67 -0
- pyshs_optics-4.0.2/src/py_shs/script_spheroid_random.py +80 -0
- pyshs_optics-4.0.2/src/py_shs/shs_angles.py +41 -0
- pyshs_optics-4.0.2/src/py_shs/shs_grid.py +167 -0
- pyshs_optics-4.0.2/src/py_shs/shs_io.py +20 -0
- pyshs_optics-4.0.2/src/py_shs/shs_mie.py +714 -0
- pyshs_optics-4.0.2/src/py_shs/shs_units.py +76 -0
- pyshs_optics-4.0.2/src/py_shs/sphere_SHS.py +579 -0
- pyshs_optics-4.0.2/src/pyshs_optics.egg-info/PKG-INFO +457 -0
- pyshs_optics-4.0.2/src/pyshs_optics.egg-info/SOURCES.txt +39 -0
- pyshs_optics-4.0.2/src/pyshs_optics.egg-info/dependency_links.txt +1 -0
- pyshs_optics-4.0.2/src/pyshs_optics.egg-info/entry_points.txt +9 -0
- pyshs_optics-4.0.2/src/pyshs_optics.egg-info/requires.txt +3 -0
- pyshs_optics-4.0.2/src/pyshs_optics.egg-info/top_level.txt +1 -0
- pyshs_optics-4.0.2/tests/test_core.py +210 -0
- pyshs_optics-4.0.2/tests/test_golden.py +32 -0
- pyshs_optics-4.0.2/tests/test_grids.py +120 -0
- pyshs_optics-4.0.2/tests/test_housekeeping.py +206 -0
- pyshs_optics-4.0.2/tests/test_models.py +150 -0
- pyshs_optics-4.0.2/tests/test_smoke.py +19 -0
- pyshs_optics-4.0.2/tests/test_tools.py +28 -0
- pyshs_optics-4.0.2/tests/test_units_angles.py +123 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020-2026 Pierre-Marie Gassin, Gaelle Gassin
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyshs-optics
|
|
3
|
+
Version: 4.0.2
|
|
4
|
+
Summary: Second Harmonic Scattering (SHS) and Hyper-Rayleigh Scattering (HRS) calculations - pure Python / NumPy
|
|
5
|
+
Author-email: Pierre-Marie Gassin <pierre-marie.gassin@enscm.fr>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/pmgassin/Py_SHS
|
|
8
|
+
Project-URL: Repository, https://github.com/pmgassin/Py_SHS
|
|
9
|
+
Project-URL: Issues, https://github.com/pmgassin/Py_SHS/issues
|
|
10
|
+
Keywords: second harmonic scattering,SHS,HRS,hyper-Rayleigh,nonlinear optics,hyperpolarizability
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Requires-Python: >=3.8
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: numpy
|
|
21
|
+
Requires-Dist: scipy
|
|
22
|
+
Requires-Dist: matplotlib
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# Py_SHS – A Python Second Harmonic Scattering package.
|
|
26
|
+
|
|
27
|
+
[](https://pypi.org/project/pyshs-optics/)
|
|
28
|
+
[](https://pypi.org/project/pyshs-optics/)
|
|
29
|
+
[](https://github.com/pmgassin/Py_SHS/blob/Py_SHS_V4/LICENSE)
|
|
30
|
+
[-orange.svg)](https://github.com/pmgassin/Py_SHS/blob/Py_SHS_V4/Documentation/PySHS_User_Manual.pdf)
|
|
31
|
+
|
|
32
|
+
**Py_SHS** is a collection of programs that compute the **second-harmonic intensity** scattered by
|
|
33
|
+
a molecule, or by a colloidal / supramolecular structure (sphere, cylinder, ellipsoid, box,
|
|
34
|
+
assembly of oriented dipoles). It covers incoherent Hyper-Rayleigh Scattering (HRS) as well as
|
|
35
|
+
coherent Second Harmonic Scattering (SHS), and comes with a graphical interface.
|
|
36
|
+
|
|
37
|
+
Written in Python on top of NumPy: **no C compiler is needed**, and it installs with a single
|
|
38
|
+
`pip` command.
|
|
39
|
+
|
|
40
|
+
> 📖 **User guide:** [PySHS_User_Manual.pdf](https://github.com/pmgassin/Py_SHS/blob/Py_SHS_V4/Documentation/PySHS_User_Manual.pdf)
|
|
41
|
+
> 🐛 **Issues and questions:** [github.com/pmgassin/Py_SHS/issues](https://github.com/pmgassin/Py_SHS/issues)
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## ✨ What it computes
|
|
46
|
+
|
|
47
|
+
| Module | Description |
|
|
48
|
+
|--------|-------------|
|
|
49
|
+
| **HRS** | Incoherent Hyper-Rayleigh Scattering (single molecule) |
|
|
50
|
+
| **SHS** | Coherent SHS of an assembly of N oriented dipoles |
|
|
51
|
+
| **Sphere** | Colloidal sphere (NLRGD / NLWKB continuum models) |
|
|
52
|
+
| **Sphere Mie** | Nonlinear Mie theory for spheres |
|
|
53
|
+
| **Cylinder** | Continuum model for colloidal cylinders |
|
|
54
|
+
| **Ellipsoid** | Spheroid / ellipsoid of revolution |
|
|
55
|
+
| **Cube / Box** | Rectangular box (or cube) |
|
|
56
|
+
|
|
57
|
+
Keywords shared by most modules:
|
|
58
|
+
|
|
59
|
+
- `polarplot_single` – polar plot at one scattering angle
|
|
60
|
+
- `polarplot_integrate` – average over a range of angles
|
|
61
|
+
- `angle_scattering` – angular distribution: you enter N, and the code computes N+1 angles from 0° to 180° (step 180°/N), identically in all modules
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 📦 Installation
|
|
66
|
+
|
|
67
|
+
### 1. Requirements
|
|
68
|
+
|
|
69
|
+
- **Python 3.8 or newer** ([python.org/downloads](https://www.python.org/downloads/))
|
|
70
|
+
- **tkinter**, only for the graphical interface. It is included in the official Python installers for
|
|
71
|
+
Windows and macOS, but is a separate system package on some systems (see the note below).
|
|
72
|
+
|
|
73
|
+
NumPy, SciPy and matplotlib are installed automatically by `pip`.
|
|
74
|
+
|
|
75
|
+
### 2. Install with pip
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install pyshs-optics
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
That's it. Check that the installation worked:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
python -c "import py_shs; print(py_shs.__version__)"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
> 💡 **Recommended:** install inside a virtual environment, so that Py_SHS and its dependencies stay
|
|
88
|
+
> separate from the rest of your Python installation.
|
|
89
|
+
>
|
|
90
|
+
> ```bash
|
|
91
|
+
> python3 -m venv pyshs-env
|
|
92
|
+
> source pyshs-env/bin/activate # Windows: pyshs-env\Scripts\activate
|
|
93
|
+
> pip install pyshs-optics
|
|
94
|
+
> ```
|
|
95
|
+
|
|
96
|
+
### 3. Update or uninstall
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
pip install --upgrade pyshs-optics
|
|
100
|
+
pip uninstall pyshs-optics
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### tkinter not found?
|
|
104
|
+
|
|
105
|
+
If launching the GUI fails with `No module named 'tkinter'`, install it for your system:
|
|
106
|
+
|
|
107
|
+
| System | Command |
|
|
108
|
+
|--------|---------|
|
|
109
|
+
| Debian / Ubuntu | `sudo apt install python3-tk` |
|
|
110
|
+
| Fedora | `sudo dnf install python3-tkinter` |
|
|
111
|
+
| macOS (Homebrew Python) | `brew install python-tk` |
|
|
112
|
+
| Windows | re-run the Python installer and tick *tcl/tk and IDLE* |
|
|
113
|
+
|
|
114
|
+
The command-line programs do not need tkinter.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## 🚀 Launching the GUI
|
|
119
|
+
|
|
120
|
+
Once the package is installed, open a terminal and type:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
pyshs-optics-gui
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
or, equivalently:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
python -m py_shs
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The graphical interface opens. Choose a module, enter your parameters and input files, and run the
|
|
133
|
+
calculation: progress is streamed live in the log panel and results are plotted in the window.
|
|
134
|
+
An *Intensity units* selector and a scale factor apply to every module.
|
|
135
|
+
|
|
136
|
+
**Where are my files?** The GUI writes its input / output files and temporary calculation folders in
|
|
137
|
+
|
|
138
|
+
```text
|
|
139
|
+
~/PySHS_Work/
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
(that is `C:\Users\<you>\PySHS_Work` on Windows). You can choose another folder with the environment
|
|
143
|
+
variable `PYSHS_WORK`:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
export PYSHS_WORK=/path/to/my/calculations # macOS / Linux
|
|
147
|
+
pyshs-optics-gui
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
If the `pyshs-optics-gui` command is not found, use `python -m py_shs` instead, which always works.
|
|
151
|
+
|
|
152
|
+
📖 The full description of the interface and of the physical models is in the
|
|
153
|
+
**[User Manual (PDF)](https://github.com/pmgassin/Py_SHS/blob/Py_SHS_V4/Documentation/PySHS_User_Manual.pdf)**.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## 💻 Command-line use (without the GUI)
|
|
158
|
+
|
|
159
|
+
Each module can also be run from a terminal. The protocol is: a keyword, the beta (or ki2) file, an
|
|
160
|
+
optional orientation file and the output file; the numerical parameters are read from standard input.
|
|
161
|
+
|
|
162
|
+
| Command | Module |
|
|
163
|
+
|---------|--------|
|
|
164
|
+
| `pyshs-optics-hrs` | HRS |
|
|
165
|
+
| `pyshs-optics-shs` | SHS (dipole assembly) |
|
|
166
|
+
| `pyshs-optics-sphere` | Sphere (NLRGD / NLWKB) |
|
|
167
|
+
| `pyshs-optics-mie` | Nonlinear Mie theory |
|
|
168
|
+
| `pyshs-optics-cylinder` | Cylinder |
|
|
169
|
+
| `pyshs-optics-ellipsoid` | Ellipsoid |
|
|
170
|
+
| `pyshs-optics-cube` | Cube / box |
|
|
171
|
+
|
|
172
|
+
Examples (macOS / Linux shell; on Windows use Git Bash or WSL), with a beta file `beta.txt`
|
|
173
|
+
in the current folder:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# HRS polar plot at 90°
|
|
177
|
+
printf "800\n1.33\n0.0\n90\n" | pyshs-optics-hrs polarplot_single beta.txt out_hrs.txt
|
|
178
|
+
|
|
179
|
+
# SHS (N dipoles + orientation file)
|
|
180
|
+
printf "100\n800\n1.33\n0.0\n90\n" | pyshs-optics-shs polarplot_single beta.txt orient.txt out_shs.txt
|
|
181
|
+
|
|
182
|
+
# Sphere NLWKB
|
|
183
|
+
printf "1\n800\n1.5\n0.0\n1.33\n0.0\n50\n90\n" | pyshs-optics-sphere polarplot_single beta.txt out_sph.txt
|
|
184
|
+
|
|
185
|
+
# Cylinder
|
|
186
|
+
printf "800\n1.5\n0.0\n1.33\n0.0\n20\n80\n90\n" | pyshs-optics-cylinder polarplot_single beta.txt out_cyl.txt
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Every module can also be started with `python -m py_shs.<module>` (for example `python -m py_shs.HRS`).
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## 📄 Input file formats
|
|
194
|
+
|
|
195
|
+
**Beta / ki(2) file** – one header line, then 27 lines `name value` (order `xxx` … `zzz`):
|
|
196
|
+
|
|
197
|
+
```text
|
|
198
|
+
# surface hyperpolarizability
|
|
199
|
+
xxx 0.0
|
|
200
|
+
xxy 0.0
|
|
201
|
+
...
|
|
202
|
+
zzz 1.0
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**Orientation file** (SHS only) – one line per dipole:
|
|
206
|
+
|
|
207
|
+
```text
|
|
208
|
+
phi theta psi x y z
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
(angles in radians, positions in nm).
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## ⚙️ Environment variables
|
|
216
|
+
|
|
217
|
+
| Variable | Effect |
|
|
218
|
+
|----------|--------|
|
|
219
|
+
| `PYSHS_WORK=dir` | Working folder of the GUI (default: `~/PySHS_Work`) |
|
|
220
|
+
| `PYSHS_THREADS=k` | Thread count for HRS / SHS (default: CPU cores) |
|
|
221
|
+
| `PYSHS_LEGACY=1` | Reproduce two old C quirks of HRS / SHS (affects only bv1, bv2, bh1, bh2, which are zero after the isotropic average) |
|
|
222
|
+
| `PYSHS_I_SCALE=x` | Intensity scale factor, applied by **every** module (HRS, SHS, sphere, cylinder, ellipsoid, cube, Mie) |
|
|
223
|
+
| `PYSHS_UNITS=rad\|raw` | Intensity units common to all modules (see *Intensity units* below) |
|
|
224
|
+
| `PYSHS_ANGLE_RANGE=half\|negative\|full` | Angle range of `angle_scattering` (see *Scattering-angle grid* below) |
|
|
225
|
+
| `PYSHS_GRID=fixed` | Use the historical fixed quadrature grids (see *Automatic quadrature grids*) |
|
|
226
|
+
| `PYSHS_GRID_SCALE=x` | Multiplies the size parameter used by the grid rules (2 = safer and slower, 0.5 = faster) |
|
|
227
|
+
| `PYSHS_GRID_MAX=n` | Upper bound on the grid size (memory / time guard) |
|
|
228
|
+
| `PYSHS_THETA_RULE=midpoint` | Former mid-point rule in theta |
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## 🔬 Technical notes
|
|
233
|
+
|
|
234
|
+
The notes below describe the numerical conventions of this version. Click a title to expand it.
|
|
235
|
+
|
|
236
|
+
<details>
|
|
237
|
+
<summary><b>Package layout</b></summary>
|
|
238
|
+
|
|
239
|
+
```text
|
|
240
|
+
py_shs/ (installed in site-packages)
|
|
241
|
+
├── pyshs_gui.py # Tkinter GUI -> command `pyshs-optics-gui`
|
|
242
|
+
├── HRS.py, SHS.py
|
|
243
|
+
├── sphere_SHS.py, cylinder_SHS.py, ellipsoid_SHS.py, cube_SHS.py
|
|
244
|
+
├── shs_mie.py # nonlinear Mie theory
|
|
245
|
+
├── graph_*.py, script_*.py # plots and dipole generators (sphere, spheroid, cylinder)
|
|
246
|
+
├── shs_grid.py, shs_units.py, shs_angles.py, shs_io.py # shared helpers
|
|
247
|
+
└── cli.py # console commands pyshs-optics-hrs, pyshs-optics-shs, ...
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
All calculation modules are pure Python and are invoked with the same interpreter
|
|
251
|
+
(`python -m py_shs.<module>`).
|
|
252
|
+
|
|
253
|
+
</details>
|
|
254
|
+
|
|
255
|
+
<details>
|
|
256
|
+
<summary><b>What changed in V4 (pure Python)</b></summary>
|
|
257
|
+
|
|
258
|
+
- All former `.c` sources (`HRS.c`, `SHS.c`, `sphere_SHS.c`, `cylinder_SHS.c`, `ellipsoid_SHS.c`,
|
|
259
|
+
`cube_SHS.c`) are replaced by equivalent NumPy implementations with the **same physics and the same
|
|
260
|
+
stdin / file protocol**.
|
|
261
|
+
- The GUI no longer compiles anything; it launches `python -u -m py_shs.<module> …`.
|
|
262
|
+
- Dependencies: Python 3 + NumPy (+ SciPy for `shs_mie.py`; tkinter / matplotlib for the GUI).
|
|
263
|
+
|
|
264
|
+
Equivalence with the previous C programs: the C sources/binaries are **not** part of this package, so
|
|
265
|
+
this package does not itself demonstrate it. What *is* verified (see the `tests/` folder of the GitHub
|
|
266
|
+
repository): analytic values, an independent brute-force evaluation of the polarisation formulas, mutual
|
|
267
|
+
consistency of all the models (absolute scale included) and a frozen snapshot of the current outputs. To
|
|
268
|
+
check against the C programs, run both on the same input and compare the output files.
|
|
269
|
+
|
|
270
|
+
`PYSHS_LEGACY=1` (HRS and SHS only) reproduces two defects of the old C code (normalisation of bv1, bv2,
|
|
271
|
+
bh1, bh2, and the pairing of the sin*cos cross terms of bh1, bh2). These four coefficients are identically
|
|
272
|
+
zero after the isotropic orientational average (shown analytically and tested numerically), so the option
|
|
273
|
+
changes only rounding noise in them and none of av, bv, cv, ah, bh, ch, I2 and I4.
|
|
274
|
+
|
|
275
|
+
</details>
|
|
276
|
+
|
|
277
|
+
<details>
|
|
278
|
+
<summary><b>Hyperpolarizability tensor (symmetrisation)</b></summary>
|
|
279
|
+
|
|
280
|
+
All modules assume beta_ijk = beta_ikj (intrinsic permutation symmetry in the last two indices). The
|
|
281
|
+
beta/surface-susceptibility file reader of HRS, SHS, sphere_SHS, cylinder_SHS, ellipsoid_SHS and cube_SHS
|
|
282
|
+
symmetrises the input (beta_ijk <- (beta_ijk + beta_ikj)/2) and prints a WARNING if the file was not
|
|
283
|
+
symmetric. `shs_mie.py` already averages the equivalent components (xzx/xxz, yzy/yyz).
|
|
284
|
+
|
|
285
|
+
</details>
|
|
286
|
+
|
|
287
|
+
<details>
|
|
288
|
+
<summary><b>Orientation quadrature (normalisation)</b></summary>
|
|
289
|
+
|
|
290
|
+
The orientation average over the polar angle theta uses a Gauss-Legendre rule in cos(theta) in HRS, SHS,
|
|
291
|
+
cylinder_SHS and ellipsoid_SHS (cube_SHS already did). The weights then sum exactly to 8*pi^2 (SHS/HRS) so
|
|
292
|
+
the 1/(8*pi^2) normalisation is exact, and all modules normalise consistently. The former midpoint rule had
|
|
293
|
+
a weight sum of 1.0041 * 8*pi^2, i.e. a +0.4 % bias on rotation-invariant quantities. Set
|
|
294
|
+
`PYSHS_THETA_RULE=midpoint` to restore the previous grid (e.g. to reproduce earlier results). Grid sizes
|
|
295
|
+
(N_PHI, N_THETA, ...) are unchanged.
|
|
296
|
+
|
|
297
|
+
</details>
|
|
298
|
+
|
|
299
|
+
<details>
|
|
300
|
+
<summary><b>Automatic quadrature grids (convergence)</b></summary>
|
|
301
|
+
|
|
302
|
+
All intensities contain the phase factor exp(i q.r) with |q| <= q_max = 2 Re(k_w) + Re(K_2w). A grid that is
|
|
303
|
+
fine for a small object silently becomes under-resolved for a large one, so the grids are sized from the
|
|
304
|
+
size parameter `a = q_max x (largest half-extent)` by `py_shs/shs_grid.py` (rules calibrated numerically
|
|
305
|
+
against very fine reference grids; typical error <= 1e-4, usually ~1e-7):
|
|
306
|
+
|
|
307
|
+
| Module | What is sized | Rule |
|
|
308
|
+
|---|---|---|
|
|
309
|
+
| `sphere_SHS` | surface grid (Gauss-Legendre in cos theta_c x trapezoid in phi_c) | ny >= a/2 + 20, nx = 2 ny |
|
|
310
|
+
| `cylinder_SHS` | azimuth points, orientation grid; axial integral is analytic (sinc) | n_beta >= qR + 14 ; N >= q sqrt(R^2+L^2/4) + 12 |
|
|
311
|
+
| `ellipsoid_SHS` | surface (alpha, beta) and orientation grids | n_alpha >= a/2+20, n_beta >= a+16, N >= a+12 |
|
|
312
|
+
| `cube_SHS` | orientation grid (faces are analytic) | N >= q d + 12, d = half diagonal |
|
|
313
|
+
| `SHS` | orientation grid (phi, theta, psi) | N_phi = N_psi >= 2 a + 8, N_theta = N/2, a = q max|r| |
|
|
314
|
+
| `HRS`, `shs_mie` | nothing to size (HRS: single molecule; Mie: Wiscombe cutoff already adaptive) | |
|
|
315
|
+
|
|
316
|
+
The grid used is printed in the run log (`Grid: ...` / `Orientation grid: ...`). The historical values (the
|
|
317
|
+
module constants) are used as minimum sizes: the grids are never coarser than before (for sphere, dipole
|
|
318
|
+
assemblies and box, small objects use exactly the historical sizes).
|
|
319
|
+
|
|
320
|
+
* `PYSHS_GRID=fixed` : use the historical fixed grids (reproduces earlier runs; may be inaccurate for large objects).
|
|
321
|
+
* `PYSHS_GRID_SCALE=<float>` : multiplies the size parameter used by the rules (2 = safer and slower, 0.5 = faster).
|
|
322
|
+
* `PYSHS_GRID_MAX=<int>` : upper bound on the grid size (memory / time guard). When the bound prevents the rule from being satisfied, a `WARNING` is printed.
|
|
323
|
+
* `PYSHS_THETA_RULE=midpoint` : former mid-point rule in theta.
|
|
324
|
+
|
|
325
|
+
Other changes: `cylinder_SHS` integrates the axial direction analytically (the former `N_Z` no longer
|
|
326
|
+
exists, so no aliasing for long rods); `ellipsoid_SHS`, `cube_SHS` and `cylinder_SHS` are vectorised
|
|
327
|
+
(5-10x faster).
|
|
328
|
+
|
|
329
|
+
</details>
|
|
330
|
+
|
|
331
|
+
<details>
|
|
332
|
+
<summary><b>Intensity units (comparing modules)</b></summary>
|
|
333
|
+
|
|
334
|
+
Two conventions exist, related by the radiative prefactor `P = (|K_2w|^2 / 4 pi)^2`
|
|
335
|
+
(`K = 4 pi n / lambda`, in nm^-1):
|
|
336
|
+
|
|
337
|
+
| Convention | Meaning | Default for |
|
|
338
|
+
|---|---|---|
|
|
339
|
+
| `rad` | `I = r^2 \|E_2w\|^2 / \|E_w\|^4`, prefactor `P` **included** | sphere, cylinder, ellipsoid, cube, `shs_mie` |
|
|
340
|
+
| `raw` | orientation average of `\|sum beta exp(i q.r)\|^2`, **no** prefactor (beta in atomic units; e.g. `<beta_ZZZ^2> = 1/7` for `beta_zzz = 1`) | HRS, SHS |
|
|
341
|
+
|
|
342
|
+
`I_rad = P * I_raw`. `PYSHS_UNITS=rad` or `raw` forces one convention on every module, and `PYSHS_I_SCALE`
|
|
343
|
+
multiplies every module's result, so any two modules can be put on the same scale. The convention used is
|
|
344
|
+
printed in the run log and in the header of the output file. Default outputs are unchanged. (HRS/SHS switch
|
|
345
|
+
to scientific notation when the multiplier is not 1, since `rad` values are ~1e-9.) The GUI has an
|
|
346
|
+
*Intensity units* selector and a scale factor that apply to all modules.
|
|
347
|
+
|
|
348
|
+
Absolute consistency (checked numerically): a continuum model with surface susceptibility `chi` is
|
|
349
|
+
equivalent to a dipole assembly of surface density `sigma` [dipoles/nm^2] and molecular `beta` with
|
|
350
|
+
`chi = sigma * beta` (so chi is in units of beta per nm^2). With both on the same scale,
|
|
351
|
+
`I_SHS(assembly) = sigma^2 * I_continuum` (agreement to 1e-5 for a sphere, cylinder and cube), and the
|
|
352
|
+
nonlinear Mie theory equals the sphere NLRGD model at matched index.
|
|
353
|
+
|
|
354
|
+
</details>
|
|
355
|
+
|
|
356
|
+
<details>
|
|
357
|
+
<summary><b>Scattering-angle grid (<code>angle_scattering</code>)</b></summary>
|
|
358
|
+
|
|
359
|
+
All modules use the same grid: the number N you enter is the number of intervals between 0 and 180
|
|
360
|
+
degrees, so N+1 angles `Theta = 0, 180/N, ..., 180`. Previously HRS, SHS and the cylinder covered
|
|
361
|
+
[-180, 0] with N+1 points, while the sphere, ellipsoid, cube and Mie covered [-180, +180] with 2N+1 points,
|
|
362
|
+
so the same N did not mean the same thing (and half of the sphere/ellipsoid/cube/Mie work was redundant).
|
|
363
|
+
|
|
364
|
+
A half range is sufficient because the four reported intensities satisfy `I(Theta) = I(-Theta)`; this was
|
|
365
|
+
checked numerically in every module with a random chiral tensor.
|
|
366
|
+
|
|
367
|
+
`PYSHS_ANGLE_RANGE` restores the former ranges: `negative` (-180...0, N+1 points; former HRS/SHS/cylinder
|
|
368
|
+
output) or `full` (-180...+180, 2N+1 points; former sphere/ellipsoid/cube/Mie output). The values at a given
|
|
369
|
+
angle are identical in all modes. `graph_angle.py` accepts any of the three ranges and plots the full
|
|
370
|
+
-180...+180 curve.
|
|
371
|
+
|
|
372
|
+
</details>
|
|
373
|
+
|
|
374
|
+
<details>
|
|
375
|
+
<summary><b>Models: notes and limitations</b></summary>
|
|
376
|
+
|
|
377
|
+
**Output files.** `out_plot` and `out_arrows_gnuplot` are written in the directory of the output file given
|
|
378
|
+
on the command line. Running twice in the same directory overwrites them.
|
|
379
|
+
|
|
380
|
+
**Models.**
|
|
381
|
+
|
|
382
|
+
- `cylinder_SHS` models the lateral surface only (no end caps): use it for objects long compared with their
|
|
383
|
+
radius. The surface frame uses the exact polar angle pi/2 (the old C code used the truncated 1.570796;
|
|
384
|
+
`PYSHS_THETA_MESO_LEGACY=1` restores it, effect ~1e-7).
|
|
385
|
+
- The classic Rayleigh-Gans sphere model is the NLWKB model with `n_p = n_m`: in the GUI enter the same
|
|
386
|
+
index twice.
|
|
387
|
+
- `shs_mie.py` has three independent surface constants (isotropic achiral surface: `zzz`, `zxx`/`zyy`,
|
|
388
|
+
`xzx`/`xxz`/`yzy`/`yyz`); other tensor components are ignored and a warning lists them. The
|
|
389
|
+
command-line/GUI interface uses the same index at omega and 2 omega and drops the imaginary part of the
|
|
390
|
+
medium index (`shs_sphere()` accepts distinct indices).
|
|
391
|
+
- With an absorbing medium (complex index) the phase factor is `exp(i q.r)` with complex `q`, so the result
|
|
392
|
+
depends on the origin of the positions (the attenuation is `exp(-Im q . r)`): put the origin where the
|
|
393
|
+
incident beam enters the object.
|
|
394
|
+
- `polarplot_integrate` is a plain average over the scattering angles, not weighted by `sin(Theta)`.
|
|
395
|
+
- The sphere and Mie outputs do not contain `b1`, `b2` (they are zero anyway, see the legacy note).
|
|
396
|
+
|
|
397
|
+
**Generators and converters (`py_shs/`).**
|
|
398
|
+
|
|
399
|
+
- `script_sphere.py`, `script_sphere_random.py`, `script_spheroid_random.py`, `script_cylinder_random.py`:
|
|
400
|
+
write `phi theta psi x y z` files for `SHS.py` (dipoles along the outward normal; disorder = Gaussian
|
|
401
|
+
noise on `phi`, `theta`; a noise on `phi` is a real tilt of `sigma*sin(theta)`).
|
|
402
|
+
`script_spheroid_random.py` (a, c, N, sigma) places the points with a uniform *surface* density and
|
|
403
|
+
reproduces `ellipsoid_SHS.py` through `chi = sigma * beta`.
|
|
404
|
+
- `script_gauss2PySHS.py job.log beta_out [--marker TEXT] [--occurrence K] [--offset N]` reads the first
|
|
405
|
+
`Beta(-2w;w,w)` block (see its docstring; the layout was not checked against every Gaussian version) and
|
|
406
|
+
writes a tensor symmetric in the last two indices.
|
|
407
|
+
- `graph_assembly.py orientation_file image.png [--positions-first]` expects `phi theta psi x y z`.
|
|
408
|
+
|
|
409
|
+
**GUI.** The *Intensity units* selector and the scale factor apply to every module; run directories
|
|
410
|
+
`~/PySHS_Work/pyshs_*` older than 7 days are removed automatically; the unit of polar plots (radians) is
|
|
411
|
+
decided once per file.
|
|
412
|
+
|
|
413
|
+
</details>
|
|
414
|
+
|
|
415
|
+
<details>
|
|
416
|
+
<summary><b>Tests (GitHub repository)</b></summary>
|
|
417
|
+
|
|
418
|
+
A regression and validation suite (standard library only, no pytest needed) is kept in the `tests/` folder
|
|
419
|
+
of the [GitHub repository](https://github.com/pmgassin/Py_SHS):
|
|
420
|
+
|
|
421
|
+
```bash
|
|
422
|
+
python tests/run_tests.py # everything, about 2 minutes
|
|
423
|
+
python tests/run_tests.py -f # fast subset (skips the slow convergence tests)
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
| File | What it checks |
|
|
427
|
+
|---|---|
|
|
428
|
+
| `test_core.py` | Euler matrices, exact orientation quadrature, analytic HRS values, HRS = SHS(N=1), the polarisation expansion against a brute-force evaluation, legacy mode, Theta -> -Theta symmetry |
|
|
429
|
+
| `test_models.py` | absolute scale of sphere, ellipsoid, cylinder, cube and Mie against dipole assemblies (chi = sigma beta), symmetrisation of beta in every module |
|
|
430
|
+
| `test_grids.py` | automatic grids against much finer references for large objects |
|
|
431
|
+
| `test_units_angles.py` | `PYSHS_UNITS`, `PYSHS_I_SCALE`, the angle grid and its compatibility ranges, `graph_angle.py` |
|
|
432
|
+
| `test_golden.py` | frozen snapshot of command-line outputs of every module (it detects unintended changes; it is not a C reference) |
|
|
433
|
+
| `test_tools.py` | `compare_outputs.py` |
|
|
434
|
+
|
|
435
|
+
The Mie tests are skipped when SciPy is not installed.
|
|
436
|
+
|
|
437
|
+
</details>
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
## 📚 How to cite
|
|
442
|
+
|
|
443
|
+
If you use Py_SHS in your work, please cite:
|
|
444
|
+
|
|
445
|
+
- J. Chem. Inf. Model. **2020**, 60, 12, 5912–5917
|
|
446
|
+
- J. Chem. Inf. Model. **2021**, 61, 11, 5719
|
|
447
|
+
|
|
448
|
+
## 👥 Authors and license
|
|
449
|
+
|
|
450
|
+
Dr Pierre-Marie GASSIN and Dr Gaelle GASSIN – ICGM / ENSCM.
|
|
451
|
+
|
|
452
|
+
Open-source research software, released under the MIT License (see the
|
|
453
|
+
[LICENSE](https://github.com/pmgassin/Py_SHS/blob/Py_SHS_V4/LICENSE) file).
|
|
454
|
+
|
|
455
|
+
## 📘 Documentation note
|
|
456
|
+
|
|
457
|
+
The PDF [User Manual] is available here: (https://github.com/pmgassin/Py_SHS/blob/Py_SHS_V4/Documentation/PySHS_User_Manual.pdf)
|