@vitessce/biomarker-select 3.5.6 → 3.5.8
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 +347 -15
- package/dist-tsc/BiomarkerSelectSubscriber.d.ts.map +1 -1
- package/dist-tsc/BiomarkerSelectSubscriber.js +65 -9
- package/dist-tsc/ComparativeHeadingSubscriber.d.ts +2 -0
- package/dist-tsc/ComparativeHeadingSubscriber.d.ts.map +1 -0
- package/dist-tsc/ComparativeHeadingSubscriber.js +9 -0
- package/dist-tsc/default-async-functions.d.ts.map +1 -1
- package/dist-tsc/default-async-functions.js +1 -0
- package/dist-tsc/index.d.ts +1 -0
- package/dist-tsc/index.js +1 -0
- package/dist-tsc/scmd-ui.d.ts.map +1 -1
- package/dist-tsc/scmd-ui.js +3 -2
- package/dist-tsc/{confirmatory-stepper.d.ts → stepper-confirmatory.d.ts} +1 -1
- package/dist-tsc/stepper-confirmatory.d.ts.map +1 -0
- package/dist-tsc/stepper-exploratory.d.ts +2 -0
- package/dist-tsc/stepper-exploratory.d.ts.map +1 -0
- package/dist-tsc/stepper-exploratory.js +61 -0
- package/package.json +4 -4
- package/src/BiomarkerSelectSubscriber.js +82 -8
- package/src/ComparativeHeadingSubscriber.js +31 -0
- package/src/default-async-functions.js +1 -0
- package/src/index.js +1 -0
- package/src/scmd-ui.js +18 -2
- package/src/stepper-exploratory.js +175 -0
- package/dist-tsc/confirmatory-stepper.d.ts.map +0 -1
- /package/dist-tsc/{confirmatory-stepper.js → stepper-confirmatory.js} +0 -0
- /package/src/{confirmatory-stepper.js → stepper-confirmatory.js} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import React__default, { Children, isValidElement, cloneElement, createElement, PureComponent, useRef, useEffect, useMemo, useState, useCallback } from "react";
|
|
3
|
-
import { useCoordination, useViewConfigStoreApi, useViewConfig, useSetViewConfig, useAsyncFunction } from "@vitessce/vit-s";
|
|
3
|
+
import { useLoaders, useCoordination, useViewConfigStoreApi, useViewConfig, useSetViewConfig, useMatchingLoader, useColumnNameMapping, useAsyncFunction, useComparisonMetadata } from "@vitessce/vit-s";
|
|
4
4
|
import * as ReactDOM from "react-dom";
|
|
5
5
|
import ReactDOM__default from "react-dom";
|
|
6
6
|
function getDefaultExportFromCjs(x) {
|
|
@@ -909,9 +909,35 @@ const ViewType = {
|
|
|
909
909
|
FEATURE_VALUE_HISTOGRAM: "featureValueHistogram",
|
|
910
910
|
DOT_PLOT: "dotPlot",
|
|
911
911
|
FEATURE_BAR_PLOT: "featureBarPlot",
|
|
912
|
+
VOLCANO_PLOT: "volcanoPlot",
|
|
913
|
+
OBS_SET_COMPOSITION_BAR_PLOT: "obsSetCompositionBarPlot",
|
|
914
|
+
FEATURE_SET_ENRICHMENT_BAR_PLOT: "featureSetEnrichmentBarPlot",
|
|
912
915
|
BIOMARKER_SELECT: "biomarkerSelect",
|
|
916
|
+
COMPARATIVE_HEADING: "comparativeHeading",
|
|
913
917
|
LINK_CONTROLLER: "linkController",
|
|
914
|
-
|
|
918
|
+
NEUROGLANCER: "neuroglancer",
|
|
919
|
+
DUAL_SCATTERPLOT: "dualScatterplot",
|
|
920
|
+
TREEMAP: "treemap"
|
|
921
|
+
};
|
|
922
|
+
const DataType = {
|
|
923
|
+
OBS_LABELS: "obsLabels",
|
|
924
|
+
OBS_EMBEDDING: "obsEmbedding",
|
|
925
|
+
OBS_FEATURE_MATRIX: "obsFeatureMatrix",
|
|
926
|
+
OBS_SETS: "obsSets",
|
|
927
|
+
FEATURE_LABELS: "featureLabels",
|
|
928
|
+
IMAGE: "image",
|
|
929
|
+
OBS_SEGMENTATIONS: "obsSegmentations",
|
|
930
|
+
NEIGHBORHOODS: "neighborhoods",
|
|
931
|
+
GENOMIC_PROFILES: "genomic-profiles",
|
|
932
|
+
OBS_SPOTS: "obsSpots",
|
|
933
|
+
OBS_POINTS: "obsPoints",
|
|
934
|
+
OBS_LOCATIONS: "obsLocations",
|
|
935
|
+
SAMPLE_SETS: "sampleSets",
|
|
936
|
+
SAMPLE_EDGES: "sampleEdges",
|
|
937
|
+
COMPARISON_METADATA: "comparisonMetadata",
|
|
938
|
+
FEATURE_STATS: "featureStats",
|
|
939
|
+
FEATURE_SET_STATS: "featureSetStats",
|
|
940
|
+
OBS_SET_STATS: "obsSetStats"
|
|
915
941
|
};
|
|
916
942
|
const AsyncFunctionType = {
|
|
917
943
|
// String input (rather than Node input)
|
|
@@ -1065,14 +1091,25 @@ const CoordinationType = {
|
|
|
1065
1091
|
SAMPLE_SET_FILTER: "sampleSetFilter",
|
|
1066
1092
|
SAMPLE_FILTER_MODE: "sampleFilterMode",
|
|
1067
1093
|
SAMPLE_SET_COLOR: "sampleSetColor",
|
|
1094
|
+
SAMPLE_HIGHLIGHT: "sampleHighlight",
|
|
1068
1095
|
EMBEDDING_POINTS_VISIBLE: "embeddingPointsVisible",
|
|
1069
1096
|
EMBEDDING_CONTOURS_VISIBLE: "embeddingContoursVisible",
|
|
1070
1097
|
EMBEDDING_CONTOURS_FILLED: "embeddingContoursFilled",
|
|
1071
1098
|
EMBEDDING_CONTOUR_PERCENTILES: "embeddingContourPercentiles",
|
|
1072
1099
|
CONTOUR_COLOR_ENCODING: "contourColorEncoding",
|
|
1073
|
-
CONTOUR_COLOR: "contourColor"
|
|
1100
|
+
CONTOUR_COLOR: "contourColor",
|
|
1101
|
+
// For volcano plot:
|
|
1102
|
+
FEATURE_POINT_SIGNIFICANCE_THRESHOLD: "featurePointSignificanceThreshold",
|
|
1103
|
+
FEATURE_LABEL_SIGNIFICANCE_THRESHOLD: "featureLabelSignificanceThreshold",
|
|
1104
|
+
FEATURE_POINT_FOLD_CHANGE_THRESHOLD: "featurePointFoldChangeThreshold",
|
|
1105
|
+
FEATURE_LABEL_FOLD_CHANGE_THRESHOLD: "featureLabelFoldChangeThreshold",
|
|
1106
|
+
// Treemap
|
|
1107
|
+
HIERARCHY_LEVELS: "hierarchyLevels"
|
|
1074
1108
|
};
|
|
1075
1109
|
const COMPONENT_COORDINATION_TYPES = {
|
|
1110
|
+
[ViewType.NEUROGLANCER]: [
|
|
1111
|
+
CoordinationType.DATASET
|
|
1112
|
+
],
|
|
1076
1113
|
[ViewType.SCATTERPLOT]: [
|
|
1077
1114
|
CoordinationType.DATASET,
|
|
1078
1115
|
CoordinationType.OBS_TYPE,
|
|
@@ -1542,14 +1579,106 @@ const COMPONENT_COORDINATION_TYPES = {
|
|
|
1542
1579
|
CoordinationType.OBS_COLOR_ENCODING,
|
|
1543
1580
|
CoordinationType.ADDITIONAL_OBS_SETS
|
|
1544
1581
|
],
|
|
1582
|
+
[ViewType.VOLCANO_PLOT]: [
|
|
1583
|
+
CoordinationType.DATASET,
|
|
1584
|
+
CoordinationType.OBS_TYPE,
|
|
1585
|
+
CoordinationType.FEATURE_TYPE,
|
|
1586
|
+
CoordinationType.SAMPLE_TYPE,
|
|
1587
|
+
// For selection of case-control sets of samples:
|
|
1588
|
+
CoordinationType.SAMPLE_SET_SELECTION,
|
|
1589
|
+
// For selection of one-vs-others sets of observations:
|
|
1590
|
+
CoordinationType.OBS_SET_SELECTION,
|
|
1591
|
+
// TODO: CoordinationType.FEATURE_SET_SELECTION,
|
|
1592
|
+
// TODO: CoordinationType.FEATURE_SET_HIGHLIGHT,
|
|
1593
|
+
// TODO: CoordinationType.FEATURE_SET_COLOR,
|
|
1594
|
+
CoordinationType.FEATURE_HIGHLIGHT,
|
|
1595
|
+
CoordinationType.FEATURE_SELECTION,
|
|
1596
|
+
CoordinationType.FEATURE_VALUE_COLORMAP,
|
|
1597
|
+
CoordinationType.FEATURE_VALUE_COLORMAP_RANGE,
|
|
1598
|
+
// TODO: CoordinationType.FEATURE_COLOR_ENCODING,
|
|
1599
|
+
// TODO: CoordinationType.ADDITIONAL_FEATURE_SETS,
|
|
1600
|
+
CoordinationType.TOOLTIPS_VISIBLE,
|
|
1601
|
+
CoordinationType.ADDITIONAL_OBS_SETS,
|
|
1602
|
+
CoordinationType.OBS_SET_COLOR,
|
|
1603
|
+
CoordinationType.SAMPLE_SET_COLOR,
|
|
1604
|
+
CoordinationType.FEATURE_POINT_SIGNIFICANCE_THRESHOLD,
|
|
1605
|
+
CoordinationType.FEATURE_LABEL_SIGNIFICANCE_THRESHOLD,
|
|
1606
|
+
CoordinationType.FEATURE_POINT_FOLD_CHANGE_THRESHOLD,
|
|
1607
|
+
CoordinationType.FEATURE_LABEL_FOLD_CHANGE_THRESHOLD
|
|
1608
|
+
],
|
|
1609
|
+
[ViewType.OBS_SET_COMPOSITION_BAR_PLOT]: [
|
|
1610
|
+
CoordinationType.DATASET,
|
|
1611
|
+
CoordinationType.OBS_TYPE,
|
|
1612
|
+
CoordinationType.SAMPLE_TYPE,
|
|
1613
|
+
// For selection of case-control sets of samples:
|
|
1614
|
+
CoordinationType.SAMPLE_SET_SELECTION,
|
|
1615
|
+
// For selection of one-vs-others sets of observations:
|
|
1616
|
+
CoordinationType.OBS_SET_SELECTION,
|
|
1617
|
+
CoordinationType.ADDITIONAL_OBS_SETS,
|
|
1618
|
+
CoordinationType.OBS_SET_COLOR,
|
|
1619
|
+
CoordinationType.SAMPLE_SET_COLOR
|
|
1620
|
+
],
|
|
1621
|
+
[ViewType.FEATURE_SET_ENRICHMENT_BAR_PLOT]: [
|
|
1622
|
+
CoordinationType.DATASET,
|
|
1623
|
+
CoordinationType.OBS_TYPE,
|
|
1624
|
+
CoordinationType.FEATURE_TYPE,
|
|
1625
|
+
CoordinationType.SAMPLE_TYPE,
|
|
1626
|
+
// For selection of case-control sets of samples:
|
|
1627
|
+
CoordinationType.SAMPLE_SET_SELECTION,
|
|
1628
|
+
// For selection of one-vs-others sets of observations:
|
|
1629
|
+
CoordinationType.OBS_SET_SELECTION,
|
|
1630
|
+
CoordinationType.ADDITIONAL_OBS_SETS,
|
|
1631
|
+
CoordinationType.OBS_SET_COLOR,
|
|
1632
|
+
CoordinationType.SAMPLE_SET_COLOR,
|
|
1633
|
+
CoordinationType.FEATURE_SELECTION
|
|
1634
|
+
],
|
|
1545
1635
|
[ViewType.LINK_CONTROLLER]: [],
|
|
1546
1636
|
[ViewType.BIOMARKER_SELECT]: [
|
|
1637
|
+
CoordinationType.DATASET,
|
|
1638
|
+
CoordinationType.OBS_TYPE,
|
|
1639
|
+
CoordinationType.SAMPLE_TYPE,
|
|
1547
1640
|
CoordinationType.FEATURE_SELECTION,
|
|
1548
1641
|
CoordinationType.SAMPLE_SET_SELECTION,
|
|
1549
1642
|
CoordinationType.SAMPLE_SET_FILTER,
|
|
1550
1643
|
CoordinationType.OBS_SET_SELECTION,
|
|
1551
1644
|
CoordinationType.OBS_SET_FILTER
|
|
1552
1645
|
// TODO: create coordination types for internal state of the biomarker selection view?
|
|
1646
|
+
],
|
|
1647
|
+
[ViewType.COMPARATIVE_HEADING]: [
|
|
1648
|
+
CoordinationType.DATASET,
|
|
1649
|
+
CoordinationType.OBS_TYPE,
|
|
1650
|
+
CoordinationType.SAMPLE_TYPE,
|
|
1651
|
+
CoordinationType.FEATURE_SELECTION,
|
|
1652
|
+
CoordinationType.SAMPLE_SET_SELECTION,
|
|
1653
|
+
CoordinationType.SAMPLE_SET_FILTER,
|
|
1654
|
+
CoordinationType.OBS_SET_SELECTION,
|
|
1655
|
+
CoordinationType.OBS_SET_FILTER
|
|
1656
|
+
],
|
|
1657
|
+
[ViewType.TREEMAP]: [
|
|
1658
|
+
CoordinationType.DATASET,
|
|
1659
|
+
CoordinationType.OBS_TYPE,
|
|
1660
|
+
CoordinationType.FEATURE_TYPE,
|
|
1661
|
+
CoordinationType.FEATURE_VALUE_TYPE,
|
|
1662
|
+
CoordinationType.OBS_FILTER,
|
|
1663
|
+
CoordinationType.OBS_HIGHLIGHT,
|
|
1664
|
+
CoordinationType.OBS_SET_SELECTION,
|
|
1665
|
+
CoordinationType.OBS_SET_FILTER,
|
|
1666
|
+
CoordinationType.OBS_SELECTION,
|
|
1667
|
+
CoordinationType.OBS_SELECTION_MODE,
|
|
1668
|
+
CoordinationType.OBS_SET_HIGHLIGHT,
|
|
1669
|
+
CoordinationType.OBS_SET_COLOR,
|
|
1670
|
+
CoordinationType.OBS_COLOR_ENCODING,
|
|
1671
|
+
CoordinationType.ADDITIONAL_OBS_SETS,
|
|
1672
|
+
CoordinationType.SAMPLE_TYPE,
|
|
1673
|
+
CoordinationType.SAMPLE_SET_SELECTION,
|
|
1674
|
+
CoordinationType.SAMPLE_SET_FILTER,
|
|
1675
|
+
CoordinationType.SAMPLE_SET_COLOR,
|
|
1676
|
+
CoordinationType.SAMPLE_SELECTION,
|
|
1677
|
+
CoordinationType.SAMPLE_SELECTION_MODE,
|
|
1678
|
+
CoordinationType.SAMPLE_FILTER,
|
|
1679
|
+
CoordinationType.SAMPLE_FILTER_MODE,
|
|
1680
|
+
CoordinationType.SAMPLE_HIGHLIGHT,
|
|
1681
|
+
CoordinationType.HIERARCHY_LEVELS
|
|
1553
1682
|
]
|
|
1554
1683
|
};
|
|
1555
1684
|
var common = {
|
|
@@ -30739,7 +30868,7 @@ function SelectStratification(props) {
|
|
|
30739
30868
|
) })
|
|
30740
30869
|
] });
|
|
30741
30870
|
}
|
|
30742
|
-
const steps = [
|
|
30871
|
+
const steps$1 = [
|
|
30743
30872
|
"Select biomarkers (modality-agnostic)",
|
|
30744
30873
|
"Derive modality-specific biomarker signature",
|
|
30745
30874
|
"Define case-control stratification"
|
|
@@ -30789,12 +30918,12 @@ function ConfirmatoryStepper(props) {
|
|
|
30789
30918
|
setActiveStep(0);
|
|
30790
30919
|
};
|
|
30791
30920
|
useEffect(() => {
|
|
30792
|
-
if (activeStep === steps.length) {
|
|
30921
|
+
if (activeStep === steps$1.length) {
|
|
30793
30922
|
onFinish();
|
|
30794
30923
|
}
|
|
30795
|
-
}, [activeStep, steps]);
|
|
30924
|
+
}, [activeStep, steps$1]);
|
|
30796
30925
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Grid$1, { item: true, container: true, xs: 12, children: [
|
|
30797
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Grid$1, { item: true, container: true, xs: 12, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Box$1, { className: classes.fullWidthBox, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Stepper$1, { activeStep, children: steps.map((label, index) => {
|
|
30926
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Grid$1, { item: true, container: true, xs: 12, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Box$1, { className: classes.fullWidthBox, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Stepper$1, { activeStep, children: steps$1.map((label, index) => {
|
|
30798
30927
|
const stepProps = {};
|
|
30799
30928
|
const labelProps = {};
|
|
30800
30929
|
if (isStepOptional(index)) {
|
|
@@ -30806,7 +30935,7 @@ function ConfirmatoryStepper(props) {
|
|
|
30806
30935
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(Step$1, { ...stepProps, children: /* @__PURE__ */ jsxRuntimeExports.jsx(StepLabel$1, { ...labelProps, children: label }) }, label);
|
|
30807
30936
|
}) }) }) }),
|
|
30808
30937
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Grid$1, { item: true, container: true, xs: 12, style: { marginTop: "20px" }, alignItems: "flex-start", children: [
|
|
30809
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(Grid$1, { item: true, container: true, xs: 8, children: activeStep === steps.length ? /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(Typography$1, { style: { marginTop: "20px", marginBottom: "10px" }, children: "All steps completed - you're finished" }) }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
30938
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Grid$1, { item: true, container: true, xs: 8, children: activeStep === steps$1.length ? /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(Typography$1, { style: { marginTop: "20px", marginBottom: "10px" }, children: "All steps completed - you're finished" }) }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
30810
30939
|
activeStep === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
30811
30940
|
SelectAgnostic,
|
|
30812
30941
|
{
|
|
@@ -30862,6 +30991,118 @@ function ConfirmatoryStepper(props) {
|
|
|
30862
30991
|
stratifications
|
|
30863
30992
|
}
|
|
30864
30993
|
) }),
|
|
30994
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Box$1, { className: classes.fullWidthBox, children: activeStep === steps$1.length ? /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Box$1, { style: { display: "flex", flexDirection: "row", paddingTop: "20px" }, children: [
|
|
30995
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Box$1, { style: { flex: "1 1 auto" } }),
|
|
30996
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button$1, { onClick: handleReset, children: "Reset" })
|
|
30997
|
+
] }) }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(Box$1, { style: { display: "flex", flexDirection: "row", paddingTop: "20px" }, children: [
|
|
30998
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
30999
|
+
Button$1,
|
|
31000
|
+
{
|
|
31001
|
+
color: "inherit",
|
|
31002
|
+
disabled: activeStep === 0,
|
|
31003
|
+
onClick: handleBack,
|
|
31004
|
+
style: { mr: 1 },
|
|
31005
|
+
children: "Back"
|
|
31006
|
+
}
|
|
31007
|
+
),
|
|
31008
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Box$1, { style: { flex: "1 1 auto" } }),
|
|
31009
|
+
isStepOptional(activeStep) && /* @__PURE__ */ jsxRuntimeExports.jsx(Button$1, { color: "inherit", onClick: handleSkip, style: { marginRight: "10px" }, children: "Skip" }),
|
|
31010
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Button$1, { onClick: handleNext, children: activeStep === steps$1.length - 1 ? "Finish" : "Next" })
|
|
31011
|
+
] }) })
|
|
31012
|
+
] })
|
|
31013
|
+
] });
|
|
31014
|
+
}
|
|
31015
|
+
const steps = [
|
|
31016
|
+
"Define case-control stratification"
|
|
31017
|
+
];
|
|
31018
|
+
function ExploratoryStepper(props) {
|
|
31019
|
+
const {
|
|
31020
|
+
autocompleteNode,
|
|
31021
|
+
currentModalityAgnosticSelection,
|
|
31022
|
+
setCurrentModalityAgnosticSelection,
|
|
31023
|
+
currentModalitySpecificSelection,
|
|
31024
|
+
setCurrentModalitySpecificSelection,
|
|
31025
|
+
currentStratificationSelection,
|
|
31026
|
+
setCurrentStratificationSelection,
|
|
31027
|
+
getEdges,
|
|
31028
|
+
stratifications,
|
|
31029
|
+
onFinish
|
|
31030
|
+
} = props;
|
|
31031
|
+
const classes = useStyles();
|
|
31032
|
+
const [activeStep, setActiveStep] = React__default.useState(0);
|
|
31033
|
+
const [skipped, setSkipped] = React__default.useState(/* @__PURE__ */ new Set());
|
|
31034
|
+
const isStepOptional = (step) => step === 2;
|
|
31035
|
+
const isStepSkipped = (step) => skipped.has(step);
|
|
31036
|
+
const handleNext = () => {
|
|
31037
|
+
let newSkipped = skipped;
|
|
31038
|
+
if (isStepSkipped(activeStep)) {
|
|
31039
|
+
newSkipped = new Set(newSkipped.values());
|
|
31040
|
+
newSkipped.delete(activeStep);
|
|
31041
|
+
}
|
|
31042
|
+
setActiveStep((prevActiveStep) => prevActiveStep + 1);
|
|
31043
|
+
setSkipped(newSkipped);
|
|
31044
|
+
};
|
|
31045
|
+
const handleBack = () => {
|
|
31046
|
+
setActiveStep((prevActiveStep) => prevActiveStep - 1);
|
|
31047
|
+
};
|
|
31048
|
+
const handleSkip = () => {
|
|
31049
|
+
if (!isStepOptional(activeStep)) {
|
|
31050
|
+
throw new Error("You can't skip a step that isn't optional.");
|
|
31051
|
+
}
|
|
31052
|
+
setActiveStep((prevActiveStep) => prevActiveStep + 1);
|
|
31053
|
+
setSkipped((prevSkipped) => {
|
|
31054
|
+
const newSkipped = new Set(prevSkipped.values());
|
|
31055
|
+
newSkipped.add(activeStep);
|
|
31056
|
+
return newSkipped;
|
|
31057
|
+
});
|
|
31058
|
+
};
|
|
31059
|
+
const handleReset = () => {
|
|
31060
|
+
setActiveStep(0);
|
|
31061
|
+
};
|
|
31062
|
+
useEffect(() => {
|
|
31063
|
+
if (activeStep === steps.length) {
|
|
31064
|
+
onFinish();
|
|
31065
|
+
}
|
|
31066
|
+
}, [activeStep, steps]);
|
|
31067
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Grid$1, { item: true, container: true, xs: 12, children: [
|
|
31068
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Grid$1, { item: true, container: true, xs: 12, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Box$1, { className: classes.fullWidthBox, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Stepper$1, { activeStep, children: steps.map((label, index) => {
|
|
31069
|
+
const stepProps = {};
|
|
31070
|
+
const labelProps = {};
|
|
31071
|
+
if (isStepOptional(index)) {
|
|
31072
|
+
labelProps.optional = /* @__PURE__ */ jsxRuntimeExports.jsx(Typography$1, { variant: "caption", children: "Optional" });
|
|
31073
|
+
}
|
|
31074
|
+
if (isStepSkipped(index)) {
|
|
31075
|
+
stepProps.completed = false;
|
|
31076
|
+
}
|
|
31077
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(Step$1, { ...stepProps, children: /* @__PURE__ */ jsxRuntimeExports.jsx(StepLabel$1, { ...labelProps, children: label }) }, label);
|
|
31078
|
+
}) }) }) }),
|
|
31079
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(Grid$1, { item: true, container: true, xs: 12, style: { marginTop: "20px" }, alignItems: "flex-start", children: [
|
|
31080
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Grid$1, { item: true, container: true, xs: 8, children: activeStep === steps.length ? /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(Typography$1, { style: { marginTop: "20px", marginBottom: "10px" }, children: "All steps completed - you're finished" }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: activeStep === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
31081
|
+
SelectStratification,
|
|
31082
|
+
{
|
|
31083
|
+
autocompleteNode,
|
|
31084
|
+
currentModalityAgnosticSelection,
|
|
31085
|
+
setCurrentModalityAgnosticSelection,
|
|
31086
|
+
currentModalitySpecificSelection,
|
|
31087
|
+
setCurrentModalitySpecificSelection,
|
|
31088
|
+
currentStratificationSelection,
|
|
31089
|
+
setCurrentStratificationSelection,
|
|
31090
|
+
getEdges,
|
|
31091
|
+
stratifications
|
|
31092
|
+
}
|
|
31093
|
+
) : null }) }),
|
|
31094
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Grid$1, { item: true, container: true, xs: 4, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
31095
|
+
ConfirmatoryCart,
|
|
31096
|
+
{
|
|
31097
|
+
currentModalityAgnosticSelection,
|
|
31098
|
+
setCurrentModalityAgnosticSelection,
|
|
31099
|
+
currentModalitySpecificSelection,
|
|
31100
|
+
setCurrentModalitySpecificSelection,
|
|
31101
|
+
currentStratificationSelection,
|
|
31102
|
+
setCurrentStratificationSelection,
|
|
31103
|
+
stratifications
|
|
31104
|
+
}
|
|
31105
|
+
) }),
|
|
30865
31106
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Box$1, { className: classes.fullWidthBox, children: activeStep === steps.length ? /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Box$1, { style: { display: "flex", flexDirection: "row", paddingTop: "20px" }, children: [
|
|
30866
31107
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Box$1, { style: { flex: "1 1 auto" } }),
|
|
30867
31108
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Button$1, { onClick: handleReset, children: "Reset" })
|
|
@@ -30928,22 +31169,60 @@ function ScmdUi(props) {
|
|
|
30928
31169
|
onFinish
|
|
30929
31170
|
}
|
|
30930
31171
|
) : null,
|
|
30931
|
-
mode === "exploratory" ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
31172
|
+
mode === "exploratory" ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
31173
|
+
ExploratoryStepper,
|
|
31174
|
+
{
|
|
31175
|
+
autocompleteNode,
|
|
31176
|
+
currentModalityAgnosticSelection,
|
|
31177
|
+
setCurrentModalityAgnosticSelection,
|
|
31178
|
+
currentModalitySpecificSelection,
|
|
31179
|
+
setCurrentModalitySpecificSelection,
|
|
31180
|
+
currentStratificationSelection,
|
|
31181
|
+
setCurrentStratificationSelection,
|
|
31182
|
+
getEdges,
|
|
31183
|
+
stratifications,
|
|
31184
|
+
onFinish
|
|
31185
|
+
}
|
|
31186
|
+
) : null
|
|
30932
31187
|
] }) : null
|
|
30933
31188
|
] });
|
|
30934
31189
|
}
|
|
30935
31190
|
function BiomarkerSelectSubscriber(props) {
|
|
30936
31191
|
const {
|
|
30937
31192
|
coordinationScopes,
|
|
30938
|
-
stratificationOptions
|
|
31193
|
+
stratificationOptions: stratificationOptionsProp
|
|
31194
|
+
// TODO: Remove; Get from comparisonMetadata instead
|
|
30939
31195
|
} = props;
|
|
30940
|
-
|
|
31196
|
+
const loaders = useLoaders();
|
|
31197
|
+
const [{
|
|
31198
|
+
dataset,
|
|
31199
|
+
obsType,
|
|
31200
|
+
sampleType,
|
|
31201
|
+
sampleSetSelection,
|
|
31202
|
+
featureSelection
|
|
31203
|
+
}, {
|
|
31204
|
+
setSampleSetSelection,
|
|
31205
|
+
setFeatureSelection
|
|
31206
|
+
}] = useCoordination(
|
|
30941
31207
|
COMPONENT_COORDINATION_TYPES[ViewType.BIOMARKER_SELECT],
|
|
30942
31208
|
coordinationScopes
|
|
30943
31209
|
);
|
|
30944
31210
|
const viewConfigStoreApi = useViewConfigStoreApi();
|
|
30945
31211
|
const viewConfig = useViewConfig();
|
|
30946
31212
|
const setViewConfig = useSetViewConfig(viewConfigStoreApi);
|
|
31213
|
+
useMatchingLoader(
|
|
31214
|
+
loaders,
|
|
31215
|
+
dataset,
|
|
31216
|
+
DataType.OBS_SETS,
|
|
31217
|
+
{ obsType }
|
|
31218
|
+
);
|
|
31219
|
+
const sampleSetsLoader = useMatchingLoader(
|
|
31220
|
+
loaders,
|
|
31221
|
+
dataset,
|
|
31222
|
+
DataType.SAMPLE_SETS,
|
|
31223
|
+
{ sampleType }
|
|
31224
|
+
);
|
|
31225
|
+
const sampleSetsColumnNameMappingReversed = useColumnNameMapping(sampleSetsLoader, true);
|
|
30947
31226
|
const [isSelecting, setIsSelecting] = useState(true);
|
|
30948
31227
|
const [mode, setMode] = useState(null);
|
|
30949
31228
|
const [step, setStep] = useState(null);
|
|
@@ -30960,6 +31239,36 @@ function BiomarkerSelectSubscriber(props) {
|
|
|
30960
31239
|
async (node, targetModality) => transformFeature2(node, targetModality),
|
|
30961
31240
|
[transformFeature2]
|
|
30962
31241
|
);
|
|
31242
|
+
const [{ comparisonMetadata }, cmpMetadataStatus, cmpMetadataUrls] = useComparisonMetadata(
|
|
31243
|
+
loaders,
|
|
31244
|
+
dataset,
|
|
31245
|
+
false,
|
|
31246
|
+
{},
|
|
31247
|
+
{},
|
|
31248
|
+
{ obsType, sampleType }
|
|
31249
|
+
);
|
|
31250
|
+
const stratificationOptions = useMemo(() => {
|
|
31251
|
+
if (comparisonMetadata == null ? void 0 : comparisonMetadata.sample_group_pairs) {
|
|
31252
|
+
return comparisonMetadata.sample_group_pairs.map((sampleGroupPair) => {
|
|
31253
|
+
const [sampleGroupCol, sampleGroupValues] = sampleGroupPair;
|
|
31254
|
+
const [sampleGroupCtrl, sampleGroupCase] = sampleGroupValues;
|
|
31255
|
+
const groupName = sampleSetsColumnNameMappingReversed == null ? void 0 : sampleSetsColumnNameMappingReversed[sampleGroupCol];
|
|
31256
|
+
return {
|
|
31257
|
+
stratificationId: `${sampleGroupCol}_${sampleGroupCtrl}-vs-${sampleGroupCase}`,
|
|
31258
|
+
name: `${groupName}: ${sampleGroupCtrl} vs. ${sampleGroupCase}`,
|
|
31259
|
+
stratificationType: "sampleSet",
|
|
31260
|
+
sampleSets: [
|
|
31261
|
+
// With sampleSets coming from the comparison_metadata,
|
|
31262
|
+
// need to use loader options from obsSets and sampleSets to get mapping
|
|
31263
|
+
// from column name to group name.
|
|
31264
|
+
[groupName, sampleGroupCtrl],
|
|
31265
|
+
[groupName, sampleGroupCase]
|
|
31266
|
+
]
|
|
31267
|
+
};
|
|
31268
|
+
});
|
|
31269
|
+
}
|
|
31270
|
+
return null;
|
|
31271
|
+
}, [comparisonMetadata, sampleSetsColumnNameMappingReversed]);
|
|
30963
31272
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: isSelecting ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
30964
31273
|
ScmdUi,
|
|
30965
31274
|
{
|
|
@@ -30977,24 +31286,46 @@ function BiomarkerSelectSubscriber(props) {
|
|
|
30977
31286
|
getEdges,
|
|
30978
31287
|
stratifications: stratificationOptions,
|
|
30979
31288
|
onFinish: () => {
|
|
30980
|
-
|
|
31289
|
+
const newViewConfig = {
|
|
30981
31290
|
...viewConfig,
|
|
30982
31291
|
coordinationSpace: {
|
|
30983
31292
|
...viewConfig.coordinationSpace,
|
|
30984
31293
|
sampleSetFilter: {
|
|
30985
31294
|
...viewConfig.coordinationSpace.sampleSetFilter,
|
|
30986
|
-
|
|
31295
|
+
__comparison__: currentStratificationSelection == null ? void 0 : currentStratificationSelection.sampleSets
|
|
30987
31296
|
},
|
|
30988
31297
|
sampleSetSelection: {
|
|
30989
31298
|
...viewConfig.coordinationSpace.sampleSetSelection,
|
|
30990
|
-
|
|
31299
|
+
__comparison__: currentStratificationSelection == null ? void 0 : currentStratificationSelection.sampleSets
|
|
31300
|
+
},
|
|
31301
|
+
featureSelection: {
|
|
31302
|
+
...viewConfig.coordinationSpace.featureSelection,
|
|
31303
|
+
__comparison__: currentModalitySpecificSelection ? currentModalitySpecificSelection.map((d) => d.label) : null
|
|
30991
31304
|
}
|
|
30992
31305
|
}
|
|
30993
|
-
}
|
|
31306
|
+
};
|
|
31307
|
+
setViewConfig(newViewConfig);
|
|
30994
31308
|
}
|
|
30995
31309
|
}
|
|
30996
31310
|
) : null });
|
|
30997
31311
|
}
|
|
31312
|
+
function ComparativeHeadingSubscriber(props) {
|
|
31313
|
+
var _a2, _b;
|
|
31314
|
+
const {
|
|
31315
|
+
coordinationScopes
|
|
31316
|
+
} = props;
|
|
31317
|
+
const [{
|
|
31318
|
+
sampleSetSelection
|
|
31319
|
+
}] = useCoordination(
|
|
31320
|
+
COMPONENT_COORDINATION_TYPES[ViewType.COMPARATIVE_HEADING],
|
|
31321
|
+
coordinationScopes
|
|
31322
|
+
);
|
|
31323
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: sampleSetSelection && sampleSetSelection.length === 2 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { width: "100%", display: "flex", flexDirection: "row" }, children: [
|
|
31324
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { width: "45%" }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { children: (_a2 = sampleSetSelection == null ? void 0 : sampleSetSelection[0]) == null ? void 0 : _a2.at(-1) }) }),
|
|
31325
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { width: "5%" }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { style: { textAlign: "right" }, children: "vs. " }) }),
|
|
31326
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { width: "50%" }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { children: (_b = sampleSetSelection == null ? void 0 : sampleSetSelection[1]) == null ? void 0 : _b.at(-1) }) })
|
|
31327
|
+
] }) : null });
|
|
31328
|
+
}
|
|
30998
31329
|
var EOL = {}, EOF = {}, QUOTE = 34, NEWLINE = 10, RETURN = 13;
|
|
30999
31330
|
function objectConverter(columns2) {
|
|
31000
31331
|
return new Function("d", "return {" + columns2.map(function(name, i) {
|
|
@@ -32193,6 +32524,7 @@ async function getTermMapping({ queryClient }, keyCuriePrefix, valCuriePrefix) {
|
|
|
32193
32524
|
}
|
|
32194
32525
|
export {
|
|
32195
32526
|
BiomarkerSelectSubscriber,
|
|
32527
|
+
ComparativeHeadingSubscriber,
|
|
32196
32528
|
autocompleteFeature,
|
|
32197
32529
|
getAlternativeTerms,
|
|
32198
32530
|
getTermMapping,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BiomarkerSelectSubscriber.d.ts","sourceRoot":"","sources":["../src/BiomarkerSelectSubscriber.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"BiomarkerSelectSubscriber.d.ts","sourceRoot":"","sources":["../src/BiomarkerSelectSubscriber.js"],"names":[],"mappings":"AAiBA;;;;;GAKG;AACH,iDAHG;IAA+F,qBAAqB,EAA5G;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAA;KAAC,EAAE;CACvF,eA0JF"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
/* eslint-disable max-len */
|
|
3
3
|
/* eslint-disable no-unused-vars */
|
|
4
|
-
import React, { useState, useCallback } from 'react';
|
|
5
|
-
import { useAsyncFunction, useViewConfigStoreApi, useSetViewConfig, useViewConfig, useCoordination, } from '@vitessce/vit-s';
|
|
6
|
-
import { AsyncFunctionType, ViewType, COMPONENT_COORDINATION_TYPES } from '@vitessce/constants-internal';
|
|
4
|
+
import React, { useState, useCallback, useMemo } from 'react';
|
|
5
|
+
import { useAsyncFunction, useViewConfigStoreApi, useSetViewConfig, useViewConfig, useCoordination, useLoaders, useComparisonMetadata, useMatchingLoader, useColumnNameMapping, } from '@vitessce/vit-s';
|
|
6
|
+
import { AsyncFunctionType, ViewType, COMPONENT_COORDINATION_TYPES, DataType } from '@vitessce/constants-internal';
|
|
7
7
|
import { ScmdUi } from './scmd-ui.js';
|
|
8
8
|
/**
|
|
9
9
|
*
|
|
@@ -12,11 +12,18 @@ import { ScmdUi } from './scmd-ui.js';
|
|
|
12
12
|
* @returns
|
|
13
13
|
*/
|
|
14
14
|
export function BiomarkerSelectSubscriber(props) {
|
|
15
|
-
const { coordinationScopes, stratificationOptions,
|
|
16
|
-
|
|
15
|
+
const { coordinationScopes, stratificationOptions: stratificationOptionsProp, // TODO: Remove; Get from comparisonMetadata instead
|
|
16
|
+
} = props;
|
|
17
|
+
const loaders = useLoaders();
|
|
18
|
+
const [{ dataset, obsType, sampleType, sampleSetSelection, featureSelection, }, { setSampleSetSelection, setFeatureSelection, }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType.BIOMARKER_SELECT], coordinationScopes);
|
|
17
19
|
const viewConfigStoreApi = useViewConfigStoreApi();
|
|
18
20
|
const viewConfig = useViewConfig();
|
|
19
21
|
const setViewConfig = useSetViewConfig(viewConfigStoreApi);
|
|
22
|
+
// Need obsSets and sampleSets options to obtain mapping between
|
|
23
|
+
// group names and column names.
|
|
24
|
+
const obsSetsLoader = useMatchingLoader(loaders, dataset, DataType.OBS_SETS, { obsType });
|
|
25
|
+
const sampleSetsLoader = useMatchingLoader(loaders, dataset, DataType.SAMPLE_SETS, { sampleType });
|
|
26
|
+
const sampleSetsColumnNameMappingReversed = useColumnNameMapping(sampleSetsLoader, true);
|
|
20
27
|
// TODO: make isSelecting a coordination type plugin.
|
|
21
28
|
// TODO: use store hooks from @vitessce/vit-s to update the view config based on the selections.
|
|
22
29
|
const [isSelecting, setIsSelecting] = useState(true);
|
|
@@ -29,20 +36,69 @@ export function BiomarkerSelectSubscriber(props) {
|
|
|
29
36
|
const transformFeature = useAsyncFunction(AsyncFunctionType.TRANSFORM_FEATURE);
|
|
30
37
|
const autocompleteNode = useCallback(async (inputValue) => autocompleteFeature(inputValue), [autocompleteFeature]);
|
|
31
38
|
const getEdges = useCallback(async (node, targetModality) => transformFeature(node, targetModality), [transformFeature]);
|
|
39
|
+
const [{ comparisonMetadata }, cmpMetadataStatus, cmpMetadataUrls] = useComparisonMetadata(loaders, dataset, false, {}, {}, { obsType, sampleType });
|
|
40
|
+
const stratificationOptions = useMemo(() => {
|
|
41
|
+
/*
|
|
42
|
+
return array of objects like {
|
|
43
|
+
stratificationId: 'aki-vs-hr',
|
|
44
|
+
name: 'Acute kidney injury (AKI) vs. Healthy reference',
|
|
45
|
+
stratificationType: 'sampleSet', // key changed from 'groupType'. value changed from 'clinical'
|
|
46
|
+
sampleSets: [
|
|
47
|
+
['Disease Type', 'AKI'],
|
|
48
|
+
['Disease Type', 'Reference'],
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
*/
|
|
52
|
+
if (comparisonMetadata?.sample_group_pairs) {
|
|
53
|
+
return comparisonMetadata.sample_group_pairs.map((sampleGroupPair) => {
|
|
54
|
+
const [sampleGroupCol, sampleGroupValues] = sampleGroupPair;
|
|
55
|
+
const [sampleGroupCtrl, sampleGroupCase] = sampleGroupValues;
|
|
56
|
+
const groupName = sampleSetsColumnNameMappingReversed?.[sampleGroupCol];
|
|
57
|
+
return {
|
|
58
|
+
stratificationId: `${sampleGroupCol}_${sampleGroupCtrl}-vs-${sampleGroupCase}`,
|
|
59
|
+
name: `${groupName}: ${sampleGroupCtrl} vs. ${sampleGroupCase}`,
|
|
60
|
+
stratificationType: 'sampleSet',
|
|
61
|
+
sampleSets: [
|
|
62
|
+
// With sampleSets coming from the comparison_metadata,
|
|
63
|
+
// need to use loader options from obsSets and sampleSets to get mapping
|
|
64
|
+
// from column name to group name.
|
|
65
|
+
[groupName, sampleGroupCtrl],
|
|
66
|
+
[groupName, sampleGroupCase],
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}, [comparisonMetadata, sampleSetsColumnNameMappingReversed]);
|
|
32
73
|
return (_jsx(_Fragment, { children: isSelecting ? (_jsx(ScmdUi, { mode: mode, setMode: setMode, step: step, setStep: setStep, currentModalityAgnosticSelection: currentModalityAgnosticSelection, setCurrentModalityAgnosticSelection: setCurrentModalityAgnosticSelection, currentModalitySpecificSelection: currentModalitySpecificSelection, setCurrentModalitySpecificSelection: setCurrentModalitySpecificSelection, currentStratificationSelection: currentStratificationSelection, setCurrentStratificationSelection: setCurrentStratificationSelection, autocompleteNode: autocompleteNode, getEdges: getEdges, stratifications: stratificationOptions, onFinish: () => {
|
|
33
|
-
|
|
74
|
+
if (mode === 'exploratory') {
|
|
75
|
+
// mode is exploratory, configure accordingly.
|
|
76
|
+
// TODO
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
// mode is confirmatory, configure accordingly.
|
|
80
|
+
// TODO
|
|
81
|
+
}
|
|
82
|
+
const newViewConfig = {
|
|
34
83
|
...viewConfig,
|
|
35
84
|
coordinationSpace: {
|
|
36
85
|
...viewConfig.coordinationSpace,
|
|
37
86
|
sampleSetFilter: {
|
|
38
87
|
...viewConfig.coordinationSpace.sampleSetFilter,
|
|
39
|
-
|
|
88
|
+
__comparison__: currentStratificationSelection?.sampleSets,
|
|
40
89
|
},
|
|
41
90
|
sampleSetSelection: {
|
|
42
91
|
...viewConfig.coordinationSpace.sampleSetSelection,
|
|
43
|
-
|
|
92
|
+
__comparison__: currentStratificationSelection?.sampleSets,
|
|
93
|
+
},
|
|
94
|
+
featureSelection: {
|
|
95
|
+
...viewConfig.coordinationSpace.featureSelection,
|
|
96
|
+
__comparison__: currentModalitySpecificSelection ? currentModalitySpecificSelection.map(d => d.label) : null,
|
|
44
97
|
},
|
|
45
98
|
},
|
|
46
|
-
}
|
|
99
|
+
};
|
|
100
|
+
// TODO: can the normal coordination value setters be used instead?
|
|
101
|
+
// (e.g., setFeatureSelection, setSampleSetSelection)
|
|
102
|
+
setViewConfig(newViewConfig);
|
|
47
103
|
} })) : null }));
|
|
48
104
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComparativeHeadingSubscriber.d.ts","sourceRoot":"","sources":["../src/ComparativeHeadingSubscriber.js"],"names":[],"mappings":"AAOA,sEAuBC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { useCoordination, } from '@vitessce/vit-s';
|
|
4
|
+
import { ViewType, COMPONENT_COORDINATION_TYPES } from '@vitessce/constants-internal';
|
|
5
|
+
export function ComparativeHeadingSubscriber(props) {
|
|
6
|
+
const { coordinationScopes, } = props;
|
|
7
|
+
const [{ sampleSetSelection, }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType.COMPARATIVE_HEADING], coordinationScopes);
|
|
8
|
+
return (_jsx(_Fragment, { children: sampleSetSelection && sampleSetSelection.length === 2 ? (_jsxs("div", { style: { width: '100%', display: 'flex', flexDirection: 'row' }, children: [_jsx("div", { style: { width: '45%' }, children: _jsx("h2", { children: sampleSetSelection?.[0]?.at(-1) }) }), _jsx("div", { style: { width: '5%' }, children: _jsx("h2", { style: { textAlign: 'right' }, children: "vs.\u00A0" }) }), _jsx("div", { style: { width: '50%' }, children: _jsx("h2", { children: sampleSetSelection?.[1]?.at(-1) }) })] })) : null }));
|
|
9
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default-async-functions.d.ts","sourceRoot":"","sources":["../src/default-async-functions.js"],"names":[],"mappings":"AAqHA;;;;;;;GAOG;AACH,qDALG;IAAyB,WAAW,EAA5B,WAAW;CACnB,WAAQ,MAAM,kBACN,IAAI,GAAG,kBAAkB,GACvB,OAAO,CAAC,MAAM,EAAE,CAAC,CAiB7B;AAeD;;;;;;;GAOG;AACH,kDALG;IAAyB,WAAW,EAA5B,WAAW;CACnB,QAAQ,MAAM,kBACN,kBAAkB,GAChB,OAAO,CAAC,MAAM,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"default-async-functions.d.ts","sourceRoot":"","sources":["../src/default-async-functions.js"],"names":[],"mappings":"AAqHA;;;;;;;GAOG;AACH,qDALG;IAAyB,WAAW,EAA5B,WAAW;CACnB,WAAQ,MAAM,kBACN,IAAI,GAAG,kBAAkB,GACvB,OAAO,CAAC,MAAM,EAAE,CAAC,CAiB7B;AAeD;;;;;;;GAOG;AACH,kDALG;IAAyB,WAAW,EAA5B,WAAW;CACnB,QAAQ,MAAM,kBACN,kBAAkB,GAChB,OAAO,CAAC,MAAM,EAAE,CAAC,CAmC7B;AAED;;;;;;GAMG;AACH,qDAJG;IAAyB,WAAW,EAA5B,WAAW;CACnB,SAAQ,MAAM,GACJ,OAAO,CAAC,MAAM,EAAE,CAAC,CA2B7B;AAED;;;;;;;GAOG;AACH,gDALG;IAAyB,WAAW,EAA5B,WAAW;CACnB,kBAAQ,MAAM,kBACN,MAAM,GACJ,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAoBxC;iCA1PsD,uBAAuB;wCADsE,iBAAiB;4BAAjB,iBAAiB"}
|
|
@@ -161,6 +161,7 @@ export async function transformFeature({ queryClient }, node, targetModality) {
|
|
|
161
161
|
staleTime: Infinity,
|
|
162
162
|
queryFn: loadPathwayToGeneEdges,
|
|
163
163
|
});
|
|
164
|
+
// TODO: support matching using ontology term (rather than requiring kgId)?
|
|
164
165
|
const matchingEdges = pathwayGeneEdges.filter((/** @type {KgEdge} */ d) => d.source === node.kgId);
|
|
165
166
|
const matchingGeneIds = matchingEdges.map((/** @type {KgEdge} */ d) => d.target);
|
|
166
167
|
const matchingGenes = geneNodes.filter(d => matchingGeneIds.includes(d.kgId));
|
package/dist-tsc/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { BiomarkerSelectSubscriber } from "./BiomarkerSelectSubscriber.js";
|
|
2
|
+
export { ComparativeHeadingSubscriber } from "./ComparativeHeadingSubscriber.js";
|
|
2
3
|
export { autocompleteFeature, transformFeature, getAlternativeTerms, getTermMapping } from "./default-async-functions.js";
|
|
3
4
|
//# sourceMappingURL=index.d.ts.map
|
package/dist-tsc/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export { BiomarkerSelectSubscriber } from './BiomarkerSelectSubscriber.js';
|
|
2
|
+
export { ComparativeHeadingSubscriber } from './ComparativeHeadingSubscriber.js';
|
|
2
3
|
export { autocompleteFeature, transformFeature, getAlternativeTerms, getTermMapping, } from './default-async-functions.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scmd-ui.d.ts","sourceRoot":"","sources":["../src/scmd-ui.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scmd-ui.d.ts","sourceRoot":"","sources":["../src/scmd-ui.js"],"names":[],"mappings":"AAQA,gDAkFC"}
|
package/dist-tsc/scmd-ui.js
CHANGED
|
@@ -2,7 +2,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
/* eslint-disable no-unused-vars */
|
|
3
3
|
import React, { useState } from 'react';
|
|
4
4
|
import { Button, ButtonGroup, Grid, Tooltip } from '@material-ui/core';
|
|
5
|
-
import { ConfirmatoryStepper } from './confirmatory
|
|
5
|
+
import { ConfirmatoryStepper } from './stepper-confirmatory.js';
|
|
6
|
+
import { ExploratoryStepper } from './stepper-exploratory.js';
|
|
6
7
|
import { useStyles } from './styles.js';
|
|
7
8
|
export function ScmdUi(props) {
|
|
8
9
|
const { mode: modeProp, setMode, step: stepProp, setStep, currentModalityAgnosticSelection, setCurrentModalityAgnosticSelection, currentModalitySpecificSelection, setCurrentModalitySpecificSelection, currentStratificationSelection, setCurrentStratificationSelection, autocompleteNode, getEdges, stratifications, onFinish, } = props;
|
|
@@ -11,5 +12,5 @@ export function ScmdUi(props) {
|
|
|
11
12
|
const step = mode === 'confirmatory' ? (stepProp || 'select-biomarkers') : (stepProp || 'define-stratification');
|
|
12
13
|
const [tempIsVisible, setTempIsVisible] = useState(true);
|
|
13
14
|
const isConfirmatoryMode = mode === 'confirmatory';
|
|
14
|
-
return (_jsxs(Grid, { container: true, style: { border: '0px solid red' }, children: [_jsxs(Grid, { item: true, container: true, xs: 12, className: classes.header, children: [_jsx(Grid, { item: true, xs: 8 }), _jsx(Grid, { item: true, container: true, xs: 4, justifyContent: "flex-end", children: _jsxs(ButtonGroup, { variant: "outlined", size: "small", color: "secondary", "aria-label": "Toggle between confirmatory and exploratory modes", children: [_jsx(Tooltip, { arrow: true, title: "Start from biomarker(s) of interest", children: _jsx(Button, { variant: isConfirmatoryMode ? 'contained' : 'outlined', onClick: () => setMode('confirmatory'), children: "Confirmatory (Hypothesis-driven)" }) }), _jsx(Tooltip, { arrow: true, title: "Lacking biomarker(s) of interest", children: _jsx(Button, { variant: !isConfirmatoryMode ? 'contained' : 'outlined', onClick: () => setMode('exploratory'), children: "Exploratory (Hypothesis-generating)" }) })] }) })] }), tempIsVisible ? (_jsxs("div", { style: { border: '2px solid #eee', borderRadius: '5px' }, children: [mode === 'confirmatory' ? (_jsx(ConfirmatoryStepper, { autocompleteNode: autocompleteNode, currentModalityAgnosticSelection: currentModalityAgnosticSelection, setCurrentModalityAgnosticSelection: setCurrentModalityAgnosticSelection, currentModalitySpecificSelection: currentModalitySpecificSelection, setCurrentModalitySpecificSelection: setCurrentModalitySpecificSelection, currentStratificationSelection: currentStratificationSelection, setCurrentStratificationSelection: setCurrentStratificationSelection, getEdges: getEdges, stratifications: stratifications, onFinish: onFinish })) : null, mode === 'exploratory' ? _jsx(
|
|
15
|
+
return (_jsxs(Grid, { container: true, style: { border: '0px solid red' }, children: [_jsxs(Grid, { item: true, container: true, xs: 12, className: classes.header, children: [_jsx(Grid, { item: true, xs: 8 }), _jsx(Grid, { item: true, container: true, xs: 4, justifyContent: "flex-end", children: _jsxs(ButtonGroup, { variant: "outlined", size: "small", color: "secondary", "aria-label": "Toggle between confirmatory and exploratory modes", children: [_jsx(Tooltip, { arrow: true, title: "Start from biomarker(s) of interest", children: _jsx(Button, { variant: isConfirmatoryMode ? 'contained' : 'outlined', onClick: () => setMode('confirmatory'), children: "Confirmatory (Hypothesis-driven)" }) }), _jsx(Tooltip, { arrow: true, title: "Lacking biomarker(s) of interest", children: _jsx(Button, { variant: !isConfirmatoryMode ? 'contained' : 'outlined', onClick: () => setMode('exploratory'), children: "Exploratory (Hypothesis-generating)" }) })] }) })] }), tempIsVisible ? (_jsxs("div", { style: { border: '2px solid #eee', borderRadius: '5px' }, children: [mode === 'confirmatory' ? (_jsx(ConfirmatoryStepper, { autocompleteNode: autocompleteNode, currentModalityAgnosticSelection: currentModalityAgnosticSelection, setCurrentModalityAgnosticSelection: setCurrentModalityAgnosticSelection, currentModalitySpecificSelection: currentModalitySpecificSelection, setCurrentModalitySpecificSelection: setCurrentModalitySpecificSelection, currentStratificationSelection: currentStratificationSelection, setCurrentStratificationSelection: setCurrentStratificationSelection, getEdges: getEdges, stratifications: stratifications, onFinish: onFinish })) : null, mode === 'exploratory' ? (_jsx(ExploratoryStepper, { autocompleteNode: autocompleteNode, currentModalityAgnosticSelection: currentModalityAgnosticSelection, setCurrentModalityAgnosticSelection: setCurrentModalityAgnosticSelection, currentModalitySpecificSelection: currentModalitySpecificSelection, setCurrentModalitySpecificSelection: setCurrentModalitySpecificSelection, currentStratificationSelection: currentStratificationSelection, setCurrentStratificationSelection: setCurrentStratificationSelection, getEdges: getEdges, stratifications: stratifications, onFinish: onFinish })) : null] })) : null] }));
|
|
15
16
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export function ConfirmatoryStepper(props: any): JSX.Element;
|
|
2
|
-
//# sourceMappingURL=confirmatory
|
|
2
|
+
//# sourceMappingURL=stepper-confirmatory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stepper-confirmatory.d.ts","sourceRoot":"","sources":["../src/stepper-confirmatory.js"],"names":[],"mappings":"AAcA,6DAkMC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stepper-exploratory.d.ts","sourceRoot":"","sources":["../src/stepper-exploratory.js"],"names":[],"mappings":"AAUA,4DAoKC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React, { useEffect } from 'react';
|
|
3
|
+
import { Stepper, Step, StepLabel, Button, Grid, Box, Typography } from '@material-ui/core';
|
|
4
|
+
import { ConfirmatoryCart } from './cart.js';
|
|
5
|
+
import { SelectStratification } from './select-stratification.js';
|
|
6
|
+
import { useStyles } from './styles.js';
|
|
7
|
+
const steps = [
|
|
8
|
+
'Define case-control stratification',
|
|
9
|
+
];
|
|
10
|
+
export function ExploratoryStepper(props) {
|
|
11
|
+
const { autocompleteNode, currentModalityAgnosticSelection, setCurrentModalityAgnosticSelection, currentModalitySpecificSelection, setCurrentModalitySpecificSelection, currentStratificationSelection, setCurrentStratificationSelection, getEdges, stratifications, onFinish, } = props;
|
|
12
|
+
const classes = useStyles();
|
|
13
|
+
const [activeStep, setActiveStep] = React.useState(0);
|
|
14
|
+
const [skipped, setSkipped] = React.useState(new Set());
|
|
15
|
+
const isStepOptional = step => step === 2;
|
|
16
|
+
const isStepSkipped = step => skipped.has(step);
|
|
17
|
+
const handleNext = () => {
|
|
18
|
+
let newSkipped = skipped;
|
|
19
|
+
if (isStepSkipped(activeStep)) {
|
|
20
|
+
newSkipped = new Set(newSkipped.values());
|
|
21
|
+
newSkipped.delete(activeStep);
|
|
22
|
+
}
|
|
23
|
+
setActiveStep(prevActiveStep => prevActiveStep + 1);
|
|
24
|
+
setSkipped(newSkipped);
|
|
25
|
+
};
|
|
26
|
+
const handleBack = () => {
|
|
27
|
+
setActiveStep(prevActiveStep => prevActiveStep - 1);
|
|
28
|
+
};
|
|
29
|
+
const handleSkip = () => {
|
|
30
|
+
if (!isStepOptional(activeStep)) {
|
|
31
|
+
// You probably want to guard against something like this,
|
|
32
|
+
// it should never occur unless someone's actively trying to break something.
|
|
33
|
+
throw new Error("You can't skip a step that isn't optional.");
|
|
34
|
+
}
|
|
35
|
+
setActiveStep(prevActiveStep => prevActiveStep + 1);
|
|
36
|
+
setSkipped((prevSkipped) => {
|
|
37
|
+
const newSkipped = new Set(prevSkipped.values());
|
|
38
|
+
newSkipped.add(activeStep);
|
|
39
|
+
return newSkipped;
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
const handleReset = () => {
|
|
43
|
+
setActiveStep(0);
|
|
44
|
+
};
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
if (activeStep === steps.length) {
|
|
47
|
+
onFinish();
|
|
48
|
+
}
|
|
49
|
+
}, [activeStep, steps]);
|
|
50
|
+
return (_jsxs(Grid, { item: true, container: true, xs: 12, children: [_jsx(Grid, { item: true, container: true, xs: 12, children: _jsx(Box, { className: classes.fullWidthBox, children: _jsx(Stepper, { activeStep: activeStep, children: steps.map((label, index) => {
|
|
51
|
+
const stepProps = {};
|
|
52
|
+
const labelProps = {};
|
|
53
|
+
if (isStepOptional(index)) {
|
|
54
|
+
labelProps.optional = (_jsx(Typography, { variant: "caption", children: "Optional" }));
|
|
55
|
+
}
|
|
56
|
+
if (isStepSkipped(index)) {
|
|
57
|
+
stepProps.completed = false;
|
|
58
|
+
}
|
|
59
|
+
return (_jsx(Step, { ...stepProps, children: _jsx(StepLabel, { ...labelProps, children: label }) }, label));
|
|
60
|
+
}) }) }) }), _jsxs(Grid, { item: true, container: true, xs: 12, style: { marginTop: '20px' }, alignItems: "flex-start", children: [_jsx(Grid, { item: true, container: true, xs: 8, children: activeStep === steps.length ? (_jsx(_Fragment, { children: _jsx(Typography, { style: { marginTop: '20px', marginBottom: '10px' }, children: "All steps completed - you're finished" }) })) : (_jsx(_Fragment, { children: activeStep === 0 ? (_jsx(SelectStratification, { autocompleteNode: autocompleteNode, currentModalityAgnosticSelection: currentModalityAgnosticSelection, setCurrentModalityAgnosticSelection: setCurrentModalityAgnosticSelection, currentModalitySpecificSelection: currentModalitySpecificSelection, setCurrentModalitySpecificSelection: setCurrentModalitySpecificSelection, currentStratificationSelection: currentStratificationSelection, setCurrentStratificationSelection: setCurrentStratificationSelection, getEdges: getEdges, stratifications: stratifications })) : null })) }), _jsx(Grid, { item: true, container: true, xs: 4, children: _jsx(ConfirmatoryCart, { currentModalityAgnosticSelection: currentModalityAgnosticSelection, setCurrentModalityAgnosticSelection: setCurrentModalityAgnosticSelection, currentModalitySpecificSelection: currentModalitySpecificSelection, setCurrentModalitySpecificSelection: setCurrentModalitySpecificSelection, currentStratificationSelection: currentStratificationSelection, setCurrentStratificationSelection: setCurrentStratificationSelection, stratifications: stratifications }) }), _jsx(Box, { className: classes.fullWidthBox, children: activeStep === steps.length ? (_jsx(_Fragment, { children: _jsxs(Box, { style: { display: 'flex', flexDirection: 'row', paddingTop: '20px' }, children: [_jsx(Box, { style: { flex: '1 1 auto' } }), _jsx(Button, { onClick: handleReset, children: "Reset" })] }) })) : (_jsxs(Box, { style: { display: 'flex', flexDirection: 'row', paddingTop: '20px' }, children: [_jsx(Button, { color: "inherit", disabled: activeStep === 0, onClick: handleBack, style: { mr: 1 }, children: "Back" }), _jsx(Box, { style: { flex: '1 1 auto' } }), isStepOptional(activeStep) && (_jsx(Button, { color: "inherit", onClick: handleSkip, style: { marginRight: '10px' }, children: "Skip" })), _jsx(Button, { onClick: handleNext, children: activeStep === steps.length - 1 ? 'Finish' : 'Next' })] })) })] })] }));
|
|
61
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vitessce/biomarker-select",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.8",
|
|
4
4
|
"author": "Gehlenborg Lab",
|
|
5
5
|
"homepage": "http://vitessce.io",
|
|
6
6
|
"repository": {
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
"react-window": "^1.8.10",
|
|
25
25
|
"fuse.js": "^7.0.0",
|
|
26
26
|
"d3-dsv": "^1.1.1",
|
|
27
|
-
"@vitessce/constants-internal": "3.5.
|
|
28
|
-
"@vitessce/vit-s": "3.5.
|
|
29
|
-
"@vitessce/types": "3.5.
|
|
27
|
+
"@vitessce/constants-internal": "3.5.8",
|
|
28
|
+
"@vitessce/vit-s": "3.5.8",
|
|
29
|
+
"@vitessce/types": "3.5.8"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@testing-library/jest-dom": "^5.16.4",
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
/* eslint-disable max-len */
|
|
2
2
|
/* eslint-disable no-unused-vars */
|
|
3
|
-
import React, { useState, useCallback } from 'react';
|
|
3
|
+
import React, { useState, useCallback, useMemo } from 'react';
|
|
4
4
|
import {
|
|
5
5
|
useAsyncFunction,
|
|
6
6
|
useViewConfigStoreApi,
|
|
7
7
|
useSetViewConfig,
|
|
8
8
|
useViewConfig,
|
|
9
9
|
useCoordination,
|
|
10
|
+
useLoaders,
|
|
11
|
+
useComparisonMetadata,
|
|
12
|
+
useMatchingLoader,
|
|
13
|
+
useColumnNameMapping,
|
|
10
14
|
} from '@vitessce/vit-s';
|
|
11
|
-
import { AsyncFunctionType, ViewType, COMPONENT_COORDINATION_TYPES } from '@vitessce/constants-internal';
|
|
15
|
+
import { AsyncFunctionType, ViewType, COMPONENT_COORDINATION_TYPES, DataType } from '@vitessce/constants-internal';
|
|
12
16
|
import { ScmdUi } from './scmd-ui.js';
|
|
13
17
|
|
|
14
|
-
|
|
15
18
|
/**
|
|
16
19
|
*
|
|
17
20
|
* @param {object} props
|
|
@@ -21,10 +24,15 @@ import { ScmdUi } from './scmd-ui.js';
|
|
|
21
24
|
export function BiomarkerSelectSubscriber(props) {
|
|
22
25
|
const {
|
|
23
26
|
coordinationScopes,
|
|
24
|
-
stratificationOptions,
|
|
27
|
+
stratificationOptions: stratificationOptionsProp, // TODO: Remove; Get from comparisonMetadata instead
|
|
25
28
|
} = props;
|
|
26
29
|
|
|
30
|
+
const loaders = useLoaders();
|
|
31
|
+
|
|
27
32
|
const [{
|
|
33
|
+
dataset,
|
|
34
|
+
obsType,
|
|
35
|
+
sampleType,
|
|
28
36
|
sampleSetSelection,
|
|
29
37
|
featureSelection,
|
|
30
38
|
}, {
|
|
@@ -40,6 +48,16 @@ export function BiomarkerSelectSubscriber(props) {
|
|
|
40
48
|
const setViewConfig = useSetViewConfig(viewConfigStoreApi);
|
|
41
49
|
|
|
42
50
|
|
|
51
|
+
// Need obsSets and sampleSets options to obtain mapping between
|
|
52
|
+
// group names and column names.
|
|
53
|
+
const obsSetsLoader = useMatchingLoader(
|
|
54
|
+
loaders, dataset, DataType.OBS_SETS, { obsType },
|
|
55
|
+
);
|
|
56
|
+
const sampleSetsLoader = useMatchingLoader(
|
|
57
|
+
loaders, dataset, DataType.SAMPLE_SETS, { sampleType },
|
|
58
|
+
);
|
|
59
|
+
const sampleSetsColumnNameMappingReversed = useColumnNameMapping(sampleSetsLoader, true);
|
|
60
|
+
|
|
43
61
|
// TODO: make isSelecting a coordination type plugin.
|
|
44
62
|
// TODO: use store hooks from @vitessce/vit-s to update the view config based on the selections.
|
|
45
63
|
const [isSelecting, setIsSelecting] = useState(true);
|
|
@@ -62,6 +80,43 @@ export function BiomarkerSelectSubscriber(props) {
|
|
|
62
80
|
[transformFeature],
|
|
63
81
|
);
|
|
64
82
|
|
|
83
|
+
const [{ comparisonMetadata }, cmpMetadataStatus, cmpMetadataUrls] = useComparisonMetadata(
|
|
84
|
+
loaders, dataset, false, {}, {}, { obsType, sampleType },
|
|
85
|
+
);
|
|
86
|
+
const stratificationOptions = useMemo(() => {
|
|
87
|
+
/*
|
|
88
|
+
return array of objects like {
|
|
89
|
+
stratificationId: 'aki-vs-hr',
|
|
90
|
+
name: 'Acute kidney injury (AKI) vs. Healthy reference',
|
|
91
|
+
stratificationType: 'sampleSet', // key changed from 'groupType'. value changed from 'clinical'
|
|
92
|
+
sampleSets: [
|
|
93
|
+
['Disease Type', 'AKI'],
|
|
94
|
+
['Disease Type', 'Reference'],
|
|
95
|
+
],
|
|
96
|
+
},
|
|
97
|
+
*/
|
|
98
|
+
if (comparisonMetadata?.sample_group_pairs) {
|
|
99
|
+
return comparisonMetadata.sample_group_pairs.map((sampleGroupPair) => {
|
|
100
|
+
const [sampleGroupCol, sampleGroupValues] = sampleGroupPair;
|
|
101
|
+
const [sampleGroupCtrl, sampleGroupCase] = sampleGroupValues;
|
|
102
|
+
const groupName = sampleSetsColumnNameMappingReversed?.[sampleGroupCol];
|
|
103
|
+
return {
|
|
104
|
+
stratificationId: `${sampleGroupCol}_${sampleGroupCtrl}-vs-${sampleGroupCase}`,
|
|
105
|
+
name: `${groupName}: ${sampleGroupCtrl} vs. ${sampleGroupCase}`,
|
|
106
|
+
stratificationType: 'sampleSet',
|
|
107
|
+
sampleSets: [
|
|
108
|
+
// With sampleSets coming from the comparison_metadata,
|
|
109
|
+
// need to use loader options from obsSets and sampleSets to get mapping
|
|
110
|
+
// from column name to group name.
|
|
111
|
+
[groupName, sampleGroupCtrl],
|
|
112
|
+
[groupName, sampleGroupCase],
|
|
113
|
+
],
|
|
114
|
+
};
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
}, [comparisonMetadata, sampleSetsColumnNameMappingReversed]);
|
|
119
|
+
|
|
65
120
|
return (
|
|
66
121
|
<>
|
|
67
122
|
{isSelecting ? (
|
|
@@ -80,20 +135,39 @@ export function BiomarkerSelectSubscriber(props) {
|
|
|
80
135
|
getEdges={getEdges}
|
|
81
136
|
stratifications={stratificationOptions}
|
|
82
137
|
onFinish={() => {
|
|
83
|
-
|
|
138
|
+
if (mode === 'exploratory') {
|
|
139
|
+
// mode is exploratory, configure accordingly.
|
|
140
|
+
|
|
141
|
+
// TODO
|
|
142
|
+
|
|
143
|
+
} else {
|
|
144
|
+
// mode is confirmatory, configure accordingly.
|
|
145
|
+
|
|
146
|
+
// TODO
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const newViewConfig = {
|
|
84
150
|
...viewConfig,
|
|
85
151
|
coordinationSpace: {
|
|
86
152
|
...viewConfig.coordinationSpace,
|
|
87
153
|
sampleSetFilter: {
|
|
88
154
|
...viewConfig.coordinationSpace.sampleSetFilter,
|
|
89
|
-
|
|
155
|
+
__comparison__: currentStratificationSelection?.sampleSets,
|
|
90
156
|
},
|
|
91
157
|
sampleSetSelection: {
|
|
92
158
|
...viewConfig.coordinationSpace.sampleSetSelection,
|
|
93
|
-
|
|
159
|
+
__comparison__: currentStratificationSelection?.sampleSets,
|
|
160
|
+
},
|
|
161
|
+
featureSelection: {
|
|
162
|
+
...viewConfig.coordinationSpace.featureSelection,
|
|
163
|
+
__comparison__: currentModalitySpecificSelection ? currentModalitySpecificSelection.map(d => d.label) : null,
|
|
94
164
|
},
|
|
95
165
|
},
|
|
96
|
-
}
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// TODO: can the normal coordination value setters be used instead?
|
|
169
|
+
// (e.g., setFeatureSelection, setSampleSetSelection)
|
|
170
|
+
setViewConfig(newViewConfig);
|
|
97
171
|
}}
|
|
98
172
|
/>
|
|
99
173
|
) : null}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
useCoordination,
|
|
4
|
+
} from '@vitessce/vit-s';
|
|
5
|
+
import { ViewType, COMPONENT_COORDINATION_TYPES } from '@vitessce/constants-internal';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
export function ComparativeHeadingSubscriber(props) {
|
|
9
|
+
const {
|
|
10
|
+
coordinationScopes,
|
|
11
|
+
} = props;
|
|
12
|
+
|
|
13
|
+
const [{
|
|
14
|
+
sampleSetSelection,
|
|
15
|
+
}] = useCoordination(
|
|
16
|
+
COMPONENT_COORDINATION_TYPES[ViewType.COMPARATIVE_HEADING],
|
|
17
|
+
coordinationScopes,
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<>
|
|
22
|
+
{sampleSetSelection && sampleSetSelection.length === 2 ? (
|
|
23
|
+
<div style={{ width: '100%', display: 'flex', flexDirection: 'row' }}>
|
|
24
|
+
<div style={{ width: '45%' }}><h2>{sampleSetSelection?.[0]?.at(-1)}</h2></div>
|
|
25
|
+
<div style={{ width: '5%' }}><h2 style={{ textAlign: 'right' }}>vs. </h2></div>
|
|
26
|
+
<div style={{ width: '50%' }}><h2>{sampleSetSelection?.[1]?.at(-1)}</h2></div>
|
|
27
|
+
</div>
|
|
28
|
+
) : null}
|
|
29
|
+
</>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -180,6 +180,7 @@ export async function transformFeature({ queryClient }, node, targetModality) {
|
|
|
180
180
|
queryFn: loadPathwayToGeneEdges,
|
|
181
181
|
});
|
|
182
182
|
|
|
183
|
+
// TODO: support matching using ontology term (rather than requiring kgId)?
|
|
183
184
|
const matchingEdges = pathwayGeneEdges.filter((/** @type {KgEdge} */ d) => d.source === node.kgId);
|
|
184
185
|
const matchingGeneIds = matchingEdges.map((/** @type {KgEdge} */ d) => d.target);
|
|
185
186
|
const matchingGenes = geneNodes.filter(d => matchingGeneIds.includes(d.kgId));
|
package/src/index.js
CHANGED
package/src/scmd-ui.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/* eslint-disable no-unused-vars */
|
|
2
2
|
import React, { useState } from 'react';
|
|
3
3
|
import { Button, ButtonGroup, Grid, Tooltip } from '@material-ui/core';
|
|
4
|
-
import { ConfirmatoryStepper } from './confirmatory
|
|
4
|
+
import { ConfirmatoryStepper } from './stepper-confirmatory.js';
|
|
5
|
+
import { ExploratoryStepper } from './stepper-exploratory.js';
|
|
5
6
|
import { useStyles } from './styles.js';
|
|
6
7
|
|
|
7
8
|
|
|
@@ -67,7 +68,22 @@ export function ScmdUi(props) {
|
|
|
67
68
|
onFinish={onFinish}
|
|
68
69
|
/>
|
|
69
70
|
) : null}
|
|
70
|
-
{mode === 'exploratory' ?
|
|
71
|
+
{mode === 'exploratory' ? (
|
|
72
|
+
<ExploratoryStepper
|
|
73
|
+
autocompleteNode={autocompleteNode}
|
|
74
|
+
|
|
75
|
+
currentModalityAgnosticSelection={currentModalityAgnosticSelection}
|
|
76
|
+
setCurrentModalityAgnosticSelection={setCurrentModalityAgnosticSelection}
|
|
77
|
+
currentModalitySpecificSelection={currentModalitySpecificSelection}
|
|
78
|
+
setCurrentModalitySpecificSelection={setCurrentModalitySpecificSelection}
|
|
79
|
+
currentStratificationSelection={currentStratificationSelection}
|
|
80
|
+
setCurrentStratificationSelection={setCurrentStratificationSelection}
|
|
81
|
+
|
|
82
|
+
getEdges={getEdges}
|
|
83
|
+
stratifications={stratifications}
|
|
84
|
+
onFinish={onFinish}
|
|
85
|
+
/>
|
|
86
|
+
) : null}
|
|
71
87
|
</div>
|
|
72
88
|
) : null}
|
|
73
89
|
</Grid>
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { Stepper, Step, StepLabel, Button, Grid, Box, Typography } from '@material-ui/core';
|
|
3
|
+
import { ConfirmatoryCart } from './cart.js';
|
|
4
|
+
import { SelectStratification } from './select-stratification.js';
|
|
5
|
+
import { useStyles } from './styles.js';
|
|
6
|
+
|
|
7
|
+
const steps = [
|
|
8
|
+
'Define case-control stratification',
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
export function ExploratoryStepper(props) {
|
|
12
|
+
const {
|
|
13
|
+
autocompleteNode,
|
|
14
|
+
|
|
15
|
+
currentModalityAgnosticSelection,
|
|
16
|
+
setCurrentModalityAgnosticSelection,
|
|
17
|
+
currentModalitySpecificSelection,
|
|
18
|
+
setCurrentModalitySpecificSelection,
|
|
19
|
+
currentStratificationSelection,
|
|
20
|
+
setCurrentStratificationSelection,
|
|
21
|
+
|
|
22
|
+
getEdges,
|
|
23
|
+
stratifications,
|
|
24
|
+
onFinish,
|
|
25
|
+
} = props;
|
|
26
|
+
const classes = useStyles();
|
|
27
|
+
const [activeStep, setActiveStep] = React.useState(0);
|
|
28
|
+
const [skipped, setSkipped] = React.useState(new Set());
|
|
29
|
+
|
|
30
|
+
const isStepOptional = step => step === 2;
|
|
31
|
+
|
|
32
|
+
const isStepSkipped = step => skipped.has(step);
|
|
33
|
+
|
|
34
|
+
const handleNext = () => {
|
|
35
|
+
let newSkipped = skipped;
|
|
36
|
+
if (isStepSkipped(activeStep)) {
|
|
37
|
+
newSkipped = new Set(newSkipped.values());
|
|
38
|
+
newSkipped.delete(activeStep);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
setActiveStep(prevActiveStep => prevActiveStep + 1);
|
|
42
|
+
setSkipped(newSkipped);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const handleBack = () => {
|
|
46
|
+
setActiveStep(prevActiveStep => prevActiveStep - 1);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const handleSkip = () => {
|
|
50
|
+
if (!isStepOptional(activeStep)) {
|
|
51
|
+
// You probably want to guard against something like this,
|
|
52
|
+
// it should never occur unless someone's actively trying to break something.
|
|
53
|
+
throw new Error("You can't skip a step that isn't optional.");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
setActiveStep(prevActiveStep => prevActiveStep + 1);
|
|
57
|
+
setSkipped((prevSkipped) => {
|
|
58
|
+
const newSkipped = new Set(prevSkipped.values());
|
|
59
|
+
newSkipped.add(activeStep);
|
|
60
|
+
return newSkipped;
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const handleReset = () => {
|
|
65
|
+
setActiveStep(0);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
if (activeStep === steps.length) {
|
|
70
|
+
onFinish();
|
|
71
|
+
}
|
|
72
|
+
}, [activeStep, steps]);
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<Grid item container xs={12}>
|
|
77
|
+
<Grid item container xs={12}>
|
|
78
|
+
<Box className={classes.fullWidthBox}>
|
|
79
|
+
<Stepper activeStep={activeStep}>
|
|
80
|
+
{steps.map((label, index) => {
|
|
81
|
+
const stepProps = {};
|
|
82
|
+
const labelProps = {};
|
|
83
|
+
if (isStepOptional(index)) {
|
|
84
|
+
labelProps.optional = (
|
|
85
|
+
<Typography variant="caption">Optional</Typography>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
if (isStepSkipped(index)) {
|
|
89
|
+
stepProps.completed = false;
|
|
90
|
+
}
|
|
91
|
+
return (
|
|
92
|
+
<Step key={label} {...stepProps}>
|
|
93
|
+
<StepLabel {...labelProps}>{label}</StepLabel>
|
|
94
|
+
</Step>
|
|
95
|
+
);
|
|
96
|
+
})}
|
|
97
|
+
</Stepper>
|
|
98
|
+
</Box>
|
|
99
|
+
</Grid>
|
|
100
|
+
<Grid item container xs={12} style={{ marginTop: '20px' }} alignItems="flex-start">
|
|
101
|
+
{/* Step contents to left of cart */}
|
|
102
|
+
<Grid item container xs={8}>
|
|
103
|
+
{activeStep === steps.length ? (
|
|
104
|
+
<>
|
|
105
|
+
<Typography style={{ marginTop: '20px', marginBottom: '10px' }}>
|
|
106
|
+
All steps completed - you're finished
|
|
107
|
+
</Typography>
|
|
108
|
+
</>
|
|
109
|
+
) : (
|
|
110
|
+
<>
|
|
111
|
+
{activeStep === 0 ? (
|
|
112
|
+
<SelectStratification
|
|
113
|
+
autocompleteNode={autocompleteNode}
|
|
114
|
+
|
|
115
|
+
currentModalityAgnosticSelection={currentModalityAgnosticSelection}
|
|
116
|
+
setCurrentModalityAgnosticSelection={setCurrentModalityAgnosticSelection}
|
|
117
|
+
currentModalitySpecificSelection={currentModalitySpecificSelection}
|
|
118
|
+
setCurrentModalitySpecificSelection={setCurrentModalitySpecificSelection}
|
|
119
|
+
currentStratificationSelection={currentStratificationSelection}
|
|
120
|
+
setCurrentStratificationSelection={setCurrentStratificationSelection}
|
|
121
|
+
|
|
122
|
+
getEdges={getEdges}
|
|
123
|
+
stratifications={stratifications}
|
|
124
|
+
/>
|
|
125
|
+
) : null}
|
|
126
|
+
</>
|
|
127
|
+
)}
|
|
128
|
+
</Grid>
|
|
129
|
+
{/* Cart */}
|
|
130
|
+
<Grid item container xs={4}>
|
|
131
|
+
<ConfirmatoryCart
|
|
132
|
+
currentModalityAgnosticSelection={currentModalityAgnosticSelection}
|
|
133
|
+
setCurrentModalityAgnosticSelection={setCurrentModalityAgnosticSelection}
|
|
134
|
+
currentModalitySpecificSelection={currentModalitySpecificSelection}
|
|
135
|
+
setCurrentModalitySpecificSelection={setCurrentModalitySpecificSelection}
|
|
136
|
+
currentStratificationSelection={currentStratificationSelection}
|
|
137
|
+
setCurrentStratificationSelection={setCurrentStratificationSelection}
|
|
138
|
+
stratifications={stratifications}
|
|
139
|
+
/>
|
|
140
|
+
</Grid>
|
|
141
|
+
{/* Step navigation button footer */}
|
|
142
|
+
<Box className={classes.fullWidthBox}>
|
|
143
|
+
{activeStep === steps.length ? (
|
|
144
|
+
<>
|
|
145
|
+
<Box style={{ display: 'flex', flexDirection: 'row', paddingTop: '20px' }}>
|
|
146
|
+
<Box style={{ flex: '1 1 auto' }} />
|
|
147
|
+
<Button onClick={handleReset}>Reset</Button>
|
|
148
|
+
</Box>
|
|
149
|
+
</>
|
|
150
|
+
) : (
|
|
151
|
+
<Box style={{ display: 'flex', flexDirection: 'row', paddingTop: '20px' }}>
|
|
152
|
+
<Button
|
|
153
|
+
color="inherit"
|
|
154
|
+
disabled={activeStep === 0}
|
|
155
|
+
onClick={handleBack}
|
|
156
|
+
style={{ mr: 1 }}
|
|
157
|
+
>
|
|
158
|
+
Back
|
|
159
|
+
</Button>
|
|
160
|
+
<Box style={{ flex: '1 1 auto' }} />
|
|
161
|
+
{isStepOptional(activeStep) && (
|
|
162
|
+
<Button color="inherit" onClick={handleSkip} style={{ marginRight: '10px' }}>
|
|
163
|
+
Skip
|
|
164
|
+
</Button>
|
|
165
|
+
)}
|
|
166
|
+
<Button onClick={handleNext}>
|
|
167
|
+
{activeStep === steps.length - 1 ? 'Finish' : 'Next'}
|
|
168
|
+
</Button>
|
|
169
|
+
</Box>
|
|
170
|
+
)}
|
|
171
|
+
</Box>
|
|
172
|
+
</Grid>
|
|
173
|
+
</Grid>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"confirmatory-stepper.d.ts","sourceRoot":"","sources":["../src/confirmatory-stepper.js"],"names":[],"mappings":"AAcA,6DAkMC"}
|
|
File without changes
|
|
File without changes
|