gramene-search 2.37.0 → 2.38.1
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.css +25 -0
- package/dist/index.css.map +1 -1
- package/dist/index.js +279 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5236,16 +5236,17 @@ const $4b8473139e48e77e$export$705aff68da3ddba0 = [
|
|
|
5236
5236
|
// Paging mirrors exprViz's doFetchExprVizData: a recursive fetchPage(offset)
|
|
5237
5237
|
// with a request-id guard so a superseded fetch can never write stale rows.
|
|
5238
5238
|
//
|
|
5239
|
-
// The offered columns are deliberately limited to
|
|
5240
|
-
// Core identifiers
|
|
5241
|
-
// front. That keeps the column picker a pure
|
|
5242
|
-
// column is instant and never triggers a refetch.
|
|
5239
|
+
// The offered columns are deliberately limited to a few field-catalog groups —
|
|
5240
|
+
// Core identifiers, Expression attributes and MAKER transcript metrics — and
|
|
5241
|
+
// *all* of them are fetched up front. That keeps the column picker a pure
|
|
5242
|
+
// visibility control: toggling a column is instant and never triggers a refetch.
|
|
5243
5243
|
const $12feb7ca48271e17$var$PAGE_SIZE = 1000;
|
|
5244
5244
|
const $12feb7ca48271e17$var$MAX_GENES = 5000;
|
|
5245
5245
|
// The catalog groups whose fields the column picker offers.
|
|
5246
5246
|
const $12feb7ca48271e17$export$53e90de8d659db95 = [
|
|
5247
5247
|
'core',
|
|
5248
|
-
'exprattrs'
|
|
5248
|
+
'exprattrs',
|
|
5249
|
+
'MAKER'
|
|
5249
5250
|
];
|
|
5250
5251
|
// The 'core' group's fields (bundles/../fieldCatalog.overlay.json).
|
|
5251
5252
|
const $12feb7ca48271e17$export$9d77d82cc773e55e = [
|
|
@@ -5260,12 +5261,28 @@ const $12feb7ca48271e17$export$9d77d82cc773e55e = [
|
|
|
5260
5261
|
'taxon_id',
|
|
5261
5262
|
'db_type'
|
|
5262
5263
|
];
|
|
5264
|
+
// The 'MAKER' group's fields: MAKER's annotation quality metrics (AED and the
|
|
5265
|
+
// quality index QI1-QI9). Only some releases have them (e.g. SorghumBase); Solr
|
|
5266
|
+
// returns nothing for them elsewhere, and the picker then hides the empty group.
|
|
5267
|
+
const $12feb7ca48271e17$export$3ae897f4a2495276 = [
|
|
5268
|
+
'MAKER__AED__attr_f',
|
|
5269
|
+
'MAKER__QI1__attr_i',
|
|
5270
|
+
'MAKER__QI2__attr_f',
|
|
5271
|
+
'MAKER__QI3__attr_f',
|
|
5272
|
+
'MAKER__QI4__attr_f',
|
|
5273
|
+
'MAKER__QI5__attr_f',
|
|
5274
|
+
'MAKER__QI6__attr_f',
|
|
5275
|
+
'MAKER__QI7__attr_i',
|
|
5276
|
+
'MAKER__QI8__attr_i',
|
|
5277
|
+
'MAKER__QI9__attr_i'
|
|
5278
|
+
];
|
|
5263
5279
|
// Always fetched, so visibility toggles never need the network. taxon_id is
|
|
5264
5280
|
// needed by the genome filter even when its column is hidden.
|
|
5265
5281
|
const $12feb7ca48271e17$var$FETCH_FIELDS = [
|
|
5266
5282
|
...new Set([
|
|
5267
5283
|
...$12feb7ca48271e17$export$9d77d82cc773e55e,
|
|
5268
|
-
...(0, $4b8473139e48e77e$export$705aff68da3ddba0)
|
|
5284
|
+
...(0, $4b8473139e48e77e$export$705aff68da3ddba0),
|
|
5285
|
+
...$12feb7ca48271e17$export$3ae897f4a2495276
|
|
5269
5286
|
])
|
|
5270
5287
|
];
|
|
5271
5288
|
// Default columns, in display order. The two stress fields are adjacent so the
|
|
@@ -13316,6 +13333,7 @@ function $76e15aea9236bd47$var$findRoots(tax) {
|
|
|
13316
13333
|
}
|
|
13317
13334
|
// Post-order: attach .leafIds (taxon_ids of maps in subtree) and .isLeaf
|
|
13318
13335
|
function $76e15aea9236bd47$var$annotate(node, tax, maps) {
|
|
13336
|
+
maps = maps || {};
|
|
13319
13337
|
const leafIds = [];
|
|
13320
13338
|
if (maps[node._id]) {
|
|
13321
13339
|
node.isLeaf = true;
|
|
@@ -13329,9 +13347,20 @@ function $76e15aea9236bd47$var$annotate(node, tax, maps) {
|
|
|
13329
13347
|
});
|
|
13330
13348
|
node.leafIds = leafIds;
|
|
13331
13349
|
}
|
|
13350
|
+
// The taxonomy's root nodes, annotated with the genomes (maps) under them. The
|
|
13351
|
+
// modal is mounted with the search status, so the taxonomy and the maps can
|
|
13352
|
+
// arrive in either order: missing maps count as no genomes, and the roots are
|
|
13353
|
+
// rebuilt when either changes.
|
|
13354
|
+
function $76e15aea9236bd47$var$buildRoots({ grameneMaps: grameneMaps, grameneTaxonomy: grameneTaxonomy }) {
|
|
13355
|
+
if (!grameneTaxonomy) return [];
|
|
13356
|
+
const roots = $76e15aea9236bd47$var$findRoots(grameneTaxonomy);
|
|
13357
|
+
roots.forEach((r)=>$76e15aea9236bd47$var$annotate(r, grameneTaxonomy, grameneMaps || {}));
|
|
13358
|
+
return roots;
|
|
13359
|
+
}
|
|
13332
13360
|
// Walk down the spine through single-child internals until a branch point,
|
|
13333
13361
|
// leaf, or node that is itself a genome.
|
|
13334
13362
|
function $76e15aea9236bd47$var$compressChain(node, tax, maps) {
|
|
13363
|
+
maps = maps || {};
|
|
13335
13364
|
const chain = [
|
|
13336
13365
|
node
|
|
13337
13366
|
];
|
|
@@ -13483,17 +13512,11 @@ function $76e15aea9236bd47$var$computeOpenState(props) {
|
|
|
13483
13512
|
class $76e15aea9236bd47$var$TaxonomyModal extends (0, ($parcel$interopDefault($gXNCa$react))).Component {
|
|
13484
13513
|
constructor(props){
|
|
13485
13514
|
super(props);
|
|
13486
|
-
const { grameneMaps: grameneMaps, grameneTaxonomy: grameneTaxonomy } = props;
|
|
13487
|
-
let roots = [];
|
|
13488
|
-
if (grameneTaxonomy) {
|
|
13489
|
-
roots = $76e15aea9236bd47$var$findRoots(grameneTaxonomy);
|
|
13490
|
-
roots.forEach((r)=>$76e15aea9236bd47$var$annotate(r, grameneTaxonomy, grameneMaps));
|
|
13491
|
-
}
|
|
13492
13515
|
const { selected: selected, expanded: expanded } = $76e15aea9236bd47$var$computeOpenState(props);
|
|
13493
13516
|
this.state = {
|
|
13494
13517
|
selected: selected,
|
|
13495
13518
|
expanded: expanded,
|
|
13496
|
-
roots:
|
|
13519
|
+
roots: $76e15aea9236bd47$var$buildRoots(props),
|
|
13497
13520
|
query: '',
|
|
13498
13521
|
highlightId: null,
|
|
13499
13522
|
activeIdx: 0
|
|
@@ -13538,6 +13561,16 @@ class $76e15aea9236bd47$var$TaxonomyModal extends (0, ($parcel$interopDefault($g
|
|
|
13538
13561
|
}
|
|
13539
13562
|
}
|
|
13540
13563
|
componentDidUpdate(prevProps, prevState) {
|
|
13564
|
+
// Maps or taxonomy arrived (or changed): rebuild the tree and reseed the
|
|
13565
|
+
// selection, which was empty if the modal mounted before the maps loaded.
|
|
13566
|
+
if (prevProps.grameneMaps !== this.props.grameneMaps || prevProps.grameneTaxonomy !== this.props.grameneTaxonomy) {
|
|
13567
|
+
const { selected: selected, expanded: expanded } = $76e15aea9236bd47$var$computeOpenState(this.props);
|
|
13568
|
+
this.setState({
|
|
13569
|
+
roots: $76e15aea9236bd47$var$buildRoots(this.props),
|
|
13570
|
+
selected: selected,
|
|
13571
|
+
expanded: expanded
|
|
13572
|
+
});
|
|
13573
|
+
}
|
|
13541
13574
|
// On each hidden→shown transition, reseed selection from current active
|
|
13542
13575
|
// genomes and expand every ancestor so selected taxa are visible.
|
|
13543
13576
|
const wasShown = prevProps.grameneGenomes && prevProps.grameneGenomes.show;
|
|
@@ -13609,7 +13642,7 @@ class $76e15aea9236bd47$var$TaxonomyModal extends (0, ($parcel$interopDefault($g
|
|
|
13609
13642
|
}
|
|
13610
13643
|
selectAll() {
|
|
13611
13644
|
const s = new Set();
|
|
13612
|
-
Object.values(this.props.grameneMaps).forEach((m)=>{
|
|
13645
|
+
Object.values(this.props.grameneMaps || {}).forEach((m)=>{
|
|
13613
13646
|
if (!m.hidden) s.add(m.taxon_id);
|
|
13614
13647
|
});
|
|
13615
13648
|
this.setState({
|
|
@@ -13626,7 +13659,7 @@ class $76e15aea9236bd47$var$TaxonomyModal extends (0, ($parcel$interopDefault($g
|
|
|
13626
13659
|
this.state.selected.forEach((id)=>{
|
|
13627
13660
|
active[id] = true;
|
|
13628
13661
|
});
|
|
13629
|
-
if (Object.keys(active).length === 0) Object.values(this.props.grameneMaps).forEach((m)=>{
|
|
13662
|
+
if (Object.keys(active).length === 0) Object.values(this.props.grameneMaps || {}).forEach((m)=>{
|
|
13630
13663
|
if (!m.hidden) active[m.taxon_id] = true;
|
|
13631
13664
|
});
|
|
13632
13665
|
this.props.doUpdateGrameneGenomes(active);
|
|
@@ -13644,7 +13677,7 @@ class $76e15aea9236bd47$var$TaxonomyModal extends (0, ($parcel$interopDefault($g
|
|
|
13644
13677
|
const someOn = selCount > 0 && !allOn;
|
|
13645
13678
|
const visibleKids = (terminal.children || []).map((cid)=>grameneTaxonomy[cid]).filter((c)=>c && c.leafIds.length > 0);
|
|
13646
13679
|
const hasKids = visibleKids.length > 0;
|
|
13647
|
-
const terminalIsGenome = !!grameneMaps[terminal._id];
|
|
13680
|
+
const terminalIsGenome = !!(grameneMaps && grameneMaps[terminal._id]);
|
|
13648
13681
|
const isOpen = expanded.has(terminal._id);
|
|
13649
13682
|
// Deepest clade colour in the chain wins; falls back to inherited.
|
|
13650
13683
|
const color = chain.reduce((acc, n)=>$76e15aea9236bd47$var$CLADE_COLORS[n.name] || acc, inheritedColor);
|
|
@@ -18705,6 +18738,84 @@ const $8f8e530286a37ce9$var$WIDTHS = {
|
|
|
18705
18738
|
expr_enhanced_in__attr_ss: 150,
|
|
18706
18739
|
expr_high_in__attr_ss: 150
|
|
18707
18740
|
};
|
|
18741
|
+
// MAKER annotation metrics: AED and the QI fractions are 0-1 (2 decimals); the
|
|
18742
|
+
// other QIs are lengths or counts (integers).
|
|
18743
|
+
const $8f8e530286a37ce9$var$MAKER_SET = new Set((0, $12feb7ca48271e17$export$3ae897f4a2495276));
|
|
18744
|
+
const $8f8e530286a37ce9$var$fmtMaker = (f, v)=>{
|
|
18745
|
+
if (v == null || v === '' || !Number.isFinite(+v)) return '';
|
|
18746
|
+
return f.endsWith('__attr_f') ? (+v).toFixed(2) : String(Math.round(+v));
|
|
18747
|
+
};
|
|
18748
|
+
const $8f8e530286a37ce9$var$makerShortName = (f)=>f.replace(/^MAKER__/, '').replace(/__attr_[a-z]$/, '');
|
|
18749
|
+
// AED gets an explanation; the QIs their catalog label, e.g. "QI1: Length of the 5' UTR".
|
|
18750
|
+
const $8f8e530286a37ce9$var$makerTooltip = (f, label)=>f === 'MAKER__AED__attr_f' ? 'MAKER Annotation Edit Distance: 0 = fully supported by evidence, 1 = no support' : label;
|
|
18751
|
+
// Summary-statistics rows, pinned above the genes. The header row collapses the
|
|
18752
|
+
// rest; stats cover every loaded gene, for each visible column whose values are
|
|
18753
|
+
// all numbers (taxon_id is an identifier, not a measurement).
|
|
18754
|
+
const $8f8e530286a37ce9$var$STAT_ROWS = [
|
|
18755
|
+
{
|
|
18756
|
+
key: 'n',
|
|
18757
|
+
label: 'N'
|
|
18758
|
+
},
|
|
18759
|
+
{
|
|
18760
|
+
key: 'min',
|
|
18761
|
+
label: 'Min'
|
|
18762
|
+
},
|
|
18763
|
+
{
|
|
18764
|
+
key: 'max',
|
|
18765
|
+
label: 'Max'
|
|
18766
|
+
},
|
|
18767
|
+
{
|
|
18768
|
+
key: 'median',
|
|
18769
|
+
label: 'Median'
|
|
18770
|
+
},
|
|
18771
|
+
{
|
|
18772
|
+
key: 'mean',
|
|
18773
|
+
label: 'Mean'
|
|
18774
|
+
},
|
|
18775
|
+
{
|
|
18776
|
+
key: 'sd',
|
|
18777
|
+
label: 'Std dev'
|
|
18778
|
+
}
|
|
18779
|
+
];
|
|
18780
|
+
const $8f8e530286a37ce9$var$NOT_MEASUREMENTS = new Set([
|
|
18781
|
+
'taxon_id'
|
|
18782
|
+
]);
|
|
18783
|
+
const $8f8e530286a37ce9$var$numericFieldsOf = (rows, fields)=>fields.filter((f)=>{
|
|
18784
|
+
if ($8f8e530286a37ce9$var$NOT_MEASUREMENTS.has(f)) return false;
|
|
18785
|
+
let numbers = 0;
|
|
18786
|
+
for (const r of rows){
|
|
18787
|
+
const v = r[f];
|
|
18788
|
+
if (v == null || v === '') continue;
|
|
18789
|
+
if (typeof v !== 'number' || !Number.isFinite(v)) return false;
|
|
18790
|
+
numbers++;
|
|
18791
|
+
}
|
|
18792
|
+
return numbers > 0;
|
|
18793
|
+
});
|
|
18794
|
+
const $8f8e530286a37ce9$var$statsOf = (values)=>{
|
|
18795
|
+
const n = values.length;
|
|
18796
|
+
if (!n) return {
|
|
18797
|
+
n: 0
|
|
18798
|
+
};
|
|
18799
|
+
const sorted = values.slice().sort((a, b)=>a - b);
|
|
18800
|
+
const mean = values.reduce((a, b)=>a + b, 0) / n;
|
|
18801
|
+
const median = n % 2 ? sorted[(n - 1) / 2] : (sorted[n / 2 - 1] + sorted[n / 2]) / 2;
|
|
18802
|
+
const sd = n > 1 ? Math.sqrt(values.reduce((a, v)=>a + (v - mean) * (v - mean), 0) / (n - 1)) : null;
|
|
18803
|
+
return {
|
|
18804
|
+
n: n,
|
|
18805
|
+
min: sorted[0],
|
|
18806
|
+
max: sorted[n - 1],
|
|
18807
|
+
median: median,
|
|
18808
|
+
mean: mean,
|
|
18809
|
+
sd: sd
|
|
18810
|
+
};
|
|
18811
|
+
};
|
|
18812
|
+
// Mean and std dev of a whole-number column still need decimals.
|
|
18813
|
+
const $8f8e530286a37ce9$var$fmtDecimal = (v)=>{
|
|
18814
|
+
if (v == null || !Number.isFinite(v)) return '';
|
|
18815
|
+
const a = Math.abs(v);
|
|
18816
|
+
return a !== 0 && (a < 0.01 || a >= 1e6) ? v.toPrecision(3) : v.toFixed(2);
|
|
18817
|
+
};
|
|
18818
|
+
const $8f8e530286a37ce9$var$isIntegerField = (f, rows)=>f.endsWith('__attr_i') || rows.every((r)=>r[f] == null || Number.isInteger(r[f]));
|
|
18708
18819
|
const $8f8e530286a37ce9$var$joinValues = (p)=>Array.isArray(p.value) ? p.value.map((v)=>String(v).replace(/_/g, ' ')).join(', ') : p.value ?? '';
|
|
18709
18820
|
const $8f8e530286a37ce9$var$StressChip = ({ c: c, dir: dir })=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
|
|
18710
18821
|
style: {
|
|
@@ -18775,6 +18886,7 @@ const $8f8e530286a37ce9$var$AttrTableViewCmp = (props)=>{
|
|
|
18775
18886
|
const [fieldQuery, setFieldQuery] = (0, $gXNCa$react.useState)('');
|
|
18776
18887
|
const [popover, setPopover] = (0, $gXNCa$react.useState)(null);
|
|
18777
18888
|
const popRef = (0, $gXNCa$react.useRef)(null);
|
|
18889
|
+
const [statsOpen, setStatsOpen] = (0, $gXNCa$react.useState)(true);
|
|
18778
18890
|
const { docs: docs, total: total, truncated: truncated, status: status, error: error, visibleFields: visibleFields } = attrTable;
|
|
18779
18891
|
const visibleSet = (0, $gXNCa$react.useMemo)(()=>new Set(visibleFields), [
|
|
18780
18892
|
visibleFields
|
|
@@ -18809,15 +18921,13 @@ const $8f8e530286a37ce9$var$AttrTableViewCmp = (props)=>{
|
|
|
18809
18921
|
}, [
|
|
18810
18922
|
docs
|
|
18811
18923
|
]);
|
|
18812
|
-
// Only the
|
|
18924
|
+
// Only the groups the bundle fetches are offered (Core identifiers, Expression
|
|
18925
|
+
// attributes, MAKER transcript metrics); the catalog drops groups a site lacks.
|
|
18813
18926
|
const pickerCatalog = (0, $gXNCa$react.useMemo)(()=>{
|
|
18814
18927
|
if (!fieldCatalog || !fieldCatalog.groups) return null;
|
|
18815
18928
|
return {
|
|
18816
18929
|
...fieldCatalog,
|
|
18817
|
-
groups: fieldCatalog.groups.filter((g)=>
|
|
18818
|
-
'core',
|
|
18819
|
-
'exprattrs'
|
|
18820
|
-
].includes(g.id))
|
|
18930
|
+
groups: fieldCatalog.groups.filter((g)=>(0, $12feb7ca48271e17$export$53e90de8d659db95).includes(g.id))
|
|
18821
18931
|
};
|
|
18822
18932
|
}, [
|
|
18823
18933
|
fieldCatalog
|
|
@@ -18844,10 +18954,11 @@ const $8f8e530286a37ce9$var$AttrTableViewCmp = (props)=>{
|
|
|
18844
18954
|
headerTooltip: (0, $4b8473139e48e77e$export$50c1f966fd3af83e)(o),
|
|
18845
18955
|
width: 22,
|
|
18846
18956
|
minWidth: 18,
|
|
18847
|
-
valueGetter: (p)=>p.data && p.data._organ[o] || '',
|
|
18957
|
+
valueGetter: (p)=>p.data && p.data._organ && p.data._organ[o] || '',
|
|
18848
18958
|
valueFormatter: ()=>'',
|
|
18849
18959
|
tooltipValueGetter: (p)=>{
|
|
18850
|
-
|
|
18960
|
+
if (p.node && p.node.rowPinned) return undefined;
|
|
18961
|
+
const lvl = p.data && p.data._organ && p.data._organ[o];
|
|
18851
18962
|
if (!lvl) return `${(0, $4b8473139e48e77e$export$50c1f966fd3af83e)(o)}: not assayed`;
|
|
18852
18963
|
const sp = p.data._specific.has(o) ? " \xb7 specific" : p.data._enhanced.has(o) ? " \xb7 enhanced" : '';
|
|
18853
18964
|
return `${(0, $4b8473139e48e77e$export$50c1f966fd3af83e)(o)}: ${(0, $4b8473139e48e77e$export$433053e2c141d410)[lvl] || lvl}${sp}`;
|
|
@@ -18900,6 +19011,18 @@ const $8f8e530286a37ce9$var$AttrTableViewCmp = (props)=>{
|
|
|
18900
19011
|
});
|
|
18901
19012
|
return;
|
|
18902
19013
|
}
|
|
19014
|
+
if ($8f8e530286a37ce9$var$MAKER_SET.has(f)) {
|
|
19015
|
+
cols.push({
|
|
19016
|
+
colId: f,
|
|
19017
|
+
field: f,
|
|
19018
|
+
headerName: labelOf(f),
|
|
19019
|
+
headerTooltip: $8f8e530286a37ce9$var$makerTooltip(f, labelOf(f)),
|
|
19020
|
+
width: 110,
|
|
19021
|
+
type: 'numericColumn',
|
|
19022
|
+
valueFormatter: (p)=>$8f8e530286a37ce9$var$fmtMaker(f, p.value)
|
|
19023
|
+
});
|
|
19024
|
+
return;
|
|
19025
|
+
}
|
|
18903
19026
|
cols.push({
|
|
18904
19027
|
colId: f,
|
|
18905
19028
|
field: f,
|
|
@@ -18919,6 +19042,110 @@ const $8f8e530286a37ce9$var$AttrTableViewCmp = (props)=>{
|
|
|
18919
19042
|
tpmRange,
|
|
18920
19043
|
fieldCatalogByName
|
|
18921
19044
|
]);
|
|
19045
|
+
// Visible columns whose values are all numbers get summary statistics.
|
|
19046
|
+
const numericFields = (0, $gXNCa$react.useMemo)(()=>{
|
|
19047
|
+
const fields = columnDefs.filter((c)=>c.field).map((c)=>c.field);
|
|
19048
|
+
return new Set($8f8e530286a37ce9$var$numericFieldsOf(rows, fields));
|
|
19049
|
+
}, [
|
|
19050
|
+
columnDefs,
|
|
19051
|
+
rows
|
|
19052
|
+
]);
|
|
19053
|
+
const stats = (0, $gXNCa$react.useMemo)(()=>{
|
|
19054
|
+
const out = {};
|
|
19055
|
+
numericFields.forEach((f)=>{
|
|
19056
|
+
out[f] = $8f8e530286a37ce9$var$statsOf(rows.map((r)=>r[f]).filter((v)=>typeof v === 'number' && Number.isFinite(v)));
|
|
19057
|
+
});
|
|
19058
|
+
return out;
|
|
19059
|
+
}, [
|
|
19060
|
+
numericFields,
|
|
19061
|
+
rows
|
|
19062
|
+
]);
|
|
19063
|
+
const pinnedTopRows = (0, $gXNCa$react.useMemo)(()=>{
|
|
19064
|
+
if (!numericFields.size || !rows.length) return [];
|
|
19065
|
+
const header = {
|
|
19066
|
+
_stat: 'header'
|
|
19067
|
+
};
|
|
19068
|
+
if (!statsOpen) return [
|
|
19069
|
+
header
|
|
19070
|
+
];
|
|
19071
|
+
return [
|
|
19072
|
+
header,
|
|
19073
|
+
...$8f8e530286a37ce9$var$STAT_ROWS.map(({ key: key, label: label })=>{
|
|
19074
|
+
const row = {
|
|
19075
|
+
_stat: key,
|
|
19076
|
+
_statLabel: label
|
|
19077
|
+
};
|
|
19078
|
+
numericFields.forEach((f)=>{
|
|
19079
|
+
row[f] = stats[f][key];
|
|
19080
|
+
});
|
|
19081
|
+
return row;
|
|
19082
|
+
})
|
|
19083
|
+
];
|
|
19084
|
+
}, [
|
|
19085
|
+
numericFields,
|
|
19086
|
+
stats,
|
|
19087
|
+
statsOpen,
|
|
19088
|
+
rows.length
|
|
19089
|
+
]);
|
|
19090
|
+
// The first column carries the stats rows' labels; numeric columns show their
|
|
19091
|
+
// statistics, formatted like the column (N as a count, mean/sd with decimals).
|
|
19092
|
+
const gridColumnDefs = (0, $gXNCa$react.useMemo)(()=>columnDefs.map((col, i)=>{
|
|
19093
|
+
const first = i === 0;
|
|
19094
|
+
const numeric = !!col.field && numericFields.has(col.field);
|
|
19095
|
+
if (!first && !numeric) return col;
|
|
19096
|
+
const intField = numeric && $8f8e530286a37ce9$var$isIntegerField(col.field, rows);
|
|
19097
|
+
const statText = (p)=>{
|
|
19098
|
+
const v = p.value;
|
|
19099
|
+
if (v == null || v === '') return '';
|
|
19100
|
+
const k = p.data._stat;
|
|
19101
|
+
if (k === 'n') return Number(v).toLocaleString();
|
|
19102
|
+
if (k === 'mean' || k === 'sd' || k === 'median' && intField && !Number.isInteger(v)) return col.field === 'expr_max_tpm__attr_f' ? (0, $4b8473139e48e77e$export$8eaa32ef86afdd9c)(v) : $8f8e530286a37ce9$var$fmtDecimal(v);
|
|
19103
|
+
return col.valueFormatter ? col.valueFormatter({
|
|
19104
|
+
...p,
|
|
19105
|
+
value: v
|
|
19106
|
+
}) : String(v);
|
|
19107
|
+
};
|
|
19108
|
+
return {
|
|
19109
|
+
...col,
|
|
19110
|
+
valueFormatter: (p)=>{
|
|
19111
|
+
if (!(p.node && p.node.rowPinned)) return col.valueFormatter ? col.valueFormatter(p) : p.value;
|
|
19112
|
+
return numeric ? statText(p) : '';
|
|
19113
|
+
},
|
|
19114
|
+
cellStyle: (p)=>p.node && p.node.rowPinned ? null : typeof col.cellStyle === 'function' ? col.cellStyle(p) : col.cellStyle,
|
|
19115
|
+
cellRenderer: (p)=>{
|
|
19116
|
+
if (p.node && p.node.rowPinned) {
|
|
19117
|
+
const k = p.data._stat;
|
|
19118
|
+
if (first && k === 'header') return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("span", {
|
|
19119
|
+
className: "attrtable-stats-toggle",
|
|
19120
|
+
title: statsOpen ? 'Hide summary statistics' : 'Show summary statistics',
|
|
19121
|
+
children: [
|
|
19122
|
+
statsOpen ? "\u25BE" : "\u25B8",
|
|
19123
|
+
" Summary statistics (",
|
|
19124
|
+
rows.length.toLocaleString(),
|
|
19125
|
+
" genes)"
|
|
19126
|
+
]
|
|
19127
|
+
});
|
|
19128
|
+
if (first) {
|
|
19129
|
+
const value = numeric ? statText(p) : '';
|
|
19130
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("span", {
|
|
19131
|
+
className: "attrtable-stats-label",
|
|
19132
|
+
children: [
|
|
19133
|
+
p.data._statLabel,
|
|
19134
|
+
value ? `: ${value}` : ''
|
|
19135
|
+
]
|
|
19136
|
+
});
|
|
19137
|
+
}
|
|
19138
|
+
return k === 'header' ? '' : p.valueFormatted;
|
|
19139
|
+
}
|
|
19140
|
+
return col.cellRenderer ? /*#__PURE__*/ (0, ($parcel$interopDefault($gXNCa$react))).createElement(col.cellRenderer, p) : p.valueFormatted ?? p.value;
|
|
19141
|
+
}
|
|
19142
|
+
};
|
|
19143
|
+
}), [
|
|
19144
|
+
columnDefs,
|
|
19145
|
+
numericFields,
|
|
19146
|
+
rows,
|
|
19147
|
+
statsOpen
|
|
19148
|
+
]);
|
|
18922
19149
|
// Build the click-popover for a cell: a title (the column meaning) and one
|
|
18923
19150
|
// filterable item per value. Each item carries the fq_field / fq_value the
|
|
18924
19151
|
// "add filter" button hands to doAcceptGrameneSuggestion.
|
|
@@ -18987,6 +19214,27 @@ const $8f8e530286a37ce9$var$AttrTableViewCmp = (props)=>{
|
|
|
18987
19214
|
]
|
|
18988
19215
|
};
|
|
18989
19216
|
}
|
|
19217
|
+
if ($8f8e530286a37ce9$var$MAKER_SET.has(colId)) {
|
|
19218
|
+
// AED: lower is better supported, so offer "at most"; the QI metrics "at least".
|
|
19219
|
+
const v = data[colId];
|
|
19220
|
+
if (!Number.isFinite(+v)) return {
|
|
19221
|
+
title: labelOf(colId),
|
|
19222
|
+
items: []
|
|
19223
|
+
};
|
|
19224
|
+
const shown = $8f8e530286a37ce9$var$fmtMaker(colId, +v);
|
|
19225
|
+
const short = $8f8e530286a37ce9$var$makerShortName(colId);
|
|
19226
|
+
return colId === 'MAKER__AED__attr_f' ? {
|
|
19227
|
+
title: labelOf(colId),
|
|
19228
|
+
items: [
|
|
19229
|
+
mk(`\u{2264} ${shown}`, colId, `[* TO ${v}]`, 'MAKER', `${short} \u{2264} ${shown}`)
|
|
19230
|
+
]
|
|
19231
|
+
} : {
|
|
19232
|
+
title: labelOf(colId),
|
|
19233
|
+
items: [
|
|
19234
|
+
mk(`\u{2265} ${shown}`, colId, `[${v} TO *]`, 'MAKER', `${short} \u{2265} ${shown}`)
|
|
19235
|
+
]
|
|
19236
|
+
};
|
|
19237
|
+
}
|
|
18990
19238
|
// Generic (Expression class, and any core / added attribute).
|
|
18991
19239
|
const label = labelOf(colId);
|
|
18992
19240
|
const raw = data[colId];
|
|
@@ -18999,6 +19247,11 @@ const $8f8e530286a37ce9$var$AttrTableViewCmp = (props)=>{
|
|
|
18999
19247
|
};
|
|
19000
19248
|
};
|
|
19001
19249
|
const onCellClicked = (e)=>{
|
|
19250
|
+
if (e.node && e.node.rowPinned) {
|
|
19251
|
+
if (e.data && e.data._stat === 'header') setStatsOpen((v)=>!v);
|
|
19252
|
+
setPopover(null);
|
|
19253
|
+
return;
|
|
19254
|
+
}
|
|
19002
19255
|
const desc = buildCellPopover(e.column.getColId(), e.data);
|
|
19003
19256
|
if (!desc || !desc.items.length) {
|
|
19004
19257
|
setPopover(null);
|
|
@@ -19161,7 +19414,9 @@ const $8f8e530286a37ce9$var$AttrTableViewCmp = (props)=>{
|
|
|
19161
19414
|
className: `ag-theme-quartz attrtable-aggrid${organShown ? ' attrtable-tall-header' : ''}`,
|
|
19162
19415
|
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$aggridreact.AgGridReact), {
|
|
19163
19416
|
rowData: rows,
|
|
19164
|
-
columnDefs:
|
|
19417
|
+
columnDefs: gridColumnDefs,
|
|
19418
|
+
pinnedTopRowData: pinnedTopRows,
|
|
19419
|
+
getRowClass: (p)=>p.node.rowPinned ? p.data._stat === 'header' ? 'attrtable-stats-header' : 'attrtable-stats-row' : undefined,
|
|
19165
19420
|
defaultColDef: $8f8e530286a37ce9$var$DEFAULT_COL_DEF,
|
|
19166
19421
|
animateRows: false,
|
|
19167
19422
|
suppressFieldDotNotation: true,
|