easyspyn 0.2.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 (36) hide show
  1. easyspyn-0.2.0/LICENSE +71 -0
  2. easyspyn-0.2.0/PKG-INFO +60 -0
  3. easyspyn-0.2.0/README.md +31 -0
  4. easyspyn-0.2.0/easyspyn.egg-info/PKG-INFO +60 -0
  5. easyspyn-0.2.0/easyspyn.egg-info/SOURCES.txt +34 -0
  6. easyspyn-0.2.0/easyspyn.egg-info/dependency_links.txt +1 -0
  7. easyspyn-0.2.0/easyspyn.egg-info/requires.txt +10 -0
  8. easyspyn-0.2.0/easyspyn.egg-info/top_level.txt +1 -0
  9. easyspyn-0.2.0/epreasy/__init__.py +68 -0
  10. easyspyn-0.2.0/epreasy/components.py +71 -0
  11. easyspyn-0.2.0/epreasy/constants.py +21 -0
  12. easyspyn-0.2.0/epreasy/data/isotopedata.txt +416 -0
  13. easyspyn-0.2.0/epreasy/endor.py +873 -0
  14. easyspyn-0.2.0/epreasy/fitting.py +1662 -0
  15. easyspyn-0.2.0/epreasy/garlic.py +558 -0
  16. easyspyn-0.2.0/epreasy/grids.py +204 -0
  17. easyspyn-0.2.0/epreasy/hamiltonian.py +327 -0
  18. easyspyn-0.2.0/epreasy/interp.py +213 -0
  19. easyspyn-0.2.0/epreasy/kernels.py +392 -0
  20. easyspyn-0.2.0/epreasy/lineshapes.py +245 -0
  21. easyspyn-0.2.0/epreasy/magnetometry.py +220 -0
  22. easyspyn-0.2.0/epreasy/nucdata.py +130 -0
  23. easyspyn-0.2.0/epreasy/oracle.py +164 -0
  24. easyspyn-0.2.0/epreasy/pepper.py +517 -0
  25. easyspyn-0.2.0/epreasy/perturb.py +282 -0
  26. easyspyn-0.2.0/epreasy/processing.py +29 -0
  27. easyspyn-0.2.0/epreasy/pulsed.py +1280 -0
  28. easyspyn-0.2.0/epreasy/resfields.py +1211 -0
  29. easyspyn-0.2.0/epreasy/rotations.py +129 -0
  30. easyspyn-0.2.0/epreasy/slowmotion.py +1520 -0
  31. easyspyn-0.2.0/epreasy/spinops.py +243 -0
  32. easyspyn-0.2.0/epreasy/spinsystem.py +549 -0
  33. easyspyn-0.2.0/epreasy/symmetry.py +226 -0
  34. easyspyn-0.2.0/epreasy/units.py +61 -0
  35. easyspyn-0.2.0/pyproject.toml +41 -0
  36. easyspyn-0.2.0/setup.cfg +4 -0
