vacspin 0.2.0__tar.gz → 0.3.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 (28) hide show
  1. {vacspin-0.2.0 → vacspin-0.3.0}/PKG-INFO +15 -4
  2. {vacspin-0.2.0 → vacspin-0.3.0}/README.md +14 -3
  3. {vacspin-0.2.0 → vacspin-0.3.0}/pyproject.toml +1 -1
  4. {vacspin-0.2.0 → vacspin-0.3.0}/src/vacspin/__init__.py +4 -4
  5. {vacspin-0.2.0 → vacspin-0.3.0}/src/vacspin/params.py +49 -2
  6. {vacspin-0.2.0 → vacspin-0.3.0}/src/vacspin.egg-info/PKG-INFO +15 -4
  7. {vacspin-0.2.0 → vacspin-0.3.0}/src/vacspin.egg-info/SOURCES.txt +1 -0
  8. vacspin-0.3.0/tests/test_gev.py +42 -0
  9. {vacspin-0.2.0 → vacspin-0.3.0}/LICENSE +0 -0
  10. {vacspin-0.2.0 → vacspin-0.3.0}/setup.cfg +0 -0
  11. {vacspin-0.2.0 → vacspin-0.3.0}/src/vacspin/cavity.py +0 -0
  12. {vacspin-0.2.0 → vacspin-0.3.0}/src/vacspin/hamiltonian.py +0 -0
  13. {vacspin-0.2.0 → vacspin-0.3.0}/src/vacspin/lab.py +0 -0
  14. {vacspin-0.2.0 → vacspin-0.3.0}/src/vacspin/readout.py +0 -0
  15. {vacspin-0.2.0 → vacspin-0.3.0}/src/vacspin/remote.py +0 -0
  16. {vacspin-0.2.0 → vacspin-0.3.0}/src/vacspin/transitions.py +0 -0
  17. {vacspin-0.2.0 → vacspin-0.3.0}/src/vacspin.egg-info/dependency_links.txt +0 -0
  18. {vacspin-0.2.0 → vacspin-0.3.0}/src/vacspin.egg-info/requires.txt +0 -0
  19. {vacspin-0.2.0 → vacspin-0.3.0}/src/vacspin.egg-info/top_level.txt +0 -0
  20. {vacspin-0.2.0 → vacspin-0.3.0}/tests/test_cavity.py +0 -0
  21. {vacspin-0.2.0 → vacspin-0.3.0}/tests/test_hamiltonian.py +0 -0
  22. {vacspin-0.2.0 → vacspin-0.3.0}/tests/test_integration.py +0 -0
  23. {vacspin-0.2.0 → vacspin-0.3.0}/tests/test_lab.py +0 -0
  24. {vacspin-0.2.0 → vacspin-0.3.0}/tests/test_metadata.py +0 -0
  25. {vacspin-0.2.0 → vacspin-0.3.0}/tests/test_params_remote.py +0 -0
  26. {vacspin-0.2.0 → vacspin-0.3.0}/tests/test_readout.py +0 -0
  27. {vacspin-0.2.0 → vacspin-0.3.0}/tests/test_snv_measured.py +0 -0
  28. {vacspin-0.2.0 → vacspin-0.3.0}/tests/test_transitions.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vacspin
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Group-IV colour-centre spin-photon interfaces: strained spin Hamiltonians, cyclicity, transition-resolved Purcell budgets and exact single-shot readout statistics
5
5
  Author: Tanvir Mahmud Mahim
6
6
  License: Apache-2.0
@@ -128,8 +128,19 @@ No physical number is made up, and none is accepted without a source
128
128
  of Hepp et al., PRL 112, 036405 (2014). Strain and orbital
129
129
  quenching are sample-specific and deliberately not shipped; the
130
130
  reference string says so.
131
-
132
- For GeV-, PbV-, or your own sample, populate `SpinParameters` and
131
+ - `gev_bhaskar2017()`: the measured GeV- splittings (152 and
132
+ 981 GHz, zero-phonon line 602 nm) of Bhaskar et al., PRL 118,
133
+ 223603 (2017), with the same deliberate omissions as SiV- --
134
+ strain and quenching are your sample's numbers, and `vacspin.lab`
135
+ exists to fit them.
136
+
137
+ The lead-vacancy (PbV-) centre is documented but not shipped, on
138
+ purpose: its ground splitting is measured (about 3900 GHz; Wang et
139
+ al., ACS Photonics 8, 2947 (2021), confirmed in 2026), but no
140
+ verified measured excited-state splitting was available, and this
141
+ package does not ship half a parameter set.
142
+
143
+ For PbV-, or your own sample of any centre, populate `SpinParameters` and
133
144
  `EmissionBudget` from your measurements or the literature; the
