Skip to content

Commit 59d7fe3

Browse files
authored
Merge pull request #36 from QTC-UMD/lazy_imports
Lazy imports for leveldiagram and arc dependencies
2 parents 74b1805 + 0717745 commit 59d7fe3

5 files changed

Lines changed: 48 additions & 18 deletions

File tree

docs/source/changelog.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ Latest
77
Improvements
88
++++++++++++
99

10+
- `leveldiagram` and `arc` dependencies are now lazy loaded at first use
11+
(`draw_diagram` and `Cell` instantiation, respectively).
12+
This improves `import rydiqule as rq` time by about a second
13+
and ensures second-order dependencies such as matplotlib and sympy are not
14+
imported unless explicitly needed.
15+
1016

1117
Bug Fixes
1218
+++++++++

src/rydiqule/arc_utils.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55
from __future__ import annotations
66
from typing import TYPE_CHECKING, Literal, Dict, Callable, Tuple
77

8-
from arc import C_e, C_c, C_h
98
from scipy.constants import pi, hbar, epsilon_0, physical_constants
9+
from scipy.constants import c as C_c
10+
from scipy.constants import h as C_h
11+
from scipy.constants import e as C_e
12+
1013
import numpy as np
1114

1215
from math import sqrt

src/rydiqule/atom_utils.py

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,48 @@
22
Utilities for interacting with atomic parameters and ARC.
33
"""
44

5-
import arc.alkali_atom_data as arc_atoms
65
from scipy.constants import epsilon_0, hbar, c
76
import numpy as np
8-
import re
7+
import re
98
from .sensor_utils import expand_statespec
109

11-
from typing import Union, Optional, Literal, Tuple, List, Dict, Callable, NamedTuple
10+
from typing import Union, Optional, Literal, Tuple, List, Dict, Callable, NamedTuple, TYPE_CHECKING
1211

13-
from .exceptions import RydiquleError
12+
from .exceptions import RydiquleError, AtomError
13+
14+
if TYPE_CHECKING:
15+
import arc.alkali_atom_data
1416

1517
ATOMS = {
16-
'H': arc_atoms.Hydrogen,
17-
'Li6': arc_atoms.Lithium6, 'Li7': arc_atoms.Lithium7,
18-
'Na': arc_atoms.Sodium,
19-
'K39': arc_atoms.Potassium39, 'K40': arc_atoms.Potassium40, 'K41': arc_atoms.Potassium41,
20-
'Rb85': arc_atoms.Rubidium85, 'Rb87': arc_atoms.Rubidium87,
21-
'Cs': arc_atoms.Caesium
18+
'H': 'Hydrogen',
19+
'Li6': 'Lithium6', 'Li7': 'Lithium7',
20+
'Na': 'Sodium',
21+
'K39': 'Potassium39', 'K40': 'Potassium40', 'K41': 'Potassium41',
22+
'Rb85': 'Rubidium85', 'Rb87': 'Rubidium87',
23+
'Cs': 'Caesium'
2224
}
2325
"""
2426
Alkali atoms defined by ARC that can be used with :class:`~.Cell`.
2527
"""
2628

29+
def _load_arc_atom(atom_flag: str) -> 'arc.alkali_atom_data.AlkaliAtom':
30+
"""
31+
Function that lazy loads ARC atoms from :external+arc:module:`~arc.alkali_atom_data`
32+
33+
Returns
34+
-------
35+
arc.alkali_atom_data.AlkaliAtom
36+
ARC alkali atom class associated with the provided atom_flag.
37+
"""
38+
39+
import arc.alkali_atom_data as arc_atoms
40+
41+
if atom_flag not in ATOMS.keys():
42+
raise AtomError(f"Atom flag must be one of {ATOMS.keys()}")
43+
44+
return getattr(arc_atoms, ATOMS[atom_flag])() # instantiate the class here
45+
46+
2747
ground_n = {
2848
"H": 1,
2949
"Li": 2,

src/rydiqule/cell.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
from .sensor import Sensor
1515
from .sensor_utils import scale_dipole
1616
from .sensor_utils import ScannableParameter, TimeFunc
17-
from .atom_utils import ATOMS, calc_kappa, calc_eta, expand_qnums, validate_qnums, A_QState, ground_state
17+
from .atom_utils import calc_kappa, calc_eta, expand_qnums, validate_qnums, A_QState, ground_state, _load_arc_atom
1818
from .arc_utils import RQ_AlkaliAtom
19-
from .exceptions import RydiquleError, AtomError, CouplingNotAllowedError
19+
from .exceptions import RydiquleError, CouplingNotAllowedError
2020
from .exceptions import RydiquleWarning, debug_state
2121

2222
from typing import Literal, Optional, Sequence, List, Tuple, Callable, Union, Dict
@@ -165,11 +165,9 @@ def __init__(self, atom_flag: AtomFlags, atomic_states: List[A_QState],
165165
(5, 0, 0.5, f=2.0, m_f=2.0)
166166
167167
"""
168-
if atom_flag not in ATOMS.keys():
169-
raise AtomError(f"Atom flag must be one of {ATOMS.keys()}")
170168

171169
self.atom_flag = atom_flag
172-
self.atom = RQ_AlkaliAtom(ATOMS[atom_flag]())
170+
self.atom = RQ_AlkaliAtom(_load_arc_atom(atom_flag))
173171
self.I = self.atom.arc_atom.I
174172

175173
#prepare states by expanding statespec into list and initialize graph

src/rydiqule/sensor_utils.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
from .exceptions import RydiquleError
1111
import scipy.constants
1212
from scipy.constants import hbar, e
13-
from leveldiagram import LD
1413

1514
from typing import Dict, Tuple, Union, List, Callable, TYPE_CHECKING
1615
if TYPE_CHECKING:
1716
# only import when type checking, avoid circular import
1817
from .sensor import Sensor
18+
from leveldiagram import LD
1919

2020
a0 = scipy.constants.physical_constants["Bohr radius"][0]
2121

@@ -713,7 +713,7 @@ def scale_dipole(dipole: Union[float, np.ndarray]) -> Union[float, np.ndarray]:
713713
return dipole
714714

715715

716-
def draw_diagram(sensor: "Sensor", include_dephasing: bool = True) -> LD:
716+
def draw_diagram(sensor: "Sensor", include_dephasing: bool = True) -> "LD":
717717
"""
718718
Draw a matplotlib plot that shows the energy level diagram, couplings, and dephasing paths.
719719
@@ -745,6 +745,9 @@ def draw_diagram(sensor: "Sensor", include_dephasing: bool = True) -> LD:
745745
Diagram handle
746746
747747
"""
748+
# lazy import of leveldiagram to avoid matplotlib import when not needed
749+
from leveldiagram import LD
750+
748751
rq_g = sensor.couplings.copy()
749752
sensor_states = sensor.states
750753

0 commit comments

Comments
 (0)