@vitessce/biomarker-select 3.5.7 → 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 +315 -13
- 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,11 +909,36 @@ 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",
|
|
918
|
+
NEUROGLANCER: "neuroglancer",
|
|
914
919
|
DUAL_SCATTERPLOT: "dualScatterplot",
|
|
915
920
|
TREEMAP: "treemap"
|
|
916
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"
|
|
941
|
+
};
|
|
917
942
|
const AsyncFunctionType = {
|
|
918
943
|
// String input (rather than Node input)
|
|
919
944
|
AUTOCOMPLETE_FEATURE: "autocompleteFeature",
|
|
@@ -1073,10 +1098,18 @@ const CoordinationType = {
|
|
|
1073
1098
|
EMBEDDING_CONTOUR_PERCENTILES: "embeddingContourPercentiles",
|
|
1074
1099
|
CONTOUR_COLOR_ENCODING: "contourColorEncoding",
|
|
1075
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",
|
|
1076
1106
|
// Treemap
|
|
1077
1107
|
HIERARCHY_LEVELS: "hierarchyLevels"
|
|
1078
1108
|
};
|
|
1079
1109
|
const COMPONENT_COORDINATION_TYPES = {
|
|
1110
|
+
[ViewType.NEUROGLANCER]: [
|
|
1111
|
+
CoordinationType.DATASET
|
|
1112
|
+
],
|
|
1080
1113
|
[ViewType.SCATTERPLOT]: [
|
|
1081
1114
|
CoordinationType.DATASET,
|
|
1082
1115
|
CoordinationType.OBS_TYPE,
|
|
@@ -1546,8 +1579,64 @@ const COMPONENT_COORDINATION_TYPES = {
|
|
|
1546
1579
|
CoordinationType.OBS_COLOR_ENCODING,
|
|
1547
1580
|
CoordinationType.ADDITIONAL_OBS_SETS
|
|
1548
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
|
+
],
|
|
1549
1635
|
[ViewType.LINK_CONTROLLER]: [],
|
|
1550
1636
|
[ViewType.BIOMARKER_SELECT]: [
|
|
1637
|
+
CoordinationType.DATASET,
|
|
1638
|
+
CoordinationType.OBS_TYPE,
|
|
1639
|
+
CoordinationType.SAMPLE_TYPE,
|
|
1551
1640
|
CoordinationType.FEATURE_SELECTION,
|
|
1552
1641
|
CoordinationType.SAMPLE_SET_SELECTION,
|
|
1553
1642
|
CoordinationType.SAMPLE_SET_FILTER,
|
|
@@ -1555,6 +1644,16 @@ const COMPONENT_COORDINATION_TYPES = {
|
|
|
1555
1644
|
CoordinationType.OBS_SET_FILTER
|
|
1556
1645
|
// TODO: create coordination types for internal state of the biomarker selection view?
|
|
1557
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
|
+
],
|
|
1558
1657
|
[ViewType.TREEMAP]: [
|
|
1559
1658
|
CoordinationType.DATASET,
|
|
1560
1659
|
CoordinationType.OBS_TYPE,
|
|
@@ -30769,7 +30868,7 @@ function SelectStratification(props) {
|
|
|
30769
30868
|
) })
|
|
30770
30869
|
] });
|
|
30771
30870
|
}
|
|
30772
|
-
const steps = [
|
|
30871
|
+
const steps$1 = [
|
|
30773
30872
|
"Select biomarkers (modality-agnostic)",
|
|
30774
30873
|
"Derive modality-specific biomarker signature",
|
|
30775
30874
|
"Define case-control stratification"
|
|
@@ -30819,12 +30918,12 @@ function ConfirmatoryStepper(props) {
|
|
|
30819
30918
|
setActiveStep(0);
|
|
30820
30919
|
};
|
|
30821
30920
|
useEffect(() => {
|
|
30822
|
-
if (activeStep === steps.length) {
|
|
30921
|
+
if (activeStep === steps$1.length) {
|
|
30823
30922
|
onFinish();
|
|
30824
30923
|
}
|
|
30825
|
-
}, [activeStep, steps]);
|
|
30924
|
+
}, [activeStep, steps$1]);
|
|
30826
30925
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Grid$1, { item: true, container: true, xs: 12, children: [
|
|
30827
|
-
/* @__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) => {
|
|
30828
30927
|
const stepProps = {};
|
|
30829
30928
|
const labelProps = {};
|
|
30830
30929
|
if (isStepOptional(index)) {
|
|
@@ -30836,7 +30935,7 @@ function ConfirmatoryStepper(props) {
|
|
|
30836
30935
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(Step$1, { ...stepProps, children: /* @__PURE__ */ jsxRuntimeExports.jsx(StepLabel$1, { ...labelProps, children: label }) }, label);
|
|
30837
30936
|
}) }) }) }),
|
|
30838
30937
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(Grid$1, { item: true, container: true, xs: 12, style: { marginTop: "20px" }, alignItems: "flex-start", children: [
|
|
30839
|
-
/* @__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: [
|
|
30840
30939
|
activeStep === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
30841
30940
|
SelectAgnostic,
|
|
30842
30941
|
{
|
|
@@ -30892,6 +30991,118 @@ function ConfirmatoryStepper(props) {
|
|
|
30892
30991
|
stratifications
|
|
30893
30992
|
}
|
|
30894
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
|
+
) }),
|
|
30895
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: [
|
|
30896
31107
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Box$1, { style: { flex: "1 1 auto" } }),
|
|
30897
31108
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Button$1, { onClick: handleReset, children: "Reset" })
|
|
@@ -30958,22 +31169,60 @@ function ScmdUi(props) {
|
|
|
30958
31169
|
onFinish
|
|
30959
31170
|
}
|
|
30960
31171
|
) : null,
|
|
30961
|
-
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
|
|
30962
31187
|
] }) : null
|
|
30963
31188
|
] });
|
|
30964
31189
|
}
|
|
30965
31190
|
function BiomarkerSelectSubscriber(props) {
|
|
30966
31191
|
const {
|
|
30967
31192
|
coordinationScopes,
|
|
30968
|
-
stratificationOptions
|
|
31193
|
+
stratificationOptions: stratificationOptionsProp
|
|
31194
|
+
// TODO: Remove; Get from comparisonMetadata instead
|
|
30969
31195
|
} = props;
|
|
30970
|
-
|
|
31196
|
+
const loaders = useLoaders();
|
|
31197
|
+
const [{
|
|
31198
|
+
dataset,
|
|
31199
|
+
obsType,
|
|
31200
|
+
sampleType,
|
|
31201
|
+
sampleSetSelection,
|
|
31202
|
+
featureSelection
|
|
31203
|
+
}, {
|
|
31204
|
+
setSampleSetSelection,
|
|
31205
|
+
setFeatureSelection
|
|
31206
|
+
}] = useCoordination(
|
|
30971
31207
|
COMPONENT_COORDINATION_TYPES[ViewType.BIOMARKER_SELECT],
|
|
30972
31208
|
coordinationScopes
|
|
30973
31209
|
);
|
|
30974
31210
|
const viewConfigStoreApi = useViewConfigStoreApi();
|
|
30975
31211
|
const viewConfig = useViewConfig();
|
|
30976
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);
|
|
30977
31226
|
const [isSelecting, setIsSelecting] = useState(true);
|
|
30978
31227
|
const [mode, setMode] = useState(null);
|
|
30979
31228
|
const [step, setStep] = useState(null);
|
|
@@ -30990,6 +31239,36 @@ function BiomarkerSelectSubscriber(props) {
|
|
|
30990
31239
|
async (node, targetModality) => transformFeature2(node, targetModality),
|
|
30991
31240
|
[transformFeature2]
|
|
30992
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]);
|
|
30993
31272
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: isSelecting ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
30994
31273
|
ScmdUi,
|
|
30995
31274
|
{
|
|
@@ -31007,24 +31286,46 @@ function BiomarkerSelectSubscriber(props) {
|
|
|
31007
31286
|
getEdges,
|
|
31008
31287
|
stratifications: stratificationOptions,
|
|
31009
31288
|
onFinish: () => {
|
|
31010
|
-
|
|
31289
|
+
const newViewConfig = {
|
|
31011
31290
|
...viewConfig,
|
|
31012
31291
|
coordinationSpace: {
|
|
31013
31292
|
...viewConfig.coordinationSpace,
|
|
31014
31293
|
sampleSetFilter: {
|
|
31015
31294
|
...viewConfig.coordinationSpace.sampleSetFilter,
|
|
31016
|
-
|
|
31295
|
+
__comparison__: currentStratificationSelection == null ? void 0 : currentStratificationSelection.sampleSets
|
|
31017
31296
|
},
|
|
31018
31297
|
sampleSetSelection: {
|
|
31019
31298
|
...viewConfig.coordinationSpace.sampleSetSelection,
|
|
31020
|
-
|
|
31299
|
+
__comparison__: currentStratificationSelection == null ? void 0 : currentStratificationSelection.sampleSets
|
|
31300
|
+
},
|
|
31301
|
+
featureSelection: {
|
|
31302
|
+
...viewConfig.coordinationSpace.featureSelection,
|
|
31303
|
+
__comparison__: currentModalitySpecificSelection ? currentModalitySpecificSelection.map((d) => d.label) : null
|
|
31021
31304
|
}
|
|
31022
31305
|
}
|
|
31023
|
-
}
|
|
31306
|
+
};
|
|
31307
|
+
setViewConfig(newViewConfig);
|
|
31024
31308
|
}
|
|
31025
31309
|
}
|
|
31026
31310
|
) : null });
|
|
31027
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
|
+
}
|
|
31028
31329
|
var EOL = {}, EOF = {}, QUOTE = 34, NEWLINE = 10, RETURN = 13;
|
|
31029
31330
|
function objectConverter(columns2) {
|
|
31030
31331
|
return new Function("d", "return {" + columns2.map(function(name, i) {
|
|
@@ -32223,6 +32524,7 @@ async function getTermMapping({ queryClient }, keyCuriePrefix, valCuriePrefix) {
|
|
|
32223
32524
|
}
|
|
32224
32525
|
export {
|
|
32225
32526
|
BiomarkerSelectSubscriber,
|
|
32527
|
+
ComparativeHeadingSubscriber,
|
|
32226
32528
|
autocompleteFeature,
|
|
32227
32529
|
getAlternativeTerms,
|
|
32228
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
|