134
145
  provenance travels with every prediction.
135
146
 
@@ -174,7 +185,7 @@ round trip is exact.
174
185
 
175
186
  ## How it is checked
176
187
 
177
- 56 tests (Python 3.9-3.13, run in CI on every push), every claim
188
+ 59 tests (Python 3.9-3.14 in CI on every push), every claim
178
189
  anchored to an exact result, a published measurement, or two
179
190
  independent code paths -- never a stored number. Highlights: exact
180
191
  Kramers doublets and the closed-form splitting against full
@@ -105,8 +105,19 @@ No physical number is made up, and none is accepted without a source
105
105
  of Hepp et al., PRL 112, 036405 (2014). Strain and orbital
106
106
  quenching are sample-specific and deliberately not shipped; the
107
107
  reference string says so.
108
-
109
- For GeV-, PbV-, or your own sample, populate `SpinParameters` and
108
+ - `gev_bhaskar2017()`: the measured GeV- splittings (152 and
109
+ 981 GHz, zero-phonon line 602 nm) of Bhaskar et al., PRL 118,
110
+ 223603 (2017), with the same deliberate omissions as SiV- --
111
+ strain and quenching are your sample's numbers, and `vacspin.lab`
112
+ exists to fit them.
113
+
114
+ The lead-vacancy (PbV-) centre is documented but not shipped, on
115
+ purpose: its ground splitting is measured (about 3900 GHz; Wang et
116
+ al., ACS Photonics 8, 2947 (2021), confirmed in 2026), but no
117
+ verified measured excited-state splitting was available, and this
118
+ package does not ship half a parameter set.
119
+
120
+ For PbV-, or your own sample of any centre, populate `SpinParameters` and
110
121
  `EmissionBudget` from your measurements or the literature; the
111
122
  provenance travels with every prediction.
112
123
 
@@ -151,7 +162,7 @@ round trip is exact.
151
162
 
152
163
  ## How it is checked
153
164
 
154
- 56 tests (Python 3.9-3.13, run in CI on every push), every claim
165
+ 59 tests (Python 3.9-3.14 in CI on every push), every claim
155
166
  anchored to an exact result, a published measurement, or two
156
167
  independent code paths -- never a stored number. Highlights: exact
157
168
  Kramers doublets and the closed-form splitting against full
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "vacspin"
7
- version = "0.2.0"
7
+ version = "0.3.0"
8
8
  description = "Group-IV colour-centre spin-photon interfaces: strained spin Hamiltonians, cyclicity, transition-resolved Purcell budgets and exact single-shot readout statistics"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -14,8 +14,8 @@ diamond nanocavity on thin-film lithium niobate" (submitted to Optics
14
14
  Express, 2026), and the effective-Hamiltonian and readout formalism of
15
15
  Rosenthal et al., PRX 13, 031022 (2023) and arXiv:2403.13110.
16
16
  """
17
- from .params import (EmissionBudget, SpinParameters, siv_hepp2014,
18
- snv_emission, snv_rosenthal2023)
17
+ from .params import (EmissionBudget, SpinParameters, gev_bhaskar2017,
18
+ siv_hepp2014, snv_emission, snv_rosenthal2023)
19
19
  from .hamiltonian import (GAMMA_GHZ_PER_T, h_manifold, lab_to_spin,
20
20
  qubit_frequency, qubit_frequency_perpendicular,
21
21
  solve, zero_field_splitting)
@@ -31,10 +31,10 @@ from .lab import (SpinFit, design_fields, fit_spin_parameters,
31
31
  load_observations_csv, parameter_information,
32
32
  save_observations_csv)
33
33
 
34
- __version__ = "0.2.0"
34
+ __version__ = "0.3.0"
35
35
  __all__ = [
36
36
  "SpinParameters", "EmissionBudget", "snv_rosenthal2023",
37
- "snv_emission", "siv_hepp2014",
37
+ "snv_emission", "siv_hepp2014", "gev_bhaskar2017",
38
38
  "GAMMA_GHZ_PER_T", "h_manifold", "lab_to_spin", "solve",
39
39
  "zero_field_splitting", "qubit_frequency",
40
40
  "qubit_frequency_perpendicular",
@@ -24,7 +24,25 @@ without a source: both dataclasses refuse to exist without a
24
24
  string, and you supply your measured values for field-dependent
25
25
  work.
26
26
 
27
- For any other centre (GeV-, PbV-, or your own SnV sample), populate the
27
+ * `gev_bhaskar2017`: the germanium-vacancy (GeV-) centre, measured
28
+ unstrained orbital splittings of M. K. Bhaskar et al., Phys. Rev.
29
+ Lett. 118, 223603 (2017) (arXiv:1612.03036): 152 GHz ground,
30
+ 981 GHz excited, 602 nm zero-phonon line. As for SiV-, strain and
31
+ orbital quenching are sample-specific and deliberately NOT shipped
32
+ (Siyushev et al., PRB 96, 081201(R) (2017) measured 170 GHz on a
33
+ strained emitter -- about 20 GHz of transverse-strain contribution
34
+ -- which is exactly why); supply your measured values, or fit them
35
+ with `vacspin.lab`.
36
+
37
+ The lead-vacancy (PbV-) centre is documented but NOT shipped, on
38
+ purpose: its ground-state splitting is measured (about 3900 GHz;
39
+ P. Wang et al., ACS Photonics 8, 2947 (2021), arXiv:2106.03413,
40
+ confirmed by Chen et al., arXiv:2605.27841 (2026)), but no verified
41
+ measured excited-state splitting was available to this package's
42
+ maintainers, and this package does not ship half a parameter set.
43
+ Populate `SpinParameters` yourself when your sample's numbers exist.
44
+
45
+ For any other centre, or your own sample of any centre, populate the
28
46
  dataclasses from your measurements or the literature; the mandatory
29
47
  `reference` field keeps the provenance attached to every prediction.
30
48
  """
