@@ -23,10 +23,29 @@ class NUFFTPlaceholder:
2323from autoarray .operators import transformer_util
2424
2525
26- try :
27- import nufftax as _nufftax
28- except ModuleNotFoundError :
29- _nufftax = None
26+ # nufftax pulls in jax at import (~0.7s), which sessions that never touch an
27+ # interferometer transformer should not pay for — deferred to _load_nufftax(),
28+ # called from TransformerNUFFT's entry points (not only __init__, because
29+ # unpickled instances in multiprocessing workers never re-run __init__).
30+ _nufftax = None
31+ _nufftax_loaded = False
32+
33+
34+ def _load_nufftax ():
35+ global _nufftax , _nufftax_loaded
36+ if _nufftax_loaded :
37+ return _nufftax
38+ _nufftax_loaded = True
39+ try :
40+ import nufftax
41+ except ModuleNotFoundError :
42+ return None
43+ _nufftax = nufftax
44+ _version = tuple (int (v ) for v in _nufftax .__version__ .split ("." )[:2 ])
45+ # Only the 0.6.x series both has the primitives module and needs the shim.
46+ if (0 , 6 ) <= _version < (0 , 7 ):
47+ _patch_nufftax_batchers ()
48+ return _nufftax
3049
3150
3251def _patch_nufftax_batchers ():
@@ -87,13 +106,6 @@ def batcher(args, dims, **kwargs):
87106 )
88107
89108
90- if _nufftax is not None :
91- _version = tuple (int (v ) for v in _nufftax .__version__ .split ("." )[:2 ])
92- # Only the 0.6.x series both has the primitives module and needs the shim.
93- if (0 , 6 ) <= _version < (0 , 7 ):
94- _patch_nufftax_batchers ()
95-
96-
97109def pynufft_exception ():
98110 raise ModuleNotFoundError (
99111 "\n --------------------\n "
@@ -643,7 +655,7 @@ def __init__(
643655 """
644656 from astropy import units
645657
646- if _nufftax is None :
658+ if _load_nufftax () is None :
647659 nufftax_exception ()
648660
649661 if chunk_size is not None and chunk_size <= 0 :
@@ -685,6 +697,8 @@ def _forward_native(self, image_native_2d, xp=np):
685697 fixed-size chunks via ``jax.lax.scan`` (JAX path) or a Python loop
686698 (numpy path) — caps the nufftax gather-buffer allocation per call.
687699 """
700+ _load_nufftax ()
701+
688702 K = int (self ._x .shape [0 ])
689703
690704 if xp .__name__ .startswith ("jax" ):
@@ -789,6 +803,8 @@ def image_from(
789803 the sparse-operator dirty image is scale-consistent across all three
790804 transformers.
791805 """
806+ _load_nufftax ()
807+
792808 n_y , n_x = self .real_space_mask .shape_native
793809 n_modes = (n_x , n_y ) # nufftax wants (n1, n2) = (N_x, N_y)
794810 K = int (self ._x .shape [0 ])
@@ -860,6 +876,8 @@ def transform_mapping_matrix(self, mapping_matrix, xp=np):
860876 ``n_src`` separate NUFFT invocations and blow up the JIT graph
861877 for pixelization-heavy fits (notably double-source-plane).
862878 """
879+ _load_nufftax ()
880+
863881 n_src = mapping_matrix .shape [1 ]
864882 rows , cols = self .real_space_mask .slim_to_native_tuple
865883 n_y , n_x = self .real_space_mask .shape_native
0 commit comments