spinguin 0.0.1__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 (40) hide show
  1. spinguin-0.0.1/LICENSE +21 -0
  2. spinguin-0.0.1/MANIFEST.in +2 -0
  3. spinguin-0.0.1/PKG-INFO +88 -0
  4. spinguin-0.0.1/README.md +53 -0
  5. spinguin-0.0.1/pyproject.toml +19 -0
  6. spinguin-0.0.1/setup.cfg +4 -0
  7. spinguin-0.0.1/setup.py +39 -0
  8. spinguin-0.0.1/src/spinguin/__init__.py +10 -0
  9. spinguin-0.0.1/src/spinguin/api/__init__.py +41 -0
  10. spinguin-0.0.1/src/spinguin/api/basis.py +161 -0
  11. spinguin-0.0.1/src/spinguin/api/composite_spin_system.py +1 -0
  12. spinguin-0.0.1/src/spinguin/api/core.py +1492 -0
  13. spinguin-0.0.1/src/spinguin/api/parameters.py +287 -0
  14. spinguin-0.0.1/src/spinguin/api/relaxation_properties.py +254 -0
  15. spinguin-0.0.1/src/spinguin/api/spin_system.py +398 -0
  16. spinguin-0.0.1/src/spinguin/core/__init__.py +13 -0
  17. spinguin-0.0.1/src/spinguin/core/basis.py +537 -0
  18. spinguin-0.0.1/src/spinguin/core/c_sparse_dot.hpp +203 -0
  19. spinguin-0.0.1/src/spinguin/core/chem.py +585 -0
  20. spinguin-0.0.1/src/spinguin/core/data_io.py +124 -0
  21. spinguin-0.0.1/src/spinguin/core/hamiltonian.py +304 -0
  22. spinguin-0.0.1/src/spinguin/core/hide_prints.py +30 -0
  23. spinguin-0.0.1/src/spinguin/core/intersect_indices.cpp +28038 -0
  24. spinguin-0.0.1/src/spinguin/core/intersect_indices.pyx +102 -0
  25. spinguin-0.0.1/src/spinguin/core/la.py +791 -0
  26. spinguin-0.0.1/src/spinguin/core/liouvillian.py +46 -0
  27. spinguin-0.0.1/src/spinguin/core/nmr_isotopes.py +210 -0
  28. spinguin-0.0.1/src/spinguin/core/operators.py +420 -0
  29. spinguin-0.0.1/src/spinguin/core/propagation.py +193 -0
  30. spinguin-0.0.1/src/spinguin/core/relaxation.py +1027 -0
  31. spinguin-0.0.1/src/spinguin/core/sparse_dot.cpp +40932 -0
  32. spinguin-0.0.1/src/spinguin/core/sparse_dot.pyx +170 -0
  33. spinguin-0.0.1/src/spinguin/core/specutils.py +178 -0
  34. spinguin-0.0.1/src/spinguin/core/states.py +785 -0
  35. spinguin-0.0.1/src/spinguin/core/superoperators.py +566 -0
  36. spinguin-0.0.1/src/spinguin.egg-info/PKG-INFO +88 -0
  37. spinguin-0.0.1/src/spinguin.egg-info/SOURCES.txt +41 -0
  38. spinguin-0.0.1/src/spinguin.egg-info/dependency_links.txt +1 -0
  39. spinguin-0.0.1/src/spinguin.egg-info/requires.txt +4 -0
  40. spinguin-0.0.1/src/spinguin.egg-info/top_level.txt +1 -0