@@ -35,7 +53,7 @@ import dataclasses
35
53
  import numpy as np
36
54
 
37
55
  __all__ = ["SpinParameters", "EmissionBudget", "snv_rosenthal2023",
38
- "snv_emission", "siv_hepp2014"]
56
+ "snv_emission", "siv_hepp2014", "gev_bhaskar2017"]
39
57
 
40
58
 
41
59
  def _check_ref(reference):
@@ -186,3 +204,32 @@ def siv_hepp2014(theta_rad=None, phi_rad=None) -> SpinParameters:
186
204
  "splittings 50/260 GHz, ZPL 737 nm; strain and "
187
205
  "orbital quenching deliberately not shipped (sample-"
188
206
  "specific) -- supply measured values")
207
+
208
+
209
+ def gev_bhaskar2017(theta_rad=None, phi_rad=None) -> SpinParameters:
210
+ """GeV- measured unstrained values of Bhaskar et al., PRL 118,
211
+ 223603 (2017): orbital splittings 152 GHz (ground) and 981 GHz
212
+ (excited), zero-phonon line 602 nm. Strain and orbital quenching
213
+ are sample-specific and NOT shipped: this set carries ups = 0 and
214
+ f = delta = 0, stated here on purpose (Siyushev et al., PRB 96,
215
+ 081201(R) (2017) measured 170 GHz on a strained emitter, about
216
+ 20 GHz of it transverse strain) -- supply your measured values,
217
+ or fit them from your own frequencies with `vacspin.lab`. Default
218
+ orientation: the <111> axis of a (001)-oriented sample, exact
219
+ crystallography, overridable. Millisecond-scale coherence at
220
+ millikelvin temperatures is measured for this centre (Senkalla et
221
+ al., PRL 132, 026901 (2024): 24.1 ms CPMG below 300 mK)."""
222
+ if theta_rad is None:
223
+ theta_rad = float(np.arccos(1.0 / np.sqrt(3.0)))
224
+ if phi_rad is None:
225
+ phi_rad = float(np.pi / 4)
226
+ return SpinParameters(
227
+ lam_g=152.0, ups_g=0.0, lam_e=981.0, ups_e=0.0,
228
+ f_g=0.0, f_e=0.0, delta_g=0.0, delta_e=0.0,
229
+ theta_rad=theta_rad, phi_rad=phi_rad,
230
+ reference="Bhaskar et al., PRL 118, 223603 (2017): measured "
231
+ "unstrained splittings 152/981 GHz, ZPL 602 nm; "
232
+ "strain and orbital quenching deliberately not "
233
+ "shipped (sample-specific; cf. Siyushev et al., "
234
+ "PRB 96, 081201(R) (2017)) -- supply measured "
235
+ "values")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vacspin
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Group-IV colour-centre spin-photon interfaces: strained spin Hamiltonians, cyclicity, transition-resolved Purcell budgets and exact single-shot readout statistics
5
5
  Author: Tanvir Mahmud Mahim
6
6
  License: Apache-2.0
@@ -128,8 +128,19 @@ No physical number is made up, and none is accepted without a source
128
128
  of Hepp et al., PRL 112, 036405 (2014). Strain and orbital
