|
17 | 17 | from scipy.spatial.distance import cdist |
18 | 18 | from scipy.optimize import linear_sum_assignment |
19 | 19 | from scipy.interpolate import InterpolatedUnivariateSpline, interp1d |
20 | | -from scipy.stats import zscore, linregress |
| 20 | +from scipy.stats import zscore |
| 21 | +from scipy.stats import linregress |
| 22 | +from scipy.sparse import issparse |
21 | 23 | from seaborn import scatterplot |
22 | 24 | import json |
23 | 25 | from pathlib import Path |
@@ -148,10 +150,10 @@ def read_anndata( |
148 | 150 | + orig[-self.nb_CS_end_ignore :] |
149 | 151 | ) |
150 | 152 | data = data[~(data.obs[array_id].isin(cs_to_remove))] |
151 | | - if data.raw is not None: |
152 | | - data.raw = data.raw.to_adata() |
153 | | - else: |
154 | | - data.raw = data.copy() |
| 153 | + # if data.raw is not None: |
| 154 | + # data.raw = data.raw.to_adata() |
| 155 | + # else: |
| 156 | + # data.raw = data.copy() |
155 | 157 | ids = range(len(data)) |
156 | 158 | self.all_cells = list(ids) |
157 | 159 | self.cell_names = dict( |
@@ -196,7 +198,7 @@ def read_anndata( |
196 | 198 | self.gene_expression = {id_: [] for id_ in ids} |
197 | 199 |
|
198 | 200 | self.array_id_num_pos = array_id_num_pos |
199 | | - if array_id in data.obs_keys(): |
| 201 | + if array_id in data.obs: |
200 | 202 | if data.obs[array_id].dtype != int: |
201 | 203 | exp = re.compile("[0-9]+") |
202 | 204 | cs = list( |
@@ -724,12 +726,10 @@ def smooth_data(self, inplace=True): |
724 | 726 | dist_sum = GG.sum(axis=1) |
725 | 727 | product_n = product / dist_sum.reshape(-1, 1) |
726 | 728 | product_sparse = sp.sparse.csr_array(product_n) |
727 | | - tmp_raw = self.anndata.raw.to_adata() |
728 | | - tmp_raw.X = product_sparse.toarray() |
729 | | - if inplace: |
730 | | - self.anndata.raw = tmp_raw |
731 | | - else: |
732 | | - return tmp_raw |
| 729 | + # tmp_raw = self.anndata.raw.to_adata() |
| 730 | + print(f"{self.anndata.X.shape=}\n{product_sparse.toarray().shape=}") |
| 731 | + self.anndata.raw._X = product_sparse.toarray() |
| 732 | + return self.anndata |
733 | 733 |
|
734 | 734 | def downsample(self, spacing=10, pos_id="pos_3D"): |
735 | 735 | """ |
@@ -991,7 +991,6 @@ def removing_spatial_outliers(self, th=0.2, n_components=3): |
991 | 991 | l_all = list(self.all_cells) |
992 | 992 | if hasattr(self, "anndata"): |
993 | 993 | self.anndata = self.anndata[l_all] |
994 | | - self.anndata.raw = self.anndata.raw.to_adata() |
995 | 994 | for t, c in self.cells_from_cover_slip.items(): |
996 | 995 | c.intersection_update(self.filtered_cells) |
997 | 996 | for t, c in self.cells_from_tissue.items(): |
@@ -1096,9 +1095,9 @@ def registration_3d( |
1096 | 1095 | "no filtering will be applied" |
1097 | 1096 | ) |
1098 | 1097 | if work_with_raw: |
1099 | | - raw_data = self.anndata.raw.to_adata() |
| 1098 | + raw_data = self.anndata.raw |
1100 | 1099 | else: |
1101 | | - raw_data = self.anndata.copy() |
| 1100 | + raw_data = self.anndata |
1102 | 1101 | if sc_imp: |
1103 | 1102 | if min_counts_genes is not None: |
1104 | 1103 | filter_1 = sc.pp.filter_genes( |
@@ -1810,7 +1809,56 @@ def save_anndata(self, output_path): |
1810 | 1809 | Args: |
1811 | 1810 | output_path (str): path to the output anndata file ('.h5ad' file) |
1812 | 1811 | """ |
1813 | | - data_tmp = self.anndata.copy() |
| 1812 | + a = self.anndata |
| 1813 | + |
| 1814 | + if a.is_view: |
| 1815 | + ref = a._adata_ref |
| 1816 | + |
| 1817 | + rows = ref.obs_names.get_indexer(a.obs_names) |
| 1818 | + cols = ref.var_names.get_indexer(a.var_names) |
| 1819 | + if (rows < 0).any() or (cols < 0).any(): |
| 1820 | + raise ValueError( |
| 1821 | + "Could not map view obs/var names back to parent AnnData." |
| 1822 | + ) |
| 1823 | + |
| 1824 | + X = ref.X[rows, :] |
| 1825 | + X = X[:, cols] |
| 1826 | + if issparse(X): |
| 1827 | + X = X.tocsr() |
| 1828 | + |
| 1829 | + data_tmp = anndata.AnnData(X=X, obs=a.obs.copy(), var=a.var.copy()) |
| 1830 | + data_tmp.uns = dict(a.uns) |
| 1831 | + |
| 1832 | + # --- IMPORTANT: keep all genes accessible for the napari viewer --- |
| 1833 | + # The viewer expects embryo.anndata.raw to contain the full gene set. |
| 1834 | + if ref.raw is not None: |
| 1835 | + Xraw = ref.raw.X[rows, :] # keep ALL genes (no col subset) |
| 1836 | + if issparse(Xraw): |
| 1837 | + Xraw = Xraw.tocsr() |
| 1838 | + raw_tmp = anndata.AnnData( |
| 1839 | + X=Xraw, obs=a.obs.copy(), var=ref.raw.var.copy() |
| 1840 | + ) |
| 1841 | + data_tmp.raw = raw_tmp |
| 1842 | + |
| 1843 | + else: |
| 1844 | + data_tmp = a # already materialized |
| 1845 | + # Ensure raw exists for viewer if possible |
| 1846 | + if ( |
| 1847 | + data_tmp.raw is None |
| 1848 | + and getattr(a, "_adata_ref", None) is not None |
| 1849 | + and a._adata_ref.raw is not None |
| 1850 | + ): |
| 1851 | + ref = a._adata_ref |
| 1852 | + rows = ref.obs_names.get_indexer(a.obs_names) |
| 1853 | + Xraw = ref.raw.X[rows, :] |
| 1854 | + if issparse(Xraw): |
| 1855 | + Xraw = Xraw.tocsr() |
| 1856 | + raw_tmp = anndata.AnnData( |
| 1857 | + X=Xraw, obs=a.obs.copy(), var=ref.raw.var.copy() |
| 1858 | + ) |
| 1859 | + data_tmp.raw = raw_tmp |
| 1860 | + |
| 1861 | + # add registered coords |
1814 | 1862 | all_c_sorted = sorted(self.all_cells) |
1815 | 1863 | pos_final = np.array([self.pos_3D[c] for c in all_c_sorted]) |
1816 | 1864 | data_tmp.obsm["X_spatial_registered"] = pos_final |
|
0 commit comments