spinguin-0.0.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) [2025] [Joni Eronen]
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,2 @@
1
+ include src/spinguin/core/sparse_dot.pyx
2
+ include src/spinguin/core/intersect_indices.pyx
@@ -0,0 +1,88 @@
1
+ Metadata-Version: 2.4
2
+ Name: spinguin
3
+ Version: 0.0.1
4
+ Summary: Spinguin is an intuitive Python package for versatile numerical spin-dynamics simulations.
5
+ Author-email: Joni Eronen <joni.eronen@oulu.fi>, Perttu Hilla <perttu.hilla@oulu.fi>
6
+ License: MIT License
7
+
8
+ Copyright (c) [2025] [Joni Eronen]
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+ Requires-Python: >=3.11
28
+ Description-Content-Type: text/markdown
29
+ License-File: LICENSE
30
+ Requires-Dist: numpy>=1.26.4
31
+ Requires-Dist: scipy>=1.14.1
32
+ Requires-Dist: sympy>=1.13.1
33
+ Requires-Dist: joblib>=1.5.1
34
+ Dynamic: license-file
35
+
36
+ # Spinguin
37
+
38
+ ## Description
39
+ Spinguin is a user-friendly Python package designed for versatile numerical
40
+ spin-dynamics simulations in liquid state. It offers tools for performing
41
+ simulations using restricted basis sets, enabling the use of large spin systems
42
+ with more than 10 spins on consumer-level hardware. Spinguin supports the
43
+ simulation of coherent dynamics, relaxation, and chemical exchange processes.
44
+
45
+ ## Documentation
46
+ Documentation for the package is available here:
47
+ https://nmroulu.github.io/Spinguin/
48
+
49
+ ## Installation
50
+ Spinguin can be installed in various ways, depending on your needs and
51
+ preferences. You can install it from the Python Package Index (PyPI) or build it
52
+ from the source code available on GitHub. Below are the instructions for both
53
+ methods.
54
+
55
+ ### Installation from PyPI
56
+ Spinguin is available from the Python Package Index (PyPI) repository for
57
+ Windows and Linux. To install the package, simply issue the command::
58
+
59
+ ```bash
60
+ pip install spinguin
61
+ ```
62
+
63
+ ### Installation from source
64
+ 1. Ensure the `build` module is installed:
65
+ ```bash
66
+ pip install build
67
+ ```
68
+ 2. Download the source code archive (.zip or .tar.gz).
69
+ 3. Extract the archive (e.g., using 7-Zip).
70
+ 4. Navigate to the extracted folder:
71
+ ```bash
72
+ cd /your/path/spinguin-X.Y.Z
73
+ ```
74
+ 5. Build the wheel from the source:
75
+ ```bash
76
+ python -m build --wheel
77
+ ```
78
+ 6. Navigate to the `dist` folder:
79
+ ```bash
80
+ cd /your/path/spinguin-X.Y.Z/dist
81
+ ```
82
+ 7. Install the wheel using pip:
83
+ ```bash
84
+ pip install spinguin-X.Y.Z-cpXYZ-cpXYZ-PLATFORM.whl
85
+ ```
86
+
87
+ ## License
88
+ This project is licensed under the [MIT License](LICENSE).
@@ -0,0 +1,53 @@
1
+ # Spinguin
2
+
3
+ ## Description
4
+ Spinguin is a user-friendly Python package designed for versatile numerical
5
+ spin-dynamics simulations in liquid state. It offers tools for performing
6
+ simulations using restricted basis sets, enabling the use of large spin systems
7
+ with more than 10 spins on consumer-level hardware. Spinguin supports the
8
+ simulation of coherent dynamics, relaxation, and chemical exchange processes.
9
+
10
+ ## Documentation
11
+ Documentation for the package is available here:
12
+ https://nmroulu.github.io/Spinguin/
13
+
14
+ ## Installation
15
+ Spinguin can be installed in various ways, depending on your needs and
16
+ preferences. You can install it from the Python Package Index (PyPI) or build it
17
+ from the source code available on GitHub. Below are the instructions for both
18
+ methods.
19
+
20
+ ### Installation from PyPI
21
+ Spinguin is available from the Python Package Index (PyPI) repository for
22
+ Windows and Linux. To install the package, simply issue the command::
23
+
24
+ ```bash
25
+ pip install spinguin
26
+ ```
27
+
28
+ ### Installation from source
29
+ 1. Ensure the `build` module is installed:
30
+ ```bash
31
+ pip install build
32
+ ```
33
+ 2. Download the source code archive (.zip or .tar.gz).
34
+ 3. Extract the archive (e.g., using 7-Zip).
35
+ 4. Navigate to the extracted folder:
36
+ ```bash
37
+ cd /your/path/spinguin-X.Y.Z
38
+ ```
39
+ 5. Build the wheel from the source:
40
+ ```bash
41
+ python -m build --wheel
42
+ ```
43
+ 6. Navigate to the `dist` folder:
44
+ ```bash
45
+ cd /your/path/spinguin-X.Y.Z/dist
46
+ ```
47
+ 7. Install the wheel using pip:
48
+ ```bash
49
+ pip install spinguin-X.Y.Z-cpXYZ-cpXYZ-PLATFORM.whl
50
+ ```
51
+
52
+ ## License
53
+ This project is licensed under the [MIT License](LICENSE).
@@ -0,0 +1,19 @@
1
+ [project]
2
+ name = "spinguin"
3
+ version = "0.0.1"
4
+ dependencies = ["numpy >= 1.26.4", "scipy >= 1.14.1", "sympy >= 1.13.1", "joblib >= 1.5.1"]
5
+ requires-python = ">=3.11"
6
+ authors = [
7
+ {name = "Joni Eronen", email = "joni.eronen@oulu.fi"},
8
+ {name = "Perttu Hilla", email = "perttu.hilla@oulu.fi"}
9
+ ]
10
+ description = "Spinguin is an intuitive Python package for versatile numerical spin-dynamics simulations."
11
+ readme = "README.md"
12
+ license = {file = "LICENSE"}
13
+
14
+ [build-system]
15
+ requires = ["setuptools>=74.1", "wheel", "cython >= 3.0.11", "numpy >= 1.26.4", "cibuildwheel"]
16
+ build-backend = "setuptools.build_meta"
17
+
18
+ [tool.cibuildwheel]
19
+ skip = ["*-win32"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,39 @@
1
+ """
2
+ This script is required for compiling the sparse_dot() and intersect_indices()
3
+ Cython functions.
4
+ """
5
+
6
+ from setuptools import Extension, setup
7
+ from Cython.Build import cythonize
8
+ import sys
9
+ import numpy as np
10
+
11
+ # Platform-specific compiler and linker settings
12
+ if sys.platform == "win32":
13
+ extra_compile_args = ['/openmp', '/O2', '/arch:SSE2', '/GS-']
14
+ extra_link_args = []
15
+ elif sys.platform == "linux":
16
+ extra_compile_args = ['-fopenmp', '-Ofast', '-march=native']
17
+ extra_link_args = ['-fopenmp']
18
+
19
+ ext_modules = [
20
+ Extension(
21
+ name = "spinguin.core.sparse_dot",
22
+ sources = ["src/spinguin/core/sparse_dot.pyx"],
23
+ include_dirs = [np.get_include()],
24
+ extra_compile_args = extra_compile_args,
25
+ extra_link_args = extra_link_args,
26
+ language = 'c++'
27
+ ),
28
+ Extension(
29
+ name = "spinguin.core.intersect_indices",
30
+ sources = ["src/spinguin/core/intersect_indices.pyx"],
31
+ extra_compile_args = extra_compile_args,
32
+ extra_link_args = extra_link_args,
33
+ language = 'c++'
34
+ )
35
+ ]
36
+
37
+ setup(
38
+ ext_modules=cythonize(ext_modules, annotate=True)
39
+ )
@@ -0,0 +1,10 @@
1
+ """
2
+ Spinguin package is desined to be imported as `import spinguin as sg`, which
3
+ reveals the user-friendly functionality to the user. This is documented under
4
+ the Spinguin (Basic). For more in-depth documentation of the package, including
5
+ the documentation of the re-usable, core functionality, see Spinguin (Advanced).
6
+ """
7
+
8
+ # Make functionality from the API accessible directly under the spinguin
9
+ # namespace
10
+ from spinguin.api import *
@@ -0,0 +1,41 @@
1
+ """
2
+ This module provides user friendly wrapper functions of the Spinguin's core
3
+ functionality by making use of the `SpinSystem` class.
4
+ """
5
+
6
+ # Expose only the necessary functions from the API
7
+ from spinguin.api.core import (
8
+ alpha_state,
9
+ beta_state,
10
+ associate,
11
+ dissociate,
12
+ equilibrium_state,
13
+ frequency_to_chemical_shift,
14
+ hamiltonian,
15
+ inversion_recovery,
16
+ liouvillian,
17
+ measure,
18
+ operator,
19
+ permute_spins,
20
+ propagator,
21
+ propagator_to_rotframe,
22
+ pulse,
23
+ pulse_and_acquire,
24
+ relaxation,
25
+ resonance_frequency,
26
+ singlet_state,
27
+ spectral_width_to_dwell_time,
28
+ spectrum,
29
+ state,
30
+ state_to_zeeman,
31
+ superoperator,
32
+ time_axis,
33
+ triplet_minus_state,
34
+ triplet_plus_state,
35
+ triplet_zero_state,
36
+ unit_state
37
+ )
38
+
39
+ from spinguin.api.parameters import parameters
40
+
41
+ from spinguin.api.spin_system import SpinSystem
@@ -0,0 +1,161 @@
1
+ """
2
+ This module provides the Basis class which is assigned as a part of `SpinSystem`
3
+ object upon its instantiation. Here is an example of accessing the most
4
+ important functionality of the class::
5
+
6
+ import spinguin as sg # Import the package
7
+ spin_system = sg.SpinSystem(["1H"]) # Create an example spin system
8
+ spin_system.basis.max_spin_order = 1 # Set the maximum spin order
9
+ spin_system.basis.build() # Build the basis set
10
+ """
11
+
12
+ # Referencing SpinSystem class
13
+ from __future__ import annotations
14
+ from typing import TYPE_CHECKING
15
+ if TYPE_CHECKING:
16
+ from spinguin.api.spin_system import SpinSystem
17
+
18
+ # Imports
19
+ import numpy as np
20
+ import scipy.sparse as sp
21
+ import warnings
22
+ from spinguin.core.states import state_to_truncated_basis
23
+ from spinguin.core.superoperators import sop_to_truncated_basis
24
+ from spinguin.core.basis import make_basis, truncate_basis_by_coherence
25
+ from spinguin.core.la import isvector
26
+
27
+ class Basis:
28
+ """
29
+ Basis class manages the basis set of a spin system. Most importantly, the
30
+ basis set contains the information on the truncation of the basis set and is
31
+ responsible for building and making changes to the basis set.
32
+ """
33
+
34
+ # Basis set properties
35
+ _basis: np.ndarray = None
36
+ _max_spin_order: int = None
37
+ _spin_system: SpinSystem = None
38
+
39
+ def __init__(self, spin_system: SpinSystem):
40
+ print("Basis set has been initialized with the following defaults:")
41
+ print(f"max_spin_order: {self.max_spin_order}\n")
42
+
43
+ # Store a reference to the SpinSystem
44
+ self._spin_system = spin_system
45
+
46
+ @property
47
+ def dim(self) -> int:
48
+ """Dimension of the basis set."""
49
+ return self.basis.shape[0]
50
+
51
+ @property
52
+ def max_spin_order(self) -> int:
53
+ """
54
+ Specifies the maximum number of a active spins that are included in the
55
+ product operators that constitute the basis set. Must be at least 1 and
56
+ not larger than the number of spins in the system.
57
+ """
58
+ return self._max_spin_order
59
+
60
+ @property
61
+ def basis(self) -> np.ndarray:
62
+ """
63
+ Contains the actual basis set as an array of dimensions (N, M) where
64
+ N is the number of states in the basis and M is the number of spins in
65
+ the system. The basis set is constructed from Kronecker products of
66
+ irreducible spherical tensor operators, which are indexed using integers
67
+ starting from 0 with increasing rank `l` and decreasing projection `q`:
68
+
69
+ - 0 --> T(0, 0)
70
+ - 1 --> T(1, 1)
71
+ - 2 --> T(1, 0)
72
+ - 3 --> T(1, -1) and so on...
73
+
74
+ """
75
+ return self._basis
76
+
77
+ @max_spin_order.setter
78
+ def max_spin_order(self, max_spin_order):
79
+ if max_spin_order < 1:
80
+ raise ValueError("Maximum spin order must be at least 1.")
81
+ if max_spin_order > self._spin_system.nspins:
82
+ raise ValueError("Maximum spin order must not be larger than "
83
+ "the number of spins in the system.")
84
+ self._max_spin_order = max_spin_order
85
+ print(f"Maximum spin order set to: {self.max_spin_order}\n")
86
+
87
+ def build(self):
88
+ """
89
+ Builds the basis set for the spin system. Prior to building the basis,
90
+ the maximum spin order should be defined. If it is not defined, it is
91
+ set equal to the number of spins in the system (may be very slow)!
92
+ """
93
+ # If maximum spin order is not specified, raise a warning and set it
94
+ # equal to the number of spins
95
+ if self.max_spin_order is None:
96
+ warnings.warn("Maximum spin order not specified. "
97
+ "Defaulting to the number of spins.")
98
+ self.max_spin_order = self._spin_system.nspins
99
+
100
+ # Build the basis
101
+ self._basis = make_basis(spins = self._spin_system.spins,
102
+ max_spin_order = self.max_spin_order)
103
+
104
+ def truncate_by_coherence(
105
+ self,
106
+ coherence_orders: list,
107
+ *objs: np.ndarray | sp.csc_array
108
+ ) -> None | np.ndarray | sp.csc_array | tuple[np.ndarray | sp.csc_array]:
109
+ """
110
+ Truncates the basis set by retaining only the product operators that
111
+ correspond to coherence orders specified in the `coherence_orders` list.
112
+
113
+ Optionally, superoperators or state vectors can be given as input. These
114
+ will be converted to the truncated basis.
115
+
116
+ Parameters
117
+ ----------
118
+ coherence_orders : list
119
+ List of coherence orders to be retained in the basis.
120
+
121
+ Returns
122
+ -------
123
+ objs_transformed : ndarray or csc_array or tuple
124
+ Superoperators and state vectors transformed into the truncated
125
+ basis.
126
+ """
127
+ # Truncate the basis and obtain the index map
128
+ truncated_basis, index_map = truncate_basis_by_coherence(
129
+ basis = self.basis,
130
+ coherence_orders = coherence_orders
131
+ )
132
+
133
+ # Update the basis
134
+ self._basis = truncated_basis
135
+
136
+ # Optionally, convert the superoperators and state vectors to the
137
+ # truncated basis
138
+ if objs:
139
+ objs_transformed = []
140
+ for obj in objs:
141
+
142
+ # Consider state vectors
143
+ if isvector(obj):
144
+ objs_transformed.append(state_to_truncated_basis(
145
+ index_map=index_map,
146
+ rho=obj))
147
+
148
+ # Consider superoperators
149
+ else:
150
+ objs_transformed.append(sop_to_truncated_basis(
151
+ index_map=index_map,
152
+ sop=obj
153
+ ))
154
+
155
+ # Convert to tuple or just single value
156
+ if len(objs_transformed) == 1:
157
+ objs_transformed = objs_transformed[0]
158
+ else:
159
+ objs_transformed = tuple(objs_transformed)
160
+
161
+ return objs_transformed