129
129
  quenching are sample-specific and deliberately not shipped; the
130
130
  reference string says so.
131
-
132
- For GeV-, PbV-, or your own sample, populate `SpinParameters` and
131
+ - `gev_bhaskar2017()`: the measured GeV- splittings (152 and
132
+ 981 GHz, zero-phonon line 602 nm) of Bhaskar et al., PRL 118,
133
+ 223603 (2017), with the same deliberate omissions as SiV- --
134
+ strain and quenching are your sample's numbers, and `vacspin.lab`
135
+ exists to fit them.
136
+
137
+ The lead-vacancy (PbV-) centre is documented but not shipped, on
138
+ purpose: its ground splitting is measured (about 3900 GHz; Wang et
139
+ al., ACS Photonics 8, 2947 (2021), confirmed in 2026), but no
140
+ verified measured excited-state splitting was available, and this
141
+ package does not ship half a parameter set.
142
+
143
+ For PbV-, or your own sample of any centre, populate `SpinParameters` and
133
144
  `EmissionBudget` from your measurements or the literature; the
134
145
  provenance travels with every prediction.
135
146
 
@@ -174,7 +185,7 @@ round trip is exact.
174
185
 
175
186
  ## How it is checked
176
187
 
177
- 56 tests (Python 3.9-3.13, run in CI on every push), every claim
188
+ 59 tests (Python 3.9-3.14 in CI on every push), every claim
178
189
  anchored to an exact result, a published measurement, or two
179
190
  independent code paths -- never a stored number. Highlights: exact
180
191
  Kramers doublets and the closed-form splitting against full
@@ -15,6 +15,7 @@ src/vacspin.egg-info/dependency_links.txt
15
15
  src/vacspin.egg-info/requires.txt
16
16
  src/vacspin.egg-info/top_level.txt
17
17
  tests/test_cavity.py
18
+ tests/test_gev.py
18
19
  tests/test_hamiltonian.py
19
20
  tests/test_integration.py
20
21
  tests/test_lab.py
@@ -0,0 +1,42 @@
1
+ """GeV- anchors: the shipped values are locked to their source
2
+ (Bhaskar et al., PRL 118, 223603 (2017): 152 GHz ground, 981 GHz
3
+ excited, measured); at zero strain the closed-form zero-field
4
+ splitting IS the spin-orbit constant, exactly; the full solver
5
+ reproduces both splittings; the dipole sum rule holds for this centre
6
+ as an identity; an aligned field keeps the flip channel exactly dark
7
+ (the same protection SnV and SiV show); and the provenance string
8
+ carries its source and its deliberate omissions."""
9
+ import numpy as np
10
+
11
+ from vacspin import (cyclicity, gev_bhaskar2017, solve,
12
+ transition_table, zero_field_splitting)
13
+
14
+
15
+ def test_values_locked_to_source():
16
+ p = gev_bhaskar2017()
17
+ assert (p.lam_g, p.lam_e) == (152.0, 981.0)
18
+ assert (p.ups_g, p.ups_e) == (0.0, 0.0)
19
+ assert (p.f_g, p.f_e, p.delta_g, p.delta_e) == (0.0,) * 4
20
+ assert "Bhaskar" in p.reference and "223603" in p.reference
21
+ assert "not" in p.reference # the omissions are stated too
22
+
23
+
24
+ def test_zero_field_splittings_exact():
25
+ p = gev_bhaskar2017()
26
+ assert zero_field_splitting(p.lam_g, p.ups_g) == 152.0
27
+ assert zero_field_splitting(p.lam_e, p.ups_e) == 981.0
28
+ eg, _, ee, _ = solve(p, [0.0, 0.0, 0.0])
29
+ assert abs((eg[2] - eg[0]) - 152.0) < 1e-9
30
+ assert abs((ee[2] - ee[0]) - 981.0) < 1e-9
31
+
32
+
33
+ def test_sum_rule_and_aligned_protection():
34
+ p = gev_bhaskar2017()
35
+ for b in ([0, 0, 0], [0.03, -0.05, 0.09]):
36
+ t = transition_table(p, b)
37
+ assert np.allclose(t["strengths"].sum(axis=1), 3.0, rtol=0,
38
+ atol=1e-10)
39
+ mu = np.array([np.sin(p.theta_rad) * np.cos(p.phi_rad),
40
+ np.sin(p.theta_rad) * np.sin(p.phi_rad),
41
+ np.cos(p.theta_rad)])
42
+ assert cyclicity(p, 0.1 * mu) > 1e12
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes