@vitessce/config 3.0.1 → 3.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.
- package/dist/index.js +515 -59
- package/dist-tsc/VitessceAutoConfig.d.ts +13 -1
- package/dist-tsc/VitessceAutoConfig.d.ts.map +1 -1
- package/dist-tsc/VitessceAutoConfig.js +233 -57
- package/dist-tsc/VitessceAutoConfig.test.js +533 -76
- package/dist-tsc/VitessceConfig.d.ts +46 -0
- package/dist-tsc/VitessceConfig.d.ts.map +1 -1
- package/dist-tsc/VitessceConfig.js +353 -0
- package/dist-tsc/VitessceConfig.test.js +328 -1
- package/dist-tsc/constants.d.ts +247 -0
- package/dist-tsc/constants.d.ts.map +1 -0
- package/dist-tsc/constants.js +87 -0
- package/dist-tsc/index.d.ts +2 -1
- package/dist-tsc/index.js +2 -1
- package/package.json +3 -3
- package/src/VitessceAutoConfig.js +271 -65
- package/src/VitessceAutoConfig.test.js +561 -78
- package/src/VitessceConfig.js +393 -0
- package/src/VitessceConfig.test.js +338 -0
- package/src/constants.js +94 -0
- package/src/index.js +2 -1
package/dist/index.js
CHANGED
|
@@ -93,6 +93,10 @@ const FileType$1 = {
|
|
|
93
93
|
ANNDATA_EXPRESSION_MATRIX_ZARR: "anndata-expression-matrix.zarr"
|
|
94
94
|
};
|
|
95
95
|
const CoordinationType$1 = {
|
|
96
|
+
// Meta coordination scopes
|
|
97
|
+
META_COORDINATION_SCOPES: "metaCoordinationScopes",
|
|
98
|
+
META_COORDINATION_SCOPES_BY: "metaCoordinationScopesBy",
|
|
99
|
+
// Other coordination scopes
|
|
96
100
|
DATASET: "dataset",
|
|
97
101
|
// Entity types
|
|
98
102
|
OBS_TYPE: "obsType",
|
|
@@ -15245,6 +15249,72 @@ class VitessceConfigDataset {
|
|
|
15245
15249
|
};
|
|
15246
15250
|
}
|
|
15247
15251
|
}
|
|
15252
|
+
function useComplexCoordinationHelper(scopes, coordinationScopes, coordinationScopesBy) {
|
|
15253
|
+
function processLevel(parentType, parentScope, levelType, levelVal) {
|
|
15254
|
+
var _a, _b;
|
|
15255
|
+
if (Array.isArray(levelVal)) {
|
|
15256
|
+
coordinationScopesBy[parentType] = {
|
|
15257
|
+
...coordinationScopesBy[parentType] || {},
|
|
15258
|
+
[levelType]: {
|
|
15259
|
+
...((_a = coordinationScopesBy[parentType]) == null ? void 0 : _a[levelType]) || {},
|
|
15260
|
+
[parentScope.cScope]: levelVal.map((childVal) => childVal.scope.cScope)
|
|
15261
|
+
}
|
|
15262
|
+
};
|
|
15263
|
+
levelVal.forEach((childVal) => {
|
|
15264
|
+
if (childVal.children) {
|
|
15265
|
+
Object.entries(childVal.children).forEach(([nextLevelType, nextLevelVal]) => processLevel(
|
|
15266
|
+
levelType,
|
|
15267
|
+
childVal.scope,
|
|
15268
|
+
nextLevelType,
|
|
15269
|
+
nextLevelVal
|
|
15270
|
+
));
|
|
15271
|
+
}
|
|
15272
|
+
});
|
|
15273
|
+
} else {
|
|
15274
|
+
coordinationScopesBy[parentType] = {
|
|
15275
|
+
...coordinationScopesBy[parentType] || {},
|
|
15276
|
+
[levelType]: {
|
|
15277
|
+
...((_b = coordinationScopesBy[parentType]) == null ? void 0 : _b[levelType]) || {},
|
|
15278
|
+
[parentScope.cScope]: levelVal.scope.cScope
|
|
15279
|
+
}
|
|
15280
|
+
};
|
|
15281
|
+
if (levelVal.children) {
|
|
15282
|
+
Object.entries(levelVal.children).forEach(([nextLevelType, nextLevelVal]) => processLevel(
|
|
15283
|
+
levelType,
|
|
15284
|
+
levelVal.scope,
|
|
15285
|
+
nextLevelType,
|
|
15286
|
+
nextLevelVal
|
|
15287
|
+
));
|
|
15288
|
+
}
|
|
15289
|
+
}
|
|
15290
|
+
}
|
|
15291
|
+
Object.entries(scopes).forEach(([topLevelType, topLevelVal]) => {
|
|
15292
|
+
if (Array.isArray(topLevelVal)) {
|
|
15293
|
+
coordinationScopes[topLevelType] = topLevelVal.map((levelVal) => levelVal.scope.cScope);
|
|
15294
|
+
topLevelVal.forEach((levelVal) => {
|
|
15295
|
+
if (levelVal.children) {
|
|
15296
|
+
Object.entries(levelVal.children).forEach(([nextLevelType, nextLevelVal]) => processLevel(
|
|
15297
|
+
topLevelType,
|
|
15298
|
+
levelVal.scope,
|
|
15299
|
+
nextLevelType,
|
|
15300
|
+
nextLevelVal
|
|
15301
|
+
));
|
|
15302
|
+
}
|
|
15303
|
+
});
|
|
15304
|
+
} else {
|
|
15305
|
+
coordinationScopes[topLevelType] = topLevelVal.scope.cScope;
|
|
15306
|
+
if (topLevelVal.children) {
|
|
15307
|
+
Object.entries(topLevelVal.children).forEach(([nextLevelType, nextLevelVal]) => processLevel(
|
|
15308
|
+
topLevelType,
|
|
15309
|
+
topLevelVal.scope,
|
|
15310
|
+
nextLevelType,
|
|
15311
|
+
nextLevelVal
|
|
15312
|
+
));
|
|
15313
|
+
}
|
|
15314
|
+
}
|
|
15315
|
+
});
|
|
15316
|
+
return [coordinationScopes, coordinationScopesBy];
|
|
15317
|
+
}
|
|
15248
15318
|
class VitessceConfigView {
|
|
15249
15319
|
/**
|
|
15250
15320
|
* Construct a new view instance.
|
|
@@ -15260,6 +15330,8 @@ class VitessceConfigView {
|
|
|
15260
15330
|
this.view = {
|
|
15261
15331
|
component,
|
|
15262
15332
|
coordinationScopes,
|
|
15333
|
+
coordinationScopesBy: void 0,
|
|
15334
|
+
// TODO: initialize from parameter?
|
|
15263
15335
|
x,
|
|
15264
15336
|
y,
|
|
15265
15337
|
w,
|
|
@@ -15279,6 +15351,41 @@ class VitessceConfigView {
|
|
|
15279
15351
|
});
|
|
15280
15352
|
return this;
|
|
15281
15353
|
}
|
|
15354
|
+
useComplexCoordination(scopes) {
|
|
15355
|
+
if (!this.view.coordinationScopes) {
|
|
15356
|
+
this.view.coordinationScopes = {};
|
|
15357
|
+
}
|
|
15358
|
+
if (!this.view.coordinationScopesBy) {
|
|
15359
|
+
this.view.coordinationScopesBy = {};
|
|
15360
|
+
}
|
|
15361
|
+
const [nextCoordinationScopes, nextCoordinationScopesBy] = useComplexCoordinationHelper(
|
|
15362
|
+
scopes,
|
|
15363
|
+
this.view.coordinationScopes,
|
|
15364
|
+
this.view.coordinationScopesBy
|
|
15365
|
+
);
|
|
15366
|
+
this.view.coordinationScopes = nextCoordinationScopes;
|
|
15367
|
+
this.view.coordinationScopesBy = nextCoordinationScopesBy;
|
|
15368
|
+
return this;
|
|
15369
|
+
}
|
|
15370
|
+
/**
|
|
15371
|
+
* Attach meta coordination scopes to this view.
|
|
15372
|
+
* @param {VitessceConfigMetaCoordinationScope} metaScope A meta coordination scope instance.
|
|
15373
|
+
* @returns {VitessceConfigView} This, to allow chaining.
|
|
15374
|
+
*/
|
|
15375
|
+
useMetaCoordination(metaScope) {
|
|
15376
|
+
if (!this.view.coordinationScopes) {
|
|
15377
|
+
this.view.coordinationScopes = {};
|
|
15378
|
+
}
|
|
15379
|
+
this.view.coordinationScopes[CoordinationType$1.META_COORDINATION_SCOPES] = [
|
|
15380
|
+
...this.view.coordinationScopes[CoordinationType$1.META_COORDINATION_SCOPES] || [],
|
|
15381
|
+
metaScope.metaScope.cScope
|
|
15382
|
+
];
|
|
15383
|
+
this.view.coordinationScopes[CoordinationType$1.META_COORDINATION_SCOPES_BY] = [
|
|
15384
|
+
...this.view.coordinationScopes[CoordinationType$1.META_COORDINATION_SCOPES_BY] || [],
|
|
15385
|
+
metaScope.metaByScope.cScope
|
|
15386
|
+
];
|
|
15387
|
+
return this;
|
|
15388
|
+
}
|
|
15282
15389
|
/**
|
|
15283
15390
|
* Set the x, y, w, h values for this view.
|
|
15284
15391
|
* @param {number} x The x-coordinate of the view in the layout.
|
|
@@ -15330,6 +15437,11 @@ function vconcat(...views) {
|
|
|
15330
15437
|
const vcvvc = new VitessceConfigViewVConcat(views);
|
|
15331
15438
|
return vcvvc;
|
|
15332
15439
|
}
|
|
15440
|
+
class CoordinationLevel {
|
|
15441
|
+
constructor(value) {
|
|
15442
|
+
this.value = value;
|
|
15443
|
+
}
|
|
15444
|
+
}
|
|
15333
15445
|
class VitessceConfigCoordinationScope {
|
|
15334
15446
|
/**
|
|
15335
15447
|
* Construct a new coordination scope instance.
|
|
@@ -15351,6 +15463,63 @@ class VitessceConfigCoordinationScope {
|
|
|
15351
15463
|
return this;
|
|
15352
15464
|
}
|
|
15353
15465
|
}
|
|
15466
|
+
class VitessceConfigMetaCoordinationScope {
|
|
15467
|
+
/**
|
|
15468
|
+
* Construct a new coordination scope instance.
|
|
15469
|
+
* @param {string} metaScope The name of the coordination scope for metaCoordinationScopes.
|
|
15470
|
+
* @param {string} metaByScope The name of the coordination scope for metaCoordinationScopesBy.
|
|
15471
|
+
*/
|
|
15472
|
+
constructor(metaScope, metaByScope) {
|
|
15473
|
+
this.metaScope = new VitessceConfigCoordinationScope(
|
|
15474
|
+
CoordinationType$1.META_COORDINATION_SCOPES,
|
|
15475
|
+
metaScope
|
|
15476
|
+
);
|
|
15477
|
+
this.metaByScope = new VitessceConfigCoordinationScope(
|
|
15478
|
+
CoordinationType$1.META_COORDINATION_SCOPES_BY,
|
|
15479
|
+
metaByScope
|
|
15480
|
+
);
|
|
15481
|
+
}
|
|
15482
|
+
/**
|
|
15483
|
+
* Attach coordination scopes to this meta scope.
|
|
15484
|
+
* @param {...VitessceConfigCoordinationScope} args A variable number of
|
|
15485
|
+
* coordination scope instances.
|
|
15486
|
+
* @returns {VitessceConfigMetaCoordinationScope} This, to allow chaining.
|
|
15487
|
+
*/
|
|
15488
|
+
useCoordination(...args) {
|
|
15489
|
+
const cScopes = args;
|
|
15490
|
+
const metaScopesVal = this.metaScope.cValue;
|
|
15491
|
+
cScopes.forEach((cScope) => {
|
|
15492
|
+
metaScopesVal[cScope.cType] = cScope.cScope;
|
|
15493
|
+
});
|
|
15494
|
+
this.metaScope.setValue(metaScopesVal);
|
|
15495
|
+
return this;
|
|
15496
|
+
}
|
|
15497
|
+
useComplexCoordination(scopes) {
|
|
15498
|
+
if (!this.metaScope.cValue) {
|
|
15499
|
+
this.metaScope.setValue({});
|
|
15500
|
+
}
|
|
15501
|
+
if (!this.metaByScope.cValue) {
|
|
15502
|
+
this.metaByScope.setValue({});
|
|
15503
|
+
}
|
|
15504
|
+
const [metaScopesVal, metaByScopesVal] = useComplexCoordinationHelper(
|
|
15505
|
+
scopes,
|
|
15506
|
+
this.metaScope.cValue,
|
|
15507
|
+
this.metaByScope.cValue
|
|
15508
|
+
);
|
|
15509
|
+
this.metaScope.setValue(metaScopesVal);
|
|
15510
|
+
this.metaByScope.setValue(metaByScopesVal);
|
|
15511
|
+
return this;
|
|
15512
|
+
}
|
|
15513
|
+
/**
|
|
15514
|
+
* Set the coordination value of the coordination scope.
|
|
15515
|
+
* @param {any} cValue The value to set.
|
|
15516
|
+
* @returns {VitessceConfigCoordinationScope} This, to allow chaining.
|
|
15517
|
+
*/
|
|
15518
|
+
setValue(cValue) {
|
|
15519
|
+
this.cValue = cValue;
|
|
15520
|
+
return this;
|
|
15521
|
+
}
|
|
15522
|
+
}
|
|
15354
15523
|
class VitessceConfig {
|
|
15355
15524
|
/**
|
|
15356
15525
|
* Construct a new view config instance.
|
|
@@ -15472,6 +15641,53 @@ class VitessceConfig {
|
|
|
15472
15641
|
});
|
|
15473
15642
|
return result;
|
|
15474
15643
|
}
|
|
15644
|
+
addMetaCoordination() {
|
|
15645
|
+
const prevMetaScopes = this.config.coordinationSpace[CoordinationType$1.META_COORDINATION_SCOPES] ? Object.keys(this.config.coordinationSpace[CoordinationType$1.META_COORDINATION_SCOPES]) : [];
|
|
15646
|
+
const prevMetaByScopes = this.config.coordinationSpace[CoordinationType$1.META_COORDINATION_SCOPES_BY] ? Object.keys(this.config.coordinationSpace[CoordinationType$1.META_COORDINATION_SCOPES_BY]) : [];
|
|
15647
|
+
const metaContainer = new VitessceConfigMetaCoordinationScope(
|
|
15648
|
+
getNextScope(prevMetaScopes),
|
|
15649
|
+
getNextScope(prevMetaByScopes)
|
|
15650
|
+
);
|
|
15651
|
+
if (!this.config.coordinationSpace[CoordinationType$1.META_COORDINATION_SCOPES]) {
|
|
15652
|
+
this.config.coordinationSpace[CoordinationType$1.META_COORDINATION_SCOPES] = {};
|
|
15653
|
+
}
|
|
15654
|
+
if (!this.config.coordinationSpace[CoordinationType$1.META_COORDINATION_SCOPES_BY]) {
|
|
15655
|
+
this.config.coordinationSpace[CoordinationType$1.META_COORDINATION_SCOPES_BY] = {};
|
|
15656
|
+
}
|
|
15657
|
+
this.config.coordinationSpace[CoordinationType$1.META_COORDINATION_SCOPES][metaContainer.metaScope.cScope] = metaContainer.metaScope;
|
|
15658
|
+
this.config.coordinationSpace[CoordinationType$1.META_COORDINATION_SCOPES_BY][metaContainer.metaByScope.cScope] = metaContainer.metaByScope;
|
|
15659
|
+
return metaContainer;
|
|
15660
|
+
}
|
|
15661
|
+
addComplexCoordination(input) {
|
|
15662
|
+
const processLevel = (level) => {
|
|
15663
|
+
const result = {};
|
|
15664
|
+
Object.entries(level).forEach(([cType, nextLevelOrInitialValue]) => {
|
|
15665
|
+
if (nextLevelOrInitialValue instanceof CoordinationLevel) {
|
|
15666
|
+
const nextLevel = nextLevelOrInitialValue.value;
|
|
15667
|
+
if (Array.isArray(nextLevel)) {
|
|
15668
|
+
result[cType] = nextLevel.map((nextEl) => {
|
|
15669
|
+
const [dummyScope] = this.addCoordination(cType);
|
|
15670
|
+
dummyScope.setValue("__dummy__");
|
|
15671
|
+
return {
|
|
15672
|
+
scope: dummyScope,
|
|
15673
|
+
children: processLevel(nextEl)
|
|
15674
|
+
};
|
|
15675
|
+
});
|
|
15676
|
+
} else {
|
|
15677
|
+
throw new Error("Expected CoordinationLevel.value to be an array.");
|
|
15678
|
+
}
|
|
15679
|
+
} else {
|
|
15680
|
+
const initialValue = nextLevelOrInitialValue;
|
|
15681
|
+
const [scope] = this.addCoordination(cType);
|
|
15682
|
+
scope.setValue(initialValue);
|
|
15683
|
+
result[cType] = { scope };
|
|
15684
|
+
}
|
|
15685
|
+
});
|
|
15686
|
+
return result;
|
|
15687
|
+
};
|
|
15688
|
+
const output = processLevel(input);
|
|
15689
|
+
return output;
|
|
15690
|
+
}
|
|
15475
15691
|
/**
|
|
15476
15692
|
* A convenience function for setting up new coordination scopes across a set of views.
|
|
15477
15693
|
* @param {VitessceConfigView[]} views An array of view objects to link together.
|
|
@@ -15584,6 +15800,109 @@ class VitessceConfig {
|
|
|
15584
15800
|
return vc;
|
|
15585
15801
|
}
|
|
15586
15802
|
}
|
|
15803
|
+
const SINGLE_CELL_WITH_HEATMAP_VIEWS = {
|
|
15804
|
+
obsSets: { x: 4, y: 0, w: 4, h: 4 },
|
|
15805
|
+
obsSetSizes: { x: 8, y: 0, w: 4, h: 4 },
|
|
15806
|
+
scatterplot: { x: 0, y: 0, w: 4, h: 4 },
|
|
15807
|
+
heatmap: { x: 0, y: 4, w: 8, h: 4 },
|
|
15808
|
+
featureList: { x: 8, y: 4, w: 4, h: 4 }
|
|
15809
|
+
};
|
|
15810
|
+
const SINGLE_CELL_WITHOUT_HEATMAP_VIEWS = {
|
|
15811
|
+
obsSets: { x: 10, y: 6, w: 2, h: 6 },
|
|
15812
|
+
obsSetSizes: { x: 8, y: 1, w: 4, h: 6 },
|
|
15813
|
+
scatterplot: { x: 0, y: 0, w: 8, h: 12 },
|
|
15814
|
+
featureList: { x: 8, y: 6, w: 2, h: 6 }
|
|
15815
|
+
};
|
|
15816
|
+
const SPATIAL_TRANSCRIPTOMICS_VIEWS = {
|
|
15817
|
+
scatterplot: { x: 0, y: 0, w: 3, h: 4 },
|
|
15818
|
+
spatial: { x: 3, y: 0, w: 5, h: 4 },
|
|
15819
|
+
obsSets: { x: 8, y: 0, w: 4, h: 2 },
|
|
15820
|
+
featureList: { x: 8, y: 0, w: 4, h: 2 },
|
|
15821
|
+
heatmap: { x: 0, y: 4, w: 6, h: 4 },
|
|
15822
|
+
obsSetFeatureValueDistribution: { x: 6, y: 4, w: 6, h: 4 }
|
|
15823
|
+
};
|
|
15824
|
+
const SPATIAL_TRANSCRIPTOMICS_WITH_HSITOLOGY_VIEWS = {
|
|
15825
|
+
spatial: { x: 0, y: 0, w: 6, h: 6 },
|
|
15826
|
+
heatmap: { x: 0, y: 6, w: 8, h: 6 },
|
|
15827
|
+
layerController: { x: 8, y: 6, w: 4, h: 6 },
|
|
15828
|
+
obsSets: { x: 9, y: 0, w: 3, h: 6 },
|
|
15829
|
+
featureList: { x: 6, y: 0, w: 3, h: 6 }
|
|
15830
|
+
};
|
|
15831
|
+
const IMAGE_VIEWS = {
|
|
15832
|
+
spatial: { x: 0, y: 0, w: 8, h: 12 },
|
|
15833
|
+
layerController: { x: 8, y: 0, w: 4, h: 7 },
|
|
15834
|
+
description: { x: 8, y: 9, w: 4, h: 5 }
|
|
15835
|
+
};
|
|
15836
|
+
const NO_HINTS_CONFIG = {
|
|
15837
|
+
views: {},
|
|
15838
|
+
coordinationValues: {}
|
|
15839
|
+
};
|
|
15840
|
+
const HINTS_CONFIG = {
|
|
15841
|
+
"No hints are available. Generate config with no hints.": NO_HINTS_CONFIG,
|
|
15842
|
+
Basic: NO_HINTS_CONFIG,
|
|
15843
|
+
"Transcriptomics / scRNA-seq (with heatmap)": {
|
|
15844
|
+
views: SINGLE_CELL_WITH_HEATMAP_VIEWS
|
|
15845
|
+
},
|
|
15846
|
+
"Transcriptomics / scRNA-seq (without heatmap)": {
|
|
15847
|
+
views: SINGLE_CELL_WITHOUT_HEATMAP_VIEWS
|
|
15848
|
+
},
|
|
15849
|
+
"Spatial transcriptomics (with polygon cell segmentations)": {
|
|
15850
|
+
views: SPATIAL_TRANSCRIPTOMICS_VIEWS
|
|
15851
|
+
},
|
|
15852
|
+
"Chromatin accessibility / scATAC-seq (with heatmap)": {
|
|
15853
|
+
views: SINGLE_CELL_WITH_HEATMAP_VIEWS,
|
|
15854
|
+
coordinationValues: {
|
|
15855
|
+
featureType: "peak"
|
|
15856
|
+
}
|
|
15857
|
+
},
|
|
15858
|
+
"Chromatin accessibility / scATAC-seq (without heatmap)": {
|
|
15859
|
+
views: SINGLE_CELL_WITHOUT_HEATMAP_VIEWS,
|
|
15860
|
+
coordinationValues: {
|
|
15861
|
+
featureType: "peak"
|
|
15862
|
+
}
|
|
15863
|
+
},
|
|
15864
|
+
"Spatial transcriptomics (with histology image and polygon cell segmentations)": {
|
|
15865
|
+
views: SPATIAL_TRANSCRIPTOMICS_WITH_HSITOLOGY_VIEWS,
|
|
15866
|
+
coordinationSpaceRequired: true
|
|
15867
|
+
},
|
|
15868
|
+
Image: {
|
|
15869
|
+
views: IMAGE_VIEWS
|
|
15870
|
+
}
|
|
15871
|
+
};
|
|
15872
|
+
const HINT_TYPE_TO_FILE_TYPE_MAP = {
|
|
15873
|
+
"AnnData-Zarr": [
|
|
15874
|
+
"Basic",
|
|
15875
|
+
"Transcriptomics / scRNA-seq (with heatmap)",
|
|
15876
|
+
"Transcriptomics / scRNA-seq (without heatmap)",
|
|
15877
|
+
"Spatial transcriptomics (with polygon cell segmentations)",
|
|
15878
|
+
"Chromatin accessibility / scATAC-seq (with heatmap)",
|
|
15879
|
+
"Chromatin accessibility / scATAC-seq (without heatmap)"
|
|
15880
|
+
],
|
|
15881
|
+
"OME-TIFF": [
|
|
15882
|
+
"Basic",
|
|
15883
|
+
"Image"
|
|
15884
|
+
],
|
|
15885
|
+
"AnnData-Zarr,OME-TIFF": [
|
|
15886
|
+
"Basic",
|
|
15887
|
+
"Spatial transcriptomics (with histology image and polygon cell segmentations)"
|
|
15888
|
+
]
|
|
15889
|
+
};
|
|
15890
|
+
const filterViews = (hintsConfig, possibleViews) => {
|
|
15891
|
+
const requiredViews = Object.keys(hintsConfig.views);
|
|
15892
|
+
if (requiredViews.length === 0) {
|
|
15893
|
+
return possibleViews;
|
|
15894
|
+
}
|
|
15895
|
+
const resultViews = [];
|
|
15896
|
+
requiredViews.forEach((requiredView) => {
|
|
15897
|
+
const match = possibleViews.find((possibleView) => possibleView[0] === requiredView);
|
|
15898
|
+
if (match)
|
|
15899
|
+
resultViews.push(match);
|
|
15900
|
+
});
|
|
15901
|
+
if (resultViews.length === 0) {
|
|
15902
|
+
throw new Error("No views found that are compatible with the supplied dataset URLs and hint.");
|
|
15903
|
+
}
|
|
15904
|
+
return resultViews;
|
|
15905
|
+
};
|
|
15587
15906
|
class AbstractAutoConfig {
|
|
15588
15907
|
async composeViewsConfig() {
|
|
15589
15908
|
throw new Error("The composeViewsConfig() method has not been implemented.");
|
|
@@ -15599,12 +15918,11 @@ class OmeTiffAutoConfig extends AbstractAutoConfig {
|
|
|
15599
15918
|
this.fileType = FileType$1.RASTER_JSON;
|
|
15600
15919
|
this.fileName = fileUrl.split("/").at(-1);
|
|
15601
15920
|
}
|
|
15602
|
-
async composeViewsConfig() {
|
|
15603
|
-
return
|
|
15604
|
-
|
|
15605
|
-
["spatial"],
|
|
15606
|
-
|
|
15607
|
-
];
|
|
15921
|
+
async composeViewsConfig(hintsConfig) {
|
|
15922
|
+
return filterViews(
|
|
15923
|
+
hintsConfig,
|
|
15924
|
+
[["description"], ["spatial"], ["layerController"]]
|
|
15925
|
+
);
|
|
15608
15926
|
}
|
|
15609
15927
|
async composeFileConfig() {
|
|
15610
15928
|
return {
|
|
@@ -15633,13 +15951,11 @@ class OmeZarrAutoConfig extends AbstractAutoConfig {
|
|
|
15633
15951
|
this.fileType = FileType$1.RASTER_OME_ZARR;
|
|
15634
15952
|
this.fileName = fileUrl.split("/").at(-1);
|
|
15635
15953
|
}
|
|
15636
|
-
async composeViewsConfig() {
|
|
15637
|
-
return
|
|
15638
|
-
|
|
15639
|
-
["spatial"],
|
|
15640
|
-
|
|
15641
|
-
["status"]
|
|
15642
|
-
];
|
|
15954
|
+
async composeViewsConfig(hintsConfig) {
|
|
15955
|
+
return filterViews(
|
|
15956
|
+
hintsConfig,
|
|
15957
|
+
[["description"], ["spatial"], ["layerController"]]
|
|
15958
|
+
);
|
|
15643
15959
|
}
|
|
15644
15960
|
async composeFileConfig() {
|
|
15645
15961
|
return {
|
|
@@ -15658,6 +15974,7 @@ class AnndataZarrAutoConfig extends AbstractAutoConfig {
|
|
|
15658
15974
|
this.metadataSummary = {};
|
|
15659
15975
|
}
|
|
15660
15976
|
async composeFileConfig() {
|
|
15977
|
+
var _a;
|
|
15661
15978
|
this.metadataSummary = await this.setMetadataSummary();
|
|
15662
15979
|
const options = {
|
|
15663
15980
|
obsEmbedding: [],
|
|
@@ -15684,8 +16001,10 @@ class AnndataZarrAutoConfig extends AbstractAutoConfig {
|
|
|
15684
16001
|
});
|
|
15685
16002
|
const supportedObsSetsKeys = [
|
|
15686
16003
|
"cluster",
|
|
16004
|
+
"clusters",
|
|
15687
16005
|
"subcluster",
|
|
15688
16006
|
"cell_type",
|
|
16007
|
+
"celltype",
|
|
15689
16008
|
"leiden",
|
|
15690
16009
|
"louvain",
|
|
15691
16010
|
"disease",
|
|
@@ -15710,6 +16029,15 @@ class AnndataZarrAutoConfig extends AbstractAutoConfig {
|
|
|
15710
16029
|
}
|
|
15711
16030
|
});
|
|
15712
16031
|
});
|
|
16032
|
+
options.obsSets = (_a = options.obsSets) == null ? void 0 : _a.map((obsSet) => {
|
|
16033
|
+
if (obsSet.path.length === 1) {
|
|
16034
|
+
return {
|
|
16035
|
+
...obsSet,
|
|
16036
|
+
path: obsSet.path[0]
|
|
16037
|
+
};
|
|
16038
|
+
}
|
|
16039
|
+
return obsSet;
|
|
16040
|
+
});
|
|
15713
16041
|
return {
|
|
15714
16042
|
options,
|
|
15715
16043
|
fileType: this.fileType,
|
|
@@ -15721,34 +16049,37 @@ class AnndataZarrAutoConfig extends AbstractAutoConfig {
|
|
|
15721
16049
|
}
|
|
15722
16050
|
};
|
|
15723
16051
|
}
|
|
15724
|
-
async composeViewsConfig() {
|
|
16052
|
+
async composeViewsConfig(hintsConfig) {
|
|
15725
16053
|
this.metadataSummary = await this.setMetadataSummary();
|
|
15726
|
-
const
|
|
15727
|
-
const hasCellSetData = this.metadataSummary.obs.filter((key) => key.toLowerCase().includes("cluster") || key.toLowerCase().includes("cell_type"));
|
|
16054
|
+
const possibleViews = [];
|
|
16055
|
+
const hasCellSetData = this.metadataSummary.obs.filter((key) => key.toLowerCase().includes("cluster") || key.toLowerCase().includes("cell_type") || key.toLowerCase().includes("celltype"));
|
|
15728
16056
|
if (hasCellSetData.length > 0) {
|
|
15729
|
-
|
|
16057
|
+
possibleViews.push(["obsSets"]);
|
|
15730
16058
|
}
|
|
15731
16059
|
this.metadataSummary.obsm.forEach((key) => {
|
|
15732
16060
|
if (key.toLowerCase().includes("obsm/x_umap")) {
|
|
15733
|
-
|
|
16061
|
+
possibleViews.push(["scatterplot", { mapping: "UMAP" }]);
|
|
15734
16062
|
}
|
|
15735
16063
|
if (key.toLowerCase().includes("obsm/x_tsne")) {
|
|
15736
|
-
|
|
16064
|
+
possibleViews.push(["scatterplot", { mapping: "t-SNE" }]);
|
|
15737
16065
|
}
|
|
15738
16066
|
if (key.toLowerCase().includes("obsm/x_pca")) {
|
|
15739
|
-
|
|
16067
|
+
possibleViews.push(["scatterplot", { mapping: "PCA" }]);
|
|
15740
16068
|
}
|
|
15741
16069
|
if (key.toLowerCase().includes("obsm/x_segmentations")) {
|
|
15742
|
-
|
|
16070
|
+
possibleViews.push(["layerController"]);
|
|
15743
16071
|
}
|
|
15744
16072
|
if (key.toLowerCase().includes("obsm/x_spatial")) {
|
|
15745
|
-
|
|
16073
|
+
possibleViews.push(["spatial"]);
|
|
15746
16074
|
}
|
|
15747
16075
|
});
|
|
16076
|
+
possibleViews.push(["obsSetSizes"]);
|
|
16077
|
+
possibleViews.push(["obsSetFeatureValueDistribution"]);
|
|
15748
16078
|
if (this.metadataSummary.X) {
|
|
15749
|
-
|
|
15750
|
-
|
|
16079
|
+
possibleViews.push(["heatmap"]);
|
|
16080
|
+
possibleViews.push(["featureList"]);
|
|
15751
16081
|
}
|
|
16082
|
+
const views = filterViews(hintsConfig, possibleViews);
|
|
15752
16083
|
return views;
|
|
15753
16084
|
}
|
|
15754
16085
|
async setMetadataSummaryWithZmetadata(response) {
|
|
@@ -15780,7 +16111,9 @@ class AnndataZarrAutoConfig extends AbstractAutoConfig {
|
|
|
15780
16111
|
"/obsm/X_spatial/.zarray",
|
|
15781
16112
|
"/obsm/X_segmentations/.zarray",
|
|
15782
16113
|
"/obs/.zattrs",
|
|
15783
|
-
"/X/.zarray"
|
|
16114
|
+
"/X/.zarray",
|
|
16115
|
+
"/X/data/.zarray"
|
|
16116
|
+
// for https://s3.amazonaws.com/vitessce-data/0.0.33/main/human-lymph-node-10x-visium/human_lymph_node_10x_visium.h5ad.zarr
|
|
15784
16117
|
];
|
|
15785
16118
|
const getObsmKey = (url) => {
|
|
15786
16119
|
const obsmKeyStartIndex = `${this.fileUrl}/`.length;
|
|
@@ -15836,32 +16169,28 @@ class AnndataZarrAutoConfig extends AbstractAutoConfig {
|
|
|
15836
16169
|
return this.setMetadataSummaryWithoutZmetadata();
|
|
15837
16170
|
}
|
|
15838
16171
|
throw new Error(`Could not generate config: ${response.statusText}`);
|
|
16172
|
+
}).catch((error) => {
|
|
16173
|
+
throw new Error(`Could not generate config for URL ${this.fileUrl}: ${error}`);
|
|
15839
16174
|
});
|
|
15840
16175
|
}
|
|
15841
16176
|
}
|
|
15842
16177
|
const configClasses = [
|
|
15843
16178
|
{
|
|
15844
16179
|
extensions: [".ome.tif", ".ome.tiff", ".ome.tf2", ".ome.tf8"],
|
|
15845
|
-
class: OmeTiffAutoConfig
|
|
16180
|
+
class: OmeTiffAutoConfig,
|
|
16181
|
+
name: "OME-TIFF"
|
|
15846
16182
|
},
|
|
15847
16183
|
{
|
|
15848
16184
|
extensions: [".h5ad.zarr", ".adata.zarr", ".anndata.zarr"],
|
|
15849
|
-
class: AnndataZarrAutoConfig
|
|
16185
|
+
class: AnndataZarrAutoConfig,
|
|
16186
|
+
name: "AnnData-Zarr"
|
|
15850
16187
|
},
|
|
15851
16188
|
{
|
|
15852
16189
|
extensions: ["ome.zarr"],
|
|
15853
|
-
class: OmeZarrAutoConfig
|
|
16190
|
+
class: OmeZarrAutoConfig,
|
|
16191
|
+
name: "OME-Zarr"
|
|
15854
16192
|
}
|
|
15855
16193
|
];
|
|
15856
|
-
function getFileType(url) {
|
|
15857
|
-
const match = configClasses.find((obj) => obj.extensions.filter(
|
|
15858
|
-
(ext) => url.endsWith(ext)
|
|
15859
|
-
).length === 1);
|
|
15860
|
-
if (!match) {
|
|
15861
|
-
throw new Error(`Could not generate config for URL: ${url}. This file type is not supported.`);
|
|
15862
|
-
}
|
|
15863
|
-
return match.class;
|
|
15864
|
-
}
|
|
15865
16194
|
function calculateCoordinates(viewsNumb) {
|
|
15866
16195
|
const rows = Math.ceil(Math.sqrt(viewsNumb));
|
|
15867
16196
|
const cols = Math.ceil(viewsNumb / rows);
|
|
@@ -15873,14 +16202,117 @@ function calculateCoordinates(viewsNumb) {
|
|
|
15873
16202
|
const col = i % cols;
|
|
15874
16203
|
const x = col * width;
|
|
15875
16204
|
const y = row * height;
|
|
15876
|
-
coords.push([
|
|
16205
|
+
coords.push([
|
|
16206
|
+
Math.floor(x),
|
|
16207
|
+
Math.floor(y),
|
|
16208
|
+
// Ensure width/height is at least 1.
|
|
16209
|
+
Math.max(1, Math.floor(width)),
|
|
16210
|
+
Math.max(1, Math.floor(height))
|
|
16211
|
+
]);
|
|
15877
16212
|
}
|
|
15878
16213
|
return coords;
|
|
15879
16214
|
}
|
|
15880
|
-
|
|
16215
|
+
const spatialSegmentationLayerValue = {
|
|
16216
|
+
radius: 65,
|
|
16217
|
+
stroked: true,
|
|
16218
|
+
visible: true,
|
|
16219
|
+
opacity: 1
|
|
16220
|
+
};
|
|
16221
|
+
function insertCoordinationSpaceForSpatial(views, vc) {
|
|
16222
|
+
const [
|
|
16223
|
+
spatialSegmentationLayer,
|
|
16224
|
+
spatialImageLayer,
|
|
16225
|
+
spatialZoom,
|
|
16226
|
+
spatialTargetX,
|
|
16227
|
+
spatialTargetY
|
|
16228
|
+
] = vc.addCoordination(
|
|
16229
|
+
CoordinationType$1.SPATIAL_SEGMENTATION_LAYER,
|
|
16230
|
+
CoordinationType$1.SPATIAL_IMAGE_LAYER,
|
|
16231
|
+
CoordinationType$1.SPATIAL_ZOOM,
|
|
16232
|
+
CoordinationType$1.SPATIAL_TARGET_X,
|
|
16233
|
+
CoordinationType$1.SPATIAL_TARGET_Y
|
|
16234
|
+
);
|
|
16235
|
+
spatialSegmentationLayer.setValue(spatialSegmentationLayerValue);
|
|
16236
|
+
spatialImageLayer.setValue([
|
|
16237
|
+
{
|
|
16238
|
+
type: "raster",
|
|
16239
|
+
index: 0,
|
|
16240
|
+
colormap: null,
|
|
16241
|
+
transparentColor: null,
|
|
16242
|
+
opacity: 1,
|
|
16243
|
+
domainType: "Min/Max",
|
|
16244
|
+
channels: [
|
|
16245
|
+
{
|
|
16246
|
+
selection: {
|
|
16247
|
+
c: 0
|
|
16248
|
+
},
|
|
16249
|
+
color: [
|
|
16250
|
+
255,
|
|
16251
|
+
0,
|
|
16252
|
+
0
|
|
16253
|
+
],
|
|
16254
|
+
visible: true,
|
|
16255
|
+
slider: [
|
|
16256
|
+
0,
|
|
16257
|
+
255
|
|
16258
|
+
]
|
|
16259
|
+
},
|
|
16260
|
+
{
|
|
16261
|
+
selection: {
|
|
16262
|
+
c: 1
|
|
16263
|
+
},
|
|
16264
|
+
color: [
|
|
16265
|
+
0,
|
|
16266
|
+
255,
|
|
16267
|
+
0
|
|
16268
|
+
],
|
|
16269
|
+
visible: true,
|
|
16270
|
+
slider: [
|
|
16271
|
+
0,
|
|
16272
|
+
255
|
|
16273
|
+
]
|
|
16274
|
+
},
|
|
16275
|
+
{
|
|
16276
|
+
selection: {
|
|
16277
|
+
c: 2
|
|
16278
|
+
},
|
|
16279
|
+
color: [
|
|
16280
|
+
0,
|
|
16281
|
+
0,
|
|
16282
|
+
255
|
|
16283
|
+
],
|
|
16284
|
+
visible: true,
|
|
16285
|
+
slider: [
|
|
16286
|
+
0,
|
|
16287
|
+
255
|
|
16288
|
+
]
|
|
16289
|
+
}
|
|
16290
|
+
]
|
|
16291
|
+
}
|
|
16292
|
+
]);
|
|
16293
|
+
views.forEach((view) => {
|
|
16294
|
+
if (view.view.component === "spatial" || view.view.component === "layerController") {
|
|
16295
|
+
view.useCoordination(spatialImageLayer);
|
|
16296
|
+
view.useCoordination(spatialSegmentationLayer);
|
|
16297
|
+
view.useCoordination(spatialZoom);
|
|
16298
|
+
view.useCoordination(spatialTargetX);
|
|
16299
|
+
view.useCoordination(spatialTargetY);
|
|
16300
|
+
}
|
|
16301
|
+
});
|
|
16302
|
+
}
|
|
16303
|
+
function getFileType(url) {
|
|
16304
|
+
const match = configClasses.find((obj) => obj.extensions.filter(
|
|
16305
|
+
(ext) => url.endsWith(ext)
|
|
16306
|
+
).length === 1);
|
|
16307
|
+
if (!match) {
|
|
16308
|
+
throw new Error("One or more of the URLs provided point to unsupported file types.");
|
|
16309
|
+
}
|
|
16310
|
+
return match;
|
|
16311
|
+
}
|
|
16312
|
+
async function generateViewDefinition(url, vc, dataset, hintsConfig) {
|
|
15881
16313
|
let ConfigClassName;
|
|
15882
16314
|
try {
|
|
15883
|
-
ConfigClassName = getFileType(url);
|
|
16315
|
+
ConfigClassName = getFileType(url).class;
|
|
15884
16316
|
} catch (err) {
|
|
15885
16317
|
return Promise.reject(err);
|
|
15886
16318
|
}
|
|
@@ -15889,12 +16321,12 @@ async function generateConfig(url, vc) {
|
|
|
15889
16321
|
let viewsConfig;
|
|
15890
16322
|
try {
|
|
15891
16323
|
fileConfig = await configInstance.composeFileConfig();
|
|
15892
|
-
viewsConfig = await configInstance.composeViewsConfig();
|
|
16324
|
+
viewsConfig = await configInstance.composeViewsConfig(hintsConfig);
|
|
15893
16325
|
} catch (error) {
|
|
15894
16326
|
console.error(error);
|
|
15895
16327
|
return Promise.reject(error);
|
|
15896
16328
|
}
|
|
15897
|
-
|
|
16329
|
+
dataset.addFile(fileConfig);
|
|
15898
16330
|
let layerControllerView = false;
|
|
15899
16331
|
let spatialView = false;
|
|
15900
16332
|
const views = [];
|
|
@@ -15906,7 +16338,7 @@ async function generateConfig(url, vc) {
|
|
|
15906
16338
|
if (v[0] === "spatial") {
|
|
15907
16339
|
spatialView = view;
|
|
15908
16340
|
}
|
|
15909
|
-
if (v[0] === "layerController"
|
|
16341
|
+
if (v[0] === "layerController") {
|
|
15910
16342
|
view.setProps({
|
|
15911
16343
|
disable3d: [],
|
|
15912
16344
|
disableChannelsIfRgbDetected: true
|
|
@@ -15918,47 +16350,71 @@ async function generateConfig(url, vc) {
|
|
|
15918
16350
|
views.push(view);
|
|
15919
16351
|
});
|
|
15920
16352
|
if (layerControllerView && spatialView && configInstance instanceof AnndataZarrAutoConfig) {
|
|
15921
|
-
const spatialSegmentationLayerValue = {
|
|
15922
|
-
opacity: 1,
|
|
15923
|
-
radius: 0,
|
|
15924
|
-
visible: true,
|
|
15925
|
-
stroked: false
|
|
15926
|
-
};
|
|
15927
16353
|
vc.linkViews(
|
|
15928
16354
|
[spatialView, layerControllerView],
|
|
15929
16355
|
[
|
|
15930
|
-
CoordinationType$1.SPATIAL_ZOOM,
|
|
15931
|
-
CoordinationType$1.SPATIAL_TARGET_X,
|
|
15932
|
-
CoordinationType$1.SPATIAL_TARGET_Y,
|
|
15933
16356
|
CoordinationType$1.SPATIAL_SEGMENTATION_LAYER
|
|
15934
16357
|
],
|
|
15935
|
-
[
|
|
16358
|
+
[spatialSegmentationLayerValue]
|
|
15936
16359
|
);
|
|
15937
16360
|
}
|
|
15938
16361
|
return views;
|
|
15939
16362
|
}
|
|
15940
|
-
|
|
16363
|
+
function getHintOptions(fileUrls) {
|
|
16364
|
+
const fileTypes = {};
|
|
16365
|
+
fileUrls.forEach((url) => {
|
|
16366
|
+
const match = getFileType(url);
|
|
16367
|
+
if (match.name === "OME-Zarr") {
|
|
16368
|
+
fileTypes["OME-TIFF"] = true;
|
|
16369
|
+
} else {
|
|
16370
|
+
fileTypes[match.name] = true;
|
|
16371
|
+
}
|
|
16372
|
+
});
|
|
16373
|
+
const datasetType = Object.keys(fileTypes).sort().join(",");
|
|
16374
|
+
return (HINT_TYPE_TO_FILE_TYPE_MAP == null ? void 0 : HINT_TYPE_TO_FILE_TYPE_MAP[datasetType]) || [];
|
|
16375
|
+
}
|
|
16376
|
+
async function generateConfig(fileUrls, hintTitle = null) {
|
|
16377
|
+
var _a;
|
|
15941
16378
|
const vc = new VitessceConfig({
|
|
15942
16379
|
schemaVersion: "1.0.15",
|
|
15943
16380
|
name: "An automatically generated config. Adjust values and add layout components if needed.",
|
|
15944
16381
|
description: "Populate with text relevant to this visualisation."
|
|
15945
16382
|
});
|
|
15946
16383
|
const allViews = [];
|
|
16384
|
+
const dataset = vc.addDataset("An automatically generated view config for dataset. Adjust values and add layout components if needed.");
|
|
16385
|
+
const hintsConfig = !hintTitle ? { views: {} } : HINTS_CONFIG == null ? void 0 : HINTS_CONFIG[hintTitle];
|
|
16386
|
+
if (!hintsConfig) {
|
|
16387
|
+
throw new Error(`Hints config not found for the supplied hint: ${hintTitle}.`);
|
|
16388
|
+
}
|
|
16389
|
+
const useHints = ((_a = Object.keys(hintsConfig == null ? void 0 : hintsConfig.views)) == null ? void 0 : _a.length) > 0;
|
|
15947
16390
|
fileUrls.forEach((url) => {
|
|
15948
|
-
allViews.push(
|
|
16391
|
+
allViews.push(generateViewDefinition(url, vc, dataset, hintsConfig));
|
|
15949
16392
|
});
|
|
15950
16393
|
return Promise.all(allViews).then((views) => {
|
|
15951
16394
|
const flattenedViews = views.flat();
|
|
15952
|
-
|
|
15953
|
-
|
|
15954
|
-
|
|
16395
|
+
if (hintsConfig == null ? void 0 : hintsConfig.coordinationSpaceRequired) {
|
|
16396
|
+
insertCoordinationSpaceForSpatial(flattenedViews, vc);
|
|
16397
|
+
}
|
|
16398
|
+
if (!useHints) {
|
|
16399
|
+
const coord = calculateCoordinates(flattenedViews.length);
|
|
16400
|
+
for (let i = 0; i < flattenedViews.length; i++) {
|
|
16401
|
+
flattenedViews[i].setXYWH(...coord[i]);
|
|
16402
|
+
}
|
|
16403
|
+
} else {
|
|
16404
|
+
flattenedViews.forEach((vitessceConfigView) => {
|
|
16405
|
+
const coordinates = Object.values(hintsConfig.views[vitessceConfigView.view.component]);
|
|
16406
|
+
vitessceConfigView.setXYWH(...coordinates);
|
|
16407
|
+
});
|
|
15955
16408
|
}
|
|
15956
16409
|
return vc.toJSON();
|
|
15957
16410
|
});
|
|
15958
16411
|
}
|
|
15959
16412
|
export {
|
|
16413
|
+
HINTS_CONFIG,
|
|
16414
|
+
HINT_TYPE_TO_FILE_TYPE_MAP,
|
|
15960
16415
|
VitessceConfig,
|
|
15961
|
-
|
|
16416
|
+
generateConfig,
|
|
16417
|
+
getHintOptions,
|
|
15962
16418
|
hconcat,
|
|
15963
16419
|
vconcat
|
|
15964
16420
|
};
|