Skip to content

Commit d0124a9

Browse files
Jammy2211claude
authored andcommitted
perf: defer scipy imports to reduce import time
Move scipy imports from module level to local function scope in convolver, delaunay interpolator, mask utilities, cholesky, and fnnls modules. This avoids loading scipy during `import autoarray`, cutting ~0.3s from the import floor in smoke tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent ff0f45e commit d0124a9

File tree

6 files changed

+17
-8
lines changed

6 files changed

+17
-8
lines changed

autoarray/inversion/inversion/inversion_util.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from autoarray.settings import Settings
66

77
from autoarray import exc
8-
from autoarray.util.fnnls import fnnls_cholesky
98

109

1110
def curvature_matrix_diag_via_psf_weighted_noise_from(
@@ -281,6 +280,8 @@ def reconstruction_positive_only_from(
281280

282281
try:
283282

283+
from autoarray.util.fnnls import fnnls_cholesky
284+
284285
return fnnls_cholesky(
285286
curvature_reg_matrix,
286287
(data_vector).T,

autoarray/inversion/mesh/interpolator/delaunay.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import numpy as np
2-
import scipy.spatial
3-
from scipy.spatial import cKDTree, Delaunay, Voronoi
42

53
from autoconf import cached_property
64

@@ -12,6 +10,7 @@
1210

1311
def scipy_delaunay(points_np, query_points_np, areas_factor):
1412
"""Compute Delaunay simplices (simplices_padded) and Voronoi areas in one call."""
13+
from scipy.spatial import Delaunay
1514

1615
max_simplices = 2 * points_np.shape[0]
1716

@@ -182,6 +181,8 @@ def pix_indexes_for_sub_slim_index_delaunay_from(
182181
# Case 2: Outside → KDTree NN
183182
# ---------------------------
184183
if outside_mask.any():
184+
from scipy.spatial import cKDTree
185+
185186
tree = cKDTree(delaunay_points)
186187
_, idx = tree.query(data_grid[outside_mask], k=1)
187188
out[outside_mask, 0] = idx.astype(np.int32)
@@ -202,6 +203,7 @@ def scipy_delaunay_matern(points_np, query_points_np):
202203
typically of shape (Q, 3), where each row gives the indices of the
203204
Delaunay mesh vertices ("pixels") associated with that query point.
204205
"""
206+
from scipy.spatial import Delaunay
205207

206208
max_simplices = 2 * points_np.shape[0]
207209

autoarray/mask/mask_2d_util.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import numpy as np
22
import warnings
3-
from scipy.ndimage import binary_dilation
43
from typing import Tuple
54

65
from autoarray import exc
@@ -465,7 +464,6 @@ def min_false_distance_to_edge(mask: np.ndarray) -> Tuple[int, int]:
465464
from typing import Tuple
466465

467466
import numpy as np
468-
from scipy.ndimage import binary_dilation
469467

470468

471469
def required_shape_for_kernel(
@@ -608,6 +606,8 @@ def blurring_mask_2d_from(
608606
)
609607

610608
# Pixels within kernel footprint of any unmasked pixel
609+
from scipy.ndimage import binary_dilation
610+
611611
near_unmasked_padded = binary_dilation(unmasked_padded, structure=structure)
612612
near_unmasked = near_unmasked_padded[
613613
pad_y : pad_y + mask_2d.shape[0],

autoarray/operators/convolver.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
import numpy as np
99
from pathlib import Path
10-
import scipy
1110
from typing import Optional, Tuple, Union
1211
import warnings
1312

@@ -116,6 +115,8 @@ class determines how masked real-space data are embedded into a padded array,
116115
full_shape = tuple(
117116
s1 + s2 - 1 for s1, s2 in zip(mask_shape, self.kernel.shape_native)
118117
)
118+
import scipy.fft
119+
119120
fft_shape = tuple(scipy.fft.next_fast_len(s, real=True) for s in full_shape)
120121

121122
self.fft_shape = fft_shape

autoarray/util/cholesky_funcs.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import numpy as np
2-
from scipy import linalg
32
import math
43
import time
54
from autoarray import numba_util
@@ -46,6 +45,8 @@ def _cholupdate(U, x):
4645

4746

4847
def cholinsert(U, index, x):
48+
from scipy import linalg
49+
4950
S = np.insert(np.insert(U, index, 0, axis=0), index, 0, axis=1)
5051

5152
S[:index, index] = S12 = linalg.solve_triangular(
@@ -70,6 +71,8 @@ def cholinsertlast(U, x):
7071
As in current Cholesky scheme implemented in fnnls, we only use this kind of insertion, so I
7172
separate it out from the `cholinsert`.
7273
"""
74+
from scipy import linalg
75+
7376
index = U.shape[0]
7477

7578
S = np.insert(np.insert(U, index, 0, axis=0), index, 0, axis=1)

autoarray/util/fnnls.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import numpy as np
2-
from scipy import linalg as slg
32

43
from autoarray.util.cholesky_funcs import cholinsertlast, choldeleteindexes
54

@@ -27,6 +26,7 @@ def fnnls_cholesky(
2726
"""
2827
Similar to fnnls, but use solving the lstsq problem by updating Cholesky factorisation.
2928
"""
29+
from scipy import linalg as slg
3030

3131
lstsq = lambda A, x: slg.solve(
3232
A,
@@ -147,6 +147,8 @@ def fix_constraint_cholesky(ZTx, s_chol, d, P, P_inorder, U, tolerance):
147147
# solve the lstsq problem by cho_solve
148148

149149
if len(P_inorder):
150+
from scipy import linalg as slg
151+
150152
# there could be a case where P_inorder is empty.
151153
s_chol[P_inorder] = slg.cho_solve((U, False), ZTx[P_inorder])
152154

0 commit comments

Comments
 (0)