Skip to content

Commit 6f54ab1

Browse files
committed
Switch to using sparse arrays instead of the deprecated sparse matrix interface
1 parent e7e6429 commit 6f54ab1

File tree

1 file changed

+45
-44
lines changed

1 file changed

+45
-44
lines changed

src/toast/ops/filterbin.py

Lines changed: 45 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,12 @@ def combine_observation_matrix(rootname):
100100
if current_row != nrow_tot:
101101
all_indptr.append(np.zeros(nrow_tot - current_row) + current_offset)
102102

103-
log.info("Constructing CSR matrix ...")
103+
log.info("Constructing CSR array ...")
104104

105105
all_data = np.hstack(all_data)
106106
all_indices = np.hstack(all_indices)
107107
all_indptr = np.hstack(all_indptr)
108-
obs_matrix = scipy.sparse.csr_matrix((all_data, all_indices, all_indptr), shape)
108+
obs_matrix = scipy.sparse.csr_array((all_data, all_indices, all_indptr), shape)
109109

110110
log.info_rank(f"Constructed in", timer=timer, comm=None)
111111

@@ -605,17 +605,18 @@ def _exec(self, data, detectors=None, **kwargs):
605605
t2 = time()
606606
all_covs = []
607607
for itemplates in range(len(all_templates)):
608+
608609
templates = all_templates[itemplates]
609610
# Normalize the templates to improve the condition number of the
610611
# template covariance matrix
611612

612613
ntemplate, nsample_tot = templates.shape
613614
good_templates = []
614615
for itemplate in range(ntemplate):
615-
template = templates[itemplate, :].toarray().ravel()
616+
template = templates[[itemplate], :].toarray().ravel()
616617
norm = np.sum(template[full_good_fit] ** 2)
617618
if norm > 1e-3:
618-
templates[itemplate] /= norm ** .5
619+
templates[[itemplate], :] /= norm ** .5
619620
good_templates.append(itemplate)
620621
nbad = ntemplate - len(good_templates)
621622
if nbad != 0:
@@ -628,7 +629,10 @@ def _exec(self, data, detectors=None, **kwargs):
628629
# Now build the inverse covariance matrix
629630

630631
invcov = templates.dot(full_noise_weights.dot(templates.T))
631-
invcov = invcov.toarray()
632+
633+
nrow, ncol = invcov.shape
634+
if nrow < 1000:
635+
invcov = invcov.toarray()
632636

633637
if self.grank == 0:
634638
log.debug(
@@ -638,25 +642,29 @@ def _exec(self, data, detectors=None, **kwargs):
638642
)
639643
t1 = time()
640644

641-
# Invert the sub-matrix that has non-zero diagonal
642-
643-
rcond = 1 / np.linalg.cond(invcov)
644-
if self.grank == 0:
645-
log.debug(
646-
f"{self.group:4} : FilterBin: Template covariance matrix "
647-
f"rcond = {rcond} in {time() - t1:.2f} s",
648-
)
649-
t1 = time()
650-
651-
if rcond > 1e-6:
652-
cov = np.linalg.inv(invcov)
645+
if isinstance(invcov, np.ndarray):
646+
# avoid inverting singular matrices
647+
648+
rcond = 1 / np.linalg.cond(invcov)
649+
if self.grank == 0:
650+
log.debug(
651+
f"{self.group:4} : FilterBin: Template covariance matrix "
652+
f"rcond = {rcond} in {time() - t1:.2f} s",
653+
)
654+
t1 = time()
655+
656+
if rcond > 1e-6:
657+
cov = np.linalg.inv(invcov)
658+
else:
659+
log.warning(
660+
f"{self.group:4} : FilterBin: WARNING: template "
661+
f"covariance matrix is poorly conditioned: "
662+
f"rcond = {rcond}. Using matrix pseudoinverse.",
663+
)
664+
cov = np.linalg.pinv(invcov, rcond=1e-12, hermitian=True)
653665
else:
654-
log.warning(
655-
f"{self.group:4} : FilterBin: WARNING: template covariance matrix "
656-
f"is poorly conditioned: "
657-
f"rcond = {rcond}. Using matrix pseudoinverse.",
658-
)
659-
cov = np.linalg.pinv(invcov, rcond=1e-12, hermitian=True)
666+
# Trust our regularization
667+
cov = scipy.sparse.linalg.inv(invcov)
660668

