@haniffalab/cherita-react 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/LICENSE +1 -1
  2. package/dist/{components → cjs/components}/full-page/FullPage.js +32 -22
  3. package/dist/{components → cjs/components}/full-page/FullPagePseudospatial.js +7 -6
  4. package/dist/{components → cjs/components}/obs-list/ObsItem.js +88 -77
  5. package/dist/{components → cjs/components}/obs-list/ObsList.js +133 -50
  6. package/dist/cjs/components/obs-list/ObsToolbar.js +24 -0
  7. package/dist/{components → cjs/components}/obsm-list/ObsmList.js +8 -5
  8. package/dist/{components → cjs/components}/offcanvas/index.js +24 -20
  9. package/dist/{components → cjs/components}/pseudospatial/Pseudospatial.js +10 -9
  10. package/dist/{components → cjs/components}/pseudospatial/PseudospatialToolbar.js +4 -3
  11. package/dist/{components → cjs/components}/scatterplot/Scatterplot.js +33 -24
  12. package/dist/{components → cjs/components}/scatterplot/SpatialControls.js +43 -42
  13. package/dist/cjs/components/scatterplot/Toolbox.js +62 -0
  14. package/dist/{components → cjs/components}/search-bar/SearchBar.js +24 -7
  15. package/dist/{components → cjs/components}/search-bar/SearchResults.js +13 -17
  16. package/dist/{components → cjs/components}/var-list/VarItem.js +38 -29
  17. package/dist/{components → cjs/components}/var-list/VarList.js +59 -31
  18. package/dist/{components → cjs/components}/var-list/VarListToolbar.js +18 -14
  19. package/dist/{components → cjs/components}/var-list/VarSet.js +24 -20
  20. package/dist/{components → cjs/components}/violin/Violin.js +4 -3
  21. package/dist/{constants → cjs/constants}/constants.js +6 -2
  22. package/dist/{context → cjs/context}/DatasetContext.js +12 -11
  23. package/dist/{context → cjs/context}/FilterContext.js +4 -3
  24. package/dist/{context → cjs/context}/ZarrDataContext.js +4 -3
  25. package/dist/{helpers → cjs/helpers}/color-helper.js +12 -11
  26. package/dist/{helpers → cjs/helpers}/map-helper.js +8 -7
  27. package/dist/{helpers → cjs/helpers}/zarr-helper.js +30 -38
  28. package/dist/{utils → cjs/utils}/Filter.js +1 -1
  29. package/dist/{utils → cjs/utils}/Histogram.js +12 -8
  30. package/dist/{utils → cjs/utils}/ImageViewer.js +6 -5
  31. package/dist/{utils → cjs/utils}/Legend.js +8 -7
  32. package/dist/{utils → cjs/utils}/LoadingIndicators.js +5 -4
  33. package/dist/cjs/utils/Skeleton.js +19 -0
  34. package/dist/{utils → cjs/utils}/VirtualizedList.js +10 -9
  35. package/dist/{utils → cjs/utils}/requests.js +37 -39
  36. package/dist/{utils → cjs/utils}/string.js +9 -4
  37. package/dist/{utils → cjs/utils}/zarrData.js +12 -4
  38. package/dist/css/cherita.css +147 -152
  39. package/dist/css/cherita.css.map +1 -1
  40. package/dist/esm/components/dotplot/Dotplot.js +135 -0
  41. package/dist/esm/components/dotplot/DotplotControls.js +148 -0
  42. package/dist/esm/components/full-page/FullPage.js +143 -0
  43. package/dist/esm/components/full-page/FullPagePseudospatial.js +151 -0
  44. package/dist/esm/components/heatmap/Heatmap.js +105 -0
  45. package/dist/esm/components/heatmap/HeatmapControls.js +23 -0
  46. package/dist/esm/components/matrixplot/Matrixplot.js +107 -0
  47. package/dist/esm/components/matrixplot/MatrixplotControls.js +38 -0
  48. package/dist/esm/components/obs-list/ObsItem.js +484 -0
  49. package/dist/esm/components/obs-list/ObsList.js +338 -0
  50. package/dist/esm/components/obs-list/ObsToolbar.js +17 -0
  51. package/dist/esm/components/obsm-list/ObsmList.js +75 -0
  52. package/dist/esm/components/offcanvas/index.js +67 -0
  53. package/dist/esm/components/pseudospatial/Pseudospatial.js +228 -0
  54. package/dist/esm/components/pseudospatial/PseudospatialToolbar.js +123 -0
  55. package/dist/esm/components/scatterplot/Scatterplot.js +394 -0
  56. package/dist/esm/components/scatterplot/ScatterplotControls.js +71 -0
  57. package/dist/esm/components/scatterplot/SpatialControls.js +140 -0
  58. package/dist/esm/components/scatterplot/Toolbox.js +55 -0
  59. package/dist/esm/components/search-bar/SearchBar.js +90 -0
  60. package/dist/esm/components/search-bar/SearchResults.js +139 -0
  61. package/dist/esm/components/var-list/VarItem.js +254 -0
  62. package/dist/esm/components/var-list/VarList.js +291 -0
  63. package/dist/esm/components/var-list/VarListToolbar.js +87 -0
  64. package/dist/esm/components/var-list/VarSet.js +194 -0
  65. package/dist/esm/components/violin/Violin.js +141 -0
  66. package/dist/esm/components/violin/ViolinControls.js +24 -0
  67. package/dist/esm/constants/colorscales.js +22 -0
  68. package/dist/esm/constants/constants.js +88 -0
  69. package/dist/esm/context/DatasetContext.js +571 -0
  70. package/dist/esm/context/FilterContext.js +48 -0
  71. package/dist/esm/context/ZarrDataContext.js +26 -0
  72. package/dist/esm/helpers/color-helper.js +66 -0
  73. package/dist/esm/helpers/map-helper.js +53 -0
  74. package/dist/esm/helpers/zarr-helper.js +111 -0
  75. package/dist/esm/index.js +22 -0
  76. package/dist/esm/utils/Filter.js +147 -0
  77. package/dist/esm/utils/Histogram.js +44 -0
  78. package/dist/esm/utils/ImageViewer.js +27 -0
  79. package/dist/esm/utils/Legend.js +58 -0
  80. package/dist/esm/utils/LoadingIndicators.js +22 -0
  81. package/dist/esm/utils/Skeleton.js +12 -0
  82. package/dist/esm/utils/VirtualizedList.js +55 -0
  83. package/dist/esm/utils/errors.js +47 -0
  84. package/dist/esm/utils/requests.js +102 -0
  85. package/dist/esm/utils/search.js +39 -0
  86. package/dist/esm/utils/string.js +59 -0
  87. package/dist/esm/utils/zarrData.js +102 -0
  88. package/package.json +19 -7
  89. package/scss/cherita.scss +19 -50
  90. package/scss/components/accordions.scss +32 -0
  91. package/scss/components/layouts.scss +2 -1
  92. package/scss/components/lists.scss +14 -0
  93. package/dist/components/obs-list/ObsToolbar.js +0 -64
  94. package/dist/components/scatterplot/Toolbox.js +0 -31
  95. /package/dist/{components → cjs/components}/dotplot/Dotplot.js +0 -0
  96. /package/dist/{components → cjs/components}/dotplot/DotplotControls.js +0 -0
  97. /package/dist/{components → cjs/components}/heatmap/Heatmap.js +0 -0
  98. /package/dist/{components → cjs/components}/heatmap/HeatmapControls.js +0 -0
  99. /package/dist/{components → cjs/components}/matrixplot/Matrixplot.js +0 -0
  100. /package/dist/{components → cjs/components}/matrixplot/MatrixplotControls.js +0 -0
  101. /package/dist/{components → cjs/components}/scatterplot/ScatterplotControls.js +0 -0
  102. /package/dist/{components → cjs/components}/violin/ViolinControls.js +0 -0
  103. /package/dist/{constants → cjs/constants}/colorscales.js +0 -0
  104. /package/dist/{index.js → cjs/index.js} +0 -0
  105. /package/dist/{utils → cjs/utils}/errors.js +0 -0
  106. /package/dist/{utils → cjs/utils}/search.js +0 -0