easyspyn-0.2.0/LICENSE ADDED
@@ -0,0 +1,71 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Alexej Jerschow
4
+
5
+ Spynach is a Python reimplementation of the Spinach spin dynamics kernel
6
+ (https://spindynamics.org). This licence derives from the Spinach MIT
7
+ licence of Ilya Kuprov (see below).
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in all
17
+ copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ SOFTWARE.
26
+
27
+
28
+ Spinach
29
+ =======
30
+
31
+ The sources, tests, molecule data, isotope table, spherical grids and
32
+ example scripts of Spynach were written by reading and translating Spinach. Spinach is distributed under the MIT License with the following
33
+ notice, which is reproduced here as that licence requires and must be kept
34
+ with any copy or substantial portion of this software.
35
+
36
+ Copyright (c) 2005-2025 ILYA KUPROV
37
+
38
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
39
+
40
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
41
+
42
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43
+
44
+
45
+ EasySpin
46
+ ========
47
+
48
+ The `epreasy` package (src/epreasy), its tests and its isotope table were
49
+ written by reading and translating EasySpin (https://easyspin.org), which
50
+ is distributed under the MIT License with the following notice, reproduced
51
+ here as that licence requires and to be kept with any copy or substantial
52
+ portion of this software.
53
+
54
+ Copyright (c) 2006-2024 Stefan Stoll and other contributors
55
+
56
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
57
+
58
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
59
+
60
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
61
+
62
+
63
+ Use of AI in the translation
64
+ ============================
65
+
66
+ The translation of Spinach from MATLAB to Python was carried out largely by
67
+ an AI coding agent (Claude, Anthropic) working under the direction of
68
+ Alexej Jerschow, who set the goals, reviewed the results and holds the
69
+ copyright above. Commits made by the agent are marked as such in the git
70
+ history. Correctness rests on the test suite, which compares Spynach with
71
+ reference data computed by Spinach, not on the method of authorship.
@@ -0,0 +1,60 @@
1
+ Metadata-Version: 2.4
2
+ Name: easyspyn
3
+ Version: 0.2.0
4
+ Summary: EasySpin's EPR simulators in Python (EPReasy): cw EPR, ENDOR, slow motion, pulse EPR, fitting
5
+ Author: Alexej Jerschow
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://ajerschow.github.io/spynach/easyspin.html
8
+ Project-URL: Documentation, https://github.com/ajerschow/spynach/blob/main/docs/epreasy.md
9
+ Project-URL: Source, https://github.com/ajerschow/spynach
10
+ Project-URL: Changelog, https://github.com/ajerschow/spynach/blob/main/CHANGELOG.md
11
+ Keywords: EPR,ESR,EasySpin,spectral simulation,ENDOR,spin dynamics
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Topic :: Scientific/Engineering :: Chemistry
16
+ Classifier: Topic :: Scientific/Engineering :: Physics
17
+ Requires-Python: >=3.11
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: numpy>=1.26
21
+ Requires-Dist: scipy>=1.11
22
+ Provides-Extra: fast
23
+ Requires-Dist: numba>=0.60; extra == "fast"
24
+ Provides-Extra: test
25
+ Requires-Dist: pytest>=8; extra == "test"
26
+ Requires-Dist: spynach; extra == "test"
27
+ Requires-Dist: h5py>=3.10; extra == "test"
28
+ Dynamic: license-file
29
+
30
+ # EasySpyn (EPReasy): EasySpin's EPR simulators in Python
31
+
32
+ A Python port of [EasySpin](https://easyspin.org), the MATLAB toolbox for EPR spectral simulation by Stefan Stoll
33
+ and co-workers (MIT licence), keeping EasySpin's interface: spin systems as dictionaries with EasySpin's field
34
+ names, fields in mT, couplings in MHz, 1-based spin numbers.
35
+
36
+ pip install easyspyn # the import name is epreasy
37
+ pip install "easyspyn[fast]" # adds Numba for the line-summation and projection kernels
38
+
39
+ ```python
40
+ import epreasy as es
41
+
42
+ nitroxide = {"g": [2.0088, 2.0061, 2.0027], "Nucs": "14N", "A": [16, 16, 86], "lwpp": 0.3}
43
+ powder = es.pepper(nitroxide, {"mwFreq": 9.5, "Range": [330, 350], "nPoints": 1024})
44
+ print(powder.x.shape, powder.spec.shape)
45
+ ```
46
+
47
+ What is ported: `pepper` and `garlic` (cw EPR of powders, crystals and solutions), `esfit` (fitting), `salt` and
48
+ `endorfrq` (ENDOR), `curry` (magnetometry), `chili` (slow motion), `saffron` (pulse EPR: ESEEM, HYSCORE, Mims
49
+ ENDOR), and the foundation underneath (`sop`, `ham`, `levels`, `resfields`, line shapes, grids). Results are
50
+ compared with EasySpin 6.0.15's own output on about 280 reference cases. Not ported: `saffron`'s `thyme` engine
51
+ and `spidyan`, the GUIs, and some options; the guide lists them.
52
+
53
+ EPReasy is part of the [Spynach](https://github.com/ajerschow/spynach) project, which also ports the Spinach
54
+ spin dynamics kernel. It is an early release (0.2.0); corrections and bug reports are welcome on GitHub.
55
+
56
+ - Guides: https://github.com/ajerschow/spynach/blob/main/docs/epreasy.md
57
+ - Differences from EasySpin: https://github.com/ajerschow/spynach/blob/main/docs/coming-from-easyspin.md
58
+ - Try it in the browser, with timings against EasySpin: https://ajerschow.github.io/spynach/easyspin.html
59
+
60
+ Attribution: EPReasy is a translation of EasySpin and keeps its notice; see `LICENSE`.
@@ -0,0 +1,31 @@
1
+ # EasySpyn (EPReasy): EasySpin's EPR simulators in Python
2
+
3
+ A Python port of [EasySpin](https://easyspin.org), the MATLAB toolbox for EPR spectral simulation by Stefan Stoll
4
+ and co-workers (MIT licence), keeping EasySpin's interface: spin systems as dictionaries with EasySpin's field
5
+ names, fields in mT, couplings in MHz, 1-based spin numbers.
6
+
7
+ pip install easyspyn # the import name is epreasy
8
+ pip install "easyspyn[fast]" # adds Numba for the line-summation and projection kernels
9
+
10
+ ```python
11
+ import epreasy as es
12
+
13
+ nitroxide = {"g": [2.0088, 2.0061, 2.0027], "Nucs": "14N", "A": [16, 16, 86], "lwpp": 0.3}
14
+ powder = es.pepper(nitroxide, {"mwFreq": 9.5, "Range": [330, 350], "nPoints": 1024})
15
+ print(powder.x.shape, powder.spec.shape)
16
+ ```
17
+
18
+ What is ported: `pepper` and `garlic` (cw EPR of powders, crystals and solutions), `esfit` (fitting), `salt` and
19
+ `endorfrq` (ENDOR), `curry` (magnetometry), `chili` (slow motion), `saffron` (pulse EPR: ESEEM, HYSCORE, Mims
20
+ ENDOR), and the foundation underneath (`sop`, `ham`, `levels`, `resfields`, line shapes, grids). Results are
21
+ compared with EasySpin 6.0.15's own output on about 280 reference cases. Not ported: `saffron`'s `thyme` engine
22
+ and `spidyan`, the GUIs, and some options; the guide lists them.
23
+
24
+ EPReasy is part of the [Spynach](https://github.com/ajerschow/spynach) project, which also ports the Spinach
25
+ spin dynamics kernel. It is an early release (0.2.0); corrections and bug reports are welcome on GitHub.
26
+
27
+ - Guides: https://github.com/ajerschow/spynach/blob/main/docs/epreasy.md
28
+ - Differences from EasySpin: https://github.com/ajerschow/spynach/blob/main/docs/coming-from-easyspin.md
29
+ - Try it in the browser, with timings against EasySpin: https://ajerschow.github.io/spynach/easyspin.html
30
+
31
+ Attribution: EPReasy is a translation of EasySpin and keeps its notice; see `LICENSE`.
@@ -0,0 +1,60 @@
1
+ Metadata-Version: 2.4
2
+ Name: easyspyn
3
+ Version: 0.2.0
4
+ Summary: EasySpin's EPR simulators in Python (EPReasy): cw EPR, ENDOR, slow motion, pulse EPR, fitting
5
+ Author: Alexej Jerschow
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://ajerschow.github.io/spynach/easyspin.html
8
+ Project-URL: Documentation, https://github.com/ajerschow/spynach/blob/main/docs/epreasy.md
9
+ Project-URL: Source, https://github.com/ajerschow/spynach
10
+ Project-URL: Changelog, https://github.com/ajerschow/spynach/blob/main/CHANGELOG.md
11
+ Keywords: EPR,ESR,EasySpin,spectral simulation,ENDOR,spin dynamics
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Topic :: Scientific/Engineering :: Chemistry
16
+ Classifier: Topic :: Scientific/Engineering :: Physics
17
+ Requires-Python: >=3.11
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: numpy>=1.26
21
+ Requires-Dist: scipy>=1.11
22
+ Provides-Extra: fast
23
+ Requires-Dist: numba>=0.60; extra == "fast"
24
+ Provides-Extra: test
25
+ Requires-Dist: pytest>=8; extra == "test"
26
+ Requires-Dist: spynach; extra == "test"
27
+ Requires-Dist: h5py>=3.10; extra == "test"
28
+ Dynamic: license-file
29
+
30
+ # EasySpyn (EPReasy): EasySpin's EPR simulators in Python
31
+
32
+ A Python port of [EasySpin](https://easyspin.org), the MATLAB toolbox for EPR spectral simulation by Stefan Stoll
33
+ and co-workers (MIT licence), keeping EasySpin's interface: spin systems as dictionaries with EasySpin's field
34
+ names, fields in mT, couplings in MHz, 1-based spin numbers.
35
+
36
+ pip install easyspyn # the import name is epreasy
37
+ pip install "easyspyn[fast]" # adds Numba for the line-summation and projection kernels
38
+
39
+ ```python
40
+ import epreasy as es
41
+
42
+ nitroxide = {"g": [2.0088, 2.0061, 2.0027], "Nucs": "14N", "A": [16, 16, 86], "lwpp": 0.3}
43
+ powder = es.pepper(nitroxide, {"mwFreq": 9.5, "Range": [330, 350], "nPoints": 1024})
44
+ print(powder.x.shape, powder.spec.shape)
45
+ ```
46
+
47
+ What is ported: `pepper` and `garlic` (cw EPR of powders, crystals and solutions), `esfit` (fitting), `salt` and
48
+ `endorfrq` (ENDOR), `curry` (magnetometry), `chili` (slow motion), `saffron` (pulse EPR: ESEEM, HYSCORE, Mims
49
+ ENDOR), and the foundation underneath (`sop`, `ham`, `levels`, `resfields`, line shapes, grids). Results are
50
+ compared with EasySpin 6.0.15's own output on about 280 reference cases. Not ported: `saffron`'s `thyme` engine
51
+ and `spidyan`, the GUIs, and some options; the guide lists them.
52
+
53
+ EPReasy is part of the [Spynach](https://github.com/ajerschow/spynach) project, which also ports the Spinach
54
+ spin dynamics kernel. It is an early release (0.2.0); corrections and bug reports are welcome on GitHub.
55
+
56
+ - Guides: https://github.com/ajerschow/spynach/blob/main/docs/epreasy.md
57
+ - Differences from EasySpin: https://github.com/ajerschow/spynach/blob/main/docs/coming-from-easyspin.md
58
+ - Try it in the browser, with timings against EasySpin: https://ajerschow.github.io/spynach/easyspin.html
59
+
60
+ Attribution: EPReasy is a translation of EasySpin and keeps its notice; see `LICENSE`.
@@ -0,0 +1,34 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ easyspyn.egg-info/PKG-INFO
5
+ easyspyn.egg-info/SOURCES.txt
6
+ easyspyn.egg-info/dependency_links.txt
7
+ easyspyn.egg-info/requires.txt
8
+ easyspyn.egg-info/top_level.txt
9
+ epreasy/__init__.py
10
+ epreasy/components.py
11
+ epreasy/constants.py
12
+ epreasy/endor.py
13
+ epreasy/fitting.py
14
+ epreasy/garlic.py
15
+ epreasy/grids.py
16
+ epreasy/hamiltonian.py
17
+ epreasy/interp.py
18
+ epreasy/kernels.py
19
+ epreasy/lineshapes.py
20
+ epreasy/magnetometry.py
21
+ epreasy/nucdata.py
22
+ epreasy/oracle.py
23
+ epreasy/pepper.py
24
+ epreasy/perturb.py
25
+ epreasy/processing.py
26
+ epreasy/pulsed.py
27
+ epreasy/resfields.py
28
+ epreasy/rotations.py
29
+ epreasy/slowmotion.py
30
+ epreasy/spinops.py
31
+ epreasy/spinsystem.py
32
+ epreasy/symmetry.py
33
+ epreasy/units.py
34
+ epreasy/data/isotopedata.txt
@@ -0,0 +1,10 @@
1
+ numpy>=1.26
2
+ scipy>=1.11
3
+
4
+ [fast]
5
+ numba>=0.60
6
+
7
+ [test]
8
+ pytest>=8
9
+ spynach
10
+ h5py>=3.10
@@ -0,0 +1 @@
1
+ epreasy
@@ -0,0 +1,68 @@
1
+ """epreasy: EasySpin's EPR simulation functions in Python, beside Spynach.
2
+
3
+ Spin systems are dicts with EasySpin's field names; units are EasySpin's
4
+ (mT, MHz); spin numbers are 1-based as in EasySpin. See ``docs/epreasy.md``
5
+ and ``docs/coming-from-easyspin.md``.
6
+ """
7
+
8
+ from .constants import amu, avogadro, bmagn, boltzm, clight, echarge, evolt, gfree, hbar, mu0, nmagn, planck
9
+ from .endor import EndorResonances, anisosubsys, endorfrq, endorfrq_perturb, orisel, salt
10
+ from .fitting import (
11
+ FitResult,
12
+ addnoise,
13
+ basecorr,
14
+ deriv,
15
+ esfit,
16
+ esfit_genetic,
17
+ esfit_grid,
18
+ esfit_levmar,
19
+ esfit_montecarlo,
20
+ esfit_simplex,
21
+ esfit_swarm,
22
+ hccm,
23
+ jacobianest,
24
+ rescaledata,
25
+ )
26
+ from .garlic import Spectrum, equivcouple, fastmotion, garlic
27
+ from .grids import SphGrid, gridparam, sphgrid
28
+ from .hamiltonian import ham, ham_ee, ham_ez, ham_hf, ham_nn, ham_nq, ham_nz, ham_zf, levels
29
+ from .interp import esspline1d, esspline2d, gridinterp
30
+ from .kernels import lisum1i, projecttriangles, projectzones
31
+ from .lineshapes import convspec, gaussian, lorentzian, lshape, voigtian
32
+ from .magnetometry import curry
33
+ from .nucdata import isotopes, nucabund, nucdata, nucgval, nucqmom, nucspin, nucstring2list
34
+ from .pepper import pepper
35
+ from .perturb import resfields_perturb
36
+ from .processing import fieldmod
37
+ from .pulsed import apowin, exponfit, fdaxis, larmorfrq, saffron, sf_pathways
38
+ from .resfields import Resonances, cubicsolve, nucspinrmv, photoselect, resfields, resfields_eig
39
+ from .rotations import ang2vec, erot, eulang, letter2vec, vec2ang
40
+ from .slowmotion import chili, tensor_cart2sph, tensor_sph2cart, wigner3j, wigner6j, wignerd
41
+ from .spinops import sop, stev
42
+ from .spinsystem import hsdim, spinvec, validatespinsys
43
+ from .symmetry import hamsymm
44
+ from .units import mhz2mt, mt2mhz, unitconvert
45
+
46
+ __version__ = "0.2.0"
47
+
48
+ __all__ = [
49
+ "amu", "avogadro", "bmagn", "boltzm", "clight", "echarge", "evolt", "gfree", "hbar", "mu0", "nmagn", "planck",
50
+ "ham", "ham_ee", "ham_ez", "ham_hf", "ham_nn", "ham_nq", "ham_nz", "ham_zf", "levels",
51
+ "Spectrum", "equivcouple", "fastmotion", "garlic",
52
+ "EndorResonances", "anisosubsys", "endorfrq", "endorfrq_perturb", "orisel", "salt", "curry",
53
+ "chili", "tensor_cart2sph", "tensor_sph2cart", "wigner3j", "wigner6j", "wignerd",
54
+ "apowin", "exponfit", "fdaxis", "larmorfrq", "saffron", "sf_pathways",
55
+ "FitResult", "addnoise", "basecorr", "deriv", "esfit", "esfit_genetic", "esfit_grid", "esfit_levmar",
56
+ "esfit_montecarlo", "esfit_simplex", "esfit_swarm", "hccm", "jacobianest", "rescaledata",
57
+ "SphGrid", "gridparam", "sphgrid",
58
+ "esspline1d", "esspline2d", "gridinterp",
59
+ "lisum1i", "projecttriangles", "projectzones",
60
+ "fieldmod", "hamsymm", "pepper", "resfields_perturb",
61
+ "convspec", "gaussian", "lorentzian", "lshape", "voigtian",
62
+ "Resonances", "cubicsolve", "nucspinrmv", "photoselect", "resfields", "resfields_eig",
63
+ "isotopes", "nucabund", "nucdata", "nucgval", "nucqmom", "nucspin", "nucstring2list",
64
+ "ang2vec", "erot", "eulang", "letter2vec", "vec2ang",
65
+ "sop", "stev",
66
+ "hsdim", "spinvec", "validatespinsys",
67
+ "mhz2mt", "mt2mhz", "unitconvert",
68
+ ] # fmt: skip
@@ -0,0 +1,71 @@
1
+ """EasySpin's loop over component spin systems (``compisoloop`` without the isotopologue expansion).
2
+
3
+ ``pepper({Sys1, Sys2}, Exp)`` sums the spectra of the components, each
4
+ weighted by ``Sys.weight`` (default 1); ``Opt.separate = 'components'``
5
+ stacks them. Isotope mixtures (``isotopologues``) are not ported, so each
6
+ component is one spin system.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from collections.abc import Callable
12
+
13
+ import numpy as np
14
+
15
+ _RANGE_FIELDS = ("Range", "CenterSweep", "mwRange", "mwCenterSweep")
16
+
17
+
18
+ def compisoloop(simfcn: Callable, systems: list | tuple, exp: dict, opt: dict | None, *, needs_range: bool = True):
19
+ """Sum (or stack) the spectra of the component systems ``systems`` simulated by ``simfcn``; ``needs_range``
20
+ is the cw simulators' demand for an explicit sweep range (pulse experiments carry their own axes)."""
21
+ from .garlic import Spectrum
22
+
23
+ opt = dict(opt or {})
24
+ separate = opt.get("separate", "") == "components"
25
+ if separate:
26
+ opt["separate"] = ""
27
+ if needs_range and len(systems) > 1 and not any(exp.get(k) is not None for k in _RANGE_FIELDS):
28
+ raise ValueError(
29
+ "For multiple components, EasySpin cannot automatically determine a sweep range. "
30
+ "Please specify sweep range manually using Exp.Range or Exp.CenterSweep "
31
+ "(Exp.mwRange or Exp.mwCenterSweep for frequency sweeps)."
32
+ )
33
+ spectra = []
34
+ inverse = [] # the other domain of pulse experiments (info["fd"]), summed with the same weights
35
+ info: dict = {"Component": [], "Transitions": [], "nTransitions": []}
36
+ x = None
37
+ for k, system in enumerate(systems, start=1):
38
+ sys_k = dict(system)
39
+ weight = float(np.asarray(sys_k.pop("weight", 1.0)).ravel()[0])
40
+ res = simfcn(sys_k, exp, opt)
41
+ x = res.x
42
+ spec_k = np.asarray(res.spec)
43
+ spectra.append((spec_k if np.iscomplexobj(spec_k) else spec_k.astype(float)) * weight)
44
+ info["Component"].append(k)
45
+ if res.info.get("fd") is not None:
46
+ inverse.append(np.asarray(res.info["fd"]) * weight)
47
+ for key in ("f", "f1", "f2"):
48
+ if key in res.info:
49
+ info[key] = res.info[key]
50
+ info["td"] = None if res.info.get("td") is None else True
51
+ for key in ("Transitions", "nOrientations", "nSites", "resfields"):
52
+ if key in res.info:
53
+ info.setdefault(key, []).append(res.info[key])
54
+ if "Transitions" in res.info:
55
+ info["nTransitions"].append(np.asarray(res.info["Transitions"]).shape[0])
56
+ if not info["Transitions"]:
57
+ info.pop("Transitions")
58
+ info.pop("nTransitions")
59
+ elif len(info["Transitions"]) == 1:
60
+ info["Transitions"] = info["Transitions"][0]
61
+ if "resfields" in info and len(info["resfields"]) == 1:
62
+ info["resfields"] = info["resfields"][0]
63
+ if separate:
64
+ spec = np.stack([np.atleast_2d(s) for s in spectra]).reshape(-1, spectra[0].shape[-1])
65
+ else:
66
+ spec = sum(spectra)
67
+ if inverse:
68
+ info["fd"] = np.stack(inverse) if separate else sum(inverse)
69
+ if info["td"] is not None:
70
+ info["td"] = spec
71
+ return Spectrum(x, spec, info)
@@ -0,0 +1,21 @@
1
+ """Physical constants with EasySpin's names and values.
2
+
3
+ EasySpin exposes each constant as a function (``bmagn()``); here they are
4
+ module attributes (``epreasy.bmagn``). Values are those of EasySpin 6.0.15
5
+ (CODATA 2022 where not exact by the 2019 SI redefinition).
6
+ """
7
+
8
+ from math import pi
9
+
10
+ bmagn = 9.2740100657e-24 # Bohr magneton, J/T
11
+ nmagn = 5.0507837393e-27 # nuclear magneton, J/T
12
+ planck = 6.62607015e-34 # Planck constant, J s (exact)
13
+ hbar = planck / (2 * pi) # reduced Planck constant, J s
14
+ gfree = 2.00231930436092 # free-electron g factor
15
+ clight = 299792458.0 # speed of light in vacuum, m/s (exact)
16
+ mu0 = 1.25663706127e-6 # vacuum permeability, N/A^2
17
+ boltzm = 1.380649e-23 # Boltzmann constant, J/K (exact)
18
+ echarge = 1.602176634e-19 # elementary charge, C (exact)
19
+ evolt = echarge # electron volt, J (exact)
20
+ amu = 1.66053906892e-27 # atomic mass unit, kg
21
+ avogadro = 6.02214076e23 # Avogadro constant, 1/mol (exact)