@haniffalab/cherita-react 1.5.0 → 2.0.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 (80) hide show
  1. package/dist/cjs/components/dotplot/Dotplot.js +24 -19
  2. package/dist/cjs/components/heatmap/Heatmap.js +24 -19
  3. package/dist/cjs/components/matrixplot/Matrixplot.js +24 -19
  4. package/dist/cjs/components/obs-list/ObsItem.js +2 -2
  5. package/dist/cjs/components/offcanvas/{index.js → OffCanvas.js} +34 -1
  6. package/dist/cjs/components/{full-page → plot}/PlotAlert.js +1 -1
  7. package/dist/cjs/components/scatterplot/Scatterplot.js +57 -32
  8. package/dist/cjs/components/scatterplot/ScatterplotControls.js +74 -28
  9. package/dist/cjs/components/scatterplot/SpatialControls.js +37 -24
  10. package/dist/cjs/components/search-bar/SearchBar.js +9 -4
  11. package/dist/cjs/components/search-bar/SearchInfo.js +68 -25
  12. package/dist/cjs/components/search-bar/SearchResults.js +56 -47
  13. package/dist/cjs/components/toolbar/Toolbar.js +47 -42
  14. package/dist/cjs/components/var-list/VarList.js +18 -12
  15. package/dist/cjs/components/var-list/VarSet.js +1 -1
  16. package/dist/cjs/components/violin/Violin.js +26 -21
  17. package/dist/cjs/context/DatasetContext.js +10 -2
  18. package/dist/cjs/context/SettingsContext.js +19 -5
  19. package/dist/cjs/helpers/zarr-helper.js +20 -6
  20. package/dist/cjs/index.js +16 -23
  21. package/dist/cjs/utils/Skeleton.js +38 -2
  22. package/dist/cjs/utils/Slider.js +61 -0
  23. package/dist/cjs/utils/VirtualizedTable.js +97 -0
  24. package/dist/cjs/utils/parquetData.js +60 -0
  25. package/dist/cjs/utils/useNCBIData.js +35 -0
  26. package/dist/cjs/utils/usePlotVisibility.js +21 -0
  27. package/dist/cjs/utils/zarrData.js +51 -2
  28. package/dist/cjs/{components/plot/Plot.js → views/ObservationFeature/EmbeddedPlot.js} +41 -37
  29. package/dist/cjs/{components/full-page/FullPage.js → views/ObservationFeature/StandardView.js} +40 -49
  30. package/dist/cjs/views/ObservationFeature/index.js +12 -0
  31. package/dist/cjs/views/PerturbationMap/EmbeddedPlot.js +56 -0
  32. package/dist/cjs/views/PerturbationMap/ObsExplorer.js +299 -0
  33. package/dist/cjs/{apps/perturbgen/PerturbGen.js → views/PerturbationMap/StandardView.js} +19 -27
  34. package/dist/cjs/views/PerturbationMap/index.js +12 -0
  35. package/dist/css/cherita.css +16 -7
  36. package/dist/css/cherita.css.map +1 -1
  37. package/dist/esm/components/dotplot/Dotplot.js +25 -20
  38. package/dist/esm/components/heatmap/Heatmap.js +25 -20
  39. package/dist/esm/components/matrixplot/Matrixplot.js +25 -20
  40. package/dist/esm/components/obs-list/ObsItem.js +2 -2
  41. package/dist/esm/components/offcanvas/{index.js → OffCanvas.js} +33 -1
  42. package/dist/esm/components/{full-page → plot}/PlotAlert.js +1 -1
  43. package/dist/esm/components/scatterplot/Scatterplot.js +57 -32
  44. package/dist/esm/components/scatterplot/ScatterplotControls.js +74 -28
  45. package/dist/esm/components/scatterplot/SpatialControls.js +37 -24
  46. package/dist/esm/components/search-bar/SearchBar.js +9 -4
  47. package/dist/esm/components/search-bar/SearchInfo.js +69 -26
  48. package/dist/esm/components/search-bar/SearchResults.js +56 -47
  49. package/dist/esm/components/toolbar/Toolbar.js +44 -39
  50. package/dist/esm/components/var-list/VarList.js +18 -12
  51. package/dist/esm/components/var-list/VarSet.js +1 -1
  52. package/dist/esm/components/violin/Violin.js +27 -22
  53. package/dist/esm/context/DatasetContext.js +10 -2
  54. package/dist/esm/context/SettingsContext.js +19 -5
  55. package/dist/esm/helpers/zarr-helper.js +19 -5
  56. package/dist/esm/index.js +4 -5
  57. package/dist/esm/utils/Skeleton.js +35 -1
  58. package/dist/esm/utils/Slider.js +54 -0
  59. package/dist/esm/utils/VirtualizedTable.js +89 -0
  60. package/dist/esm/utils/parquetData.js +51 -0
  61. package/dist/esm/utils/useNCBIData.js +28 -0
  62. package/dist/esm/utils/usePlotVisibility.js +14 -0
  63. package/dist/esm/utils/zarrData.js +48 -0
  64. package/dist/esm/{components/plot/Plot.js → views/ObservationFeature/EmbeddedPlot.js} +37 -33
  65. package/dist/esm/{components/full-page/FullPage.js → views/ObservationFeature/StandardView.js} +35 -44
  66. package/dist/esm/views/ObservationFeature/index.js +6 -0
  67. package/dist/esm/views/PerturbationMap/EmbeddedPlot.js +50 -0
  68. package/dist/esm/views/PerturbationMap/ObsExplorer.js +292 -0
  69. package/dist/esm/{apps/perturbgen/PerturbGen.js → views/PerturbationMap/StandardView.js} +15 -23
  70. package/dist/esm/views/PerturbationMap/index.js +6 -0
  71. package/package.json +8 -4
  72. package/scss/cherita.scss +1 -1
  73. package/scss/components/layouts.scss +0 -1
  74. package/scss/components/lists.scss +1 -1
  75. package/scss/components/plotly.scss +10 -1
  76. package/scss/components/plots.scss +7 -4
  77. package/dist/cjs/apps/perturbgen/ObsExplorer.js +0 -153
  78. package/dist/esm/apps/perturbgen/ObsExplorer.js +0 -147
  79. /package/dist/cjs/components/{full-page → plot}/PlotTypeSelector.js +0 -0
  80. /package/dist/esm/components/{full-page → plot}/PlotTypeSelector.js +0 -0
@@ -7,37 +7,36 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
7
7
  function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
8
8
  function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
9
9
  import { useEffect, useMemo, useState } from 'react';
10
- import { useMediaQuery } from '@mui/material';
11
10
  import { Card, Container, Modal } from 'react-bootstrap';
12
- import { BREAKPOINTS, PLOT_TYPES, SELECTION_MODES, VIOLIN_MODES } from '../../constants/constants';
11
+ import { Dotplot } from '../../components/dotplot/Dotplot';
12
+ import { DotplotControls } from '../../components/dotplot/DotplotControls';
13
+ import { Heatmap } from '../../components/heatmap/Heatmap';
14
+ import { HeatmapControls } from '../../components/heatmap/HeatmapControls';
15
+ import { Matrixplot } from '../../components/matrixplot/Matrixplot';
16
+ import { MatrixplotControls } from '../../components/matrixplot/MatrixplotControls';
17
+ import { ObsColsList } from '../../components/obs-list/ObsList';
18
+ import { OffcanvasControls, OffcanvasObs, OffcanvasObsm, OffcanvasVars } from '../../components/offcanvas/OffCanvas';
19
+ import { PlotTypeSelector } from '../../components/plot/PlotTypeSelector';
20
+ import { Pseudospatial } from '../../components/pseudospatial/Pseudospatial';
21
+ import { PseudospatialToolbar } from '../../components/pseudospatial/PseudospatialToolbar';
22
+ import { Scatterplot } from '../../components/scatterplot/Scatterplot';
23
+ import { ScatterplotControls } from '../../components/scatterplot/ScatterplotControls';
24
+ import { SearchBar } from '../../components/search-bar/SearchBar';
25
+ import { VarNamesList } from '../../components/var-list/VarList';
26
+ import { Violin } from '../../components/violin/Violin';
27
+ import { ViolinControls } from '../../components/violin/ViolinControls';
28
+ import { PLOT_TYPES, SELECTION_MODES, VIOLIN_MODES } from '../../constants/constants';
13
29
  import { DatasetProvider } from '../../context/DatasetContext';