661669
all_templates[itemplates] = templates
662670
all_covs.append(cov)
@@ -669,9 +677,6 @@ def _exec(self, data, detectors=None, **kwargs):
669677
)
670678
t1 = time()
671679

672-
import pdb
673-
pdb.set_trace()
674-
675680
if self.grank == 0:
676681
log.debug(
677682
f"{self.group:4} : FilterBin: Built template covariance "
@@ -684,8 +689,7 @@ def _exec(self, data, detectors=None, **kwargs):
684689
templates = all_templates[itemplates]
685690
cov = all_covs[itemplates]
686691
proj = templates.dot(full_noise_weights.dot(full_signal))
687-
coeff = np.dot(cov, proj)
688-
692+
coeff = cov.dot(proj)
689693
full_signal -= np.array(templates.T.dot(coeff.T)).ravel()
690694

691695
full_signal = full_signal.reshape([ndet, -1])
@@ -803,7 +807,7 @@ def _get_ground_templates(self, obs):
803807
legendre_filter.append(temp)
804808
legendre_filter = np.vstack(legendre_filter)
805809

806-
return scipy.sparse.csr_matrix(legendre_filter)
810+
return scipy.sparse.csr_array(legendre_filter)
807811

808812
@function_timer
809813
def _get_poly_templates(self, obs):
@@ -815,7 +819,7 @@ def _get_poly_templates(self, obs):
815819
ninterval = len(intervals)
816820
ntemplate = ninterval * norder
817821
nsample = obs.n_all_samples
818-
templates = scipy.sparse.lil_matrix((ntemplate, nsample))
822+
templates = scipy.sparse.lil_array((ntemplate, nsample))
819823

820824
if self.shared_flags is None:
821825
shared_flags = np.zeros(obs.n_local_samples, dtype=np.uint8)
@@ -868,7 +872,7 @@ def _expand_templates(self, templates, ndet):
868872
ntemplate_full += ntemplate
869873
if ntemplate_full == 0:
870874
return None
871-
full_templates = scipy.sparse.lil_matrix((ntemplate_full, nsample * ndet))
875+
full_templates = scipy.sparse.lil_array((ntemplate_full, nsample * ndet))
872876
offset = 0
873877
for idet, det_templates in enumerate(templates):
874878
ntemplate, nsample = det_templates.shape
@@ -880,7 +884,7 @@ def _expand_templates(self, templates, ndet):
880884
else:
881885
# Only one set of templates to apply to all detectors
882886
ntemplate, nsample = templates.shape
883-
full_templates = scipy.sparse.lil_matrix((ntemplate * ndet, nsample * ndet))
887+
full_templates = scipy.sparse.lil_array((ntemplate * ndet, nsample * ndet))
884888
for idet in range(ndet):
885889
full_templates[
886890
idet * ntemplate : (idet + 1) * ntemplate,
@@ -899,7 +903,7 @@ def _get_spatial_templates(self, obs, detectors):
899903
norder = (self.poly2d_filter_order + 1) ** 2
900904
ntemplate = nsample * norder
901905
# The templates matrix will be transposed before returning it
902-
templates = scipy.sparse.lil_matrix((nsample * ndet, ntemplate))
906+
templates = scipy.sparse.lil_array((nsample * ndet, ntemplate))
903907

904908
focalplane = obs.telescope.focalplane
905909

@@ -974,7 +978,7 @@ def _get_deprojection_templates(self, data, obs, pixels, templates):
974978
norm = np.dot(common_templates[0], common_templates[0])
975979

976980
ntemplate = nnz
977-
templates = scipy.sparse.lil_matrix((ntemplate, nsample))
981+
templates = scipy.sparse.lil_array((ntemplate, nsample))
978982
for inz in range(self._deproject_nnz):
979983
weights[:] = 0
980984
weights[:, inz] = 1
@@ -1024,7 +1028,7 @@ def _expand_matrix(self, compressed_matrix, local_to_global):
10241028
indptr,
10251029
)
10261030

1027-
sparse_matrix = scipy.sparse.csr_matrix(
1031+
sparse_matrix = scipy.sparse.csr_array(
10281032
(compressed_matrix.ravel(), indices, indptr),
10291033
shape=(self.npixtot, self.npixtot),
10301034
)
@@ -1066,7 +1070,7 @@ def _accumulate_full_observation_matrix(
10661070
mm_data = np.load(fname_cache + ".data.npy")
10671071
mm_indices = np.load(fname_cache + ".indices.npy")
10681072
mm_indptr = np.load(fname_cache + ".indptr.npy")
1069-
local_obs_matrix = scipy.sparse.csr_matrix(
1073+
local_obs_matrix = scipy.sparse.csr_array(
10701074
(mm_data, mm_indices, mm_indptr),
10711075
self.obs_matrix.shape,
10721076
)
@@ -1105,7 +1109,7 @@ def _accumulate_full_observation_matrix(
11051109

11061110
Ztot = None
11071111
for templates, cov in zip(all_templates, all_covs):
1108-
cov = scipy.sparse.csr_matrix(cov)
1112+
cov = scipy.sparse.csr_array(cov)
11091113
Z = scipy.sparse.identity(nsample * ndet) \
11101114
- templates.T.dot(cov.dot(templates.dot(noise_weights)))
11111115
if Ztot is None:
@@ -1118,7 +1122,7 @@ def _accumulate_full_observation_matrix(
11181122
npix = c_npix
11191123
npixtot = c_npixtot
11201124

1121-
P = scipy.sparse.lil_matrix((nsample * ndet, npixtot))
1125+
P = scipy.sparse.lil_array((nsample * ndet, npixtot))
11221126
for idet in range(ndet):
11231127
for isample in range(nsample):
11241128
pix = c_pixels[idet * nsample + isample]
@@ -1133,9 +1137,6 @@ def _accumulate_full_observation_matrix(
11331137
det_weights = scipy.sparse.diags((det_weights))
11341138

11351139
c_obs_matrix = P.T.dot(det_weights.dot(Ztot.dot(P))).toarray()
1136-
#import pdb
1137-
#import matplotlib.pyplot as plt
1138-
#pdb.set_trace()
11391140

11401141
if self.grank == 0:
11411142
log.debug(
@@ -1215,7 +1216,7 @@ def _initialize_comm(self, data):
12151216
@function_timer
12161217
def _initialize_obs_matrix(self):
12171218
if self.write_obs_matrix:
1218-
self.obs_matrix = scipy.sparse.csr_matrix(
1219+
self.obs_matrix = scipy.sparse.csr_array(
12191220
(self.npixtot, self.npixtot), dtype=np.float64
12201221
)
12211222
if self.rank == 0 and self.cache_dir is not None:
@@ -1233,7 +1234,7 @@ def _noiseweight_obs_matrix(self, data):
12331234
return
12341235
# Apply the white noise covariance to the observation matrix
12351236
white_noise_cov = data[self.binning.covariance]
1236-
cc = scipy.sparse.dok_matrix((self.npixtot, self.npixtot), dtype=np.float64)
1237+
cc = scipy.sparse.dok_array((self.npixtot, self.npixtot), dtype=np.float64)
12371238
nsubmap = white_noise_cov.distribution.n_submap
12381239
npix_submap = white_noise_cov.distribution.n_pix_submap
12391240
for isubmap_local, isubmap_global in enumerate(
@@ -1328,7 +1329,7 @@ def _collect_obs_matrix(self):
13281329
source=receive_from,
13291330
tag=factor + 3 * self.ntask,
13301331
)
1331-
obs_matrix_slice += scipy.sparse.csr_matrix(
1332+
obs_matrix_slice += scipy.sparse.csr_array(
13321333
(data_recv, indices_recv, indptr_recv),
13331334
obs_matrix_slice.shape,
13341335
)

0 commit comments

Comments
 (0)