@@ -0,0 +1,141 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import { faCircleInfo } from "@fortawesome/free-solid-svg-icons";
3
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
4
+ import _ from "lodash";
5
+ import { Alert, OverlayTrigger, Tooltip } from "react-bootstrap";
6
+ import Plot from "react-plotly.js";
7
+ import { VIOLIN_MODES } from "../../constants/constants";
8
+ import { useDataset } from "../../context/DatasetContext";
9
+ import { useFilteredData } from "../../context/FilterContext";
10
+ import { LoadingSpinner } from "../../utils/LoadingIndicators";
11
+ import { useDebouncedFetch } from "../../utils/requests";
12
+ export function Violin(_ref) {
13
+ let {
14
+ mode = VIOLIN_MODES.MULTIKEY
15
+ } = _ref;
16
+ const ENDPOINT = "violin";
17
+ const dataset = useDataset();
18
+ const {
19
+ obsIndices,
20
+ isSliced
21
+ } = useFilteredData();
22
+ const [data, setData] = useState([]);
23
+ const [layout, setLayout] = useState({});
24
+ const [hasSelections, setHasSelections] = useState(false);
25
+ const [params, setParams] = useState({
26
+ url: dataset.url,
27
+ mode: mode,
28
+ scale: dataset.controls.scale.violinplot.value,
29
+ varNamesCol: dataset.varNamesCol,
30
+ ...{
31
+ [VIOLIN_MODES.MULTIKEY]: {
32
+ varKeys: dataset.selectedMultiVar.map(i => i.isSet ? {
33
+ name: i.name,
34
+ indices: i.vars.map(v => v.index)
35
+ } : i.index),
36
+ obsKeys: [] // @TODO: implement
37
+ },
38
+ [VIOLIN_MODES.GROUPBY]: {
39
+ varKey: dataset.selectedVar?.isSet ? {
40
+ name: dataset.selectedVar?.name,
41
+ indices: dataset.selectedVar?.vars.map(v => v.index)
42
+ } : dataset.selectedVar?.index,
43
+ obsCol: dataset.selectedObs,
44
+ obsValues: !dataset.selectedObs?.omit.length ? null : _.difference(_.values(dataset.selectedObs?.codes), dataset.selectedObs?.omit).map(c => dataset.selectedObs?.codesMap[c]),
45
+ obsIndices: isSliced ? [...(obsIndices || [])] : null
46
+ }
47
+ }[mode]
48
+ });
49
+ // @TODO: set default scale
50
+
51
+ useEffect(() => {
52
+ if (mode === VIOLIN_MODES.MULTIKEY) {
53
+ if (dataset.selectedMultiVar.length) {
54
+ setHasSelections(true);
55
+ } else {
56
+ setHasSelections(false);
57
+ }
58
+ setParams(p => {
59
+ return {
60
+ ...p,
61
+ url: dataset.url,
62
+ mode: mode,
63
+ varKeys: dataset.selectedMultiVar.map(i => i.isSet ? {
64
+ name: i.name,
65
+ indices: i.vars.map(v => v.index)
66
+ } : i.index),
67
+ scale: dataset.controls.scale.violinplot.value,
68
+ varNamesCol: dataset.varNamesCol
69
+ };
70
+ });
71
+ } else if (mode === VIOLIN_MODES.GROUPBY) {
72
+ if (dataset.selectedObs && dataset.selectedVar) {
73
+ setHasSelections(true);
74
+ } else {
75
+ setHasSelections(false);
76
+ }
77
+ setParams(p => {
78
+ return {
79
+ ...p,
80
+ url: dataset.url,
81
+ mode: mode,
82
+ varKey: dataset.selectedVar?.isSet ? {
83
+ name: dataset.selectedVar?.name,
84
+ indices: dataset.selectedVar?.vars.map(v => v.index)
85
+ } : dataset.selectedVar?.index,
86
+ obsCol: dataset.selectedObs,
87
+ obsValues: !dataset.selectedObs?.omit.length ? null : _.difference(_.values(dataset.selectedObs?.codes), dataset.selectedObs?.omit).map(c => dataset.selectedObs?.codesMap[c]),
88
+ obsIndices: isSliced ? [...(obsIndices || [])] : null,
89
+ scale: dataset.controls.scale.violinplot.value,
90
+ varNamesCol: dataset.varNamesCol
91
+ };
92
+ });
93
+ }
94
+ }, [dataset.controls.scale.violinplot.value, dataset.selectedMultiVar, dataset.selectedObs, dataset.selectedVar, dataset.url, dataset.varNamesCol, obsIndices, isSliced, mode]);
95
+ const {
96
+ fetchedData,
97
+ isPending,
98
+ serverError
99
+ } = useDebouncedFetch(ENDPOINT, params, 500, {
100
+ enabled: mode === VIOLIN_MODES.MULTIKEY && (!!params.varKeys.length || !!params.obsKeys.length) || mode === VIOLIN_MODES.GROUPBY && !!params.varKey && !!params.obsCol
101
+ });
102
+ useEffect(() => {
103
+ if (hasSelections && !isPending && !serverError) {
104
+ setData(fetchedData.data);
105
+ setLayout(fetchedData.layout);
106
+ }
107
+ }, [fetchedData, hasSelections, isPending, serverError]);
108
+ if (!serverError) {
109
+ if (hasSelections) {
110
+ return /*#__PURE__*/React.createElement("div", {
111
+ className: "cherita-violin position-relative"
112
+ }, isPending && /*#__PURE__*/React.createElement(LoadingSpinner, null), /*#__PURE__*/React.createElement(Plot, {
113
+ data: data,
114
+ layout: layout,
115
+ useResizeHandler: true,
116
+ style: {
117
+ maxWidth: "100%",
118
+ maxHeight: "100%"
119
+ }
120
+ }), fetchedData?.resampled && /*#__PURE__*/React.createElement(Alert, {
121
+ variant: "warning"
122
+ }, /*#__PURE__*/React.createElement("b", null, "Warning:"), " For performance reasons this plot was generated with resampled data. It will not be exactly the same as one produced with the entire dataset. \xA0", /*#__PURE__*/React.createElement(OverlayTrigger, {
123
+ placement: "top",
124
+ overlay: /*#__PURE__*/React.createElement(Tooltip, null, "Resampled to 100K values following a Monte Carlo style approach to help ensure resampled data is a good representation of the original dataset's distribution.")
125
+ }, /*#__PURE__*/React.createElement(FontAwesomeIcon, {
126
+ icon: faCircleInfo
127
+ }))));
128
+ }
129
+ return /*#__PURE__*/React.createElement("div", {
130
+ className: "cherita-violin"
131
+ }, mode === VIOLIN_MODES.MULTIKEY && /*#__PURE__*/React.createElement(Alert, {
132
+ variant: "light"
133
+ }, "Select features"), mode === VIOLIN_MODES.GROUPBY && /*#__PURE__*/React.createElement(Alert, {
134
+ variant: "light"
135
+ }, "Select categories and a feature"));
136
+ } else {
137
+ return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Alert, {
138
+ variant: "danger"
139
+ }, serverError.message));
140
+ }
141
+ }
@@ -0,0 +1,24 @@
1
+ import React from "react";
2
+ import _ from "lodash";
3
+ import { Dropdown, ButtonGroup, ButtonToolbar, InputGroup } from "react-bootstrap";
4
+ import { VIOLINPLOT_SCALES } from "../../constants/constants";
5
+ import { useDataset, useDatasetDispatch } from "../../context/DatasetContext";
6
+ export function ViolinControls() {
7
+ const dataset = useDataset();
8
+ const dispatch = useDatasetDispatch();
9
+ const scaleList = _.values(VIOLINPLOT_SCALES).map(scale => /*#__PURE__*/React.createElement(Dropdown.Item, {
10
+ key: scale.value,
11
+ active: dataset.controls.scale.violinplot === scale,
12
+ onClick: () => {
13
+ dispatch({
14
+ type: "set.controls.scale",
15
+ plot: "violinplot",
16
+ scale: scale
17
+ });
18
+ }
19
+ }, scale.name));
20
+ return /*#__PURE__*/React.createElement(ButtonToolbar, null, /*#__PURE__*/React.createElement(ButtonGroup, null, /*#__PURE__*/React.createElement(InputGroup, null, /*#__PURE__*/React.createElement(InputGroup.Text, null, "Scale"), /*#__PURE__*/React.createElement(Dropdown, null, /*#__PURE__*/React.createElement(Dropdown.Toggle, {
21
+ id: "dropdownStandardScale",
22
+ variant: "light"
23
+ }, dataset.controls.scale.violinplot.name), /*#__PURE__*/React.createElement(Dropdown.Menu, null, scaleList)))));
24
+ }
@@ -0,0 +1,22 @@
1
+ // From plotly https://github.com/plotly/plotly.js/blob/5bc25b490702e5ed61265207833dbd58e8ab27f1/src/components/colorscale/scales.js
2
+ export const COLORSCALES = {
3
+ Greys: ["#000000", "#ffffff"],
4
+ YlGnBu: ["#081d58", "#253494", "#225ea8", "#1d91c0", "#41b6c4", "#7fcdbb", "#c7e9b4", "#edf8d9", "#ffffd9"],
5
+ Greens: ["#00441b", "#006d2c", "#238b45", "#41ab5d", "#74c476", "#a1d9a5", "#c7e9c0", "#e5f5e0", "#f7fcf5"],
6
+ YlOrRd: ["#800026", "#bd0026", "#e31a1c", "#fc4e2a", "#fd8d3c", "#feb24c", "#fed976", "#ffed9f", "#ffffcc"],
7
+ Bluered: ["#0000ff", "#ff0000"],
8
+ RdBu: ["#050aac", "#6a89f7", "#bebebe", "#dcaa84", "#e6915a", "#b20a1c"],
9
+ Reds: ["#dcdcdc", "#f5c39d", "#f5a069", "#b20a1c"],
10
+ Blues: ["#050aac", "#283cba", "#4664f5", "#5a78f5", "#6a89f7", "#dcdcdc"],
11
+ Picnic: ["#0000ff", "#3399ff", "#66ccff", "#99ccff", "#ccccff", "#ffffff", "#ffccff", "#ff99ff", "#ff66cc", "#ff6666", "#ff0000"],
12
+ Rainbow: ["#96005a", "#0000c8", "#0019ff", "#0098ff", "#2cff96", "#97ff00", "#ffe600", "#ff6f00", "#ff0000"],
13
+ Portland: ["#0c3383", "#0a88ba", "#f2d338", "#f28f38", "#d91e1e"],
14
+ Jet: ["#000083", "#003caa", "#05ffff", "#ffff00", "#fa0000", "#800000"],
15
+ Hot: ["#000000", "#e60000", "#ffd200", "#ffffff"],
16
+ Blackbody: ["#000000", "#e60000", "#e6d200", "#ffffff", "#a0c8ff"],
17
+ Earth: ["#000082", "#00b4b4", "#28d228", "#e6e632", "#784614", "#ffffff"],
18
+ Electric: ["#000000", "#1e0064", "#780064", "#a05a00", "#e6c800", "#fffadc"],
19
+ Viridis: ["#440154", "#48186a", "#472d7b", "#424086", "#3b528b", "#33638d", "#2c728e", "#26828e", "#21918c", "#1fa088", "#28ae80", "#3fbc73", "#5ec962", "#84d44b", "#addc30", "#d8e219", "#fde725"],
20
+ Cividis: ["#00204c", "#002a66", "#00346e", "#273f6c", "#3c4a6c", "#4c556b", "#5b5f6d", "#686a70", "#757575", "#838178", "#929c78", "#a19676", "#b0a572", "#c0af6d", "#d1ba65", "#e1c75c", "#f3db4f", "#ffe945"],
21
+ Accent: ["#7fc97f", "#beaed4", "#fdc086", "#ffff99", "#386cb0", "#f0027f", "#bf5b17", "#666666"]
22
+ };
@@ -0,0 +1,88 @@
1
+ export const LOCAL_STORAGE_KEY = "CHERITA";
2
+ export const COLOR_ENCODINGS = {
3
+ VAR: "var",
4
+ OBS: "obs"
5
+ };
6
+ export const OBS_TYPES = {
7
+ CATEGORICAL: "categorical",
8
+ DISCRETE: "discrete",
9
+ CONTINUOUS: "continuous",
10
+ BOOLEAN: "boolean"
11
+ };
12
+ export const VAR_SORT = {
13
+ NONE: null,
14
+ NAME: "name",
15
+ MATRIX: "matrix"
16
+ };
17
+ export const VAR_SORT_ORDER = {
18
+ ASC: "asc",
19
+ DESC: "desc"
20
+ };
21
+ export const SELECTED_POLYGON_FILLCOLOR = [107, 170, 209, 255 / 2];
22
+ export const UNSELECTED_POLYGON_FILLCOLOR = [167, 191, 211, 255 / 3];
23
+ export const SELECTION_MODES = {
24
+ SINGLE: "single",
25
+ MULTIPLE: "multiple"
26
+ };
27
+ export const VIOLIN_MODES = {
28
+ MULTIKEY: "multikey",
29
+ GROUPBY: "groupby"
30
+ };
31
+ export const MATRIXPLOT_SCALES = {
32
+ NONE: {
33
+ value: null,
34
+ name: "None"
35
+ },
36
+ GROUP: {
37
+ value: "group",
38
+ name: "Group"
39
+ },
40
+ VAR: {
41
+ value: "var",
42
+ name: "Var"
43
+ }
44
+ };
45
+ export const DOTPLOT_SCALES = {
46
+ NONE: {
47
+ value: null,
48
+ name: "None"
49
+ },
50
+ GROUP: {
51
+ value: "group",
52
+ name: "Group"
53
+ },
54
+ VAR: {
55
+ value: "var",
56
+ name: "Var"
57
+ }
58
+ };
59
+ export const VIOLINPLOT_SCALES = {
60
+ WIDTH: {
61
+ value: "width",
62
+ name: "Width"
63
+ },
64
+ COUNT: {
65
+ value: "count",
66
+ name: "Count"
67
+ }
68
+ };
69
+ export const PSEUDOSPATIAL_PLOT_TYPES = {
70
+ GENE: "gene",
71
+ CATEGORICAL: "categorical",
72
+ CONTINUOUS: "continuous",
73
+ MASKS: "masks"
74
+ };
75
+ export const PSEUDOSPATIAL_CATEGORICAL_MODES = {
76
+ ACROSS: {
77
+ value: "across",
78
+ name: "% across sections"
79
+ },
80
+ WITHIN: {
81
+ value: "within",
82
+ name: "% within section"
83
+ }
84
+ };
85
+
86
+ // `default` cols to be shown out of accordion, at top of obslist
87
+ // default values from cellxgene schema
88
+ export const DEFAULT_OBS_GROUP = ["assay", "cell_type", "development_stage", "disease", "donor_id", "organism", "self_reported_ethnicity", "sex", "suspension_type", "tissue", "tissue_type"];