spatialquery.js 0.0.0-stage → 0.1.0

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.
@@ -0,0 +1,325 @@
1
+ // Port of the multi-FOV class spatial_query_multi.
2
+ // Reference: https://github.com/ShaokunAn/Spatial-Query/blob/9250b61/SpatialQuery/spatial_query_multiple_fov.py
3
+ import { buildContext, findCellIndicesOfType, knnTransactions, radiusTransactions, centerQueryPoints, knnNeighborhood, radiusNeighborhood, countMotifs, computeMotifEnrichment, normalizeMotifs, normalizeMotifList, motifCompositionRows, assertEnrichmentMode, findFpKnn as findFpKnnSingle, findFpDist as findFpDistSingle, } from './single-fov.js';
4
+ import { mineFrequentPatterns } from './fpgrowth.js';
5
+ import { nestedMotifDescent } from './nested.js';
6
+ import { applyFdrCorrection, fdrCorrection, mannWhitneyU, rankAverage, median, mean } from './stats.js';
7
+ // Build the multi-FOV context object.
8
+ // Unlike Python, which derives unique FOV names from the (possibly repeated) dataset names
9
+ // ('name' -> 'name_0', 'name_1', ...), each FOV has an explicit ID and class.
10
+ // Reference: https://github.com/ShaokunAn/Spatial-Query/blob/9250b61/SpatialQuery/spatial_query_multiple_fov.py#L43
11
+ export function buildMultiContext(fovs) {
12
+ const datasetIds = fovs.map(fov => fov.datasetId);
13
+ const duplicates = datasetIds.filter((id, i) => datasetIds.indexOf(id) !== i);
14
+ if (duplicates.length > 0) {
15
+ throw new Error(`Dataset IDs must be unique. Found duplicates: ${Array.from(new Set(duplicates)).join(', ')}`);
16
+ }
17
+ return {
18
+ datasetIds,
19
+ datasetClasses: fovs.map(fov => fov.datasetClass),
20
+ contexts: fovs.map(fov => buildContext(fov)),
21
+ };
22
+ }
23
+ // The datasets (FOVs) belonging to the selected classes (all classes if not provided).
24
+ function selectFovs(multi, datasetClass) {
25
+ const validClasses = new Set(multi.datasetClasses);
26
+ const selected = datasetClass === undefined
27
+ ? validClasses
28
+ : new Set(typeof datasetClass === 'string' ? [datasetClass] : datasetClass);
29
+ for (const c of selected) {
30
+ if (!validClasses.has(c)) {
31
+ throw new Error(`Invalid dataset class: ${c}. Valid dataset classes are: ${Array.from(validClasses).join(', ')}`);
32
+ }
33
+ }
34
+ return multi.contexts
35
+ .map((context, i) => ({ datasetId: multi.datasetIds[i], datasetClass: multi.datasetClasses[i], context }))
36
+ .filter(fov => selected.has(fov.datasetClass));
37
+ }
38
+ // Throws if the cell type is absent from every FOV (selected or not, as in Python).
39
+ function assertCellTypeInAnyFov(multi, ct) {
40
+ if (!multi.contexts.some(context => context.labels.includes(ct))) {
41
+ throw new Error(`Found no ${ct} in any datasets!`);
42
+ }
43
+ }
44
+ // Unique cell type labels across all FOVs.
45
+ function allLabels(multi) {
46
+ return new Set(multi.contexts.flatMap(context => context.labels));
47
+ }
48
+ // Find frequent patterns within the k-NN neighborhoods of a cell type, pooling the
49
+ // neighborhoods of all selected FOVs.
50
+ // Reference: https://github.com/ShaokunAn/Spatial-Query/blob/9250b61/SpatialQuery/spatial_query_multiple_fov.py#L116
51
+ export async function multiFindFpKnn(multi, params) {
52
+ const { ct, datasetClass, k = 30, minSupport = 0.5, maxDist = 20, ifMax = true } = params;
53
+ assertCellTypeInAnyFov(multi, ct);
54
+ const transactions = selectFovs(multi, datasetClass).flatMap(({ context }) => (knnTransactions(context, findCellIndicesOfType(context, ct), k, maxDist)));
55
+ return mineFrequentPatterns(transactions, minSupport, ifMax);
56
+ }
57
+ // Find frequent patterns within the radius-based neighborhoods of a cell type, pooling the
58
+ // neighborhoods of all selected FOVs.
59
+ // Reference: https://github.com/ShaokunAn/Spatial-Query/blob/9250b61/SpatialQuery/spatial_query_multiple_fov.py#L219
60
+ export async function multiFindFpDist(multi, params) {
61
+ const { ct, datasetClass, maxDist = 20, minSize = 0, minSupport = 0.5, ifMax = true } = params;
62
+ assertCellTypeInAnyFov(multi, ct);
63
+ const transactions = selectFovs(multi, datasetClass).flatMap(({ context }) => {
64
+ const points = centerQueryPoints(context, findCellIndicesOfType(context, ct));
65
+ return radiusTransactions(context, points, maxDist, minSize).transactions;
66
+ });
67
+ return mineFrequentPatterns(transactions, minSupport, ifMax);
68
+ }
69
+ function getFov(multi, datasetId) {
70
+ const index = multi.datasetIds.indexOf(datasetId);
71
+ if (index === -1) {
72
+ throw new Error(`Found no dataset with ID ${datasetId}.`);
73
+ }
74
+ return multi.contexts[index];
75
+ }
76
+ // Find frequent (maximal) patterns within the k-NN neighborhoods of a cell type in a single FOV.
77
+ // Reference: https://github.com/ShaokunAn/Spatial-Query/blob/9250b61/SpatialQuery/spatial_query_multiple_fov.py#L993
78
+ export async function findFpKnnFov(multi, params) {
79
+ const { ct, datasetId, k = 30, minSupport = 0.5, maxDist = 20 } = params;
80
+ const context = getFov(multi, datasetId);
81
+ if (!context.labels.includes(ct))
82
+ return [];
83
+ return findFpKnnSingle(context, { ct, k, minSupport, maxDist });
84
+ }
85
+ // Find frequent (maximal) patterns within the radius-based neighborhoods of a cell type in a single FOV.
86
+ // Reference: https://github.com/ShaokunAn/Spatial-Query/blob/9250b61/SpatialQuery/spatial_query_multiple_fov.py#L1049
87
+ export async function findFpDistFov(multi, params) {
88
+ const { ct, datasetId, maxDist = 20, minSize = 0, minSupport = 0.5 } = params;
89
+ const context = getFov(multi, datasetId);
90
+ if (!context.labels.includes(ct))
91
+ return [];
92
+ return findFpDistSingle(context, { ct, maxDist, minSize, minSupport });
93
+ }
94
+ // Normalize user-specified motifs against the labels of all FOVs, throwing if none remain.
95
+ function normalizeMultiMotifs(multi, motifs) {
96
+ const filtered = normalizeMotifs(motifs, allLabels(multi));
97
+ if (filtered.length === 0) {
98
+ throw new Error("All cell types in motifs are missing in the cell type labels.");
99
+ }
100
+ return filtered;
101
+ }
102
+ function multiMotifEnrichment(fovs, ct, motifs, neighborhood, returnCellIds) {
103
+ const totals = motifs.map(() => ({ numCells: 0, numCenter: 0, numMotif: 0, numCenterMotif: 0 }));
104
+ const neighborIds = motifs.map(() => ({}));
105
+ const centerIds = motifs.map(() => ({}));
106
+ for (const { datasetId, context } of fovs) {
107
+ const counts = countMotifs(context, ct, motifs, neighborhood(context), returnCellIds);
108
+ counts.forEach((c, m) => {
109
+ totals[m].numCells += c.numCells;
110
+ totals[m].numCenter += c.numCenter;
111
+ totals[m].numMotif += c.numMotif;
112
+ totals[m].numCenterMotif += c.numCenterMotif;
113
+ if (returnCellIds && c.centerIndices.length > 0) {
114
+ neighborIds[m][datasetId] = c.neighborIndices.map(j => context.obsIndex[j]);
115
+ centerIds[m][datasetId] = c.centerIndices.map(i => context.obsIndex[i]);
116
+ }
117
+ });
118
+ }
119
+ const out = motifs.map((motif, m) => {
120
+ const { neighborIds: _n, centerIds: _c, ...result } = computeMotifEnrichment({ center: ct, motif, ...totals[m] });
121
+ return returnCellIds
122
+ ? { ...result, neighborIds: neighborIds[m], centerIds: centerIds[m] }
123
+ : result;
124
+ });
125
+ return applyFdrCorrection(out);
126
+ }
127
+ // Perform motif enrichment analysis using k-nearest neighbors in multiple FOVs.
128
+ // Reference: https://github.com/ShaokunAn/Spatial-Query/blob/9250b61/SpatialQuery/spatial_query_multiple_fov.py#L319
129
+ export async function multiMotifEnrichmentKnn(multi, params) {
130
+ const { ct, datasetClass, k = 30, minSupport = 0.5, maxDist = 20, returnCellIds = false, mode = 'maximal' } = params;
131
+ const fovs = selectFovs(multi, datasetClass);
132
+ assertCellTypeInAnyFov(multi, ct);
133
+ assertEnrichmentMode(mode);
134
+ if (mode === 'nested' && params.motifs === undefined) {
135
+ return nestedMotifDescent({
136
+ testMotifs: motifs => multiMotifEnrichmentKnn(multi, { ...params, motifs, mode: 'maximal' }),
137
+ frequentPatterns: await multiFindFpKnn(multi, { ct, datasetClass, k, minSupport, maxDist, ifMax: false }),
138
+ });
139
+ }
140
+ const motifs = params.motifs === undefined
141
+ ? (await multiFindFpKnn(multi, { ct, datasetClass, k, minSupport, maxDist })).map(p => p.itemsets)
142
+ : normalizeMultiMotifs(multi, params.motifs);
143
+ return multiMotifEnrichment(fovs, ct, motifs, context => knnNeighborhood(context, k, maxDist), returnCellIds);
144
+ }
145
+ // Perform motif enrichment analysis within a radius-based neighborhood in multiple FOVs.
146
+ // Reference: https://github.com/ShaokunAn/Spatial-Query/blob/9250b61/SpatialQuery/spatial_query_multiple_fov.py#L581
147
+ export async function multiMotifEnrichmentDist(multi, params) {
148
+ const { ct, datasetClass, maxDist = 20, minSize = 0, minSupport = 0.5, returnCellIds = false, mode = 'maximal' } = params;
149
+ const fovs = selectFovs(multi, datasetClass);
150
+ assertCellTypeInAnyFov(multi, ct);
151
+ assertEnrichmentMode(mode);
152
+ if (mode === 'nested' && params.motifs === undefined) {
153
+ return nestedMotifDescent({
154
+ testMotifs: motifs => multiMotifEnrichmentDist(multi, { ...params, motifs, mode: 'maximal' }),
155
+ frequentPatterns: await multiFindFpDist(multi, { ct, datasetClass, maxDist, minSize, minSupport, ifMax: false }),
156
+ });
157
+ }
158
+ const motifs = params.motifs === undefined
159
+ ? (await multiFindFpDist(multi, { ct, datasetClass, maxDist, minSize, minSupport })).map(p => p.itemsets)
160
+ : normalizeMultiMotifs(multi, params.motifs);
161
+ return multiMotifEnrichment(fovs, ct, motifs, context => radiusNeighborhood(context, maxDist), returnCellIds);
162
+ }
163
+ // Pool the motif composition over the selected FOVs.
164
+ // Reference: https://github.com/ShaokunAn/Spatial-Query/blob/9250b61/SpatialQuery/spatial_query_multiple_fov.py#L851
165
+ function multiMotifComposition(multi, ct, motifsParam, datasetClass, neighborhood) {
166
+ const fovs = selectFovs(multi, datasetClass);
167
+ assertCellTypeInAnyFov(multi, ct);
168
+ const motifs = normalizeMotifList(motifsParam, allLabels(multi));
169
+ return fovs.flatMap(({ datasetId, context }) => {
170
+ const cinds = findCellIndicesOfType(context, ct);
171
+ const labelsUnique = new Set(context.labels);
172
+ // A motif with a cell type missing from this FOV has no motif-positive center here.
173
+ const active = motifs.filter(m => m.every(t => labelsUnique.has(t)));
174
+ if (cinds.length === 0 || active.length === 0)
175
+ return [];
176
+ return motifCompositionRows(context, ct, active, cinds, neighborhood(context))
177
+ .map(row => ({ datasetId, ...row }));
178
+ });
179
+ }
180
+ // Compute the composition of motif cell types in the k-NN neighborhoods of center cells across multiple FOVs.
181
+ // Reference: https://github.com/ShaokunAn/Spatial-Query/blob/9250b61/SpatialQuery/spatial_query_multiple_fov.py#L931
182
+ export function multiMotifCompositionKnn(multi, params) {
183
+ const { ct, motifs, datasetClass, k = 30, maxDist = 20 } = params;
184
+ return multiMotifComposition(multi, ct, motifs, datasetClass, context => knnNeighborhood(context, k, maxDist));
185
+ }
186
+ // Compute the composition of motif cell types in the radius-based neighborhoods of center cells across multiple FOVs.
187
+ // Reference: https://github.com/ShaokunAn/Spatial-Query/blob/9250b61/SpatialQuery/spatial_query_multiple_fov.py#L888
188
+ export function multiMotifCompositionDist(multi, params) {
189
+ const { ct, motifs, datasetClass, maxDist = 20 } = params;
190
+ return multiMotifComposition(multi, ct, motifs, datasetClass, context => radiusNeighborhood(context, maxDist));
191
+ }
192
+ // Normalize motifs as differential_analysis_motif_* does (no filtering of unknown cell types).
193
+ function toDifferentialMotifs(motifs) {
194
+ if (typeof motifs === 'string')
195
+ return [[motifs]];
196
+ if (motifs.length > 0 && typeof motifs[0] === 'string')
197
+ return [motifs];
198
+ return motifs;
199
+ }
200
+ // Test every motif for a difference in support between the datasets of two classes.
201
+ // Returns all tested motifs, unlike differentialAnalysisKnn/Dist which return only the significant ones.
202
+ // Reference: https://github.com/ShaokunAn/Spatial-Query/blob/9250b61/SpatialQuery/spatial_differential_pattern.py
203
+ function differentialTests(multi, datasetClasses, ct, motifsParam,
204
+ // Support of each motif among the given center cells of a dataset.
205
+ supportsInFov) {
206
+ const motifs = [];
207
+ const motifKeys = new Set();
208
+ for (const motif of toDifferentialMotifs(motifsParam)) {
209
+ const sorted = motif.toSorted();
210
+ const key = JSON.stringify(sorted);
211
+ if (!motifKeys.has(key)) {
212
+ motifKeys.add(key);
213
+ motifs.push(sorted);
214
+ }
215
+ }
216
+ const supports = motifs.map(() => Object.fromEntries(datasetClasses.map(c => [c, []])));
217
+ for (const datasetClass of datasetClasses) {
218
+ for (const { context } of selectFovs(multi, datasetClass)) {
219
+ const cinds = findCellIndicesOfType(context, ct);
220
+ const fovSupports = cinds.length === 0 ? motifs.map(() => 0) : supportsInFov(context, cinds, motifs);
221
+ fovSupports.forEach((s, m) => supports[m][datasetClass].push(s));
222
+ }
223
+ }
224
+ const [c0, c1] = datasetClasses;
225
+ const results = motifs.map((itemsets, m) => {
226
+ const group1 = supports[m][c0];
227
+ const group2 = supports[m][c1];
228
+ let pValue = 1.0;
229
+ let datasetClassHigherFrequency = 'neither';
230
+ if (group1.length > 0 && group2.length > 0) {
231
+ pValue = mannWhitneyU(group1, group2).pValue;
232
+ // Determine which class has higher frequency using the median rank.
233
+ const ranks = rankAverage([...group1, ...group2]);
234
+ const medianRank1 = median(ranks.slice(0, group1.length));
235
+ const medianRank2 = median(ranks.slice(group1.length));
236
+ datasetClassHigherFrequency = medianRank1 > medianRank2 ? c0 : c1;
237
+ }
238
+ return {
239
+ itemsets,
240
+ supports: supports[m],
241
+ supportMean: { [c0]: mean(group1), [c1]: mean(group2) },
242
+ pValue,
243
+ datasetClassHigherFrequency,
244
+ };
245
+ });
246
+ if (results.length > 1) {
247
+ const { rejected, adjusted } = fdrCorrection(results.map(r => r.pValue), 0.05);
248
+ return results.map((r, i) => ({ ...r, adjPValue: adjusted[i], ifSignificant: rejected[i] }));
249
+ }
250
+ return results.map(r => ({ ...r, adjPValue: r.pValue, ifSignificant: r.pValue < 0.05 }));
251
+ }
252
+ // Split the significant results by the class with the higher frequency, sorted by adjusted p-value.
253
+ function splitSignificant(results, datasetClasses) {
254
+ return Object.fromEntries(datasetClasses.map(c => [
255
+ c,
256
+ results
257
+ .filter(r => r.datasetClassHigherFrequency === c && r.ifSignificant)
258
+ .map(({ itemsets, supportMean, adjPValue }) => ({ itemsets, supportMean, adjPValue }))
259
+ .toSorted((a, b) => a.adjPValue - b.adjPValue),
260
+ ]));
261
+ }
262
+ // Union of the frequent patterns discovered in each dataset of the two classes.
263
+ async function discoverMotifs(multi, datasetClasses, findFpFov) {
264
+ const motifs = new Map();
265
+ for (const datasetClass of datasetClasses) {
266
+ for (const { datasetId } of selectFovs(multi, datasetClass)) {
267
+ for (const { itemsets } of await findFpFov(datasetId)) {
268
+ motifs.set(JSON.stringify(itemsets.toSorted()), itemsets.toSorted());
269
+ }
270
+ }
271
+ }
272
+ return Array.from(motifs.values());
273
+ }
274
+ function validateDifferentialClasses(multi, datasetClasses) {
275
+ if (datasetClasses.length !== 2) {
276
+ throw new Error("Require 2 dataset classes for differential analysis.");
277
+ }
278
+ selectFovs(multi, datasetClasses);
279
+ }
280
+ // Fraction of the center cells whose neighborhood contains every motif cell type
281
+ // (0 for motifs with a cell type missing from the dataset).
282
+ function motifSupports(context, cinds, motifs, neighborsOf, isValidCenter = () => true) {
283
+ const labelsUnique = new Set(context.labels);
284
+ const neighborTypes = cinds.map((i) => {
285
+ const neighbors = neighborsOf(i);
286
+ return isValidCenter(neighbors) ? new Set(neighbors.map(j => context.labels[j])) : null;
287
+ });
288
+ return motifs.map((motif) => {
289
+ if (!motif.every(t => labelsUnique.has(t)))
290
+ return 0;
291
+ const count = neighborTypes.filter(types => types !== null && motif.every(t => types.has(t))).length;
292
+ return count / cinds.length;
293
+ });
294
+ }
295
+ // Test all motifs for differential support between two dataset classes using k-NN neighborhoods.
296
+ // Returns every tested motif (including non-significant ones).
297
+ export async function differentialTestsKnn(multi, params) {
298
+ const { ct, datasetClasses, k = 30, minSupport = 0.5, maxDist = 20 } = params;
299
+ validateDifferentialClasses(multi, datasetClasses);
300
+ const motifs = params.motifs ?? await discoverMotifs(multi, datasetClasses, datasetId => (findFpKnnFov(multi, { ct, datasetId, k, minSupport, maxDist })));
301
+ return differentialTests(multi, datasetClasses, ct, motifs, (context, cinds, ms) => (motifSupports(context, cinds, ms, knnNeighborhood(context, k, maxDist))));
302
+ }
303
+ // Perform differential analysis of motif patterns between two dataset classes using k-NN neighborhoods.
304
+ // Returns, for each class, the motifs significantly more frequent in that class.
305
+ // Reference: https://github.com/ShaokunAn/Spatial-Query/blob/9250b61/SpatialQuery/spatial_query_multiple_fov.py#L1105
306
+ export async function differentialAnalysisKnn(multi, params) {
307
+ return splitSignificant(await differentialTestsKnn(multi, params), params.datasetClasses);
308
+ }
309
+ // Test all motifs for differential support between two dataset classes using radius-based neighborhoods.
310
+ // Returns every tested motif (including non-significant ones).
311
+ export async function differentialTestsDist(multi, params) {
312
+ const { ct, datasetClasses, maxDist = 20, minSupport = 0.5, minSize = 0 } = params;
313
+ validateDifferentialClasses(multi, datasetClasses);
314
+ const motifs = params.motifs ?? await discoverMotifs(multi, datasetClasses, datasetId => (findFpDistFov(multi, { ct, datasetId, maxDist, minSize, minSupport })));
315
+ // Center cells with neighborhoods not larger than minSize never count as having the motif,
316
+ // but still count in the denominator of the support.
317
+ return differentialTests(multi, datasetClasses, ct, motifs, (context, cinds, ms) => (motifSupports(context, cinds, ms, radiusNeighborhood(context, maxDist), neighbors => neighbors.length > minSize)));
318
+ }
319
+ // Perform differential analysis of motif patterns between two dataset classes using radius-based neighborhoods.
320
+ // Returns, for each class, the motifs significantly more frequent in that class.
321
+ // Reference: https://github.com/ShaokunAn/Spatial-Query/blob/9250b61/SpatialQuery/spatial_query_multiple_fov.py#L1206
322
+ export async function differentialAnalysisDist(multi, params) {
323
+ return splitSignificant(await differentialTestsDist(multi, params), params.datasetClasses);
324
+ }
325
+ //# sourceMappingURL=multi-fov.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multi-fov.js","sourceRoot":"","sources":["../src/multi-fov.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { type FrequentPattern } from './fpgrowth.js';
2
+ type TestedMotif = {
3
+ motifs: string[];
4
+ pValue: number;
5
+ adjPValue?: number;
6
+ ifSignificant?: boolean;
7
+ };
8
+ type NestedMotifDescentParams<T> = {
9
+ testMotifs: (motifs: string[][]) => Promise<T[]>;
10
+ frequentPatterns: FrequentPattern[];
11
+ supportTol?: number;
12
+ maxTestedPatterns?: number;
13
+ maxExpansionFactor?: number;
14
+ };
15
+ export declare function nestedMotifDescent<T extends TestedMotif>(params: NestedMotifDescentParams<T>): Promise<T[]>;
16
+ export {};
17
+ //# sourceMappingURL=nested.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nested.d.ts","sourceRoot":"","sources":["../src/nested.ts"],"names":[],"mappings":"AACA,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AA4B1E,KAAK,WAAW,GAAG;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAKrG,KAAK,wBAAwB,CAAC,CAAC,IAAI;IAGjC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAGjD,gBAAgB,EAAE,eAAe,EAAE,CAAC;IAEpC,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAIF,wBAAsB,kBAAkB,CAAC,CAAC,SAAS,WAAW,EAAE,MAAM,EAAE,wBAAwB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAwFjH"}
package/dist/nested.js ADDED
@@ -0,0 +1,106 @@
1
+ import { applyFdrCorrection } from './stats.js';
2
+ import { findMaximalPatterns } from './fpgrowth.js';
3
+ // Nested motif testing.
4
+ // Reference: https://github.com/ShaokunAn/Spatial-Query/blob/9250b61/SpatialQuery/spatial_utils.py#L97
5
+ //
6
+ // The maximal-pattern reduction happens BEFORE the hypergeometric test, so a sub-pattern
7
+ // of a non-significant maximal pattern never enters the tested set at all. When a maximal
8
+ // pattern is diluted by one abundant, unrelated cell type, the whole pattern fails the
9
+ // test and the informative core inside it is never examined.
10
+ //
11
+ // Nested testing walks into those patterns:
12
+ //
13
+ // 1. Test every maximal pattern, exactly as the maximal mode does.
14
+ // 2. A maximal pattern that IS significant is a finding in its own right -- stop, and do
15
+ // not test its sub-patterns.
16
+ // 3. A maximal pattern that is NOT significant is expanded into its immediate (k-1)
17
+ // sub-patterns, which are then tested.
18
+ // 4. Descent continues only along branches that stay non-significant. A branch ends when
19
+ // it becomes significant or reaches length 1.
20
+ // 5. A sub-pattern reachable from several parents is tested once.
21
+ // 6. Multiple-testing correction is applied over every pattern actually tested.
22
+ // 7. A child whose support equals its parent's marks the same neighborhoods as the
23
+ // parent, so it carries no extra information and is not reported.
24
+ const NESTED_SUPPORT_TOL = 1e-9;
25
+ const NESTED_MAX_TESTED_PATTERNS = 5000;
26
+ const NESTED_MAX_EXPANSION_FACTOR = 50.0;
27
+ // Canonical motif key: the sorted motif.
28
+ const canonicalKey = (motif) => JSON.stringify(motif.toSorted());
29
+ // Run the nested descent and return the corrected results over everything tested.
30
+ // Reference: https://github.com/ShaokunAn/Spatial-Query/blob/9250b61/SpatialQuery/spatial_utils.py#L161
31
+ export async function nestedMotifDescent(params) {
32
+ const { testMotifs, frequentPatterns, supportTol = NESTED_SUPPORT_TOL, maxTestedPatterns = NESTED_MAX_TESTED_PATTERNS, maxExpansionFactor = NESTED_MAX_EXPANSION_FACTOR, } = params;
33
+ if (frequentPatterns.length === 0) {
34
+ return [];
35
+ }
36
+ const supportOf = new Map(frequentPatterns.map(p => [canonicalKey(p.itemsets), p.support]));
37
+ const maximal = findMaximalPatterns(frequentPatterns).map(p => p.itemsets.toSorted());
38
+ // Level 0 is the maximal patterns; gating them decides where the descent starts.
39
+ const gateRes = maximal.length > 0 ? await testMotifs(maximal) : [];
40
+ if (gateRes.length === 0) {
41
+ return [];
42
+ }
43
+ const significance = (results) => new Map(results.map(r => [canonicalKey(r.motifs), Boolean(r.ifSignificant)]));
44
+ const gateSig = significance(gateRes);
45
+ // `tested` records every pattern the descent touches, significant or not: correction
46
+ // in rule 6 must cover them all. Insertion order keeps the final results reproducible.
47
+ const tested = new Set(maximal.map(canonicalKey));
48
+ const parentOf = new Map();
49
+ const levelTables = [gateRes];
50
+ let frontier = maximal.filter(m => !gateSig.get(canonicalKey(m)));
51
+ while (frontier.length > 0) {
52
+ const children = [];
53
+ for (const parent of frontier) {
54
+ if (parent.length <= 1)
55
+ continue;
56
+ // Immediate sub-patterns, in the order of itertools.combinations(parent, len(parent) - 1).
57
+ for (let drop = parent.length - 1; drop >= 0; drop--) {
58
+ const child = parent.filter((_, n) => n !== drop);
59
+ const childKey = canonicalKey(child);
60
+ if (tested.has(childKey)) {
61
+ // Reachable from an earlier parent already: test it once, and keep the
62
+ // shallowest parent, which breadth-first order guarantees is this one.
63
+ continue;
64
+ }
65
+ tested.add(childKey);
66
+ parentOf.set(childKey, canonicalKey(parent));
67
+ children.push(child);
68
+ }
69
+ }
70
+ if (children.length === 0)
71
+ break;
72
+ if (tested.size > maxTestedPatterns || tested.size > maxExpansionFactor * Math.max(maximal.length, 1)) {
73
+ console.warn(`Nested descent stopped early at ${tested.size} tested patterns `
74
+ + `(limits: maxTestedPatterns=${maxTestedPatterns}, `
75
+ + `maxExpansionFactor=${maxExpansionFactor} x ${maximal.length} maximal patterns). `
76
+ + `Reported results cover the patterns reached so far.`);
77
+ break;
78
+ }
79
+ const levelRes = await testMotifs(children);
80
+ levelTables.push(levelRes);
81
+ const levelSig = significance(levelRes);
82
+ frontier = children.filter(c => !levelSig.get(canonicalKey(c)));
83
+ }
84
+ // Every field except the FDR ones depends only on the motif and the data, so the
85
+ // results computed level by level are reused; only the correction is redone over the union.
86
+ const seen = new Set();
87
+ const combined = levelTables.flat().filter((r) => {
88
+ const key = canonicalKey(r.motifs);
89
+ if (seen.has(key))
90
+ return false;
91
+ seen.add(key);
92
+ return true;
93
+ });
94
+ // Rule 7: a child marking the same neighborhoods as its parent adds nothing. It stays
95
+ // in the correction -- it was tested -- but is not reported.
96
+ const redundant = new Set();
97
+ for (const [child, parent] of parentOf) {
98
+ const supportChild = supportOf.get(child);
99
+ const supportParent = supportOf.get(parent);
100
+ if (supportChild !== undefined && supportParent !== undefined && Math.abs(supportChild - supportParent) <= supportTol) {
101
+ redundant.add(child);
102
+ }
103
+ }
104
+ return applyFdrCorrection(combined).filter(r => !redundant.has(canonicalKey(r.motifs)));
105
+ }
106
+ //# sourceMappingURL=nested.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nested.js","sourceRoot":"","sources":["../src/nested.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,149 @@
1
+ import Flatbush from 'flatbush';
2
+ import { type FrequentPattern } from './fpgrowth.js';
3
+ export declare function generateObsIdToObsSetName(obsSetsMembership: Map<string, string[][]>, currSelectedSetGroup: string): (obsId: string) => string;
4
+ type ToObsSetNameFunc = ReturnType<typeof generateObsIdToObsSetName>;
5
+ type Coords = Float32Array | Float64Array;
6
+ export type InitParams = {
7
+ obsIndex: string[];
8
+ xCoords: Coords;
9
+ yCoords: Coords;
10
+ obsIdToObsSetName: ToObsSetNameFunc;
11
+ leafSize?: number;
12
+ normalizeSpatialCoord?: boolean;
13
+ };
14
+ export type SqContext = {
15
+ obsIndex: string[];
16
+ labels: string[];
17
+ xCoords: Coords;
18
+ yCoords: Coords;
19
+ flatbushIndex: Flatbush;
20
+ xExtent: [number, number];
21
+ yExtent: [number, number];
22
+ };
23
+ export declare function normalizeSpatialCoords(xCoords: Coords, yCoords: Coords): {
24
+ xCoords: Float64Array<ArrayBuffer>;
25
+ yCoords: Float64Array<ArrayBuffer>;
26
+ scaleFactor: number;
27
+ };
28
+ export declare function buildContext(params: InitParams): SqContext;
29
+ export declare function findCellIndicesOfType(context: SqContext, ct: string): number[];
30
+ export type QueryPoint = {
31
+ x: number;
32
+ y: number;
33
+ exclude?: number;
34
+ };
35
+ export declare function knnNeighborhood(context: SqContext, k: number, maxDist: number): (i: number) => number[];
36
+ export declare function radiusNeighborhood(context: SqContext, maxDist: number): (i: number) => number[];
37
+ export declare function radiusTransactions(context: SqContext, points: QueryPoint[], maxDist: number, minSize: number): {
38
+ transactions: string[][];
39
+ neighborLists: number[][];
40
+ };
41
+ export declare function knnTransactions(context: SqContext, cinds: number[], k: number, maxDist: number): string[][];
42
+ type FindPatternsParams = {
43
+ maxDist?: number;
44
+ minSize?: number;
45
+ minSupport?: number;
46
+ returnCellIds?: boolean;
47
+ };
48
+ export declare function buildGridPoints(context: SqContext, maxDist?: number): [number, number][];
49
+ export declare function findPatternsGrid(context: SqContext, params?: FindPatternsParams): Promise<FrequentPattern[]>;
50
+ export declare function findPatternsRand(context: SqContext, params?: FindPatternsParams & {
51
+ nPoints?: number;
52
+ }): Promise<FrequentPattern[]>;
53
+ type FindFpKnnParams = {
54
+ ct: string;
55
+ k?: number;
56
+ minSupport?: number;
57
+ maxDist?: number;
58
+ ifMax?: boolean;
59
+ };
60
+ export declare function findFpKnn(context: SqContext, params: FindFpKnnParams): Promise<FrequentPattern[]>;
61
+ type FindFpDistParams = {
62
+ ct: string;
63
+ maxDist?: number;
64
+ minSize?: number;
65
+ minSupport?: number;
66
+ ifMax?: boolean;
67
+ };
68
+ export declare function findFpDist(context: SqContext, params: FindFpDistParams): Promise<FrequentPattern[]>;
69
+ export declare function centerQueryPoints(context: SqContext, cinds: number[]): QueryPoint[];
70
+ type MotifEnrichmentCountsParams = {
71
+ center: string;
72
+ motif: string[];
73
+ numCells: number;
74
+ numCenter: number;
75
+ numMotif: number;
76
+ numCenterMotif: number;
77
+ };
78
+ export type MotifEnrichmentResult = {
79
+ center: string;
80
+ motifs: string[];
81
+ nCenterMotif: number;
82
+ nCenter: number;
83
+ nMotif: number;
84
+ expectation: number;
85
+ pValue: number;
86
+ ifSignificant?: boolean;
87
+ adjPValue?: number;
88
+ neighborIds?: string[];
89
+ centerIds?: string[];
90
+ };
91
+ export declare function computeMotifEnrichment(params: MotifEnrichmentCountsParams): MotifEnrichmentResult;
92
+ export type MotifsParam = string | string[] | string[][];
93
+ export declare function normalizeMotifs(motifs: MotifsParam, labelsUnique: Set<string>): string[][];
94
+ export declare function normalizeMotifList(motifs: MotifsParam, labelsUnique: Set<string>): string[][];
95
+ export type MotifCounts = {
96
+ numCells: number;
97
+ numCenter: number;
98
+ numMotif: number;
99
+ numCenterMotif: number;
100
+ centerIndices?: number[];
101
+ neighborIndices?: number[];
102
+ };
103
+ export declare function countMotifs(context: SqContext, ct: string, motifs: string[][], neighborsOf: (i: number) => number[], returnCellIds: boolean): MotifCounts[];
104
+ export type EnrichmentMode = 'maximal' | 'nested';
105
+ export declare function assertEnrichmentMode(mode: string): void;
106
+ type MotifEnrichmentKnnParams = {
107
+ ct: string;
108
+ motifs?: MotifsParam;
109
+ k?: number;
110
+ minSupport?: number;
111
+ maxDist?: number;
112
+ returnCellIds?: boolean;
113
+ mode?: EnrichmentMode;
114
+ };
115
+ export declare function motifEnrichmentKnn(context: SqContext, params: MotifEnrichmentKnnParams): Promise<MotifEnrichmentResult[]>;
116
+ type MotifEnrichmentDistParams = {
117
+ ct: string;
118
+ motifs?: MotifsParam;
119
+ maxDist?: number;
120
+ minSize?: number;
121
+ minSupport?: number;
122
+ returnCellIds?: boolean;
123
+ mode?: EnrichmentMode;
124
+ };
125
+ export declare function motifEnrichmentDist(context: SqContext, params: MotifEnrichmentDistParams): Promise<MotifEnrichmentResult[]>;
126
+ export type MotifCompositionRow = {
127
+ center: string;
128
+ motifs: string[];
129
+ cellType: string;
130
+ nCells: number;
131
+ nMotifCells: number;
132
+ proportion: number;
133
+ };
134
+ export declare function motifCompositionRows(context: SqContext, ct: string, motifs: string[][], cinds: number[], neighborsOf: (i: number) => number[]): MotifCompositionRow[];
135
+ type MotifCompositionKnnParams = {
136
+ ct: string;
137
+ motifs: MotifsParam;
138
+ k?: number;
139
+ maxDist?: number;
140
+ };
141
+ export declare function motifCompositionKnn(context: SqContext, params: MotifCompositionKnnParams): MotifCompositionRow[];
142
+ type MotifCompositionDistParams = {
143
+ ct: string;
144
+ motifs: MotifsParam;
145
+ maxDist?: number;
146
+ };
147
+ export declare function motifCompositionDist(context: SqContext, params: MotifCompositionDistParams): MotifCompositionRow[];
148
+ export {};
149
+ //# sourceMappingURL=single-fov.d.ts.map