smftools 0.3.0__py3-none-any.whl → 0.3.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. smftools/_version.py +1 -1
  2. smftools/cli/chimeric_adata.py +1563 -0
  3. smftools/cli/helpers.py +49 -7
  4. smftools/cli/hmm_adata.py +250 -32
  5. smftools/cli/latent_adata.py +773 -0
  6. smftools/cli/load_adata.py +78 -74
  7. smftools/cli/preprocess_adata.py +122 -58
  8. smftools/cli/recipes.py +26 -0
  9. smftools/cli/spatial_adata.py +74 -112
  10. smftools/cli/variant_adata.py +423 -0
  11. smftools/cli_entry.py +52 -4
  12. smftools/config/conversion.yaml +1 -1
  13. smftools/config/deaminase.yaml +3 -0
  14. smftools/config/default.yaml +85 -12
  15. smftools/config/experiment_config.py +146 -1
  16. smftools/constants.py +69 -0
  17. smftools/hmm/HMM.py +88 -0
  18. smftools/hmm/call_hmm_peaks.py +1 -1
  19. smftools/informatics/__init__.py +6 -0
  20. smftools/informatics/bam_functions.py +358 -8
  21. smftools/informatics/binarize_converted_base_identities.py +2 -89
  22. smftools/informatics/converted_BAM_to_adata.py +636 -175
  23. smftools/informatics/h5ad_functions.py +198 -2
  24. smftools/informatics/modkit_extract_to_adata.py +1007 -425
  25. smftools/informatics/sequence_encoding.py +72 -0
  26. smftools/logging_utils.py +21 -2
  27. smftools/metadata.py +1 -1
  28. smftools/plotting/__init__.py +26 -3
  29. smftools/plotting/autocorrelation_plotting.py +22 -4
  30. smftools/plotting/chimeric_plotting.py +1893 -0
  31. smftools/plotting/classifiers.py +28 -14
  32. smftools/plotting/general_plotting.py +62 -1583
  33. smftools/plotting/hmm_plotting.py +1670 -8
  34. smftools/plotting/latent_plotting.py +804 -0
  35. smftools/plotting/plotting_utils.py +243 -0
  36. smftools/plotting/position_stats.py +16 -8
  37. smftools/plotting/preprocess_plotting.py +281 -0
  38. smftools/plotting/qc_plotting.py +8 -3
  39. smftools/plotting/spatial_plotting.py +1134 -0
  40. smftools/plotting/variant_plotting.py +1231 -0
  41. smftools/preprocessing/__init__.py +4 -0
  42. smftools/preprocessing/append_base_context.py +18 -18
  43. smftools/preprocessing/append_mismatch_frequency_sites.py +187 -0
  44. smftools/preprocessing/append_sequence_mismatch_annotations.py +171 -0
  45. smftools/preprocessing/append_variant_call_layer.py +480 -0
  46. smftools/preprocessing/calculate_consensus.py +1 -1
  47. smftools/preprocessing/calculate_read_modification_stats.py +6 -1
  48. smftools/preprocessing/flag_duplicate_reads.py +4 -4
  49. smftools/preprocessing/invert_adata.py +1 -0
  50. smftools/readwrite.py +159 -99
  51. smftools/schema/anndata_schema_v1.yaml +15 -1
  52. smftools/tools/__init__.py +10 -0
  53. smftools/tools/calculate_knn.py +121 -0
  54. smftools/tools/calculate_leiden.py +57 -0
  55. smftools/tools/calculate_nmf.py +130 -0
  56. smftools/tools/calculate_pca.py +180 -0
  57. smftools/tools/calculate_umap.py +79 -80
  58. smftools/tools/position_stats.py +4 -4
  59. smftools/tools/rolling_nn_distance.py +872 -0
  60. smftools/tools/sequence_alignment.py +140 -0
  61. smftools/tools/tensor_factorization.py +217 -0
  62. {smftools-0.3.0.dist-info → smftools-0.3.2.dist-info}/METADATA +9 -5
  63. {smftools-0.3.0.dist-info → smftools-0.3.2.dist-info}/RECORD +66 -45
  64. {smftools-0.3.0.dist-info → smftools-0.3.2.dist-info}/WHEEL +0 -0
  65. {smftools-0.3.0.dist-info → smftools-0.3.2.dist-info}/entry_points.txt +0 -0
  66. {smftools-0.3.0.dist-info → smftools-0.3.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,140 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Literal
5
+
6
+
7
+ @dataclass(frozen=True)
8
+ class AlignmentMismatch:
9
+ """Record a mismatch or gap between two aligned sequences."""
10
+
11
+ event: Literal["substitution", "insertion", "deletion"]
12
+ seq1_pos: int | None
13
+ seq1_base: str | None
14
+ seq2_pos: int | None
15
+ seq2_base: str | None
16
+
17
+
18
+ def align_sequences_with_mismatches(
19
+ seq1: str,
20
+ seq2: str,
21
+ match_score: int = 1,
22
+ mismatch_score: int = -1,
23
+ gap_score: int = -1,
24
+ ignore_n: bool = True,
25
+ ) -> tuple[str, str, list[AlignmentMismatch]]:
26
+ """Globally align two sequences and return mismatch positions/bases.
27
+
28
+ The alignment uses a simple Needleman-Wunsch dynamic programming approach
29
+ with configurable scores. Mismatch reporting is based on the aligned
30
+ sequences and returns 0-based coordinates in each sequence. Gap events
31
+ are represented with a ``None`` coordinate for the gapped sequence.
32
+
33
+ Args:
34
+ seq1: First sequence (treated as reference for positions).
35
+ seq2: Second sequence.
36
+ match_score: Score for matching bases.
37
+ mismatch_score: Score for mismatching bases.
38
+ gap_score: Score for introducing a gap.
39
+ ignore_n: Whether to ignore mismatches involving the base ``N``.
40
+
41
+ Returns:
42
+ Tuple of (aligned_seq1, aligned_seq2, mismatches).
43
+ """
44
+ seq1 = seq1.upper()
45
+ seq2 = seq2.upper()
46
+ n, m = len(seq1), len(seq2)
47
+
48
+ scores = [[0] * (m + 1) for _ in range(n + 1)]
49
+ traceback = [[None] * (m + 1) for _ in range(n + 1)]
50
+
51
+ for i in range(1, n + 1):
52
+ scores[i][0] = scores[i - 1][0] + gap_score
53
+ traceback[i][0] = "up"
54
+ for j in range(1, m + 1):
55
+ scores[0][j] = scores[0][j - 1] + gap_score
56
+ traceback[0][j] = "left"
57
+
58
+ for i in range(1, n + 1):
59
+ for j in range(1, m + 1):
60
+ diag_score = scores[i - 1][j - 1] + (
61
+ match_score if seq1[i - 1] == seq2[j - 1] else mismatch_score
62
+ )
63
+ up_score = scores[i - 1][j] + gap_score
64
+ left_score = scores[i][j - 1] + gap_score
65
+
66
+ best_score = max(diag_score, up_score, left_score)
67
+ scores[i][j] = best_score
68
+ if best_score == diag_score:
69
+ traceback[i][j] = "diag"
70
+ elif best_score == up_score:
71
+ traceback[i][j] = "up"
72
+ else:
73
+ traceback[i][j] = "left"
74
+
75
+ aligned1: list[str] = []
76
+ aligned2: list[str] = []
77
+ i, j = n, m
78
+ while i > 0 or j > 0:
79
+ direction = traceback[i][j]
80
+ if direction == "diag":
81
+ aligned1.append(seq1[i - 1])
82
+ aligned2.append(seq2[j - 1])
83
+ i -= 1
84
+ j -= 1
85
+ elif direction == "up":
86
+ aligned1.append(seq1[i - 1])
87
+ aligned2.append("-")
88
+ i -= 1
89
+ else:
90
+ aligned1.append("-")
91
+ aligned2.append(seq2[j - 1])
92
+ j -= 1
93
+
94
+ aligned_seq1 = "".join(reversed(aligned1))
95
+ aligned_seq2 = "".join(reversed(aligned2))
96
+
97
+ mismatches: list[AlignmentMismatch] = []
98
+ seq1_index = 0
99
+ seq2_index = 0
100
+ for base1, base2 in zip(aligned_seq1, aligned_seq2, strict=True):
101
+ if base1 == "-":
102
+ if not (ignore_n and base2 == "N"):
103
+ mismatches.append(
104
+ AlignmentMismatch(
105
+ event="insertion",
106
+ seq1_pos=None,
107
+ seq1_base=None,
108
+ seq2_pos=seq2_index,
109
+ seq2_base=base2,
110
+ )
111
+ )
112
+ seq2_index += 1
113
+ continue
114
+ if base2 == "-":
115
+ if not (ignore_n and base1 == "N"):
116
+ mismatches.append(
117
+ AlignmentMismatch(
118
+ event="deletion",
119
+ seq1_pos=seq1_index,
120
+ seq1_base=base1,
121
+ seq2_pos=None,
122
+ seq2_base=None,
123
+ )
124
+ )
125
+ seq1_index += 1
126
+ continue
127
+ if base1 != base2 and not (ignore_n and "N" in (base1, base2)):
128
+ mismatches.append(
129
+ AlignmentMismatch(
130
+ event="substitution",
131
+ seq1_pos=seq1_index,
132
+ seq1_base=base1,
133
+ seq2_pos=seq2_index,
134
+ seq2_base=base2,
135
+ )
136
+ )
137
+ seq1_index += 1
138
+ seq2_index += 1
139
+
140
+ return aligned_seq1, aligned_seq2, mismatches
@@ -0,0 +1,217 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Iterable, Sequence
4
+
5
+ import numpy as np
6
+
7
+ from smftools.constants import MODKIT_EXTRACT_SEQUENCE_BASE_TO_INT
8
+ from smftools.logging_utils import get_logger
9
+ from smftools.optional_imports import require
10
+
11
+ if TYPE_CHECKING:
12
+ import anndata as ad
13
+
14
+ logger = get_logger(__name__)
15
+
16
+
17
+ def build_sequence_one_hot_and_mask(
18
+ encoded_sequences: np.ndarray,
19
+ *,
20
+ bases: Sequence[str] = ("A", "C", "G", "T"),
21
+ dtype: np.dtype | type[np.floating] = np.float32,
22
+ ) -> tuple[np.ndarray, np.ndarray]:
23
+ """Build one-hot encoded reads and a seen/unseen mask.
24
+
25
+ Args:
26
+ encoded_sequences: Integer-encoded sequences shaped (n_reads, seq_len).
27
+ bases: Bases to one-hot encode.
28
+ dtype: Output dtype for the one-hot tensor.
29
+
30
+ Returns:
31
+ Tuple of (one_hot_tensor, mask) where:
32
+ - one_hot_tensor: (n_reads, seq_len, n_bases)
33
+ - mask: (n_reads, seq_len) boolean array indicating seen bases.
34
+ """
35
+ encoded = np.asarray(encoded_sequences)
36
+ if encoded.ndim != 2:
37
+ raise ValueError(
38
+ f"encoded_sequences must be 2D with shape (n_reads, seq_len); got {encoded.shape}."
39
+ )
40
+
41
+ base_values = np.array(
42
+ [MODKIT_EXTRACT_SEQUENCE_BASE_TO_INT[base] for base in bases],
43
+ dtype=encoded.dtype,
44
+ )
45
+
46
+ if np.issubdtype(encoded.dtype, np.floating):
47
+ encoded = encoded.copy()
48
+ encoded[np.isnan(encoded)] = -1
49
+
50
+ mask = np.isin(encoded, base_values)
51
+ one_hot = np.zeros((*encoded.shape, len(base_values)), dtype=dtype)
52
+
53
+ for idx, base_value in enumerate(base_values):
54
+ one_hot[..., idx] = encoded == base_value
55
+
56
+ return one_hot, mask
57
+
58
+
59
+ def calculate_sequence_cp_decomposition(
60
+ adata: "ad.AnnData",
61
+ *,
62
+ layer: str,
63
+ var_mask: np.ndarray | None = None,
64
+ var_mask_name: str | None = None,
65
+ rank: int = 5,
66
+ n_iter_max: int = 100,
67
+ random_state: int = 0,
68
+ overwrite: bool = True,
69
+ embedding_key: str = "X_cp_sequence",
70
+ components_key: str = "H_cp_sequence",
71
+ uns_key: str = "cp_sequence",
72
+ bases: Iterable[str] = ("A", "C", "G", "T"),
73
+ backend: str = "pytorch",
74
+ show_progress: bool = False,
75
+ init: str = "random",
76
+ non_negative: bool = False,
77
+ ) -> "ad.AnnData":
78
+ """Compute CP decomposition on one-hot encoded sequence data with masking.
79
+
80
+ Args:
81
+ adata: AnnData object to update.
82
+ layer: Layer name containing integer-encoded sequences.
83
+ var_mask: Optional boolean mask over variables to include in the CP fit.
84
+ var_mask_name: Optional label describing the provided ``var_mask``.
85
+ rank: CP rank.
86
+ n_iter_max: Maximum number of iterations for the solver.
87
+ random_state: Random seed for initialization.
88
+ overwrite: Whether to recompute if the embedding already exists.
89
+ embedding_key: Key for embedding in ``adata.obsm``.
90
+ components_key: Key for position factors in ``adata.varm``.
91
+ uns_key: Key for metadata stored in ``adata.uns``.
92
+ bases: Bases to one-hot encode (in order).
93
+ backend: Tensorly backend to use (``numpy`` or ``pytorch``).
94
+ show_progress: Whether to display progress during factorization if supported.
95
+ non_negative: Whether to request a non-negative CP decomposition.
96
+
97
+ Returns:
98
+ Updated AnnData object containing the CP decomposition outputs.
99
+ """
100
+ if embedding_key in adata.obsm and components_key in adata.varm and not overwrite:
101
+ logger.info("CP embedding and components already present; skipping recomputation.")
102
+ return adata
103
+
104
+ if backend not in {"numpy", "pytorch"}:
105
+ raise ValueError(f"Unsupported backend '{backend}'. Use 'numpy' or 'pytorch'.")
106
+
107
+ tensorly = require("tensorly", extra="ml-base", purpose="CP decomposition")
108
+ from tensorly.decomposition import parafac
109
+
110
+ try:
111
+ from tensorly.decomposition import non_negative_parafac
112
+ except ImportError:
113
+ non_negative_parafac = None
114
+
115
+ tensorly.set_backend(backend)
116
+
117
+ if layer not in adata.layers:
118
+ raise KeyError(f"Layer '{layer}' not found in adata.layers.")
119
+
120
+ layer_data = adata.layers[layer]
121
+ mask_indices = None
122
+ if var_mask is not None:
123
+ var_mask_array = np.asarray(var_mask, dtype=bool)
124
+ if var_mask_array.shape[0] != adata.n_vars:
125
+ raise ValueError(
126
+ "var_mask must match adata.n_vars; "
127
+ f"got {var_mask_array.shape[0]} vs {adata.n_vars}."
128
+ )
129
+ if not var_mask_array.any():
130
+ raise ValueError("var_mask must include at least one variable.")
131
+ mask_indices = var_mask_array
132
+ layer_data = layer_data[:, var_mask_array]
133
+
134
+ one_hot, mask = build_sequence_one_hot_and_mask(layer_data, bases=tuple(bases))
135
+ mask_tensor = np.repeat(mask[:, :, None], one_hot.shape[2], axis=2)
136
+
137
+ device = "numpy"
138
+ if backend == "pytorch":
139
+ torch = require("torch", extra="ml-base", purpose="CP decomposition backend")
140
+ if torch.cuda.is_available():
141
+ device = torch.device("cuda")
142
+ elif getattr(torch.backends, "mps", None) and torch.backends.mps.is_available():
143
+ device = torch.device("mps")
144
+ else:
145
+ device = torch.device("cpu")
146
+
147
+ one_hot = torch.tensor(one_hot, dtype=torch.float32, device=device)
148
+ mask_tensor = torch.tensor(mask_tensor, dtype=torch.float32, device=device)
149
+
150
+ parafac_kwargs = {
151
+ "rank": rank,
152
+ "n_iter_max": n_iter_max,
153
+ "init": init,
154
+ "mask": mask_tensor,
155
+ "random_state": random_state,
156
+ }
157
+ import inspect
158
+
159
+ decomposition_fn = parafac
160
+ if non_negative:
161
+ if non_negative_parafac is not None:
162
+ decomposition_fn = non_negative_parafac
163
+ elif "non_negative" in inspect.signature(parafac).parameters:
164
+ parafac_kwargs["non_negative"] = True
165
+ else:
166
+ raise ValueError(
167
+ "Non-negative CP decomposition requested but tensorly does not support it."
168
+ )
169
+
170
+ if "verbose" in inspect.signature(decomposition_fn).parameters:
171
+ parafac_kwargs["verbose"] = show_progress
172
+
173
+ cp = decomposition_fn(one_hot, **parafac_kwargs)
174
+
175
+ if backend == "pytorch":
176
+ weights = cp.weights.detach().cpu().numpy()
177
+ read_factors, position_factors, base_factors = [
178
+ factor.detach().cpu().numpy() for factor in cp.factors
179
+ ]
180
+ else:
181
+ weights = np.asarray(cp.weights)
182
+ read_factors, position_factors, base_factors = [np.asarray(f) for f in cp.factors]
183
+
184
+ adata.obsm[embedding_key] = read_factors
185
+ if mask_indices is None:
186
+ adata.varm[components_key] = position_factors
187
+ else:
188
+ full_components = np.full(
189
+ (adata.n_vars, position_factors.shape[1]),
190
+ np.nan,
191
+ dtype=position_factors.dtype,
192
+ )
193
+ full_components[mask_indices] = position_factors
194
+ adata.varm[components_key] = full_components
195
+ adata.uns[uns_key] = {
196
+ "rank": rank,
197
+ "n_iter_max": n_iter_max,
198
+ "random_state": random_state,
199
+ "layer": layer,
200
+ "components_key": components_key,
201
+ "weights": weights,
202
+ "base_factors": base_factors,
203
+ "base_labels": list(bases),
204
+ "backend": backend,
205
+ "device": str(device),
206
+ "non_negative": non_negative,
207
+ "var_mask_name": var_mask_name,
208
+ "var_mask_count": int(np.sum(mask_indices)) if mask_indices is not None else None,
209
+ }
210
+
211
+ logger.info(
212
+ "Stored: adata.obsm['%s'], adata.varm['%s'], adata.uns['%s']",
213
+ embedding_key,
214
+ components_key,
215
+ uns_key,
216
+ )
217
+ return adata
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: smftools
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: Single Molecule Footprinting Analysis in Python.
5
5
  Project-URL: Source, https://github.com/jkmckenna/smftools
6
6
  Project-URL: Documentation, https://smftools.readthedocs.io/
@@ -65,16 +65,19 @@ Requires-Dist: omegaconf; extra == 'all'
65
65
  Requires-Dist: pod5>=0.1.21; extra == 'all'
66
66
  Requires-Dist: pybedtools>=0.12.0; extra == 'all'
67
67
  Requires-Dist: pybigwig>=0.3.24; extra == 'all'
68
+ Requires-Dist: pynndescent>=0.5.10; extra == 'all'
68
69
  Requires-Dist: pysam>=0.19.1; extra == 'all'
69
- Requires-Dist: scanpy>=1.9; extra == 'all'
70
70
  Requires-Dist: scikit-learn>=1.0.2; extra == 'all'
71
71
  Requires-Dist: seaborn>=0.11; extra == 'all'
72
72
  Requires-Dist: shap; extra == 'all'
73
+ Requires-Dist: tensorly; extra == 'all'
73
74
  Requires-Dist: torch>=1.9.0; extra == 'all'
75
+ Requires-Dist: umap-learn>=0.5.5; extra == 'all'
74
76
  Requires-Dist: upsetplot; extra == 'all'
75
77
  Requires-Dist: wandb; extra == 'all'
76
78
  Provides-Extra: cluster
77
79
  Requires-Dist: fastcluster; extra == 'cluster'
80
+ Requires-Dist: igraph; extra == 'cluster'
78
81
  Requires-Dist: leidenalg; extra == 'cluster'
79
82
  Provides-Extra: dev
80
83
  Requires-Dist: pre-commit; extra == 'dev'
@@ -103,6 +106,7 @@ Requires-Dist: networkx>=3.2; extra == 'misc'
103
106
  Requires-Dist: upsetplot; extra == 'misc'
104
107
  Provides-Extra: ml-base
105
108
  Requires-Dist: scikit-learn>=1.0.2; extra == 'ml-base'
109
+ Requires-Dist: tensorly; extra == 'ml-base'
106
110
  Requires-Dist: torch>=1.9.0; extra == 'ml-base'
107
111
  Provides-Extra: ml-extended
108
112
  Requires-Dist: captum; extra == 'ml-extended'
@@ -124,11 +128,11 @@ Provides-Extra: pysam
124
128
  Requires-Dist: pysam>=0.19.1; extra == 'pysam'
125
129
  Provides-Extra: qc
126
130
  Requires-Dist: multiqc; extra == 'qc'
127
- Provides-Extra: scanpy
128
- Requires-Dist: igraph; extra == 'scanpy'
129
- Requires-Dist: scanpy>=1.9; extra == 'scanpy'
130
131
  Provides-Extra: torch
131
132
  Requires-Dist: torch>=1.9.0; extra == 'torch'
133
+ Provides-Extra: umap
134
+ Requires-Dist: pynndescent>=0.5.10; extra == 'umap'
135
+ Requires-Dist: umap-learn>=0.5.5; extra == 'umap'
132
136
  Description-Content-Type: text/markdown
133
137
 
134
138
  [![PyPI](https://img.shields.io/pypi/v/smftools.svg)](https://pypi.org/project/smftools)
@@ -1,34 +1,38 @@
1
1
  smftools/__init__.py,sha256=Wun5eO3FHy7sAelTLlLdFj3NurqZFQxfO3U5YHJ3KcY,1247
2
2
  smftools/_settings.py,sha256=QqZzjz6Y_-gZH4VJAPRCL68HRlGjzl3hXU7d-dMi8-M,418
3
- smftools/_version.py,sha256=KdHlm9KKc9XEB182bG2710ZrIpNwJdS5TBcAjXA8U_M,58
4
- smftools/cli_entry.py,sha256=wTjwx520HJIez2I1CGXAHhWXUC-nsRBZ6yUFJd_84XM,10519
5
- smftools/constants.py,sha256=SWOJ76KTP2p3geyVkNQ8LB96NOmDDtjFEur2hSw7iyU,1289
6
- smftools/logging_utils.py,sha256=jOptBgSW7NQcw7JTnw2-oWcN2qyrtfJkDpIZsfcU1Mk,1323
7
- smftools/metadata.py,sha256=yGTMof2hAUR43QfgRSwK9mnOiTAznV3Usxzsvt185s4,14898
3
+ smftools/_version.py,sha256=xm1u7RHIf6fYv7ou5-vxQ9OiaAwZ0vJK7AngPQ7IBek,58
4
+ smftools/cli_entry.py,sha256=rFd_rSY8KA28LdHGS5wnSY1nCaiSZMSlhG4bm2Dn1w0,11675
5
+ smftools/constants.py,sha256=NZjUgTD57StBaktxPIpUGoAmNjNB6D68Yr6ueAQJ8KY,4111
6
+ smftools/logging_utils.py,sha256=OpDul2P5FCWhjJqunYK2MrSaYtbKEPGFE0Z7vZhSX0Y,2193
7
+ smftools/metadata.py,sha256=-U8jVzjBsXbZ2SKRcyPHMCDPnsQQRR4djzerjpeQvzU,14917
8
8
  smftools/optional_imports.py,sha256=PpjWa-H-rlxwXJjkPLSHkiuim922xwDVsqlgFY8wWqw,1039
9
- smftools/readwrite.py,sha256=GCCBAWXQezTtXMBr-2NeV-jJfdnl_yB_x5nuz7Bt11c,52413
9
+ smftools/readwrite.py,sha256=fvCJsIZ6Idjp0QIzbxXTPSXmQOb6ggx8idRaTbDck7w,54876
10
10
  smftools/cli/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
11
- smftools/cli/helpers.py,sha256=Euf0e3rNgKAlnghlJvr5fKaiMxqPum1HD6CYI__Z3Ko,1435
12
- smftools/cli/hmm_adata.py,sha256=2W1OLU_KaEtwUzkL_ZaecK4rQA9XyHJEurZEKQqnU00,40795
13
- smftools/cli/load_adata.py,sha256=mVsXQQB8sRIIettJhC1Y1xnrBcSTrRs-p-O72TlhO1o,32453
14
- smftools/cli/preprocess_adata.py,sha256=m_IWvUEBwIA5goJ2W7FQdqaA8tqQZB7gAXjjCWrcFCU,22632
15
- smftools/cli/spatial_adata.py,sha256=rzEPJ5pM78zE27rp-Sgif0fw_I6NiPK71xyGnZnXYcc,32001
11
+ smftools/cli/chimeric_adata.py,sha256=roX2qpIg_84lpRFCHgD9MPLTh_Qv8XQU0250_RLyhtI,73758
12
+ smftools/cli/helpers.py,sha256=LGiQyJfqB8mTQ6BhJWG1vc4hkZv0BmxBCbCzY7vAE2A,2932
13
+ smftools/cli/hmm_adata.py,sha256=ZGzU9cfLaYUrUTtGFzUvmgFNQHHzBTkN1jXsGMEpZzE,49363
14
+ smftools/cli/latent_adata.py,sha256=q4PupWWPR8ZY-Qsmj6Ug2WoTRf8SUA4-caNq5Vie2-M,26523
15
+ smftools/cli/load_adata.py,sha256=RSgX1kvEcqSx3JRXL055m2u4hro8uM-sNvA5jVVxOr8,31539
16
+ smftools/cli/preprocess_adata.py,sha256=D2LGNto2aeAvPjMwSPKR9CzxTIewhTtBUL3n47gE5Pw,25161
17
+ smftools/cli/recipes.py,sha256=v3CnuNOyizD_tdNlHF2Qv9LsUkNMYDIVlqr_I3275QA,735
18
+ smftools/cli/spatial_adata.py,sha256=MLsCo8PTYw1jxxXh9bdUG1Ftjuk2bp36oSGmnw7GvF8,30149
19
+ smftools/cli/variant_adata.py,sha256=RNV0WyLVOdJhFAaM6XjUVh__kLMD7kv1BTSym7HIezY,16889
16
20
  smftools/cli/archived/cli_flows.py,sha256=w1rPHSH8WzZn7owz0ra7WOUGlJSEsaRw_W3x-9Ra42k,4977
17
21
  smftools/config/__init__.py,sha256=rcI3qG1DGfRcvQzh8bffiHuRPcmPsas5T8MN6uhScxA,106
18
- smftools/config/conversion.yaml,sha256=N7lUO7-yAaJR6VhxRGCRc-ceAi0cp5xNASSIsXl9KwI,1242
19
- smftools/config/deaminase.yaml,sha256=JCE1nF39AX436-3RyvuZN24gdJfriDijNv5XNHrMT8I,1357
20
- smftools/config/default.yaml,sha256=yhcMASjqqccuHpTFepyjt6KHfNNR6IDNSH0rmEERXm4,13933
22
+ smftools/config/conversion.yaml,sha256=djZTJ1EwHc1Ax_fIsZo1UnERDpyER15rgo8APrOtAwE,1243
23
+ smftools/config/deaminase.yaml,sha256=uZZzWeNc3TcBGY7o58lqQb3XOMAi3kIpHsUBqWUuM9g,1388
24
+ smftools/config/default.yaml,sha256=gCWhoemO97zyaNTrt0A40RWnaHJ6R65mJJ4gEMUjgC4,16242
21
25
  smftools/config/direct.yaml,sha256=Jw8Nj3QKQrCfJpVl8sGgCKdRvjk5cV66dzRlNfoDOzI,2269
22
26
  smftools/config/discover_input_files.py,sha256=NcOqNYoXggLDieam8UMJAc2sWmoYOZ_Wqp2mApnlBfs,4015
23
- smftools/config/experiment_config.py,sha256=IqSN7JwnnWWjOoDZWbQ2zATwjm_uywSSs8mhagII6ms,67521
27
+ smftools/config/experiment_config.py,sha256=soaTSwVbZELCDS1D5EQa2MF5RvPFP3lNQAaDhYMIbjM,75729
24
28
  smftools/datasets/F1_hybrid_NKG2A_enhander_promoter_GpC_conversion_SMF.h5ad.gz,sha256=q6wJtgFRDln0o20XNCx1qad3lwcdCoylqPN7wskTfI8,2926497
25
29
  smftools/datasets/F1_sample_sheet.csv,sha256=9PodIIOXK2eamYPbC6DGnXdzgi9bRDovf296j1aM0ak,259
26
30
  smftools/datasets/__init__.py,sha256=_G08ZAMlA9zpY5UjWTVlpAbW2YPS4PLCmz5g1pZdcCw,157
27
31
  smftools/datasets/dCas9_m6A_invitro_kinetics.h5ad.gz,sha256=niOcVHaYY7h3XyvwSkN-V_NMBaRt2vTP5TrJO0CwMCs,8385050
28
32
  smftools/datasets/datasets.py,sha256=-VOdONP-K_ftLDtLktRKbq3S6vSB4pzRQ6VYBxAy_4A,1074
29
- smftools/hmm/HMM.py,sha256=_kYhqfmz46XBbx9Y12KF6dKp2XPcSHreZiQgavgx6h4,82437
33
+ smftools/hmm/HMM.py,sha256=Yq7awVwCtTPb4HET1UIx2VTHVvgiwu_2pjEgZTTkTP4,85660
30
34
  smftools/hmm/__init__.py,sha256=vs-fjo-v9y8EwdoErK6KDBm-YzD_XmTtflsdTJlRgTg,746
31
- smftools/hmm/call_hmm_peaks.py,sha256=CzTEz3EP_LNLirIVYzRxbV7_5fCBpLa9azLPSEt6s7s,13529
35
+ smftools/hmm/call_hmm_peaks.py,sha256=jfmo-zzmA57d3pNG1RM1FqjsHue3IErgjOWIf3EuXtQ,13533
32
36
  smftools/hmm/display_hmm.py,sha256=N94hmEKZGehPdsB9yLyY7U1_tTWDk2NTMU-PuWnEQqA,1321
33
37
  smftools/hmm/hmm_readwrite.py,sha256=n-ok3wH1-anSn90vEA91jWKRbtq0bxM66hp2eYoWk34,687
34
38
  smftools/hmm/nucleosome_hmm_refinement.py,sha256=lHB6XVJWhwN-jR1TjBOMIOBQ5soncAJbv3djbkyH1NU,6882
@@ -36,20 +40,21 @@ smftools/hmm/archived/apply_hmm_batched.py,sha256=W2-qx1XbcDJz4q38YCxb1eQn9h-hqA
36
40
  smftools/hmm/archived/calculate_distances.py,sha256=MfBhXZNkjQvu9Y8LVMDpiQ4aS9uyfa4TUQbLGjQ1aM0,680
37
41
  smftools/hmm/archived/call_hmm_peaks.py,sha256=6SklWXCn4H8LnlGvBncIsLhnf2gaNy8Qro_jxGJn7I0,5249
38
42
  smftools/hmm/archived/train_hmm.py,sha256=sYF4RTEKPhE6MwK2eTAv4ghf-f7_33-FvhwUG6tegTU,2513
39
- smftools/informatics/__init__.py,sha256=jxyzu37yR1lho4LP3WhQ6_Oez4f-un7vCqP80s8xR3g,2885
40
- smftools/informatics/bam_functions.py,sha256=ErTV3ZrguIaGAqMnLnf-0QmfvvDRix0h_ehSRqKU2Ls,59008
43
+ smftools/informatics/__init__.py,sha256=Q2l7iGOEuZXtGmqWG3NwF-_vNwl4VmJPsElg7-eANO0,3226
44
+ smftools/informatics/bam_functions.py,sha256=b_Vb08HmOl8-hXLbkVNBw-zl-1loXqw-yQJkklJUvyY,73636
41
45
  smftools/informatics/basecalling.py,sha256=PgjWoOgfQaUOCoKpyaKO8m8sauMW3el6wdEtzGlvy4s,3699
42
46
  smftools/informatics/bed_functions.py,sha256=9y3XNNl6QivqkWEfoH5XszP3Qsj0P-rCopgfd0HpFgs,21268
43
- smftools/informatics/binarize_converted_base_identities.py,sha256=KRL-KT8MYADadHgRbTgoOFD30LlZazKHe10Hz9nO6Z4,7850
47
+ smftools/informatics/binarize_converted_base_identities.py,sha256=2vncAGQ84GD-yvZpvnbBLj_ex9ABNACOzYAeX9yOPB4,4023
44
48
  smftools/informatics/complement_base_list.py,sha256=6DInlD4cdjKJmmUv4Cp4UU9HHLe60Pm8RF9AoBfBfF0,571
45
- smftools/informatics/converted_BAM_to_adata.py,sha256=YU7KBHgr0ulYZBv0I9PKI-p71JMZRvJbY9SlECWcQ3Q,25741
49
+ smftools/informatics/converted_BAM_to_adata.py,sha256=qDdY5S7oCkH9Ov6a0BADnt2ytZYtcXSU1K2RyoNZxoo,44986
46
50
  smftools/informatics/fasta_functions.py,sha256=MD-fL0BkExiDXMUSPkHaHrkOK7aqzOozWREGr5Gzw8w,14111
47
- smftools/informatics/h5ad_functions.py,sha256=fX4CgO9ZSgYh9VbCmgGPXwNg5uolLJoNPcBZgzNwgMk,13167
48
- smftools/informatics/modkit_extract_to_adata.py,sha256=wcat5i002BxBpSMPCLENDdu-cnH0K87p6NN1vFSbfc4,63551
51
+ smftools/informatics/h5ad_functions.py,sha256=V-lLmrff4Yv02PiKp9ePjYK7dHZALJInHID3_bSabTY,21178
52
+ smftools/informatics/modkit_extract_to_adata.py,sha256=YF0zeg6k0FiPRCzLLrTcZQ5Q97fI8tZRnzNWco5Jwa0,84581
49
53
  smftools/informatics/modkit_functions.py,sha256=BvWd_qulVOQKZJFMd4pLTVD3ruo1dT48BmvQsdHB0_E,6103
50
54
  smftools/informatics/ohe.py,sha256=fdMEdXG45hiCsHtmYkPsXJKLJ-SBaZktdGx-bmfI3a0,5997
51
55
  smftools/informatics/pod5_functions.py,sha256=6_EA2StpslOe0phSwR9TDB_U-Tmx4ykuBcTAiOL0LPU,10327
52
56
  smftools/informatics/run_multiqc.py,sha256=M67HhO5FIJl8qn3Qc9YUlnbk7kdDWyYVL0B9SenrqMo,1115
57
+ smftools/informatics/sequence_encoding.py,sha256=9u6E1IcUFL6Cn2BOWW4l_VYY9qQ-6KJo7M1bprMLV30,2244
53
58
  smftools/informatics/archived/bam_conversion.py,sha256=Gvy8X8AmCNYQEiwGjnmzs4YRMO3b5Cy6YDuVX8uLwJc,3366
54
59
  smftools/informatics/archived/bam_direct.py,sha256=Dj0YGeQzPb2jdFdO6qW6gyTxgdfCHI_c-xpYUc2MARQ,3642
55
60
  smftools/informatics/archived/basecall_pod5s.py,sha256=EAGHhKeCkFHybZmJrVR12kInnY5k0TXM__gLuplUOu4,3966
@@ -121,33 +126,42 @@ smftools/machine_learning/training/train_sklearn_model.py,sha256=zQ5SQpu_sl7IVcZ
121
126
  smftools/machine_learning/utils/__init__.py,sha256=aiCNpHD08ENEBtz8jzDfVZ8cB7ef9uOE7YaOPDkQUYg,99
122
127
  smftools/machine_learning/utils/device.py,sha256=2D5TF6DQIZKTcyNqIcJ7UMFeiWS_kCAvZUBK6XngCXk,432
123
128
  smftools/machine_learning/utils/grl.py,sha256=ptr-08dRKAGBZ1cySy_B90GgMn5kXtNXlcUC4PJ5mNA,485
124
- smftools/plotting/__init__.py,sha256=JrfnlocBQdW2QeP207PDUcx_4DMiOPLszxZBBml9POw,1478
125
- smftools/plotting/autocorrelation_plotting.py,sha256=gc3iyGgFEvMcyHXE2K8S956Nx6IfduglOOeJj3te8nU,30590
126
- smftools/plotting/classifiers.py,sha256=9Qt0eixvgE3WXl6jcwPm7O3ATA7Q6mfqRh_B_9M2qTQ,16749
127
- smftools/plotting/general_plotting.py,sha256=ShN8R0yauo-Br_IDy3ZlM5VR3wuetFaEtLxK5r6Nn8A,69455
128
- smftools/plotting/hmm_plotting.py,sha256=wPROxP-IJj-lY1I70s5YYy-H-XFfbcVol8PS2aw7srQ,11644
129
- smftools/plotting/position_stats.py,sha256=yxZx0Hjx4MsKINe9kkq-R7TkjODBGaDrbH9y0mrrTWs,19351
130
- smftools/plotting/qc_plotting.py,sha256=ODK8UrjVrAJeG8Qfu09DmAJ_o9GJaXRxGwN0pEgbHAU,10358
131
- smftools/preprocessing/__init__.py,sha256=l_oNlEOjrzoAZbTa66y9prIkEPbGcH4F1J2MyyMmesE,1855
132
- smftools/preprocessing/append_base_context.py,sha256=Z18Izb9-gZ4_ifXOHFZqcmPOradjCiyJZMZ5oTDfiLQ,7102
129
+ smftools/plotting/__init__.py,sha256=HfDYE0N7ZQSpA6gnFVd1XwEIIAq7Z2U8N4deWtCn1g4,3095
130
+ smftools/plotting/autocorrelation_plotting.py,sha256=fnnvzl_5cD09Jz2wH3iGIZE3UT5oyHQ1OtwPSVk2cbM,31314
131
+ smftools/plotting/chimeric_plotting.py,sha256=j-TMqKg0bzt2Fssi89FWR04WvLYFGkMOyksjN9T-qjo,70200
132
+ smftools/plotting/classifiers.py,sha256=EouBhnrHbBbeL8mJZEPU3GbFyIO1p6aERp0FIqp-3j4,17362
133
+ smftools/plotting/general_plotting.py,sha256=Tj9_V27K0f4mymsNWfwRbgQkPwvgiyoDw7yzM8JVSRo,1809
134
+ smftools/plotting/hmm_plotting.py,sha256=afEAZVknf8wP8yYFA7-tT8Hlwy6sLGKuZKHlu7a-tg8,79999
135
+ smftools/plotting/latent_plotting.py,sha256=vC12rJg-8_luYmX6XI3meMw-oyD3bYYIu0nFTvTiZfQ,28584
136
+ smftools/plotting/plotting_utils.py,sha256=HYNDbCJUMyo_JlIjZ5JtVmv02ncpFoiGzqc1vCRbJKA,7282
137
+ smftools/plotting/position_stats.py,sha256=ITG4tEuZgjn3mCoGCNs2SQfiWAzqfl_cki9VOGD_RAA,19862
138
+ smftools/plotting/preprocess_plotting.py,sha256=VbQWKgO-Tlu2hYT2IOupsATEb6jxgqAwinUbivnNYNw,11736
139
+ smftools/plotting/qc_plotting.py,sha256=h1JGCNzDOTNHq2Zr93mI_qqkdqaNxrragmJyZ9PDIyw,10556
140
+ smftools/plotting/spatial_plotting.py,sha256=uVzpdh7pYRqRoDRvQR_fQaOl44FIMkq8YhfwDRYSbTE,44372
141
+ smftools/plotting/variant_plotting.py,sha256=AGcPZ2WSO4VSWTIn9rbxhOzud7sH4CnmZkxcwPVIo5M,54080
142
+ smftools/preprocessing/__init__.py,sha256=Hcq89k8M2kbzOW7vl7X91PEn4npsOPFShmyrUXeBtmA,2232
143
+ smftools/preprocessing/append_base_context.py,sha256=1C8ZeULZNbAWmD5sZxNh14axI4OZMnsOAaZifjeOZHE,7134
133
144
  smftools/preprocessing/append_binary_layer_by_base_context.py,sha256=7mFG7xjAPgm_60AcdCnnjJZK5gJe4VuLohopkrAHmvQ,7640
145
+ smftools/preprocessing/append_mismatch_frequency_sites.py,sha256=cB-lg8GEEoFu2ESSxCyVObIcuMZTFip4Es96a-EJQQ4,7446
146
+ smftools/preprocessing/append_sequence_mismatch_annotations.py,sha256=wa2hMtsAkk3IYz1dAUBfBUS-5fwHZWUH98stujW4E00,6429
147
+ smftools/preprocessing/append_variant_call_layer.py,sha256=dhvIPVWRSv-Tn9JoTKmeAz6kbHg-iocpRGq_YGA0hHM,19098
134
148
  smftools/preprocessing/binarize.py,sha256=eDFLybKKIF2wcrtN3JWVjeGXSUayezxLhX76UllAhVc,888
135
149
  smftools/preprocessing/binarize_on_Youden.py,sha256=JTHosTDy9-gJ0bPrHkGnz_Ao_AeE8IiutqFA6MksdM8,4887
136
150
  smftools/preprocessing/binary_layers_to_ohe.py,sha256=nYvAefdIKGj-JyNtBqHcekJKI4BI2CM9pN-Mq1BT-28,1931
137
151
  smftools/preprocessing/calculate_complexity_II.py,sha256=iVh5BcLCPOndVeN4A7Gw74pMBa83UQuxtV5o_sVFUNs,10367
138
- smftools/preprocessing/calculate_consensus.py,sha256=1_-ldkwQ3JT5Rns9thIfV-HJbSKFW2b1Auida96lhGE,2377
152
+ smftools/preprocessing/calculate_consensus.py,sha256=YbeHFwyhH8MIl_2Acdg5B3DOyFJW8hVqFCZQYSZTLAU,2382
139
153
  smftools/preprocessing/calculate_coverage.py,sha256=HZ8rtEmb-z6XCr-EvMfl4rc_9nbTJRztyEk8xUg7feE,2777
140
154
  smftools/preprocessing/calculate_pairwise_differences.py,sha256=BRht5E8BtmJp_mxUSH5WfguhXaYV1zdPXZQLL1Wu6lI,1799
141
155
  smftools/preprocessing/calculate_pairwise_hamming_distances.py,sha256=86MioHtN6mpH04bj-3UNv2Vistglt8I0ZMALKNEAq7g,999
142
156
  smftools/preprocessing/calculate_position_Youden.py,sha256=HKnQAZvff1i8FVSxLkhcGwR2kmAq63izsOBGdCd3ws8,9146
143
157
  smftools/preprocessing/calculate_read_length_stats.py,sha256=y2R5lU6ObRBCAhSHKLEZYpgm88woPd9d15NWVthIi_A,4790
144
- smftools/preprocessing/calculate_read_modification_stats.py,sha256=L1X0LatpjPI5wA1j7MjFgukePYGo75DcgJCYPlhVAGM,5319
158
+ smftools/preprocessing/calculate_read_modification_stats.py,sha256=dc8QWwGqctnk6xbTNUaFy_uA4gg8ZaM6fN_KvEyzm64,5555
145
159
  smftools/preprocessing/clean_NaN.py,sha256=hrPhbKfqDpSiXLXXJxvcmtwqFhOecJVC29Z7PMIxi5I,2163
146
160
  smftools/preprocessing/filter_adata_by_nan_proportion.py,sha256=5V1PNJISYm92QtEGmS9XSqx456Ult8RY8LMBclNylno,1490
147
161
  smftools/preprocessing/filter_reads_on_length_quality_mapping.py,sha256=83G8ovetiAmh8EbikqAUhNnzaX_KnWe0rZ7vfrgeye4,8018
148
162
  smftools/preprocessing/filter_reads_on_modification_thresholds.py,sha256=yxYZB9Ran1ZxuZm9iHi5bpLo6xcro5zKyv9rnYUtT6g,21688
149
- smftools/preprocessing/flag_duplicate_reads.py,sha256=7MooUKnUULJY6IiCNO7P0idE7_6X0usMtX7F9us8n4U,75420
150
- smftools/preprocessing/invert_adata.py,sha256=-aiidr_PXSf8IIpC4PMRm2RlLAWi-dtZDpr0iSOY-PY,1367
163
+ smftools/preprocessing/flag_duplicate_reads.py,sha256=Khauxw8_stBLmmkM1z4HVVuXpcWIhgTjJwoH-WfOoko,75436
164
+ smftools/preprocessing/invert_adata.py,sha256=QIbNDWra34hp_HHGvYfUYpqwtimIuKys-mVwrb1ChPI,1418
151
165
  smftools/preprocessing/load_sample_sheet.py,sha256=rzY76rCYVf3idu2ZRw4pEjVRBB5AyUkSYY-UzpmE_aw,2193
152
166
  smftools/preprocessing/make_dirs.py,sha256=SjeiXoWsy_SldM-RoQbpfo2mXdnP78xhHVHywTD7IZI,662
153
167
  smftools/preprocessing/min_non_diagonal.py,sha256=2sOWl7zKWltNmv-Jv-ZXb099dYBX28suAOE6DUlUO-U,749
@@ -160,23 +174,30 @@ smftools/preprocessing/archived/mark_duplicates.py,sha256=Acj27Xc8ht8e1HYZFgq57z
160
174
  smftools/preprocessing/archived/preprocessing.py,sha256=l0Im9O45kaMYxipyFiPFBA8M7NLiOxWuONf8igmHaPc,34567
161
175
  smftools/preprocessing/archived/remove_duplicates.py,sha256=W1Y2ufD2nE9Tnx3NXpEPxso08tiV50iRy77_X3RZkyQ,735
162
176
  smftools/schema/__init__.py,sha256=0chkz2Zc3UKSJO4m0MUemfs-WjGUSSghiuuFM28UvsY,293
163
- smftools/schema/anndata_schema_v1.yaml,sha256=uNFTrsTLNoE3kgJgrcg-hM6iYtDRsu6SHwWCkbcgIuk,7746
164
- smftools/tools/__init__.py,sha256=MqvwhrFQsTvoSpbJ4HIzV9LWwNLef0RXe9iI3VZReMI,976
165
- smftools/tools/calculate_umap.py,sha256=oj4EJP4M3cZ50T0bYNVAfZAssEG9ZxKmNgjgKmqxf-g,3594
177
+ smftools/schema/anndata_schema_v1.yaml,sha256=FCMjYIqgt-YxQxehcgkdwWBzqk1k-aSZ3fUcksX1bH4,8310
178
+ smftools/tools/__init__.py,sha256=40LW8N6CiQMyRkujbm12cCJf8X2PdqrLWYwFiFUeNbg,1650
179
+ smftools/tools/calculate_knn.py,sha256=pPnkZpbO6qUD0Te62kB1D_6f7Y5UzUnrIu7b_XhtVNg,3921
180
+ smftools/tools/calculate_leiden.py,sha256=48Y72NIzGb6yxtnUund7gS_2jIFro5lwJC0ycNOoAJI,1867
181
+ smftools/tools/calculate_nmf.py,sha256=E1SCqOycGAdPm_-VLauLtyy4fd5UaFKNiNlVK3nr8Lo,4577
182
+ smftools/tools/calculate_pca.py,sha256=4dm2sEDkKZhW9_0q1e2lfpr6zVgmUNNReuEyCWbOa3g,6444
183
+ smftools/tools/calculate_umap.py,sha256=D5kTWRR6VIvSXWH_6uWC8q8PSnnK5f1g3yN4xxzQXVE,3370
166
184
  smftools/tools/cluster_adata_on_methylation.py,sha256=NsU11zFyBB_TZFdVZxjqeSZsiVZgb8iCXaOBY54FA9U,7684
167
185
  smftools/tools/general_tools.py,sha256=XO8em-clV4onfbYEH6JTfNj3svLQnwBZ1Tja7s8qsXg,3260
168
- smftools/tools/position_stats.py,sha256=FiFidt3b5cdEMylFoPPrCZbLAXQHsehxFFcTaHvTtt4,27425
186
+ smftools/tools/position_stats.py,sha256=6tDCgnLNZMU_bKs784ku-gdDZDW-2xbZSsQFdvhpLGQ,27441
169
187
  smftools/tools/read_stats.py,sha256=8rV2BXymdPuPihh0Ev-HqPT40lobyt5WExoYjbmrbcI,6534
188
+ smftools/tools/rolling_nn_distance.py,sha256=k0Ut59wc2A0nTIOvocMM6zxHbQwswYE65ZKYXFqnCbA,32388
189
+ smftools/tools/sequence_alignment.py,sha256=KgnDC9Ve66v_xmb4rzGWHsGAlbrPi2K930sSx6NkGkA,4562
170
190
  smftools/tools/spatial_autocorrelation.py,sha256=euunec6Mmkm5iBDN7TM4q4NXLl9n8UP77-6GSGYCVOk,25473
171
191
  smftools/tools/subset_adata.py,sha256=6xPf6hyKcYwg4L2n0iCnz-Pl84fS4jLgxmD47J-OEco,1012
192
+ smftools/tools/tensor_factorization.py,sha256=c5p2DtltUIUYRUuoPiNQnAj-ms-V2C-WEcwgF1p4-5k,7697
172
193
  smftools/tools/archived/apply_hmm.py,sha256=b1DKT_02weiPgkfQ0_Zfk7wN8FRZAMeYvBe74H3QuDU,9357
173
194
  smftools/tools/archived/classifiers.py,sha256=iKkK9UyEwEdNwLx-t_r52CURkP3iZ-pFwmQtXF_lnLY,42191
174
195
  smftools/tools/archived/classify_methylated_features.py,sha256=uXWXl4t9cP4inRiSvL4MxGbwC2MxT5uT-D1FFdex8oE,2933
175
196
  smftools/tools/archived/classify_non_methylated_features.py,sha256=vhfLbR5fqALps5HXxQ91x3lUTGLcfciaEsQkSFeLOgM,3292
176
197
  smftools/tools/archived/subset_adata_v1.py,sha256=CBTbHolOil7m4eR0bwIzxS7ZPvo3hmDsPVZGUBzWYrs,1361
177
198
  smftools/tools/archived/subset_adata_v2.py,sha256=npic7cuFIOeUiyRjATVrP4A0O7cV0EgHvRXi9aMMOcI,2311
178
- smftools-0.3.0.dist-info/METADATA,sha256=JuAG9ifECVbhIjC2lKmIqgzosM1Ao2naUcmGh7zgpHk,7840
179
- smftools-0.3.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
180
- smftools-0.3.0.dist-info/entry_points.txt,sha256=q4hg4w-mKkI2leekM_-YZc5XRJzp96Mh1FcU3hac82g,52
181
- smftools-0.3.0.dist-info/licenses/LICENSE,sha256=F8LwmL6vMPddaCt1z1S83Kh_OZv50alTlY7BvVx1RXw,1066
182
- smftools-0.3.0.dist-info/RECORD,,
199
+ smftools-0.3.2.dist-info/METADATA,sha256=nOOfJCCWKHQMZU-BSGiipUtnuKEA70esQj-w2Nc_NHE,8036
200
+ smftools-0.3.2.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
201
+ smftools-0.3.2.dist-info/entry_points.txt,sha256=q4hg4w-mKkI2leekM_-YZc5XRJzp96Mh1FcU3hac82g,52
202
+ smftools-0.3.2.dist-info/licenses/LICENSE,sha256=F8LwmL6vMPddaCt1z1S83Kh_OZv50alTlY7BvVx1RXw,1066
203
+ smftools-0.3.2.dist-info/RECORD,,