14
- import { Dotplot } from '../dotplot/Dotplot';
15
- import { DotplotControls } from '../dotplot/DotplotControls';
16
- import { Heatmap } from '../heatmap/Heatmap';
17
- import { HeatmapControls } from '../heatmap/HeatmapControls';
18
- import { Matrixplot } from '../matrixplot/Matrixplot';
19
- import { MatrixplotControls } from '../matrixplot/MatrixplotControls';
20
- import { ObsColsList } from '../obs-list/ObsList';
21
- import { OffcanvasControls, OffcanvasObs, OffcanvasObsm, OffcanvasVars } from '../offcanvas';
22
- import { PlotTypeSelector } from './PlotTypeSelector';
23
- import { Pseudospatial } from '../pseudospatial/Pseudospatial';
24
- import { PseudospatialToolbar } from '../pseudospatial/PseudospatialToolbar';
25
- import { Scatterplot } from '../scatterplot/Scatterplot';
26
- import { ScatterplotControls } from '../scatterplot/ScatterplotControls';
27
- import { SearchBar } from '../search-bar/SearchBar';
28
- import { VarNamesList } from '../var-list/VarList';
29
- import { Violin } from '../violin/Violin';
30
- import { ViolinControls } from '../violin/ViolinControls';
31
30
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
32
- export function FullPage(_ref) {
31
+ export function StandardView(_ref) {
33
32
  let {
34
33
  searchDiseases = true,
35
34
  defaultPlotType = PLOT_TYPES.SCATTERPLOT
36
35
  } = _ref,
37
36
  props = _objectWithoutProperties(_ref, _excluded);
38
- const [showObs, setShowObs] = useState(false);
39
- const [showObsm, setShowObsm] = useState(false);
40
- const [showVars, setShowVars] = useState(false);
37
+ const [showCategories, setShowCategories] = useState(false);
38
+ const [showEmbeddings, setShowEmbeddings] = useState(false);
39
+ const [showSearch, setShowSearch] = useState(false);
41
40
  const [showControls, setShowControls] = useState(false);
42
41
  const [showModal, setShowModal] = useState(false);
43
42
  const [plotType, setPlotType] = useState(defaultPlotType || PLOT_TYPES.SCATTERPLOT);
@@ -49,10 +48,6 @@ export function FullPage(_ref) {
49
48
  useEffect(() => {
50
49
  setPlotType(defaultPlotType || PLOT_TYPES.SCATTERPLOT);
51
50
  }, [defaultPlotType]);
52
- const LgBreakpoint = useMediaQuery(BREAKPOINTS.LG);
53
- const XlBreakpoint = useMediaQuery(BREAKPOINTS.XL);
54
- const showObsBtn = LgBreakpoint;
55
- const showVarsBtn = XlBreakpoint;
56
51
  const {
57
52
  plotControls,
58
53
  varMode,
@@ -85,16 +80,14 @@ export function FullPage(_ref) {
85
80
  }
86
81
  }[plotType];
87
82
  const plot = useMemo(() => {
88
- const commonProps = {
89
- showObsBtn,
90
- showVarsBtn,
91
- showCtrlsBtn: true,
83
+ const commonProps = _objectSpread({
92
84
  plotType,
93
- setShowObs,
94
- setShowVars,
85
+ isFullscreen: true,
86
+ setShowCategories,
87
+ setShowSearch,
95
88
  setShowControls,
96
89
  setPlotType
97
- };
90
+ }, props);
98
91
  switch (plotType) {
99
92
  case PLOT_TYPES.DOTPLOT:
100
93
  return /*#__PURE__*/_jsx(Dotplot, _objectSpread({}, commonProps));
@@ -108,11 +101,9 @@ export function FullPage(_ref) {
108
101
  }, commonProps));
109
102
  case PLOT_TYPES.SCATTERPLOT:
110
103
  default:
111
- return /*#__PURE__*/_jsx(Scatterplot, _objectSpread(_objectSpread({}, commonProps), {}, {
112
- isFullscreen: true
113
- }));
104
+ return /*#__PURE__*/_jsx(Scatterplot, _objectSpread({}, commonProps));
114
105
  }
115
- }, [plotType, showObsBtn, showVarsBtn]);
106
+ }, [plotType]);
116
107
  return /*#__PURE__*/_jsx("div", {
117
108
  className: "cherita-app",
118
109
  children: /*#__PURE__*/_jsxs(DatasetProvider, _objectSpread(_objectSpread({}, props), {}, {
@@ -171,19 +162,19 @@ export function FullPage(_ref) {
171
162
  }), /*#__PURE__*/_jsx(Modal.Body, {})]
172
163
  }), /*#__PURE__*/_jsx(OffcanvasObs, _objectSpread(_objectSpread({}, props), {}, {
173
164
  showSelectedAsActive: showSelectedAsActive,
174
- show: showObs,
175
- handleClose: () => setShowObs(false)
165
+ show: showCategories,
166
+ handleClose: () => setShowCategories(false)
176
167
  })), /*#__PURE__*/_jsx(OffcanvasVars, {
177
- show: showVars,
178
- handleClose: () => setShowVars(false),
168
+ show: showSearch,
169
+ handleClose: () => setShowSearch(false),
179
170
  mode: varMode
180
171
  }), plotControls && /*#__PURE__*/_jsx(OffcanvasControls, {
181
172
  show: showControls,
182
173
  handleClose: () => setShowControls(false),
183
174
  Controls: plotControls
184
175
  }), /*#__PURE__*/_jsx(OffcanvasObsm, {
185
- show: showObsm,
186
- handleClose: () => setShowObsm(false)
176
+ show: showEmbeddings,
177
+ handleClose: () => setShowEmbeddings(false)
187
178
  }), /*#__PURE__*/_jsx(OffcanvasControls, {
188
179
  show: showPseudospatialControls,
189
180
  handleClose: () => setShowPseudospatialControls(false),
@@ -0,0 +1,6 @@
1
+ import { EmbeddedPlot } from './EmbeddedPlot';
2
+ import { StandardView } from './StandardView';
3
+ export const ObservationFeature = {
4
+ EmbeddedPlot,
5
+ StandardView
6
+ };
@@ -0,0 +1,50 @@
1
+ const _excluded = ["showCtrlsBtn"];
2
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
5
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
6
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
7
+ function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
8
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
9
+ import { useState } from 'react';
10
+ import { OffcanvasControls, OffcanvasObs, OffcanvasObsExplorer, OffcanvasObsm } from '../../components/offcanvas/OffCanvas';
11
+ import { Scatterplot } from '../../components/scatterplot/Scatterplot';
12
+ import { ScatterplotControls } from '../../components/scatterplot/ScatterplotControls';
13
+ import { DatasetProvider } from '../../context/DatasetContext';
14
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
15
+ export function EmbeddedPlot(_ref) {
16
+ let {
17
+ showCtrlsBtn = true
18
+ } = _ref,
19
+ props = _objectWithoutProperties(_ref, _excluded);
20
+ const [showCategories, setShowCategories] = useState(false);
21
+ const [showEmbeddings, setShowEmbeddings] = useState(false);
22
+ const [showSearch, setShowSearch] = useState(false);
23
+ const [showControls, setShowControls] = useState(false);
24
+ const commonProps = _objectSpread({
25
+ setShowCategories,
26
+ setShowSearch,
27
+ setShowControls
28
+ }, props);
29
+ return /*#__PURE__*/_jsxs(DatasetProvider, _objectSpread(_objectSpread({
30
+ canOverrideSettings: false
31
+ }, props), {}, {
32
+ children: [/*#__PURE__*/_jsx(Scatterplot, _objectSpread(_objectSpread({}, commonProps), {}, {
33
+ pointInteractionEnabled: true
34
+ })), /*#__PURE__*/_jsx(OffcanvasObs, _objectSpread(_objectSpread({}, props), {}, {
35
+ showSelectedAsActive: false,
36
+ show: showCategories,
37
+ handleClose: () => setShowCategories(false)
38
+ })), /*#__PURE__*/_jsx(OffcanvasObsExplorer, _objectSpread(_objectSpread({}, props), {}, {
39
+ show: showSearch,
40
+ handleClose: () => setShowSearch(false)
41
+ })), /*#__PURE__*/_jsx(OffcanvasControls, _objectSpread(_objectSpread({}, props), {}, {
42
+ show: showControls,
43
+ handleClose: () => setShowControls(false),
44
+ Controls: ScatterplotControls
45
+ })), /*#__PURE__*/_jsx(OffcanvasObsm, _objectSpread(_objectSpread({}, props), {}, {
46
+ show: showEmbeddings,
47
+ handleClose: () => setShowEmbeddings(false)
48
+ }))]
49
+ }));
50
+ }
@@ -0,0 +1,292 @@
1
+ import { useMemo, useState, useEffect, useCallback } from 'react';
2
+ import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
3
+ import OpenInFullIcon from '@mui/icons-material/OpenInFull';
4
+ import IconButton from '@mui/material/IconButton';
5
+ import Paper from '@mui/material/Paper';
6
+ import Table from '@mui/material/Table';
7
+ import TableBody from '@mui/material/TableBody';
8
+ import TableCell from '@mui/material/TableCell';
9
+ import TableContainer from '@mui/material/TableContainer';
10
+ import TableRow from '@mui/material/TableRow';
11
+ import Tooltip from '@mui/material/Tooltip';
12
+ import _ from 'lodash';
13
+ import { Alert, Modal } from 'react-bootstrap';
14
+ import { OBS_TYPES } from '../../constants/constants';
15
+ import { useDataset } from '../../context/DatasetContext';
16
+ import { useSettings } from '../../context/SettingsContext';
17
+ import { useParquet, useParquetQuery } from '../../utils/parquetData';
18
+ import { DataTableSkeleton } from '../../utils/Skeleton';
19
+ import { formatNumerical } from '../../utils/string';
20
+ import { useNCBIData } from '../../utils/useNCBIData';
21
+ import { VirtualizedTable } from '../../utils/VirtualizedTable';
22
+ import { useObsColsData } from '../../utils/zarrData';
23
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
24
+ const NCBIData = _ref => {
25
+ var _fetchedData$reports;
26
+ let {
27
+ symbol
28
+ } = _ref;
29
+ const {
30
+ fetchedData,
31
+ isPending,
32
+ serverError
33
+ } = useNCBIData({
34
+ symbol
35
+ });
36
+ const {
37
+ description
38
+ } = (fetchedData === null || fetchedData === void 0 || (_fetchedData$reports = fetchedData.reports) === null || _fetchedData$reports === void 0 || (_fetchedData$reports = _fetchedData$reports[0]) === null || _fetchedData$reports === void 0 || (_fetchedData$reports = _fetchedData$reports.gene) === null || _fetchedData$reports === void 0 || (_fetchedData$reports = _fetchedData$reports.summary) === null || _fetchedData$reports === void 0 ? void 0 : _fetchedData$reports[0]) || {};
39
+ if (!isPending && !serverError && description) {
40
+ return /*#__PURE__*/_jsxs(_Fragment, {
41
+ children: [/*#__PURE__*/_jsx("p", {
42
+ children: description
43
+ }), /*#__PURE__*/_jsxs("p", {
44
+ className: "text-muted small",
45
+ children: ["Data fetched from", ' ', /*#__PURE__*/_jsx("a", {
46
+ href: "https://www.ncbi.nlm.nih.gov/datasets/docs/v2/api/rest-api/",
47
+ target: "_blank",
48
+ rel: "noreferrer",
49
+ children: "NCBI API"
50
+ }), ' · ', /*#__PURE__*/_jsx("a", {
51
+ href: "https://www.ncbi.nlm.nih.gov/gene/?term=".concat(encodeURIComponent(symbol)),
52
+ target: "_blank",
53
+ rel: "noreferrer",
54
+ children: "Gene page"
55
+ })]
56
+ })]
57
+ });
58
+ }
59
+ return null;
60
+ };
61
+ const DataTable = _ref2 => {
62
+ let {
63
+ query: baseQuery,
64
+ pageSize = 100
65
+ } = _ref2;
66
+ const [offset, setOffset] = useState(0);
67
+ const [data, setData] = useState([]);
68
+ const [fields, setFields] = useState([]);
69
+ useEffect(() => {
70
+ setData([]);
71
+ setOffset(0);
72
+ }, [baseQuery]);
73
+ const query = useMemo(() => {
74
+ if (!baseQuery) return null;
75
+ return "\n ".concat(baseQuery, "\n LIMIT ").concat(pageSize, " OFFSET ").concat(offset, "\n ");
76
+ }, [baseQuery, offset, pageSize]);
77
+ const {
78
+ data: queryData,
79
+ isLoading,
80
+ error
81
+ } = useParquetQuery(query);
82
+ useEffect(() => {
83
+ if (queryData) {
84
+ var _queryData$schema;
85
+ const newData = queryData.toArray().map(row => row.toJSON());
86
+ setData(prevData => [...prevData, ...newData]);
87
+ setFields(((_queryData$schema = queryData.schema) === null || _queryData$schema === void 0 ? void 0 : _queryData$schema.fields) || []);
88
+ }
89
+ }, [queryData]);
90
+ const loadMore = useCallback(() => {
91
+ if (isLoading) return;
92
+ if (queryData && !queryData.numRows) return;
93
+ setOffset(prev => prev + pageSize);
94
+ }, [isLoading, pageSize, queryData]);
95
+ if (isLoading && offset === 0) {
96
+ return /*#__PURE__*/_jsx(DataTableSkeleton, {});
97
+ }
98
+ if (error) {
99
+ return /*#__PURE__*/_jsx(Alert, {
100
+ variant: "danger",
101
+ children: "Error loading data"
102
+ });
103
+ }
104
+ if (!data || data.length === 0) {
105
+ return null;
106
+ }
107
+ return /*#__PURE__*/_jsx(VirtualizedTable, {
108
+ fields: fields,
109
+ data: data,
110
+ loadMore: loadMore,
111
+ isLoading: isLoading
112
+ });
113
+ };
114
+ const ObsExplorerTable = _ref3 => {
115
+ let {
116
+ colsData
117
+ } = _ref3;
118
+ const {
119
+ selectedObsIndex
120
+ } = useSettings();
121
+ const {
122
+ obsExplorer = {}
123
+ } = useDataset();
124
+ const {
125
+ dataUrl,
126
+ dataFilterCols
127
+ } = obsExplorer;
128
+ const query = useMemo(() => {
129
+ if (!selectedObsIndex || !dataUrl || dataFilterCols && !colsData) return null;
130
+ const where = _.map(_.keys(dataFilterCols), colName => {
131
+ return "".concat(dataFilterCols[colName], "='").concat(colsData === null || colsData === void 0 ? void 0 : colsData[colName], "'");
132
+ }).join(' AND ');
133
+ return "\n SELECT *\n FROM read_parquet('".concat(dataUrl, "')\n ") + (where ? "WHERE ".concat(where) : '');
134
+ }, [selectedObsIndex, dataUrl, dataFilterCols, colsData]);
135
+ return /*#__PURE__*/_jsx(DataTable, {
136
+ query: query
137
+ });
138
+ };
139
+ export function ObsExplorer() {
140
+ const [showModal, setShowModal] = useState(false);
141
+ const {
142
+ selectedObsIndex
143
+ } = useSettings();
144
+ const {
145
+ obsExplorer = {}
146
+ } = useDataset();
147
+ useParquet(); // initialize duckdb instance
148
+
149
+ const {
150
+ obsCols,
151
+ data: colsData,
152
+ isPending,
153
+ serverError
154
+ } = useObsColsData(obsExplorer === null || obsExplorer === void 0 ? void 0 : obsExplorer.obsCols);
155
+ if (selectedObsIndex == null) {
156
+ return /*#__PURE__*/_jsx("div", {
157
+ className: "my-4 text-muted",
158
+ children: "Select a point in the scatterplot to view details about the gene perturbation."
159
+ });
160
+ }
161
+ if (isPending) {
162
+ return /*#__PURE__*/_jsx("div", {
163
+ className: "my-3",
164
+ children: "Loading..."
165
+ });
166
+ }
167
+ if (serverError) {
168
+ return /*#__PURE__*/_jsx("div", {
169
+ className: "my-3",
170
+ children: "Error loading data"
171
+ });
172
+ }
173
+ return /*#__PURE__*/_jsx("div", {
174
+ className: "mt-3 d-flex flex-column h-100",
175
+ children: /*#__PURE__*/_jsxs("div", {
176
+ className: "overflow-auto flex-grow-1 modern-scrollbars",
177
+ children: [/*#__PURE__*/_jsx("h2", {
178
+ className: "fw-bold mb-2",
179
+ children: /*#__PURE__*/_jsx(Tooltip, {
180
+ title: /*#__PURE__*/_jsx(_Fragment, {
181
+ children: "This panel shows metadata and predicted downstream effects for the selected gene perturbation across the atlas."
182
+ }),
183
+ placement: "right",
184
+ arrow: true,
185
+ children: /*#__PURE__*/_jsx("span", {
186
+ children: colsData === null || colsData === void 0 ? void 0 : colsData[obsExplorer.symbolCol]
187
+ })
188
+ })
189
+ }), /*#__PURE__*/_jsx(NCBIData, {
190
+ symbol: colsData === null || colsData === void 0 ? void 0 : colsData[obsExplorer.symbolCol]
191
+ }), /*#__PURE__*/_jsxs("div", {
192
+ className: "mb-0",
193
+ children: [/*#__PURE__*/_jsx("h5", {
194
+ className: "fw-bold mb-2",
195
+ children: /*#__PURE__*/_jsx(Tooltip, {
196
+ title: /*#__PURE__*/_jsx(_Fragment, {
197
+ children: "These values describe how the selected gene perturbation is annotated in the atlas, including lineage, biological context, and summary scores used in the perturbation landscape."
198
+ }),
199
+ placement: "right",
200
+ arrow: true,
201
+ children: /*#__PURE__*/_jsxs("span", {
202
+ children: ["Perturbation metadata ", /*#__PURE__*/_jsx(InfoOutlinedIcon, {
203
+ fontSize: "small"
204
+ })]
205
+ })
206
+ })
207
+ }), /*#__PURE__*/_jsx(TableContainer, {
208
+ component: Paper,
209
+ sx: {
210
+ borderRadius: 2,
211
+ marginBottom: 2,
212
+ border: 1,
213
+ borderColor: 'divider'
214
+ },
215
+ children: /*#__PURE__*/_jsx(Table, {
216
+ size: "small",
217
+ "aria-label": "perturbation metadata",
218
+ children: /*#__PURE__*/_jsx(TableBody, {
219
+ children: _.map(colsData, (value, colName) => {
220
+ const col = (obsCols === null || obsCols === void 0 ? void 0 : obsCols[colName]) || {};
221
+ let v;
222
+ if (col.type === OBS_TYPES.CONTINUOUS) {
223
+ v = formatNumerical(parseFloat(value));
224
+ } else if (col.type === OBS_TYPES.DISCRETE) {
225
+ v = value;
226
+ } else if (col.type === OBS_TYPES.BOOLEAN) {
227
+ var _col$codesMap;
228
+ v = ((_col$codesMap = col.codesMap) === null || _col$codesMap === void 0 ? void 0 : _col$codesMap[+value]) || value;
229
+ } else {
230
+ var _col$codesMap2;
231
+ v = ((_col$codesMap2 = col.codesMap) === null || _col$codesMap2 === void 0 ? void 0 : _col$codesMap2[value]) || value;
232
+ }
233
+ return /*#__PURE__*/_jsxs(TableRow, {
234
+ hover: true,
235
+ children: [/*#__PURE__*/_jsx(TableCell, {
236
+ scope: "row",
237
+ children: col.displayName || colName
238
+ }), /*#__PURE__*/_jsx(TableCell, {
239
+ children: v
240
+ })]
241
+ }, colName);
242
+ })
243
+ })
244
+ })
245
+ })]
246
+ }), (obsExplorer === null || obsExplorer === void 0 ? void 0 : obsExplorer.dataUrl) && /*#__PURE__*/_jsxs("div", {
247
+ className: "mb-3",
248
+ children: [/*#__PURE__*/_jsxs("h5", {
249
+ className: "fw-bold mb-2 d-flex align-items-center justify-content-between",
250
+ children: [/*#__PURE__*/_jsx(Tooltip, {
251
+ title: /*#__PURE__*/_jsx(_Fragment, {
252
+ children: "This table shows genes predicted to change expression in response to the selected perturbation. Results can be sorted and explored to identify affected pathways and regulatory programs."
253
+ }),
254
+ placement: "right",
255
+ arrow: true,
256
+ children: /*#__PURE__*/_jsxs("span", {
257
+ className: "d-i{' '} nline-flex align-items-center",
258
+ children: ["Predicted downstream effects", ' ', /*#__PURE__*/_jsx(InfoOutlinedIcon, {
259
+ fontSize: "small",
260
+ className: "ms-1"
261
+ })]
262
+ })
263
+ }), /*#__PURE__*/_jsx(IconButton, {
264
+ size: "small",
265
+ onClick: () => setShowModal(true),
266
+ "aria-label": "Expand full table",
267
+ children: /*#__PURE__*/_jsx(OpenInFullIcon, {
268
+ fontSize: "small"
269
+ })
270
+ })]
271
+ }), /*#__PURE__*/_jsx(ObsExplorerTable, {
272
+ colsData: colsData
273
+ })]
274
+ }), /*#__PURE__*/_jsxs(Modal, {
275
+ show: showModal,
276
+ onHide: () => setShowModal(false),
277
+ size: "xl",
278
+ scrollable: true,
279
+ children: [/*#__PURE__*/_jsx(Modal.Header, {
280
+ closeButton: true,
281
+ children: /*#__PURE__*/_jsx(Modal.Title, {
282
+ children: "Full downstream effects table"
283
+ })
284
+ }), /*#__PURE__*/_jsx(Modal.Body, {
285
+ children: /*#__PURE__*/_jsx(ObsExplorerTable, {
286
+ colsData: colsData
287
+ })
288
+ })]
289
+ })]
290
+ })
291
+ });
292
+ }
@@ -6,30 +6,25 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
6
6
  function _objectDestructuringEmpty(t) { if (null == t) throw new TypeError("Cannot destructure " + t); }
7
7
  function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
8
8
  import { useState } from 'react';
9
- import { useMediaQuery } from '@mui/material';
10
9
  import { Card, Container, Modal } from 'react-bootstrap';
11
10
  import { ObsExplorer } from './ObsExplorer';
12
11
  import { ObsColsList } from '../../components/obs-list/ObsList';
13
- import { OffcanvasControls, OffcanvasObs, OffcanvasObsm, OffcanvasVars } from '../../components/offcanvas';
12
+ import { OffcanvasControls, OffcanvasObs, OffcanvasObsm, OffcanvasObsExplorer } from '../../components/offcanvas/OffCanvas';
14
13
  import { PseudospatialToolbar } from '../../components/pseudospatial/PseudospatialToolbar';
15
14
  import { Scatterplot } from '../../components/scatterplot/Scatterplot';
16
15
  import { ScatterplotControls } from '../../components/scatterplot/ScatterplotControls';
17
16
  import { SearchBar } from '../../components/search-bar/SearchBar';
18
- import { BREAKPOINTS, SELECTION_MODES } from '../../constants/constants';
17
+ import { SELECTION_MODES } from '../../constants/constants';
19
18
  import { DatasetProvider } from '../../context/DatasetContext';
20
19
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
21
- export function PerturbGen(_ref) {
20
+ export function StandardView(_ref) {
22
21
  let props = _extends({}, (_objectDestructuringEmpty(_ref), _ref));
23
- const [showObs, setShowObs] = useState(false);
24
- const [showObsm, setShowObsm] = useState(false);
25
- const [showVars, setShowVars] = useState(false);
22
+ const [showCategories, setShowCategories] = useState(false);
23
+ const [showEmbeddings, setShowEmbeddings] = useState(false);
24
+ const [showObsExplorer, setShowObsExplorer] = useState(false);
26
25
  const [showControls, setShowControls] = useState(false);
27
26
  const [showModal, setShowModal] = useState(false);
28
27
  const [showPseudospatialControls, setShowPseudospatialControls] = useState(false);
29
- const LgBreakpoint = useMediaQuery(BREAKPOINTS.LG);
30
- const XlBreakpoint = useMediaQuery(BREAKPOINTS.XL);
31
- const showObsBtn = LgBreakpoint;
32
- const showVarsBtn = XlBreakpoint;
33
28
  return /*#__PURE__*/_jsx("div", {
34
29
  className: "cherita-app",
35
30
  children: /*#__PURE__*/_jsxs(DatasetProvider, _objectSpread(_objectSpread({}, props), {}, {
@@ -46,11 +41,8 @@ export function PerturbGen(_ref) {
46
41
  }), /*#__PURE__*/_jsx("div", {
47
42
  className: "cherita-app-canvas",
48
43
  children: /*#__PURE__*/_jsx(Scatterplot, {
49
- showObsBtn: showObsBtn,
50
- showVarsBtn: showVarsBtn,
51
- showCtrlsBtn: true,
52
- setShowObs: setShowObs,
53
- setShowVars: setShowVars,
44
+ setShowCategories: setShowCategories,
45
+ setShowSearch: setShowObsExplorer,
54
46
  setShowControls: setShowControls,
55
47
  isFullscreen: true,
56
48
  pointInteractionEnabled: true
@@ -81,21 +73,21 @@ export function PerturbGen(_ref) {
81
73
  closeButton: true
82
74
  }), /*#__PURE__*/_jsx(Modal.Body, {})]
83
75
  }), /*#__PURE__*/_jsx(OffcanvasObs, _objectSpread(_objectSpread({
84
- show: showObs,
85
- handleClose: () => setShowObs(false)
76
+ show: showCategories,
77
+ handleClose: () => setShowCategories(false)
86
78
  }, props), {}, {
87
79
  showSelectedAsActive: false
88
- })), /*#__PURE__*/_jsx(OffcanvasVars, {
89
- show: showVars,
90
- handleClose: () => setShowVars(false),
80
+ })), /*#__PURE__*/_jsx(OffcanvasObsExplorer, {
81
+ show: showObsExplorer,
82
+ handleClose: () => setShowObsExplorer(false),
91
83
  mode: SELECTION_MODES.SINGLE
92
84
  }), /*#__PURE__*/_jsx(OffcanvasControls, {
93
85
  show: showControls,
94
86
  handleClose: () => setShowControls(false),
95
87
  Controls: ScatterplotControls
96
88
  }), /*#__PURE__*/_jsx(OffcanvasObsm, {
97
- show: showObsm,
98
- handleClose: () => setShowObsm(false)
89
+ show: showEmbeddings,
90
+ handleClose: () => setShowEmbeddings(false)
99
91
  }), /*#__PURE__*/_jsx(OffcanvasControls, {
100
92
  show: showPseudospatialControls,
101
93
  handleClose: () => setShowPseudospatialControls(false),
@@ -0,0 +1,6 @@
1
+ import { EmbeddedPlot } from './EmbeddedPlot';
2
+ import { StandardView } from './StandardView';
3
+ export const PerturbationMap = {
4
+ EmbeddedPlot,
5
+ StandardView
6
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haniffalab/cherita-react",
3
- "version": "1.5.0",
3
+ "version": "2.0.0",
4
4
  "author": "Haniffa Lab",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -26,6 +26,7 @@
26
26
  "./dist/*.css": "./dist/css/*.css"
27
27
  },
28
28
  "dependencies": {
29
+ "@duckdb/duckdb-wasm": "^1.33.1-dev18.0",
29
30
  "@emotion/react": "^11.11.4",
30
31
  "@emotion/styled": "^11.11.5",
31
32
  "@fortawesome/fontawesome-svg-core": "^6.4.0",
@@ -42,10 +43,12 @@
42
43
  "@tanstack/react-virtual": "^3.7.0",
43
44
  "@turf/turf": "^7.0.0",
44
45
  "@uidotdev/usehooks": "^2.4.1",
45
- "@zarrita/ndarray": "^0.1.5",
46
+ "@zarrita/ndarray": "0.1.6",
46
47
  "bootstrap": "^5.3.3",
47
48
  "deck.gl": "8.8.27",
49
+ "isndarray": "^1.0.0",
48
50
  "jquery": "^3.7.1",
51
+ "ndarray": "^1.0.19",
49
52
  "ndarray-unpack": "^1.0.0",
50
53
  "nebula.gl": "^1.0.4",
51
54
  "numbro": "^2.5.0",
@@ -54,7 +57,8 @@
54
57
  "react-bootstrap": "^2.7.4",
55
58
  "react-plotly.js": "^2.6.0",
56
59
  "react-scripts": "^5.0.1",
57
- "zarrita": "^0.5.4"
60
+ "react-virtuoso": "^4.18.1",
61
+ "zarrita": "0.6.0"
58
62
  },
59
63
  "peerDependencies": {
60
64
  "react": "^18.2.0",
@@ -110,7 +114,7 @@
110
114
  "test": "jest",
111
115
  "test:ci": "jest --coverage --ci --no-watch",
112
116
  "lint:scss": "stylelint 'src/**/*.scss' --fix",
113
- "lint:js": "eslint 'src/**/*.js' --fix",
117
+ "lint:js": "eslint 'src/**/*.{js,jsx}' --fix",
114
118
  "lint": "npm run lint:scss && npm run lint:js",
115
119
  "start-demo": "npm run dev --prefix sites/demo",
116
120
  "reinstall": "rm -rf node_modules package-lock.json && npm install"
package/scss/cherita.scss CHANGED
@@ -440,7 +440,7 @@ input[type='checkbox'] {
440
440
  .cherita-search-modal {
441
441
  .form-control:focus {
442
442
  box-shadow: none;
443
- border: var(--bs-border-width) solid var(--bs-border-color);
443
+ border: var(--geeks-border-width) solid var(--geeks-input-border);
444
444
  }
445
445
  }
446
446
 
@@ -137,7 +137,6 @@
137
137
 
138
138
  .search-modal-info {
139
139
  overflow-y: auto;
140
- border-left: 1px solid #dee2e6;
141
140
  }
142
141
 
143
142
  .cherita-app-canvas {
@@ -1,6 +1,6 @@
1
1
  .list-group.cherita-list {
2
2
  .virtualized-list-wrapper {
3
- padding: 0 0.25rem 0.25rem;
3
+ padding-bottom: 0.25rem;
4
4
  }
5
5
 
6
6
  .list-group-item.unstyled {