gramene-search 2.0.5 → 2.0.7
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/.claude/settings.local.json +1 -1
- package/.parcel-cache/83e7562660f7cc15-BundleGraph +0 -0
- package/.parcel-cache/d3a1b9507cb44047-AssetGraph +0 -0
- package/.parcel-cache/data.mdb +0 -0
- package/.parcel-cache/dc1da35000e13623-RequestGraph +0 -0
- package/.parcel-cache/lock.mdb +0 -0
- package/.parcel-cache/snapshot-dc1da35000e13623.txt +2 -2
- package/dist/index.css +176 -0
- package/dist/index.css.map +1 -1
- package/dist/index.js +2354 -817
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/bundles/docs.js +42 -15
- package/src/bundles/gsea.js +568 -0
- package/src/bundles/index.js +2 -1
- package/src/bundles/ontologies.js +52 -60
- package/src/bundles/swaggerFields.js +5 -6
- package/src/bundles/views.js +7 -1
- package/src/components/exporter/expressionResolver.js +2 -2
- package/src/components/exprViz/ExprTable.js +13 -2
- package/src/components/exprViz/ExprVizView.js +43 -5
- package/src/components/geneSearchUI.js +2 -0
- package/src/components/results/GSEA.js +618 -0
- package/src/components/results/HelpDemo.js +30 -0
- package/src/components/results/gsea.css +177 -0
- package/src/fieldCatalog.overlay.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11,6 +11,7 @@ var $gXNCa$gramenebinsclient = require("gramene-bins-client");
|
|
|
11
11
|
var $gXNCa$gramenetreesclient = require("gramene-trees-client");
|
|
12
12
|
var $gXNCa$gramenetaxonomywithgenomes = require("gramene-taxonomy-with-genomes");
|
|
13
13
|
var $gXNCa$reactga4 = require("react-ga4");
|
|
14
|
+
var $gXNCa$moneyclip = require("money-clip");
|
|
14
15
|
var $gXNCa$reactbootstrap = require("react-bootstrap");
|
|
15
16
|
var $gXNCa$reactswitch = require("react-switch");
|
|
16
17
|
var $gXNCa$reacticonsio5 = require("react-icons/io5");
|
|
@@ -1456,6 +1457,12 @@ const $24971af0a229e0e3$var$grameneViews = {
|
|
|
1456
1457
|
show: 'off',
|
|
1457
1458
|
shouldScroll: false
|
|
1458
1459
|
},
|
|
1460
|
+
{
|
|
1461
|
+
id: 'gsea',
|
|
1462
|
+
name: 'Gene set enrichment',
|
|
1463
|
+
show: 'off',
|
|
1464
|
+
shouldScroll: false
|
|
1465
|
+
},
|
|
1459
1466
|
{
|
|
1460
1467
|
id: 'userLists',
|
|
1461
1468
|
name: 'User Gene Lists',
|
|
@@ -1551,7 +1558,9 @@ const $24971af0a229e0e3$var$grameneViews = {
|
|
|
1551
1558
|
const resultDependentIds = new Set([
|
|
1552
1559
|
'taxonomy',
|
|
1553
1560
|
'list',
|
|
1554
|
-
'export'
|
|
1561
|
+
'export',
|
|
1562
|
+
'exprViz',
|
|
1563
|
+
'gsea'
|
|
1555
1564
|
]);
|
|
1556
1565
|
const autoDisable = numFound === 0 || !hasFilters;
|
|
1557
1566
|
const hasFirebase = !!(config && config.firebaseConfig);
|
|
@@ -1599,6 +1608,16 @@ const $24971af0a229e0e3$var$grameneViews = {
|
|
|
1599
1608
|
var $24971af0a229e0e3$export$2e2bcd8739ae039 = $24971af0a229e0e3$var$grameneViews;
|
|
1600
1609
|
|
|
1601
1610
|
|
|
1611
|
+
|
|
1612
|
+
// Dedicated IndexedDB store for the full pathway corpus, persisted
|
|
1613
|
+
// indefinitely (default maxAge of `Infinity`). The pathway set is small
|
|
1614
|
+
// and stable enough to keep around across sessions, so we bulk-load it
|
|
1615
|
+
// once with `?rows=-1` and reuse it instead of issuing per-id requests.
|
|
1616
|
+
const $671312b287158a8a$var$pathwayCache = (0, $gXNCa$moneyclip.getConfiguredCache)({
|
|
1617
|
+
version: 1,
|
|
1618
|
+
name: 'gramene_pathways'
|
|
1619
|
+
});
|
|
1620
|
+
let $671312b287158a8a$var$pathwaysBulkPromise = null;
|
|
1602
1621
|
const $671312b287158a8a$var$grameneDocs = {
|
|
1603
1622
|
name: 'grameneDocs',
|
|
1604
1623
|
getReducer: ()=>{
|
|
@@ -1803,26 +1822,37 @@ const $671312b287158a8a$var$grameneDocs = {
|
|
|
1803
1822
|
});
|
|
1804
1823
|
}
|
|
1805
1824
|
},
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
if (
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1825
|
+
// Signature kept for backward compatibility; the `ids` argument is
|
|
1826
|
+
// ignored. On first call we bulk-load every pathway record from the
|
|
1827
|
+
// dedicated IndexedDB cache (or `${api}/pathways?rows=-1` on miss),
|
|
1828
|
+
// dispatch a single GRAMENE_PATHWAYS_RECEIVED, and short-circuit all
|
|
1829
|
+
// subsequent calls.
|
|
1830
|
+
doRequestGramenePathways: (_ids)=>({ dispatch: dispatch, store: store })=>{
|
|
1831
|
+
if ($671312b287158a8a$var$pathwaysBulkPromise) return $671312b287158a8a$var$pathwaysBulkPromise;
|
|
1832
|
+
$671312b287158a8a$var$pathwaysBulkPromise = $671312b287158a8a$var$pathwayCache.get('all').then((cached)=>{
|
|
1833
|
+
if (cached) {
|
|
1834
|
+
dispatch({
|
|
1835
|
+
type: 'GRAMENE_PATHWAYS_RECEIVED',
|
|
1836
|
+
payload: cached
|
|
1837
|
+
});
|
|
1838
|
+
return;
|
|
1839
|
+
}
|
|
1840
|
+
return fetch(`${store.selectGrameneAPI()}/pathways?rows=-1`).then((res)=>res.json()).then((res)=>{
|
|
1841
|
+
const pathways = {};
|
|
1842
|
+
(res || []).forEach((p)=>{
|
|
1843
|
+
if (p && p._id != null) pathways[p._id] = p;
|
|
1819
1844
|
});
|
|
1820
1845
|
dispatch({
|
|
1821
1846
|
type: 'GRAMENE_PATHWAYS_RECEIVED',
|
|
1822
1847
|
payload: pathways
|
|
1823
1848
|
});
|
|
1849
|
+
$671312b287158a8a$var$pathwayCache.set('all', pathways).catch((e)=>console.warn('Failed to cache pathways', e));
|
|
1824
1850
|
});
|
|
1825
|
-
}
|
|
1851
|
+
}).catch((err)=>{
|
|
1852
|
+
console.error('Failed to load pathways', err);
|
|
1853
|
+
$671312b287158a8a$var$pathwaysBulkPromise = null; // allow retry on next call
|
|
1854
|
+
});
|
|
1855
|
+
return $671312b287158a8a$var$pathwaysBulkPromise;
|
|
1826
1856
|
},
|
|
1827
1857
|
doRequestExpressionStudies: (id)=>({ dispatch: dispatch, store: store })=>{
|
|
1828
1858
|
fetch(`${store.selectGrameneAPI()}/experiments?rows=-1`).then((res)=>res.json()).then((res)=>{
|
|
@@ -2076,7 +2106,7 @@ var $0d54502f6cafe273$export$2e2bcd8739ae039 = $0d54502f6cafe273$var$grameneGeno
|
|
|
2076
2106
|
|
|
2077
2107
|
|
|
2078
2108
|
var $65709bd8598fce20$exports = {};
|
|
2079
|
-
$65709bd8598fce20$exports = JSON.parse('{"groups":{"core":{"label":"Core identifiers","order":0},"location":{"label":"Genomic location","order":1},"structure":{"label":"Gene structure","order":2},"homology":{"label":"Homology","order":3},"expression":{"label":"Gene expression","order":4},"differential":{"label":"Differential expression","order":5},"hierarchical":{"label":"Hierarchical annotations","order":6},"pathways":{"label":"Pathways","order":7},"GO":{"label":"Gene Ontology","order":7},"PO":{"label":"Plant Ontology","order":8},"lof":{"label":"Loss of function alleles","order":9},"MAKER":{"label":"MAKER transcript metrics","order":10},"xrefs":{"label":"External references","order":11},"other":{"label":"Other","order":99}},"patterns":[{"id":"homology","match":"^homology__(.+)$","group":"homology","multiValued":true,"labelTemplate":"Homology: $1"},{"id":"pathways","match":"^pathways__(.+)$","group":"pathways","multiValued":true,"labelTemplate":"Pathway: $1"},{"id":"maker","match":"^MAKER__(.+)__attr_([a-z])$","group":"MAKER","labelTemplate":"MAKER: $1"},{"id":"xrefs","match":"^(.+)__xrefs$","group":"xrefs","multiValued":true,"labelTemplate":"$1 (xrefs)"},{"id":"expr","match":"^(E[-_][A-Za-z0-9_-]+?)_g(\\\\d+)__expr$","group":"expression","expression":true,"labelTemplate":"$1 \xb7 g$2"},{"id":"diffexpr","match":"^(E[-_][A-Za-z0-9_-]+?)_g(\\\\d+)_g(\\\\d+)_(pval|
|
|
2109
|
+
$65709bd8598fce20$exports = JSON.parse('{"groups":{"core":{"label":"Core identifiers","order":0},"location":{"label":"Genomic location","order":1},"structure":{"label":"Gene structure","order":2},"homology":{"label":"Homology","order":3},"expression":{"label":"Gene expression","order":4},"differential":{"label":"Differential expression","order":5},"hierarchical":{"label":"Hierarchical annotations","order":6},"pathways":{"label":"Pathways","order":7},"GO":{"label":"Gene Ontology","order":7},"PO":{"label":"Plant Ontology","order":8},"lof":{"label":"Loss of function alleles","order":9},"MAKER":{"label":"MAKER transcript metrics","order":10},"xrefs":{"label":"External references","order":11},"other":{"label":"Other","order":99}},"patterns":[{"id":"homology","match":"^homology__(.+)$","group":"homology","multiValued":true,"labelTemplate":"Homology: $1"},{"id":"pathways","match":"^pathways__(.+)$","group":"pathways","multiValued":true,"labelTemplate":"Pathway: $1"},{"id":"maker","match":"^MAKER__(.+)__attr_([a-z])$","group":"MAKER","labelTemplate":"MAKER: $1"},{"id":"xrefs","match":"^(.+)__xrefs$","group":"xrefs","multiValued":true,"labelTemplate":"$1 (xrefs)"},{"id":"expr","match":"^(E[-_][A-Za-z0-9_-]+?)_g(\\\\d+)__expr$","group":"expression","expression":true,"labelTemplate":"$1 \xb7 g$2"},{"id":"diffexpr","match":"^(E[-_][A-Za-z0-9_-]+?)_g(\\\\d+)_g(\\\\d+)_(pval|l2fc)_attr_([a-z])$","group":"differential","diffExpression":true,"labelTemplate":"$1 \xb7 g$2 vs g$3 \xb7 $4"},{"id":"bins","match":"^(fixed|uniform)_([0-9a-zA-Z]+)__bin$","group":"bins","is_hidden":true,"labelTemplate":"$1 bin ($2)"},{"id":"neighbors","match":".*neighbors_[0-9]+$","group":"neighbors","is_hidden":true,"labelTemplate":"neighbors"},{"id":"vep_merged","match":"^VEP__merged__(NAT|EMS)__attr_ss$","group":"lof","multiValued":true,"labelTemplate":"Merged $1 accessions"},{"id":"vep_detail","match":"^VEP__(.+?)__(homo|het)__(.+?)__(\\\\d+)__attr_ss$","group":"lof","multiValued":true,"labelTemplate":"$1 ($2) $3/$4"},{"id":"generic_attr","match":"^(.+)__attr_([a-z])$","group":"other","labelTemplate":"$1"}],"fields":{"id":{"group":"core","label":"Gene ID","order":1},"name":{"group":"core","label":"Name","order":2},"description":{"group":"core","label":"Description","order":4},"summary":{"group":"core","label":"Summary","order":5},"synonyms":{"group":"core","label":"Synonyms","multiValued":true,"order":3},"biotype":{"group":"core","label":"Biotype","order":6},"taxon_id":{"group":"core","label":"Taxon ID","order":8},"system_name":{"group":"core","label":"System name","order":7},"db_type":{"group":"core","label":"DB type","order":9},"closest_rep_id":{"group":"homology","label":"Closest representative ID","order":1},"closest_rep_name":{"group":"homology","label":"Closest representative name","order":2},"closest_rep_identity":{"group":"homology","label":"Closest representative identity","order":3},"closest_rep_taxon_id":{"group":"homology","label":"Closest representative taxon","order":4},"closest_rep_description":{"group":"homology","label":"Closest representative description","order":5},"model_rep_id":{"group":"homology","label":"Model representative ID","order":6},"model_rep_name":{"group":"homology","label":"Model representative name","order":7},"model_rep_identity":{"group":"homology","label":"Model representative identity","order":8},"model_rep_taxon_id":{"group":"homology","label":"Model representative taxon","order":9},"model_rep_description":{"group":"homology","label":"Model representative description","order":10},"gene_tree":{"group":"homology","label":"Gene tree ID","order":11},"pan_tree":{"group":"homology","label":"Pan-gene tree ID","order":14},"capabilities":{"group":"other","label":"Capabilities","multiValued":true},"map":{"group":"location","label":"Map","order":1},"region":{"group":"location","label":"Region","order":2},"start":{"group":"location","label":"Start","order":3},"end":{"group":"location","label":"End","order":4},"strand":{"group":"location","label":"Strand","order":5},"GO__ancestors":{"group":"hierarchical","label":"GO terms","multiValued":true,"order":1},"PO__ancestors":{"group":"hierarchical","label":"PO terms","multiValued":true,"order":2},"TO__ancestors":{"group":"hierarchical","label":"TO terms","multiValued":true,"order":3},"QTL_TO__ancestors":{"group":"hierarchical","label":"QTL traits (TO)","multiValued":true,"order":7},"domains__ancestors":{"group":"hierarchical","label":"Domains","multiValued":true,"order":4},"taxonomy__ancestors":{"group":"hierarchical","label":"Taxonomy","multiValued":true,"order":6},"supertree_attr_s":{"group":"homology","label":"Supertree","order":13},"gene_tree_root_taxon_id":{"group":"homology","label":"Gene tree root taxon","order":12},"protein__length":{"group":"structure","label":"Protein length"},"transcript__count":{"group":"structure","label":"Transcript count"},"transcript__exons":{"group":"structure","label":"Exon count"},"transcript__length":{"group":"structure","label":"Transcript length"},"expressed_in_gxa_attr_ss":{"group":"expression","label":"Expressed in GXA","multiValued":true},"MAKER__AED__attr_f":{"group":"MAKER","label":"AED","description":"Annotation Edit Distance"},"MAKER__QI1__attr_i":{"group":"MAKER","label":"QI1: Length of the 5\' UTR"},"MAKER__QI2__attr_f":{"group":"MAKER","label":"QI2: Fraction of splice sites confirmed by EST"},"MAKER__QI3__attr_f":{"group":"MAKER","label":"QI3: Fraction of exons overlapping an EST"},"MAKER__QI4__attr_f":{"group":"MAKER","label":"QI4: Fraction of exons overlapping EST or protein"},"MAKER__QI5__attr_f":{"group":"MAKER","label":"QI5: Fraction of splice sites confirmed by SNAP"},"MAKER__QI6__attr_f":{"group":"MAKER","label":"QI6: Fraction of exons overlapping a SNAP"},"MAKER__QI7__attr_i":{"group":"MAKER","label":"QI7: Number of exons in the mRNA"},"MAKER__QI8__attr_i":{"group":"MAKER","label":"QI8: Length of the 3\' UTR"},"MAKER__QI9__attr_i":{"group":"MAKER","label":"QI9: Length of the protein sequence"},"homology__all_orthologs":{"group":"homology","label":"All orthologs","multiValued":true,"order":15},"homology__ortholog_one2one":{"group":"homology","label":"1:1 orthologs","multiValued":true,"order":16},"homology__ortholog_one2many":{"group":"homology","label":"1:many orthologs","multiValued":true,"order":17},"homology__ortholog_many2many":{"group":"homology","label":"Many:many orthologs","multiValued":true,"order":18},"homology__syntenic_ortholog_one2one":{"group":"homology","label":"Syntenic 1:1 orthologs","multiValued":true,"order":19},"homology__within_species_paralog":{"group":"homology","label":"Within-species paralogs","multiValued":true,"order":20},"pathways__ancestors":{"group":"hierarchical","label":"Pathways","multiValued":true,"order":5},"canonical_transcript__attr_s":{"group":"structure","label":"Canonical transcript ID"}},"hidden":["_version_","_terms","score","gene_idx","gene_idx_multi","species_idx","compara_idx","compara_idx_multi","_id","annotations","bins","gene_structure","homology","location","xrefs","domain_roots","familyRoot__ancestors","taxonomy__ancestors","capabilities","saved_search"]}');
|
|
2080
2110
|
|
|
2081
2111
|
|
|
2082
2112
|
const $49d5cbca2ec74b2f$export$428c2f647a2a7545 = {
|
|
@@ -2379,14 +2409,13 @@ function $0f839422d0d8c772$var$buildSpeciesNameIndex(grameneMaps) {
|
|
|
2379
2409
|
function $0f839422d0d8c772$var$fieldExperimentId(name) {
|
|
2380
2410
|
let m = name.match(/^(\w+?)_g\d+__expr$/);
|
|
2381
2411
|
if (m) return m[1].replace(/_/g, '-');
|
|
2382
|
-
m = name.match(/^(\w+?)_g\d+_g\d+_(pval|
|
|
2412
|
+
m = name.match(/^(\w+?)_g\d+_g\d+_(pval|l2fc)_attr_[a-z]$/);
|
|
2383
2413
|
if (m) return m[1].replace(/_/g, '-');
|
|
2384
2414
|
return null;
|
|
2385
2415
|
}
|
|
2386
2416
|
const $0f839422d0d8c772$var$STAT_RANK = {
|
|
2387
2417
|
l2fc: 0,
|
|
2388
|
-
|
|
2389
|
-
pval: 2
|
|
2418
|
+
pval: 1
|
|
2390
2419
|
};
|
|
2391
2420
|
function $0f839422d0d8c772$var$collapseDiffExprInSubgroups(subgroups, fieldsOut, collator) {
|
|
2392
2421
|
for (const taxGroup of subgroups)for (const expGroup of taxGroup.subgroups || []){
|
|
@@ -2423,7 +2452,7 @@ function $0f839422d0d8c772$var$collapseDiffExprInSubgroups(subgroups, fieldsOut,
|
|
|
2423
2452
|
});
|
|
2424
2453
|
const rep = names[0];
|
|
2425
2454
|
const repEntry = fieldsOut[rep];
|
|
2426
|
-
const label = (repEntry.label || rep).replace(/\s+\((?:pval|
|
|
2455
|
+
const label = (repEntry.label || rep).replace(/\s+\((?:pval|l2fc)\)/, '');
|
|
2427
2456
|
fieldsOut[rep] = {
|
|
2428
2457
|
...repEntry,
|
|
2429
2458
|
label: label,
|
|
@@ -2726,15 +2755,12 @@ $0f839422d0d8c772$var$grameneFieldCatalog.selectFieldCatalog = (0, $gXNCa$reduxb
|
|
|
2726
2755
|
const present = new Set(fieldNames);
|
|
2727
2756
|
// Build a synthetic doc from the discovered field names; values carry the
|
|
2728
2757
|
// right JS type so inferType picks the correct multiValued/type (arrays
|
|
2729
|
-
// for multi-valued fields, scalars otherwise). Derive pval
|
|
2730
|
-
//
|
|
2758
|
+
// for multi-valued fields, scalars otherwise). Derive the pval companion
|
|
2759
|
+
// from every l2fc field.
|
|
2731
2760
|
const doc = {};
|
|
2732
2761
|
for (const name of present){
|
|
2733
2762
|
doc[name] = $0f839422d0d8c772$var$synthesizedValue(name);
|
|
2734
|
-
if (/_l2fc_attr_f$/.test(name))
|
|
2735
|
-
doc[name.replace('_l2fc_', '_pval_')] = 0;
|
|
2736
|
-
doc[name.replace('_l2fc_', '_logfc_')] = 0;
|
|
2737
|
-
}
|
|
2763
|
+
if (/_l2fc_attr_f$/.test(name)) doc[name.replace('_l2fc_', '_pval_')] = 0;
|
|
2738
2764
|
}
|
|
2739
2765
|
const catalog = $0f839422d0d8c772$var$buildCatalog([
|
|
2740
2766
|
doc
|
|
@@ -2749,7 +2775,7 @@ var $0f839422d0d8c772$export$2e2bcd8739ae039 = $0f839422d0d8c772$var$grameneFiel
|
|
|
2749
2775
|
|
|
2750
2776
|
|
|
2751
2777
|
const $6d28e8e62a4d602f$var$EXPR_FIELD_RE = /^(E[-_][A-Za-z0-9_-]+?)_g(\d+)__expr$/;
|
|
2752
|
-
const $6d28e8e62a4d602f$var$DIFFEXPR_FIELD_RE = /^(E[-_][A-Za-z0-9_-]+?)_g(\d+)_g(\d+)_(pval|
|
|
2778
|
+
const $6d28e8e62a4d602f$var$DIFFEXPR_FIELD_RE = /^(E[-_][A-Za-z0-9_-]+?)_g(\d+)_g(\d+)_(pval|l2fc)_attr_([a-z])$/;
|
|
2753
2779
|
const $6d28e8e62a4d602f$export$adbe84e3322ddf23 = [
|
|
2754
2780
|
'experiment',
|
|
2755
2781
|
'experiment_name',
|
|
@@ -2874,7 +2900,7 @@ function $6d28e8e62a4d602f$export$ba4cd509d0763838(doc, diffExpressionFields, ex
|
|
|
2874
2900
|
byContrast.set(key, entry);
|
|
2875
2901
|
}
|
|
2876
2902
|
if (parsed.stat === 'pval') entry.pval = val;
|
|
2877
|
-
else entry.l2fc = val;
|
|
2903
|
+
else entry.l2fc = val;
|
|
2878
2904
|
}
|
|
2879
2905
|
const maxPval = cutoffs && cutoffs.diffMaxPval;
|
|
2880
2906
|
const maxPvalActive = maxPval !== null && maxPval !== undefined && maxPval !== '' && Number.isFinite(+maxPval);
|
|
@@ -3769,13 +3795,21 @@ const $1508f5a42be6e7b5$var$exporter = {
|
|
|
3769
3795
|
var $1508f5a42be6e7b5$export$2e2bcd8739ae039 = $1508f5a42be6e7b5$var$exporter;
|
|
3770
3796
|
|
|
3771
3797
|
|
|
3798
|
+
|
|
3772
3799
|
const $c921a0d2b34aadb6$var$ONT_KEYS = [
|
|
3773
3800
|
'GO',
|
|
3774
3801
|
'PO',
|
|
3775
3802
|
'TO',
|
|
3776
3803
|
'domains'
|
|
3777
3804
|
];
|
|
3778
|
-
|
|
3805
|
+
// Dedicated IndexedDB store for ontology records. The full term set per
|
|
3806
|
+
// ontology is stable enough to keep around indefinitely (default maxAge of
|
|
3807
|
+
// `Infinity`), and we don't want it to share the short TTL of the app-wide
|
|
3808
|
+
// cache configured in demo.js.
|
|
3809
|
+
const $c921a0d2b34aadb6$var$cache = (0, $gXNCa$moneyclip.getConfiguredCache)({
|
|
3810
|
+
version: 1,
|
|
3811
|
+
name: 'gramene_ontologies'
|
|
3812
|
+
});
|
|
3779
3813
|
const $c921a0d2b34aadb6$var$inflight = {};
|
|
3780
3814
|
const $c921a0d2b34aadb6$var$ontologies = {
|
|
3781
3815
|
name: 'ontologies',
|
|
@@ -3784,95 +3818,64 @@ const $c921a0d2b34aadb6$var$ontologies = {
|
|
|
3784
3818
|
GO: {},
|
|
3785
3819
|
PO: {},
|
|
3786
3820
|
TO: {},
|
|
3787
|
-
domains: {}
|
|
3821
|
+
domains: {},
|
|
3822
|
+
loaded: {}
|
|
3788
3823
|
};
|
|
3789
3824
|
return (state = initialState, { type: type, payload: payload })=>{
|
|
3790
3825
|
switch(type){
|
|
3791
|
-
case '
|
|
3792
|
-
{
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
[key]: bucket
|
|
3801
|
-
};
|
|
3802
|
-
}
|
|
3803
|
-
case 'ONTOLOGY_RECORDS_RECEIVED':
|
|
3804
|
-
{
|
|
3805
|
-
const { key: key, records: records } = payload;
|
|
3806
|
-
return {
|
|
3807
|
-
...state,
|
|
3808
|
-
[key]: {
|
|
3809
|
-
...state[key],
|
|
3810
|
-
...records
|
|
3811
|
-
}
|
|
3812
|
-
};
|
|
3813
|
-
}
|
|
3826
|
+
case 'ONTOLOGY_BULK_LOADED':
|
|
3827
|
+
return {
|
|
3828
|
+
...state,
|
|
3829
|
+
[payload.key]: payload.records,
|
|
3830
|
+
loaded: {
|
|
3831
|
+
...state.loaded,
|
|
3832
|
+
[payload.key]: true
|
|
3833
|
+
}
|
|
3834
|
+
};
|
|
3814
3835
|
default:
|
|
3815
3836
|
return state;
|
|
3816
3837
|
}
|
|
3817
3838
|
};
|
|
3818
3839
|
},
|
|
3819
|
-
|
|
3840
|
+
// Signature kept for backward compatibility — the `ids` argument is
|
|
3841
|
+
// ignored. On first call per ontology key we load the full term set
|
|
3842
|
+
// (cache hit if available, otherwise `${api}/${key}?rows=-1`) and
|
|
3843
|
+
// dispatch a single bulk load. Subsequent calls are no-ops.
|
|
3844
|
+
doEnsureOntologyRecords: (key, _ids)=>({ dispatch: dispatch, store: store })=>{
|
|
3820
3845
|
if (!$c921a0d2b34aadb6$var$ONT_KEYS.includes(key)) return Promise.resolve();
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
if (
|
|
3826
|
-
const idNum = +id;
|
|
3827
|
-
if (!existing.hasOwnProperty(idNum) && !($c921a0d2b34aadb6$var$inflight[key] && $c921a0d2b34aadb6$var$inflight[key].has(idNum))) missing.push(idNum);
|
|
3828
|
-
}
|
|
3829
|
-
if (missing.length === 0) return Promise.resolve();
|
|
3830
|
-
if (!$c921a0d2b34aadb6$var$inflight[key]) $c921a0d2b34aadb6$var$inflight[key] = new Set();
|
|
3831
|
-
for (const id of missing)$c921a0d2b34aadb6$var$inflight[key].add(id);
|
|
3832
|
-
dispatch({
|
|
3833
|
-
type: 'ONTOLOGY_RECORDS_REQUESTED',
|
|
3834
|
-
payload: {
|
|
3835
|
-
key: key,
|
|
3836
|
-
ids: missing
|
|
3837
|
-
}
|
|
3838
|
-
});
|
|
3839
|
-
const api = store.selectGrameneAPI();
|
|
3840
|
-
const batches = [];
|
|
3841
|
-
for(let i = 0; i < missing.length; i += $c921a0d2b34aadb6$var$BATCH_SIZE)batches.push(missing.slice(i, i + $c921a0d2b34aadb6$var$BATCH_SIZE));
|
|
3842
|
-
const fetchBatch = (batch)=>{
|
|
3843
|
-
const idList = batch.length === 1 ? `${batch[0]},0` : batch.join(',');
|
|
3844
|
-
return fetch(`${api}/${key}?idList=${idList}&rows=${batch.length + 1}`).then((r)=>r.json()).then((docs)=>{
|
|
3845
|
-
const records = {};
|
|
3846
|
-
for (const d of docs || [])if (d && d._id != null) records[d._id] = d;
|
|
3847
|
-
for (const id of batch)if (!records.hasOwnProperty(id)) records[id] = {
|
|
3848
|
-
_id: id,
|
|
3849
|
-
missing: true
|
|
3850
|
-
};
|
|
3846
|
+
const state = store.selectOntologies();
|
|
3847
|
+
if (state.loaded && state.loaded[key]) return Promise.resolve();
|
|
3848
|
+
if ($c921a0d2b34aadb6$var$inflight[key]) return $c921a0d2b34aadb6$var$inflight[key];
|
|
3849
|
+
$c921a0d2b34aadb6$var$inflight[key] = $c921a0d2b34aadb6$var$cache.get(key).then((cached)=>{
|
|
3850
|
+
if (cached) {
|
|
3851
3851
|
dispatch({
|
|
3852
|
-
type: '
|
|
3852
|
+
type: 'ONTOLOGY_BULK_LOADED',
|
|
3853
3853
|
payload: {
|
|
3854
3854
|
key: key,
|
|
3855
|
-
records:
|
|
3855
|
+
records: cached
|
|
3856
3856
|
}
|
|
3857
3857
|
});
|
|
3858
|
-
|
|
3858
|
+
return;
|
|
3859
|
+
}
|
|
3860
|
+
const api = store.selectGrameneAPI();
|
|
3861
|
+
return fetch(`${api}/${key}?rows=-1`).then((r)=>r.json()).then((docs)=>{
|
|
3859
3862
|
const records = {};
|
|
3860
|
-
for (const
|
|
3861
|
-
_id: id,
|
|
3862
|
-
missing: true
|
|
3863
|
-
};
|
|
3863
|
+
for (const d of docs || [])if (d && d._id != null) records[d._id] = d;
|
|
3864
3864
|
dispatch({
|
|
3865
|
-
type: '
|
|
3865
|
+
type: 'ONTOLOGY_BULK_LOADED',
|
|
3866
3866
|
payload: {
|
|
3867
3867
|
key: key,
|
|
3868
3868
|
records: records
|
|
3869
3869
|
}
|
|
3870
3870
|
});
|
|
3871
|
-
|
|
3872
|
-
for (const id of batch)$c921a0d2b34aadb6$var$inflight[key].delete(id);
|
|
3871
|
+
$c921a0d2b34aadb6$var$cache.set(key, records).catch((e)=>console.warn('Failed to cache ontology', key, e));
|
|
3873
3872
|
});
|
|
3874
|
-
}
|
|
3875
|
-
|
|
3873
|
+
}).catch((err)=>{
|
|
3874
|
+
console.error(`Failed to load ontology ${key}`, err);
|
|
3875
|
+
}).finally(()=>{
|
|
3876
|
+
delete $c921a0d2b34aadb6$var$inflight[key];
|
|
3877
|
+
});
|
|
3878
|
+
return $c921a0d2b34aadb6$var$inflight[key];
|
|
3876
3879
|
},
|
|
3877
3880
|
selectOntologies: (state)=>state.ontologies
|
|
3878
3881
|
};
|
|
@@ -4447,232 +4450,910 @@ const $4f15cd8a7d970b18$var$exprViz = {
|
|
|
4447
4450
|
var $4f15cd8a7d970b18$export$2e2bcd8739ae039 = $4f15cd8a7d970b18$var$exprViz;
|
|
4448
4451
|
|
|
4449
4452
|
|
|
4450
|
-
var $5df6c55c1bef3469$export$2e2bcd8739ae039 = [
|
|
4451
|
-
...(0, $9d9aeaf9299e61a1$export$2e2bcd8739ae039),
|
|
4452
|
-
(0, $671312b287158a8a$export$2e2bcd8739ae039),
|
|
4453
|
-
(0, $af4441dd29af05df$export$2e2bcd8739ae039),
|
|
4454
|
-
(0, $24971af0a229e0e3$export$2e2bcd8739ae039),
|
|
4455
|
-
(0, $0d54502f6cafe273$export$2e2bcd8739ae039),
|
|
4456
|
-
(0, $0f839422d0d8c772$export$2e2bcd8739ae039),
|
|
4457
|
-
(0, $1508f5a42be6e7b5$export$2e2bcd8739ae039),
|
|
4458
|
-
(0, $c921a0d2b34aadb6$export$2e2bcd8739ae039),
|
|
4459
|
-
(0, $4f15cd8a7d970b18$export$2e2bcd8739ae039)
|
|
4460
|
-
];
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
4453
|
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4454
|
+
// Gene Set Enrichment Analysis bundle.
|
|
4455
|
+
//
|
|
4456
|
+
// For each species tab we run:
|
|
4457
|
+
// foreground: q=<filters>&fq=taxon_id:<tid>&rows=0 + facet on six __ancestors fields
|
|
4458
|
+
// background: q=taxon_id:<tid>&rows=0 + same facets (cached forever per tid)
|
|
4459
|
+
//
|
|
4460
|
+
// Per-ontology denominators (n_ont, N_ont) come from the root term's facet
|
|
4461
|
+
// count, since every annotated gene carries the root in __ancestors. Roots
|
|
4462
|
+
// are identified once ontology records are loaded by picking the ancestor
|
|
4463
|
+
// (or self) with the highest background facet count — this works for
|
|
4464
|
+
// multi-rooted GO (BP/MF/CC) and for the rice-rooted pathway tree.
|
|
4465
|
+
//
|
|
4466
|
+
// Enrichment uses the upper-tail Fisher exact (hypergeometric); p-values
|
|
4467
|
+
// are corrected per ontology with Benjamini–Hochberg. The "most-specific"
|
|
4468
|
+
// collapse is applied AFTER BH so a parent term that's significant on its
|
|
4469
|
+
// own is preserved even when none of its children clear the cutoff.
|
|
4470
|
+
const $0736cb5a41609896$var$ONTOLOGIES = [
|
|
4471
|
+
{
|
|
4472
|
+
key: 'GO',
|
|
4473
|
+
field: 'GO__ancestors',
|
|
4474
|
+
label: 'Gene Ontology',
|
|
4475
|
+
bucket: 'GO'
|
|
4476
|
+
},
|
|
4477
|
+
{
|
|
4478
|
+
key: 'PO',
|
|
4479
|
+
field: 'PO__ancestors',
|
|
4480
|
+
label: 'Plant Ontology',
|
|
4481
|
+
bucket: 'PO'
|
|
4482
|
+
},
|
|
4483
|
+
{
|
|
4484
|
+
key: 'TO',
|
|
4485
|
+
field: 'TO__ancestors',
|
|
4486
|
+
label: 'Trait Ontology',
|
|
4487
|
+
bucket: 'TO'
|
|
4488
|
+
},
|
|
4489
|
+
{
|
|
4490
|
+
key: 'QTL_TO',
|
|
4491
|
+
field: 'QTL_TO__ancestors',
|
|
4492
|
+
label: 'QTL Traits (TO)',
|
|
4493
|
+
bucket: 'TO'
|
|
4494
|
+
},
|
|
4495
|
+
{
|
|
4496
|
+
key: 'domains',
|
|
4497
|
+
field: 'domains__ancestors',
|
|
4498
|
+
label: 'InterPro Domains',
|
|
4499
|
+
bucket: 'domains'
|
|
4500
|
+
},
|
|
4501
|
+
{
|
|
4502
|
+
key: 'pathways',
|
|
4503
|
+
field: 'pathways__ancestors',
|
|
4504
|
+
label: 'Pathways',
|
|
4505
|
+
bucket: null
|
|
4500
4506
|
}
|
|
4501
|
-
|
|
4502
|
-
const $
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
}
|
|
4507
|
-
}
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
}
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
className: "container mb40 anchor",
|
|
4558
|
-
children: [
|
|
4559
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
4560
|
-
className: "fancy-title mb40",
|
|
4561
|
-
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("h4", {
|
|
4562
|
-
children: "Species"
|
|
4563
|
-
})
|
|
4564
|
-
}),
|
|
4565
|
-
results.taxonomy.map((doc, idx)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($2fec4872fbf7ebd2$var$Taxon, {
|
|
4566
|
-
taxon: doc
|
|
4567
|
-
}, idx))
|
|
4568
|
-
]
|
|
4569
|
-
});
|
|
4570
|
-
};
|
|
4571
|
-
const $2fec4872fbf7ebd2$var$ResultList = ({ grameneGenes: grameneGenes, grameneDomains: grameneDomains, gramenePathways: gramenePathways, grameneTaxonomy: grameneTaxonomy, searchUI: searchUI, searchUpdated: searchUpdated, doChangeQuantity: doChangeQuantity })=>{
|
|
4572
|
-
if (searchUI.Gramene) return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
4573
|
-
id: "gramene",
|
|
4574
|
-
className: "row",
|
|
4575
|
-
children: [
|
|
4576
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
4577
|
-
className: "fancy-title pt50",
|
|
4578
|
-
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("h3", {
|
|
4579
|
-
children: "Gramene search results"
|
|
4580
|
-
})
|
|
4581
|
-
}),
|
|
4582
|
-
searchUI.Genes && $2fec4872fbf7ebd2$var$Genes(grameneGenes, searchUI.rows.Genes, doChangeQuantity),
|
|
4583
|
-
searchUI.Domains && $2fec4872fbf7ebd2$var$Domains(grameneDomains),
|
|
4584
|
-
searchUI.Pathways && $2fec4872fbf7ebd2$var$Pathways(gramenePathways),
|
|
4585
|
-
searchUI.Species && $2fec4872fbf7ebd2$var$Species(grameneTaxonomy)
|
|
4586
|
-
]
|
|
4587
|
-
});
|
|
4588
|
-
else return null;
|
|
4589
|
-
};
|
|
4590
|
-
var $2fec4872fbf7ebd2$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.connect)('selectGrameneGenes', 'selectGrameneDomains', 'selectGramenePathways', 'selectGrameneTaxonomy', 'selectSearchUI', 'selectSearchUpdated', 'doChangeQuantity', $2fec4872fbf7ebd2$var$ResultList);
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
const $27617dbc24e7faf0$var$getStatus = (cat, results, isChecked, toggle)=>{
|
|
4597
|
-
const tally = results ? results.numFound : /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("img", {
|
|
4598
|
-
src: "/static/images/dna_spinner.svg"
|
|
4599
|
-
});
|
|
4600
|
-
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("li", {
|
|
4601
|
-
className: "category-leaf",
|
|
4602
|
-
children: [
|
|
4603
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("input", {
|
|
4604
|
-
type: "checkbox",
|
|
4605
|
-
checked: isChecked,
|
|
4606
|
-
onChange: (e)=>toggle(cat)
|
|
4607
|
-
}),
|
|
4608
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("a", {
|
|
4609
|
-
"data-scroll": true,
|
|
4610
|
-
href: `#${cat}`,
|
|
4611
|
-
className: "nav-link active",
|
|
4612
|
-
children: [
|
|
4613
|
-
cat,
|
|
4614
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
|
|
4615
|
-
style: {
|
|
4616
|
-
float: "right"
|
|
4507
|
+
];
|
|
4508
|
+
const $0736cb5a41609896$var$FACET_PARAMS = $0736cb5a41609896$var$ONTOLOGIES.map((o)=>`facet.field=${encodeURIComponent(`{!facet.limit=10000 facet.mincount=1 key=${o.key}}${o.field}`)}`).join('&');
|
|
4509
|
+
const $0736cb5a41609896$var$fgPending = {};
|
|
4510
|
+
const $0736cb5a41609896$var$bgPending = {};
|
|
4511
|
+
function $0736cb5a41609896$var$fgSig(q, taxon) {
|
|
4512
|
+
return `${q}|${taxon}`;
|
|
4513
|
+
}
|
|
4514
|
+
function $0736cb5a41609896$var$bgSig(taxon) {
|
|
4515
|
+
return `bg|${taxon}`;
|
|
4516
|
+
}
|
|
4517
|
+
function $0736cb5a41609896$var$parseFacets(json) {
|
|
4518
|
+
const out = {};
|
|
4519
|
+
const ff = json && json.facet_counts && json.facet_counts.facet_fields || {};
|
|
4520
|
+
for (const o of $0736cb5a41609896$var$ONTOLOGIES){
|
|
4521
|
+
const arr = ff[o.key] || [];
|
|
4522
|
+
const map = {};
|
|
4523
|
+
for(let i = 0; i < arr.length; i += 2)map[+arr[i]] = +arr[i + 1];
|
|
4524
|
+
out[o.key] = map;
|
|
4525
|
+
}
|
|
4526
|
+
return out;
|
|
4527
|
+
}
|
|
4528
|
+
const $0736cb5a41609896$var$gsea = {
|
|
4529
|
+
name: 'gsea',
|
|
4530
|
+
// Background facet counts depend only on the species — they're invariant
|
|
4531
|
+
// across filter changes and across sessions, so we persist whenever a bg
|
|
4532
|
+
// fetch completes. Foreground state piggybacks on the same write but is
|
|
4533
|
+
// self-invalidated by the signature check in the reactor.
|
|
4534
|
+
persistActions: [
|
|
4535
|
+
'GSEA_BG_SUCCEEDED'
|
|
4536
|
+
],
|
|
4537
|
+
getReducer: ()=>{
|
|
4538
|
+
const initialState = {
|
|
4539
|
+
activeTaxon: null,
|
|
4540
|
+
byTaxon: {},
|
|
4541
|
+
ui: {
|
|
4542
|
+
pAdjCutoff: 0.05,
|
|
4543
|
+
minK: 2,
|
|
4544
|
+
mostSpecific: true,
|
|
4545
|
+
ontology: 'all',
|
|
4546
|
+
search: ''
|
|
4547
|
+
}
|
|
4548
|
+
};
|
|
4549
|
+
function ensureTaxon(state, tid) {
|
|
4550
|
+
if (state.byTaxon[tid]) return state;
|
|
4551
|
+
return {
|
|
4552
|
+
...state,
|
|
4553
|
+
byTaxon: {
|
|
4554
|
+
...state.byTaxon,
|
|
4555
|
+
[tid]: {
|
|
4556
|
+
fg: {
|
|
4557
|
+
status: 'idle',
|
|
4558
|
+
signature: null,
|
|
4559
|
+
requestId: 0,
|
|
4560
|
+
terms: null,
|
|
4561
|
+
numFound: 0,
|
|
4562
|
+
error: null
|
|
4617
4563
|
},
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4564
|
+
bg: {
|
|
4565
|
+
status: 'idle',
|
|
4566
|
+
signature: null,
|
|
4567
|
+
requestId: 0,
|
|
4568
|
+
terms: null,
|
|
4569
|
+
numFound: 0,
|
|
4570
|
+
error: null
|
|
4571
|
+
}
|
|
4572
|
+
}
|
|
4573
|
+
}
|
|
4574
|
+
};
|
|
4575
|
+
}
|
|
4576
|
+
return (state = initialState, { type: type, payload: payload })=>{
|
|
4577
|
+
switch(type){
|
|
4578
|
+
case 'GSEA_ACTIVE_TAXON_SET':
|
|
4579
|
+
return {
|
|
4580
|
+
...ensureTaxon(state, payload),
|
|
4581
|
+
activeTaxon: payload
|
|
4582
|
+
};
|
|
4583
|
+
case 'GSEA_UI_SET':
|
|
4584
|
+
return {
|
|
4585
|
+
...state,
|
|
4586
|
+
ui: {
|
|
4587
|
+
...state.ui,
|
|
4588
|
+
...payload || {}
|
|
4589
|
+
}
|
|
4590
|
+
};
|
|
4591
|
+
case 'GSEA_FG_STARTED':
|
|
4592
|
+
{
|
|
4593
|
+
const next = ensureTaxon(state, payload.taxon);
|
|
4594
|
+
const t = next.byTaxon[payload.taxon];
|
|
4595
|
+
return {
|
|
4596
|
+
...next,
|
|
4597
|
+
byTaxon: {
|
|
4598
|
+
...next.byTaxon,
|
|
4599
|
+
[payload.taxon]: {
|
|
4600
|
+
...t,
|
|
4601
|
+
fg: {
|
|
4602
|
+
status: 'loading',
|
|
4603
|
+
signature: payload.signature,
|
|
4604
|
+
requestId: payload.requestId,
|
|
4605
|
+
terms: t.fg.terms,
|
|
4606
|
+
numFound: t.fg.numFound,
|
|
4607
|
+
error: null
|
|
4608
|
+
}
|
|
4609
|
+
}
|
|
4610
|
+
}
|
|
4611
|
+
};
|
|
4612
|
+
}
|
|
4613
|
+
case 'GSEA_FG_SUCCEEDED':
|
|
4614
|
+
{
|
|
4615
|
+
const t = state.byTaxon[payload.taxon];
|
|
4616
|
+
if (!t || payload.requestId !== t.fg.requestId) return state;
|
|
4617
|
+
return {
|
|
4618
|
+
...state,
|
|
4619
|
+
byTaxon: {
|
|
4620
|
+
...state.byTaxon,
|
|
4621
|
+
[payload.taxon]: {
|
|
4622
|
+
...t,
|
|
4623
|
+
fg: {
|
|
4624
|
+
...t.fg,
|
|
4625
|
+
status: 'ready',
|
|
4626
|
+
terms: payload.terms,
|
|
4627
|
+
numFound: payload.numFound
|
|
4628
|
+
}
|
|
4629
|
+
}
|
|
4630
|
+
}
|
|
4631
|
+
};
|
|
4632
|
+
}
|
|
4633
|
+
case 'GSEA_FG_FAILED':
|
|
4634
|
+
{
|
|
4635
|
+
const t = state.byTaxon[payload.taxon];
|
|
4636
|
+
if (!t || payload.requestId !== t.fg.requestId) return state;
|
|
4637
|
+
return {
|
|
4638
|
+
...state,
|
|
4639
|
+
byTaxon: {
|
|
4640
|
+
...state.byTaxon,
|
|
4641
|
+
[payload.taxon]: {
|
|
4642
|
+
...t,
|
|
4643
|
+
fg: {
|
|
4644
|
+
...t.fg,
|
|
4645
|
+
status: 'error',
|
|
4646
|
+
error: payload.error
|
|
4647
|
+
}
|
|
4648
|
+
}
|
|
4649
|
+
}
|
|
4650
|
+
};
|
|
4651
|
+
}
|
|
4652
|
+
case 'GSEA_BG_STARTED':
|
|
4653
|
+
{
|
|
4654
|
+
const next = ensureTaxon(state, payload.taxon);
|
|
4655
|
+
const t = next.byTaxon[payload.taxon];
|
|
4656
|
+
return {
|
|
4657
|
+
...next,
|
|
4658
|
+
byTaxon: {
|
|
4659
|
+
...next.byTaxon,
|
|
4660
|
+
[payload.taxon]: {
|
|
4661
|
+
...t,
|
|
4662
|
+
bg: {
|
|
4663
|
+
status: 'loading',
|
|
4664
|
+
signature: payload.signature,
|
|
4665
|
+
requestId: payload.requestId,
|
|
4666
|
+
terms: t.bg.terms,
|
|
4667
|
+
numFound: t.bg.numFound,
|
|
4668
|
+
error: null
|
|
4669
|
+
}
|
|
4670
|
+
}
|
|
4671
|
+
}
|
|
4672
|
+
};
|
|
4673
|
+
}
|
|
4674
|
+
case 'GSEA_BG_SUCCEEDED':
|
|
4675
|
+
{
|
|
4676
|
+
const t = state.byTaxon[payload.taxon];
|
|
4677
|
+
if (!t || payload.requestId !== t.bg.requestId) return state;
|
|
4678
|
+
return {
|
|
4679
|
+
...state,
|
|
4680
|
+
byTaxon: {
|
|
4681
|
+
...state.byTaxon,
|
|
4682
|
+
[payload.taxon]: {
|
|
4683
|
+
...t,
|
|
4684
|
+
bg: {
|
|
4685
|
+
...t.bg,
|
|
4686
|
+
status: 'ready',
|
|
4687
|
+
terms: payload.terms,
|
|
4688
|
+
numFound: payload.numFound
|
|
4689
|
+
}
|
|
4690
|
+
}
|
|
4691
|
+
}
|
|
4692
|
+
};
|
|
4693
|
+
}
|
|
4694
|
+
case 'GSEA_BG_FAILED':
|
|
4695
|
+
{
|
|
4696
|
+
const t = state.byTaxon[payload.taxon];
|
|
4697
|
+
if (!t || payload.requestId !== t.bg.requestId) return state;
|
|
4698
|
+
return {
|
|
4699
|
+
...state,
|
|
4700
|
+
byTaxon: {
|
|
4701
|
+
...state.byTaxon,
|
|
4702
|
+
[payload.taxon]: {
|
|
4703
|
+
...t,
|
|
4704
|
+
bg: {
|
|
4705
|
+
...t.bg,
|
|
4706
|
+
status: 'error',
|
|
4707
|
+
error: payload.error
|
|
4708
|
+
}
|
|
4709
|
+
}
|
|
4710
|
+
}
|
|
4711
|
+
};
|
|
4712
|
+
}
|
|
4713
|
+
case 'GRAMENE_SEARCH_CLEARED':
|
|
4714
|
+
{
|
|
4715
|
+
// Filters changed — invalidate foreground but keep background
|
|
4716
|
+
// (it depends only on taxon).
|
|
4717
|
+
const newByTaxon = {};
|
|
4718
|
+
for (const tid of Object.keys(state.byTaxon)){
|
|
4719
|
+
const t = state.byTaxon[tid];
|
|
4720
|
+
newByTaxon[tid] = {
|
|
4721
|
+
...t,
|
|
4722
|
+
fg: {
|
|
4723
|
+
status: 'idle',
|
|
4724
|
+
signature: null,
|
|
4725
|
+
requestId: 0,
|
|
4726
|
+
terms: null,
|
|
4727
|
+
numFound: 0,
|
|
4728
|
+
error: null
|
|
4729
|
+
}
|
|
4730
|
+
};
|
|
4731
|
+
}
|
|
4732
|
+
return {
|
|
4733
|
+
...state,
|
|
4734
|
+
byTaxon: newByTaxon
|
|
4735
|
+
};
|
|
4736
|
+
}
|
|
4737
|
+
default:
|
|
4738
|
+
return state;
|
|
4739
|
+
}
|
|
4740
|
+
};
|
|
4741
|
+
},
|
|
4742
|
+
doSetGseaActiveTaxon: (tid)=>({ dispatch: dispatch })=>dispatch({
|
|
4743
|
+
type: 'GSEA_ACTIVE_TAXON_SET',
|
|
4744
|
+
payload: tid
|
|
4643
4745
|
}),
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4746
|
+
doSetGseaUI: (patch)=>({ dispatch: dispatch })=>dispatch({
|
|
4747
|
+
type: 'GSEA_UI_SET',
|
|
4748
|
+
payload: patch
|
|
4749
|
+
}),
|
|
4750
|
+
doFetchGseaForeground: (taxon)=>({ dispatch: dispatch, store: store })=>{
|
|
4751
|
+
const q = store.selectGrameneFiltersQueryString();
|
|
4752
|
+
const signature = $0736cb5a41609896$var$fgSig(q, taxon);
|
|
4753
|
+
const state = store.selectGsea();
|
|
4754
|
+
const t = state.byTaxon[taxon];
|
|
4755
|
+
if (t && t.fg.signature === signature && (t.fg.status === 'loading' || t.fg.status === 'ready')) return;
|
|
4756
|
+
const requestId = $0736cb5a41609896$var$fgPending[taxon] = ($0736cb5a41609896$var$fgPending[taxon] || 0) + 1;
|
|
4757
|
+
dispatch({
|
|
4758
|
+
type: 'GSEA_FG_STARTED',
|
|
4759
|
+
payload: {
|
|
4760
|
+
taxon: taxon,
|
|
4761
|
+
signature: signature,
|
|
4762
|
+
requestId: requestId
|
|
4763
|
+
}
|
|
4764
|
+
});
|
|
4765
|
+
const api = store.selectGrameneAPI();
|
|
4766
|
+
const url = `${api}/search?q=${q}&fq=taxon_id:${taxon}&rows=0&facet=true&${$0736cb5a41609896$var$FACET_PARAMS}`;
|
|
4767
|
+
fetch(url).then((r)=>r.json()).then((json)=>{
|
|
4768
|
+
if (requestId !== $0736cb5a41609896$var$fgPending[taxon]) return;
|
|
4769
|
+
const terms = $0736cb5a41609896$var$parseFacets(json);
|
|
4770
|
+
const numFound = json && json.response && json.response.numFound || 0;
|
|
4771
|
+
dispatch({
|
|
4772
|
+
type: 'GSEA_FG_SUCCEEDED',
|
|
4773
|
+
payload: {
|
|
4774
|
+
taxon: taxon,
|
|
4775
|
+
requestId: requestId,
|
|
4776
|
+
terms: terms,
|
|
4777
|
+
numFound: numFound
|
|
4778
|
+
}
|
|
4779
|
+
});
|
|
4780
|
+
store.doEnsureGseaTermRecords(taxon);
|
|
4781
|
+
}).catch((err)=>{
|
|
4782
|
+
if (requestId !== $0736cb5a41609896$var$fgPending[taxon]) return;
|
|
4783
|
+
dispatch({
|
|
4784
|
+
type: 'GSEA_FG_FAILED',
|
|
4785
|
+
payload: {
|
|
4786
|
+
taxon: taxon,
|
|
4787
|
+
requestId: requestId,
|
|
4788
|
+
error: String(err)
|
|
4789
|
+
}
|
|
4790
|
+
});
|
|
4791
|
+
});
|
|
4792
|
+
},
|
|
4793
|
+
doFetchGseaBackground: (taxon)=>({ dispatch: dispatch, store: store })=>{
|
|
4794
|
+
const signature = $0736cb5a41609896$var$bgSig(taxon);
|
|
4795
|
+
const state = store.selectGsea();
|
|
4796
|
+
const t = state.byTaxon[taxon];
|
|
4797
|
+
if (t && t.bg.signature === signature && (t.bg.status === 'loading' || t.bg.status === 'ready')) return;
|
|
4798
|
+
const requestId = $0736cb5a41609896$var$bgPending[taxon] = ($0736cb5a41609896$var$bgPending[taxon] || 0) + 1;
|
|
4799
|
+
dispatch({
|
|
4800
|
+
type: 'GSEA_BG_STARTED',
|
|
4801
|
+
payload: {
|
|
4802
|
+
taxon: taxon,
|
|
4803
|
+
signature: signature,
|
|
4804
|
+
requestId: requestId
|
|
4805
|
+
}
|
|
4806
|
+
});
|
|
4807
|
+
const api = store.selectGrameneAPI();
|
|
4808
|
+
const url = `${api}/search?q=taxon_id:${taxon}&rows=0&facet=true&${$0736cb5a41609896$var$FACET_PARAMS}`;
|
|
4809
|
+
fetch(url).then((r)=>r.json()).then((json)=>{
|
|
4810
|
+
if (requestId !== $0736cb5a41609896$var$bgPending[taxon]) return;
|
|
4811
|
+
const terms = $0736cb5a41609896$var$parseFacets(json);
|
|
4812
|
+
const numFound = json && json.response && json.response.numFound || 0;
|
|
4813
|
+
dispatch({
|
|
4814
|
+
type: 'GSEA_BG_SUCCEEDED',
|
|
4815
|
+
payload: {
|
|
4816
|
+
taxon: taxon,
|
|
4817
|
+
requestId: requestId,
|
|
4818
|
+
terms: terms,
|
|
4819
|
+
numFound: numFound
|
|
4820
|
+
}
|
|
4821
|
+
});
|
|
4822
|
+
store.doEnsureGseaTermRecords(taxon);
|
|
4823
|
+
}).catch((err)=>{
|
|
4824
|
+
if (requestId !== $0736cb5a41609896$var$bgPending[taxon]) return;
|
|
4825
|
+
dispatch({
|
|
4826
|
+
type: 'GSEA_BG_FAILED',
|
|
4827
|
+
payload: {
|
|
4828
|
+
taxon: taxon,
|
|
4829
|
+
requestId: requestId,
|
|
4830
|
+
error: String(err)
|
|
4831
|
+
}
|
|
4832
|
+
});
|
|
4833
|
+
});
|
|
4834
|
+
},
|
|
4835
|
+
doEnsureGseaTermRecords: (taxon)=>({ store: store })=>{
|
|
4836
|
+
const state = store.selectGsea();
|
|
4837
|
+
if (!state.byTaxon[taxon]) return;
|
|
4838
|
+
// The ontologies and pathways bundles bulk-load + persist on first
|
|
4839
|
+
// request; we just need to nudge each one once.
|
|
4840
|
+
const buckets = new Set();
|
|
4841
|
+
for (const o of $0736cb5a41609896$var$ONTOLOGIES)if (o.bucket) buckets.add(o.bucket);
|
|
4842
|
+
for (const k of buckets)store.doEnsureOntologyRecords(k);
|
|
4843
|
+
if (store.doRequestGramenePathways) store.doRequestGramenePathways();
|
|
4844
|
+
},
|
|
4845
|
+
reactGseaFetch: (0, $gXNCa$reduxbundler.createSelector)('selectGsea', 'selectGrameneFiltersStatus', 'selectGrameneFiltersQueryString', 'selectGrameneViewsOn', (gs, fStatus, q, viewsOn)=>{
|
|
4846
|
+
if (!viewsOn || !viewsOn.has('gsea')) return;
|
|
4847
|
+
if (fStatus === 'init') return;
|
|
4848
|
+
const tid = gs.activeTaxon;
|
|
4849
|
+
if (!tid) return;
|
|
4850
|
+
const t = gs.byTaxon[tid];
|
|
4851
|
+
if (!t) return;
|
|
4852
|
+
const sig = $0736cb5a41609896$var$fgSig(q, tid);
|
|
4853
|
+
// A 'loading' status from a rehydrated state with no live request is
|
|
4854
|
+
// treated as idle — otherwise we'd deadlock waiting on a fetch that
|
|
4855
|
+
// ended when the previous tab closed.
|
|
4856
|
+
const fgInFlight = t.fg.status === 'loading' && ($0736cb5a41609896$var$fgPending[tid] || 0) === t.fg.requestId && t.fg.requestId > 0;
|
|
4857
|
+
if (t.fg.signature !== sig && !fgInFlight) return {
|
|
4858
|
+
actionCreator: 'doFetchGseaForeground',
|
|
4859
|
+
args: [
|
|
4860
|
+
tid
|
|
4667
4861
|
]
|
|
4668
|
-
}
|
|
4669
|
-
|
|
4862
|
+
};
|
|
4863
|
+
const bgInFlight = t.bg.status === 'loading' && ($0736cb5a41609896$var$bgPending[tid] || 0) === t.bg.requestId && t.bg.requestId > 0;
|
|
4864
|
+
if (t.bg.status !== 'ready' && !bgInFlight) return {
|
|
4865
|
+
actionCreator: 'doFetchGseaBackground',
|
|
4866
|
+
args: [
|
|
4867
|
+
tid
|
|
4868
|
+
]
|
|
4869
|
+
};
|
|
4870
|
+
}),
|
|
4871
|
+
selectGsea: (state)=>state.gsea,
|
|
4872
|
+
selectGseaUI: (state)=>state.gsea.ui,
|
|
4873
|
+
selectGseaOntologyDefs: ()=>$0736cb5a41609896$var$ONTOLOGIES,
|
|
4874
|
+
selectGseaResults: (0, $gXNCa$reduxbundler.createSelector)('selectGsea', 'selectOntologies', 'selectGramenePathways', (gs, ontoBuckets, pathwayDocs)=>{
|
|
4875
|
+
const tid = gs.activeTaxon;
|
|
4876
|
+
if (!tid) return null;
|
|
4877
|
+
const t = gs.byTaxon[tid];
|
|
4878
|
+
if (!t || !t.fg.terms || !t.bg.terms) return null;
|
|
4879
|
+
const ui = gs.ui;
|
|
4880
|
+
const out = {};
|
|
4881
|
+
for (const o of $0736cb5a41609896$var$ONTOLOGIES){
|
|
4882
|
+
const fg = t.fg.terms[o.key] || {};
|
|
4883
|
+
const bg = t.bg.terms[o.key] || {};
|
|
4884
|
+
const recs = o.key === 'pathways' ? pathwayDocs || {} : ontoBuckets && ontoBuckets[o.bucket] || {};
|
|
4885
|
+
// Forest-fallback denominators: when a term is itself a forest root
|
|
4886
|
+
// (no parents in `recs` — common for InterPro), root finding returns
|
|
4887
|
+
// the term and we'd get fold=1 by construction. Use the maximum
|
|
4888
|
+
// counts across the ontology as a proxy for "annotated in this
|
|
4889
|
+
// ontology" instead. For ontologies with a true synthetic root,
|
|
4890
|
+
// these maxima equal the root counts and the answer is unchanged.
|
|
4891
|
+
let maxFg = 0, maxBg = 0;
|
|
4892
|
+
for (const idStr of Object.keys(bg)){
|
|
4893
|
+
const v = bg[idStr];
|
|
4894
|
+
if (v > maxBg) maxBg = v;
|
|
4895
|
+
}
|
|
4896
|
+
for (const idStr of Object.keys(fg)){
|
|
4897
|
+
const v = fg[idStr];
|
|
4898
|
+
if (v > maxFg) maxFg = v;
|
|
4899
|
+
}
|
|
4900
|
+
const rootCache = {};
|
|
4901
|
+
const rootOf = (id)=>{
|
|
4902
|
+
if (rootCache.hasOwnProperty(id)) return rootCache[id];
|
|
4903
|
+
const r = $0736cb5a41609896$var$findRoot(o.key, id, recs, bg);
|
|
4904
|
+
rootCache[id] = r;
|
|
4905
|
+
return r;
|
|
4906
|
+
};
|
|
4907
|
+
const rows = [];
|
|
4908
|
+
for (const idStr of Object.keys(fg)){
|
|
4909
|
+
const id = +idStr;
|
|
4910
|
+
const k = fg[id];
|
|
4911
|
+
const K = bg[id] || 0;
|
|
4912
|
+
if (K < k) continue; // bg should always be >= fg
|
|
4913
|
+
if (k < ui.minK) continue;
|
|
4914
|
+
const termRec = recs && recs[id];
|
|
4915
|
+
if (termRec && (termRec.is_obsolete || termRec.obsolete)) continue;
|
|
4916
|
+
const root = rootOf(id);
|
|
4917
|
+
// If the "root" is the term itself, the term is a forest root in
|
|
4918
|
+
// this ontology — fall back to ontology-wide maxima.
|
|
4919
|
+
const fellBack = +root === id;
|
|
4920
|
+
const n = fellBack ? maxFg : root != null && fg[root] ? fg[root] : k;
|
|
4921
|
+
const N = fellBack ? maxBg : root != null && bg[root] ? bg[root] : K;
|
|
4922
|
+
if (n <= 0 || N <= 0) continue;
|
|
4923
|
+
if (k > n || K > N) continue;
|
|
4924
|
+
const fold = k / n / (K / N);
|
|
4925
|
+
const p = $0736cb5a41609896$var$fisherUpperTail(k, n, K, N);
|
|
4926
|
+
rows.push({
|
|
4927
|
+
ontology: o.key,
|
|
4928
|
+
ontology_label: o.label,
|
|
4929
|
+
term_id: id,
|
|
4930
|
+
field: o.field,
|
|
4931
|
+
k: k,
|
|
4932
|
+
n: n,
|
|
4933
|
+
K: K,
|
|
4934
|
+
N: N,
|
|
4935
|
+
fold: fold,
|
|
4936
|
+
p: p,
|
|
4937
|
+
pAdj: 1,
|
|
4938
|
+
root: root,
|
|
4939
|
+
denomFallback: fellBack
|
|
4940
|
+
});
|
|
4941
|
+
}
|
|
4942
|
+
// GO is split into its three top-level namespaces (BP / MF / CC)
|
|
4943
|
+
// and each is tested as its own ontology — both BH correction and
|
|
4944
|
+
// most-specific collapse run within a namespace. We only split once
|
|
4945
|
+
// ontology records have arrived and root finding has produced
|
|
4946
|
+
// canonical roots; otherwise we'd see a swarm of singleton groups
|
|
4947
|
+
// during the brief loading window between bg landing and records
|
|
4948
|
+
// being fetched.
|
|
4949
|
+
if (o.key === 'GO' && Object.keys(recs).length > 0) {
|
|
4950
|
+
const byRoot = {};
|
|
4951
|
+
for (const r of rows){
|
|
4952
|
+
const k = String(r.root);
|
|
4953
|
+
if (!byRoot[k]) byRoot[k] = [];
|
|
4954
|
+
byRoot[k].push(r);
|
|
4955
|
+
}
|
|
4956
|
+
const rootKeys = Object.keys(byRoot).sort((a, b)=>{
|
|
4957
|
+
const na = $0736cb5a41609896$var$goRootName(recs[+a]) || a;
|
|
4958
|
+
const nb = $0736cb5a41609896$var$goRootName(recs[+b]) || b;
|
|
4959
|
+
return na.localeCompare(nb);
|
|
4960
|
+
});
|
|
4961
|
+
for (const rootKey of rootKeys){
|
|
4962
|
+
const rootRec = recs[+rootKey];
|
|
4963
|
+
const rootName = $0736cb5a41609896$var$goRootName(rootRec);
|
|
4964
|
+
const sectionKey = `GO:${rootKey}`;
|
|
4965
|
+
const sectionLabel = rootName ? `GO: ${$0736cb5a41609896$var$titleCase(rootName)}` : `GO: ${rootKey}`;
|
|
4966
|
+
out[sectionKey] = $0736cb5a41609896$var$finalizeBlock(byRoot[rootKey], o.key, o.field, recs, ui, sectionKey, sectionLabel);
|
|
4967
|
+
}
|
|
4968
|
+
} else out[o.key] = $0736cb5a41609896$var$finalizeBlock(rows, o.key, o.field, recs, ui, o.key, o.label);
|
|
4969
|
+
}
|
|
4970
|
+
return out;
|
|
4971
|
+
})
|
|
4670
4972
|
};
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4973
|
+
function $0736cb5a41609896$var$goRootName(rec) {
|
|
4974
|
+
if (!rec) return '';
|
|
4975
|
+
return rec.name || rec.display_name || rec.namespace || '';
|
|
4976
|
+
}
|
|
4977
|
+
function $0736cb5a41609896$var$titleCase(s) {
|
|
4978
|
+
return String(s).split('_').map((w)=>w ? w[0].toUpperCase() + w.slice(1) : '').join(' ');
|
|
4979
|
+
}
|
|
4980
|
+
// BH correction + most-specific collapse + metadata + final sort, returning
|
|
4981
|
+
// the block descriptor consumed by the view layer.
|
|
4982
|
+
function $0736cb5a41609896$var$finalizeBlock(rows, ontKey, ontField, recs, ui, sectionKey, sectionLabel) {
|
|
4983
|
+
rows.sort((a, b)=>a.p - b.p);
|
|
4984
|
+
const m = rows.length;
|
|
4985
|
+
let prev = 1;
|
|
4986
|
+
for(let i = m - 1; i >= 0; i--){
|
|
4987
|
+
const adj = Math.min(prev, rows[i].p * m / (i + 1));
|
|
4988
|
+
rows[i].pAdj = adj;
|
|
4989
|
+
prev = adj;
|
|
4990
|
+
}
|
|
4991
|
+
const passing = rows.filter((r)=>r.pAdj <= ui.pAdjCutoff);
|
|
4992
|
+
let display = passing;
|
|
4993
|
+
if (ui.mostSpecific) display = $0736cb5a41609896$var$collapseToMostSpecific(ontKey, passing, recs);
|
|
4994
|
+
for (const r of display){
|
|
4995
|
+
const rec = recs && recs[r.term_id];
|
|
4996
|
+
if (rec) {
|
|
4997
|
+
r.term_name = rec.name || rec.display_name || '';
|
|
4998
|
+
r.term_namespace = rec.namespace || rec.type || '';
|
|
4999
|
+
r.term_display_id = rec.id != null ? String(rec.id) : String(r.term_id);
|
|
5000
|
+
} else {
|
|
5001
|
+
r.term_name = '';
|
|
5002
|
+
r.term_namespace = '';
|
|
5003
|
+
r.term_display_id = String(r.term_id);
|
|
5004
|
+
}
|
|
5005
|
+
}
|
|
5006
|
+
display.sort((a, b)=>a.pAdj - b.pAdj || b.fold - a.fold);
|
|
5007
|
+
return {
|
|
5008
|
+
ontology: sectionKey,
|
|
5009
|
+
label: sectionLabel,
|
|
5010
|
+
field: ontField,
|
|
5011
|
+
tested: rows.length,
|
|
5012
|
+
passing: passing.length,
|
|
5013
|
+
rows: display
|
|
5014
|
+
};
|
|
5015
|
+
}
|
|
5016
|
+
// ---------- math helpers ----------
|
|
5017
|
+
const $0736cb5a41609896$var$LF_CACHE = [
|
|
5018
|
+
0,
|
|
5019
|
+
0
|
|
5020
|
+
];
|
|
5021
|
+
function $0736cb5a41609896$var$logFactorial(n) {
|
|
5022
|
+
if (n < $0736cb5a41609896$var$LF_CACHE.length) return $0736cb5a41609896$var$LF_CACHE[n];
|
|
5023
|
+
let lf = $0736cb5a41609896$var$LF_CACHE[$0736cb5a41609896$var$LF_CACHE.length - 1];
|
|
5024
|
+
for(let i = $0736cb5a41609896$var$LF_CACHE.length; i <= n; i++){
|
|
5025
|
+
lf += Math.log(i);
|
|
5026
|
+
$0736cb5a41609896$var$LF_CACHE.push(lf);
|
|
5027
|
+
}
|
|
5028
|
+
return $0736cb5a41609896$var$LF_CACHE[n];
|
|
5029
|
+
}
|
|
5030
|
+
function $0736cb5a41609896$var$logChoose(n, k) {
|
|
5031
|
+
if (k < 0 || k > n) return -Infinity;
|
|
5032
|
+
return $0736cb5a41609896$var$logFactorial(n) - $0736cb5a41609896$var$logFactorial(k) - $0736cb5a41609896$var$logFactorial(n - k);
|
|
5033
|
+
}
|
|
5034
|
+
function $0736cb5a41609896$var$logHypergeom(x, n, K, N) {
|
|
5035
|
+
return $0736cb5a41609896$var$logChoose(K, x) + $0736cb5a41609896$var$logChoose(N - K, n - x) - $0736cb5a41609896$var$logChoose(N, n);
|
|
5036
|
+
}
|
|
5037
|
+
function $0736cb5a41609896$var$logSumExp(a, b) {
|
|
5038
|
+
if (a === -Infinity) return b;
|
|
5039
|
+
if (b === -Infinity) return a;
|
|
5040
|
+
const m = Math.max(a, b);
|
|
5041
|
+
return m + Math.log(Math.exp(a - m) + Math.exp(b - m));
|
|
5042
|
+
}
|
|
5043
|
+
function $0736cb5a41609896$var$fisherUpperTail(k, n, K, N) {
|
|
5044
|
+
const upper = Math.min(n, K);
|
|
5045
|
+
let logP = -Infinity;
|
|
5046
|
+
for(let x = k; x <= upper; x++)logP = $0736cb5a41609896$var$logSumExp(logP, $0736cb5a41609896$var$logHypergeom(x, n, K, N));
|
|
5047
|
+
const p = Math.exp(logP);
|
|
5048
|
+
if (!isFinite(p)) return 1;
|
|
5049
|
+
return Math.min(1, Math.max(0, p));
|
|
5050
|
+
}
|
|
5051
|
+
// ---------- ontology graph helpers ----------
|
|
5052
|
+
// Pick the "root" for a term as the ancestor (or self) with the highest
|
|
5053
|
+
// background facet count. The true root has every annotated gene under it,
|
|
5054
|
+
// so this selects BP/MF/CC for GO terms automatically and the rice root
|
|
5055
|
+
// for pathways without needing per-ontology hardcoded ids.
|
|
5056
|
+
function $0736cb5a41609896$var$findRoot(ontKey, id, recs, bgCounts) {
|
|
5057
|
+
const rec = recs && recs[id];
|
|
5058
|
+
const candidates = new Set([
|
|
5059
|
+
+id
|
|
5060
|
+
]);
|
|
5061
|
+
if (rec) {
|
|
5062
|
+
if (ontKey === 'pathways') for (const k of Object.keys(rec)){
|
|
5063
|
+
if (k.startsWith('ancestors_') && Array.isArray(rec[k])) for (const a of rec[k])candidates.add(+a);
|
|
5064
|
+
}
|
|
5065
|
+
else if (Array.isArray(rec.ancestors)) for (const a of rec.ancestors)candidates.add(+a);
|
|
5066
|
+
else if (Array.isArray(rec.is_a)) {
|
|
5067
|
+
const stack = rec.is_a.slice();
|
|
5068
|
+
while(stack.length){
|
|
5069
|
+
const cur = +stack.pop();
|
|
5070
|
+
if (candidates.has(cur)) continue;
|
|
5071
|
+
candidates.add(cur);
|
|
5072
|
+
const r = recs[cur];
|
|
5073
|
+
if (r && Array.isArray(r.is_a)) for (const p of r.is_a)stack.push(p);
|
|
5074
|
+
}
|
|
5075
|
+
}
|
|
5076
|
+
}
|
|
5077
|
+
let best = +id;
|
|
5078
|
+
let bestCount = bgCounts[+id] || 0;
|
|
5079
|
+
for (const c of candidates){
|
|
5080
|
+
const cnt = bgCounts[c] || 0;
|
|
5081
|
+
if (cnt > bestCount) {
|
|
5082
|
+
bestCount = cnt;
|
|
5083
|
+
best = c;
|
|
5084
|
+
}
|
|
5085
|
+
}
|
|
5086
|
+
return best;
|
|
5087
|
+
}
|
|
5088
|
+
function $0736cb5a41609896$var$ancestorsOf(ontKey, id, recs) {
|
|
5089
|
+
const out = new Set();
|
|
5090
|
+
const rec = recs && recs[id];
|
|
5091
|
+
if (!rec) return out;
|
|
5092
|
+
if (ontKey === 'pathways') {
|
|
5093
|
+
for (const k of Object.keys(rec))if (k.startsWith('ancestors_') && Array.isArray(rec[k])) {
|
|
5094
|
+
for (const a of rec[k])if (+a !== +id) out.add(+a);
|
|
5095
|
+
}
|
|
5096
|
+
return out;
|
|
5097
|
+
}
|
|
5098
|
+
if (Array.isArray(rec.ancestors)) {
|
|
5099
|
+
for (const a of rec.ancestors)if (+a !== +id) out.add(+a);
|
|
5100
|
+
return out;
|
|
5101
|
+
}
|
|
5102
|
+
if (Array.isArray(rec.is_a)) {
|
|
5103
|
+
const stack = rec.is_a.slice();
|
|
5104
|
+
while(stack.length){
|
|
5105
|
+
const cur = +stack.pop();
|
|
5106
|
+
if (out.has(cur)) continue;
|
|
5107
|
+
out.add(cur);
|
|
5108
|
+
const r = recs[cur];
|
|
5109
|
+
if (r && Array.isArray(r.is_a)) for (const p of r.is_a)stack.push(p);
|
|
5110
|
+
}
|
|
5111
|
+
}
|
|
5112
|
+
return out;
|
|
5113
|
+
}
|
|
5114
|
+
// Drop any term that is an ancestor of another term in the same passing set.
|
|
5115
|
+
// Applied AFTER BH so a parent term can survive when none of its children
|
|
5116
|
+
// pass the p_adj cutoff.
|
|
5117
|
+
function $0736cb5a41609896$var$collapseToMostSpecific(ontKey, rows, recs) {
|
|
5118
|
+
if (!rows || rows.length <= 1) return rows;
|
|
5119
|
+
const inSet = new Set(rows.map((r)=>+r.term_id));
|
|
5120
|
+
const covered = new Set();
|
|
5121
|
+
for (const r of rows){
|
|
5122
|
+
const ancs = $0736cb5a41609896$var$ancestorsOf(ontKey, +r.term_id, recs);
|
|
5123
|
+
for (const a of ancs)if (inSet.has(a)) covered.add(a);
|
|
5124
|
+
}
|
|
5125
|
+
return rows.filter((r)=>!covered.has(+r.term_id));
|
|
5126
|
+
}
|
|
5127
|
+
var $0736cb5a41609896$export$2e2bcd8739ae039 = $0736cb5a41609896$var$gsea;
|
|
5128
|
+
|
|
5129
|
+
|
|
5130
|
+
var $5df6c55c1bef3469$export$2e2bcd8739ae039 = [
|
|
5131
|
+
...(0, $9d9aeaf9299e61a1$export$2e2bcd8739ae039),
|
|
5132
|
+
(0, $671312b287158a8a$export$2e2bcd8739ae039),
|
|
5133
|
+
(0, $af4441dd29af05df$export$2e2bcd8739ae039),
|
|
5134
|
+
(0, $24971af0a229e0e3$export$2e2bcd8739ae039),
|
|
5135
|
+
(0, $0d54502f6cafe273$export$2e2bcd8739ae039),
|
|
5136
|
+
(0, $0f839422d0d8c772$export$2e2bcd8739ae039),
|
|
5137
|
+
(0, $1508f5a42be6e7b5$export$2e2bcd8739ae039),
|
|
5138
|
+
(0, $c921a0d2b34aadb6$export$2e2bcd8739ae039),
|
|
5139
|
+
(0, $4f15cd8a7d970b18$export$2e2bcd8739ae039),
|
|
5140
|
+
(0, $0736cb5a41609896$export$2e2bcd8739ae039)
|
|
5141
|
+
];
|
|
5142
|
+
|
|
5143
|
+
|
|
5144
|
+
|
|
5145
|
+
|
|
5146
|
+
|
|
5147
|
+
const $2fec4872fbf7ebd2$var$Gene = ({ gene: gene })=>{
|
|
5148
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
5149
|
+
className: "row",
|
|
5150
|
+
children: gene.id
|
|
5151
|
+
});
|
|
5152
|
+
};
|
|
5153
|
+
const $2fec4872fbf7ebd2$var$Genes = (results, rows, doChangeQuantity)=>{
|
|
5154
|
+
if (results && results.numFound > 0) {
|
|
5155
|
+
const moreButton = results.numFound > rows ? /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("button", {
|
|
5156
|
+
onClick: (e)=>doChangeQuantity('Genes', 20),
|
|
5157
|
+
children: "more"
|
|
5158
|
+
}) : '';
|
|
5159
|
+
const fewerButton = rows > 20 ? /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("button", {
|
|
5160
|
+
onClick: (e)=>doChangeQuantity('Genes', -20),
|
|
5161
|
+
children: "fewer"
|
|
5162
|
+
}) : '';
|
|
5163
|
+
const docsToShow = results.response.docs.slice(0, rows);
|
|
5164
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
5165
|
+
id: "Genes",
|
|
5166
|
+
className: "container mb40 anchor",
|
|
5167
|
+
children: [
|
|
5168
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
5169
|
+
className: "fancy-title mb40",
|
|
5170
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("h4", {
|
|
5171
|
+
children: "Genes"
|
|
5172
|
+
})
|
|
5173
|
+
}),
|
|
5174
|
+
docsToShow.map((doc, idx)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($2fec4872fbf7ebd2$var$Gene, {
|
|
5175
|
+
gene: doc
|
|
5176
|
+
}, idx)),
|
|
5177
|
+
fewerButton,
|
|
5178
|
+
moreButton
|
|
5179
|
+
]
|
|
5180
|
+
});
|
|
5181
|
+
}
|
|
5182
|
+
};
|
|
5183
|
+
const $2fec4872fbf7ebd2$var$Pathway = ({ pathway: pathway })=>{
|
|
5184
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
5185
|
+
className: "row",
|
|
5186
|
+
children: pathway.name
|
|
5187
|
+
});
|
|
5188
|
+
};
|
|
5189
|
+
const $2fec4872fbf7ebd2$var$Pathways = (results)=>{
|
|
5190
|
+
if (results && results.numFound > 0) return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
5191
|
+
id: "Pathways",
|
|
5192
|
+
className: "container mb40 anchor",
|
|
5193
|
+
children: [
|
|
5194
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
5195
|
+
className: "fancy-title",
|
|
5196
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("h4", {
|
|
5197
|
+
children: "Pathways"
|
|
5198
|
+
})
|
|
5199
|
+
}),
|
|
5200
|
+
results.pathways.map((doc, idx)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($2fec4872fbf7ebd2$var$Pathway, {
|
|
5201
|
+
pathway: doc
|
|
5202
|
+
}, idx))
|
|
5203
|
+
]
|
|
5204
|
+
});
|
|
5205
|
+
};
|
|
5206
|
+
const $2fec4872fbf7ebd2$var$Domain = ({ domain: domain })=>{
|
|
5207
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
5208
|
+
className: "row",
|
|
5209
|
+
children: domain.id
|
|
5210
|
+
});
|
|
5211
|
+
};
|
|
5212
|
+
const $2fec4872fbf7ebd2$var$Domains = (results)=>{
|
|
5213
|
+
if (results && results.numFound > 0) return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
5214
|
+
id: "Domains",
|
|
5215
|
+
className: "container mb40 anchor",
|
|
5216
|
+
children: [
|
|
5217
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
5218
|
+
className: "fancy-title mb40",
|
|
5219
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("h4", {
|
|
5220
|
+
children: "Domains"
|
|
5221
|
+
})
|
|
5222
|
+
}),
|
|
5223
|
+
results.domains.map((doc, idx)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($2fec4872fbf7ebd2$var$Domain, {
|
|
5224
|
+
domain: doc
|
|
5225
|
+
}, idx))
|
|
5226
|
+
]
|
|
5227
|
+
});
|
|
5228
|
+
};
|
|
5229
|
+
const $2fec4872fbf7ebd2$var$Taxon = ({ taxon: taxon })=>{
|
|
5230
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
5231
|
+
className: "row",
|
|
5232
|
+
children: taxon.id
|
|
5233
|
+
});
|
|
5234
|
+
};
|
|
5235
|
+
const $2fec4872fbf7ebd2$var$Species = (results)=>{
|
|
5236
|
+
if (results && results.numFound > 0) return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
5237
|
+
id: "Species",
|
|
5238
|
+
className: "container mb40 anchor",
|
|
5239
|
+
children: [
|
|
5240
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
5241
|
+
className: "fancy-title mb40",
|
|
5242
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("h4", {
|
|
5243
|
+
children: "Species"
|
|
5244
|
+
})
|
|
5245
|
+
}),
|
|
5246
|
+
results.taxonomy.map((doc, idx)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($2fec4872fbf7ebd2$var$Taxon, {
|
|
5247
|
+
taxon: doc
|
|
5248
|
+
}, idx))
|
|
5249
|
+
]
|
|
5250
|
+
});
|
|
5251
|
+
};
|
|
5252
|
+
const $2fec4872fbf7ebd2$var$ResultList = ({ grameneGenes: grameneGenes, grameneDomains: grameneDomains, gramenePathways: gramenePathways, grameneTaxonomy: grameneTaxonomy, searchUI: searchUI, searchUpdated: searchUpdated, doChangeQuantity: doChangeQuantity })=>{
|
|
5253
|
+
if (searchUI.Gramene) return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
5254
|
+
id: "gramene",
|
|
5255
|
+
className: "row",
|
|
5256
|
+
children: [
|
|
5257
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
5258
|
+
className: "fancy-title pt50",
|
|
5259
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("h3", {
|
|
5260
|
+
children: "Gramene search results"
|
|
5261
|
+
})
|
|
5262
|
+
}),
|
|
5263
|
+
searchUI.Genes && $2fec4872fbf7ebd2$var$Genes(grameneGenes, searchUI.rows.Genes, doChangeQuantity),
|
|
5264
|
+
searchUI.Domains && $2fec4872fbf7ebd2$var$Domains(grameneDomains),
|
|
5265
|
+
searchUI.Pathways && $2fec4872fbf7ebd2$var$Pathways(gramenePathways),
|
|
5266
|
+
searchUI.Species && $2fec4872fbf7ebd2$var$Species(grameneTaxonomy)
|
|
5267
|
+
]
|
|
5268
|
+
});
|
|
5269
|
+
else return null;
|
|
5270
|
+
};
|
|
5271
|
+
var $2fec4872fbf7ebd2$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.connect)('selectGrameneGenes', 'selectGrameneDomains', 'selectGramenePathways', 'selectGrameneTaxonomy', 'selectSearchUI', 'selectSearchUpdated', 'doChangeQuantity', $2fec4872fbf7ebd2$var$ResultList);
|
|
5272
|
+
|
|
5273
|
+
|
|
5274
|
+
|
|
5275
|
+
|
|
5276
|
+
|
|
5277
|
+
const $27617dbc24e7faf0$var$getStatus = (cat, results, isChecked, toggle)=>{
|
|
5278
|
+
const tally = results ? results.numFound : /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("img", {
|
|
5279
|
+
src: "/static/images/dna_spinner.svg"
|
|
5280
|
+
});
|
|
5281
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("li", {
|
|
5282
|
+
className: "category-leaf",
|
|
5283
|
+
children: [
|
|
5284
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("input", {
|
|
5285
|
+
type: "checkbox",
|
|
5286
|
+
checked: isChecked,
|
|
5287
|
+
onChange: (e)=>toggle(cat)
|
|
5288
|
+
}),
|
|
5289
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("a", {
|
|
5290
|
+
"data-scroll": true,
|
|
5291
|
+
href: `#${cat}`,
|
|
5292
|
+
className: "nav-link active",
|
|
5293
|
+
children: [
|
|
5294
|
+
cat,
|
|
5295
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
|
|
5296
|
+
style: {
|
|
5297
|
+
float: "right"
|
|
5298
|
+
},
|
|
5299
|
+
children: tally
|
|
5300
|
+
})
|
|
5301
|
+
]
|
|
5302
|
+
})
|
|
5303
|
+
]
|
|
5304
|
+
});
|
|
5305
|
+
};
|
|
5306
|
+
const $27617dbc24e7faf0$var$ResultSummary = ({ grameneGenes: grameneGenes, gramenePathways: gramenePathways, grameneDomains: grameneDomains, grameneTaxonomy: grameneTaxonomy, searchUI: searchUI, searchUpdated: searchUpdated, doToggleCategory: doToggleCategory })=>{
|
|
5307
|
+
const status = grameneGenes ? grameneGenes.numFound : /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("img", {
|
|
5308
|
+
src: "/static/images/dna_spinner.svg"
|
|
5309
|
+
});
|
|
5310
|
+
if (searchUI.Gramene) return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("li", {
|
|
5311
|
+
className: "active category-expanded",
|
|
5312
|
+
children: [
|
|
5313
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("a", {
|
|
5314
|
+
onClick: (e)=>doToggleCategory('Gramene'),
|
|
5315
|
+
children: [
|
|
5316
|
+
"Gramene Search",
|
|
5317
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
|
|
5318
|
+
style: {
|
|
5319
|
+
float: "right"
|
|
5320
|
+
},
|
|
5321
|
+
children: status
|
|
5322
|
+
})
|
|
5323
|
+
]
|
|
5324
|
+
}),
|
|
5325
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("ul", {
|
|
5326
|
+
className: "list-unstyled",
|
|
5327
|
+
children: [
|
|
5328
|
+
$27617dbc24e7faf0$var$getStatus('Genes', grameneGenes, searchUI.Genes, doToggleCategory),
|
|
5329
|
+
$27617dbc24e7faf0$var$getStatus('Domains', grameneDomains, searchUI.Domains, doToggleCategory),
|
|
5330
|
+
$27617dbc24e7faf0$var$getStatus('Pathways', gramenePathways, searchUI.Pathways, doToggleCategory),
|
|
5331
|
+
$27617dbc24e7faf0$var$getStatus('Species', grameneTaxonomy, searchUI.Species, doToggleCategory)
|
|
5332
|
+
]
|
|
5333
|
+
})
|
|
5334
|
+
]
|
|
5335
|
+
});
|
|
5336
|
+
else return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("li", {
|
|
5337
|
+
className: "active category-collapsed",
|
|
5338
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("a", {
|
|
5339
|
+
onClick: (e)=>doToggleCategory('Gramene'),
|
|
5340
|
+
children: [
|
|
5341
|
+
"Gramene Search",
|
|
5342
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
|
|
5343
|
+
style: {
|
|
5344
|
+
float: "right"
|
|
5345
|
+
},
|
|
5346
|
+
children: status
|
|
5347
|
+
})
|
|
5348
|
+
]
|
|
5349
|
+
})
|
|
5350
|
+
});
|
|
5351
|
+
};
|
|
5352
|
+
var $27617dbc24e7faf0$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.connect)('selectGrameneGenes', 'selectGramenePathways', 'selectGrameneDomains', 'selectGrameneTaxonomy', 'selectSearchUI', 'selectSearchUpdated', 'doToggleCategory', $27617dbc24e7faf0$var$ResultSummary);
|
|
5353
|
+
|
|
5354
|
+
|
|
5355
|
+
|
|
5356
|
+
|
|
4676
5357
|
|
|
4677
5358
|
|
|
4678
5359
|
|
|
@@ -7920,6 +8601,36 @@ const $b36244140732570a$var$examples = [
|
|
|
7920
8601
|
]
|
|
7921
8602
|
}
|
|
7922
8603
|
},
|
|
8604
|
+
{
|
|
8605
|
+
subsite: {
|
|
8606
|
+
maize: 1,
|
|
8607
|
+
sorghum: 1,
|
|
8608
|
+
grapevine: 1,
|
|
8609
|
+
rice: 1,
|
|
8610
|
+
main: 1
|
|
8611
|
+
},
|
|
8612
|
+
text: "Which genes are curated in the scientific literature?",
|
|
8613
|
+
filters: {
|
|
8614
|
+
status: 'init',
|
|
8615
|
+
rows: 20,
|
|
8616
|
+
operation: 'AND',
|
|
8617
|
+
negate: false,
|
|
8618
|
+
leftIdx: 0,
|
|
8619
|
+
rightIdx: 3,
|
|
8620
|
+
children: [
|
|
8621
|
+
{
|
|
8622
|
+
fq_field: 'capabilities',
|
|
8623
|
+
fq_value: 'pubs',
|
|
8624
|
+
name: 'publication',
|
|
8625
|
+
category: 'Curated',
|
|
8626
|
+
leftIdx: 1,
|
|
8627
|
+
rightIdx: 2,
|
|
8628
|
+
negate: false,
|
|
8629
|
+
marked: false
|
|
8630
|
+
}
|
|
8631
|
+
]
|
|
8632
|
+
}
|
|
8633
|
+
},
|
|
7923
8634
|
{
|
|
7924
8635
|
subsite: {
|
|
7925
8636
|
grapevine: 1
|
|
@@ -11390,12 +12101,22 @@ const $4ab64e76c1caef59$var$baseColDefs = [
|
|
|
11390
12101
|
suppressMovable: true
|
|
11391
12102
|
}
|
|
11392
12103
|
];
|
|
12104
|
+
// Hoisted so the reference is stable across renders. ag-grid otherwise sees a
|
|
12105
|
+
// "new" defaultColDef on every parent re-render (e.g. when hovering a row
|
|
12106
|
+
// triggers setHoveredId in the parent) and re-applies column state, which
|
|
12107
|
+
// snaps any user-resized columns back to their original widths.
|
|
12108
|
+
const $4ab64e76c1caef59$var$DEFAULT_COL_DEF = {
|
|
12109
|
+
resizable: true,
|
|
12110
|
+
sortable: true,
|
|
12111
|
+
filter: false,
|
|
12112
|
+
suppressMenu: true
|
|
12113
|
+
};
|
|
11393
12114
|
function $4ab64e76c1caef59$var$arraysEqual(a, b) {
|
|
11394
12115
|
if (a.length !== b.length) return false;
|
|
11395
12116
|
for(let i = 0; i < a.length; i++)if (a[i] !== b[i]) return false;
|
|
11396
12117
|
return true;
|
|
11397
12118
|
}
|
|
11398
|
-
function $4ab64e76c1caef59$
|
|
12119
|
+
function $4ab64e76c1caef59$export$7b242440eb2c300d(fields, studies, expressionSamples) {
|
|
11399
12120
|
const info = {};
|
|
11400
12121
|
if (!fields || !studies || !expressionSamples) return info;
|
|
11401
12122
|
const wanted = new Set(fields);
|
|
@@ -11684,7 +12405,7 @@ function $4ab64e76c1caef59$var$buildColumnDefs(fields, fieldInfo, expanded, togg
|
|
|
11684
12405
|
];
|
|
11685
12406
|
}
|
|
11686
12407
|
const $4ab64e76c1caef59$var$ExprTable = ({ rows: rows, fields: fields, onReorder: onReorder, studies: studies, expressionSamples: expressionSamples, onHoverRow: onHoverRow })=>{
|
|
11687
|
-
const fieldInfo = (0, $gXNCa$react.useMemo)(()=>$4ab64e76c1caef59$
|
|
12408
|
+
const fieldInfo = (0, $gXNCa$react.useMemo)(()=>$4ab64e76c1caef59$export$7b242440eb2c300d(fields, studies, expressionSamples), [
|
|
11688
12409
|
fields,
|
|
11689
12410
|
studies,
|
|
11690
12411
|
expressionSamples
|
|
@@ -11730,12 +12451,7 @@ const $4ab64e76c1caef59$var$ExprTable = ({ rows: rows, fields: fields, onReorder
|
|
|
11730
12451
|
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$aggridreact.AgGridReact), {
|
|
11731
12452
|
rowData: rows,
|
|
11732
12453
|
columnDefs: columnDefs,
|
|
11733
|
-
defaultColDef:
|
|
11734
|
-
resizable: true,
|
|
11735
|
-
sortable: true,
|
|
11736
|
-
filter: false,
|
|
11737
|
-
suppressMenu: true
|
|
11738
|
-
},
|
|
12454
|
+
defaultColDef: $4ab64e76c1caef59$var$DEFAULT_COL_DEF,
|
|
11739
12455
|
animateRows: false,
|
|
11740
12456
|
suppressFieldDotNotation: true,
|
|
11741
12457
|
suppressDragLeaveHidesColumns: true,
|
|
@@ -12071,564 +12787,1384 @@ const $caf32827df861c4e$var$ParallelCoordsPlot = ({ rows: rows, fields: fields,
|
|
|
12071
12787
|
const target = paths.filter(function() {
|
|
12072
12788
|
return this.getAttribute('data-id') === String(hoveredId);
|
|
12073
12789
|
});
|
|
12074
|
-
target.classed('exprviz-pc-line-hover', true).raise();
|
|
12075
|
-
}, [
|
|
12076
|
-
hoveredId,
|
|
12077
|
-
rows,
|
|
12078
|
-
fields,
|
|
12079
|
-
scale
|
|
12080
|
-
]);
|
|
12081
|
-
if (!fields || fields.length === 0) return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
12082
|
-
className: "exprviz-plot-empty",
|
|
12083
|
-
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("em", {
|
|
12084
|
-
children: "Select fields to plot."
|
|
12085
|
-
})
|
|
12790
|
+
target.classed('exprviz-pc-line-hover', true).raise();
|
|
12791
|
+
}, [
|
|
12792
|
+
hoveredId,
|
|
12793
|
+
rows,
|
|
12794
|
+
fields,
|
|
12795
|
+
scale
|
|
12796
|
+
]);
|
|
12797
|
+
if (!fields || fields.length === 0) return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
12798
|
+
className: "exprviz-plot-empty",
|
|
12799
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("em", {
|
|
12800
|
+
children: "Select fields to plot."
|
|
12801
|
+
})
|
|
12802
|
+
});
|
|
12803
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
12804
|
+
ref: containerRef,
|
|
12805
|
+
className: "exprviz-pc-container",
|
|
12806
|
+
children: [
|
|
12807
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("svg", {
|
|
12808
|
+
ref: svgRef,
|
|
12809
|
+
width: "100%",
|
|
12810
|
+
height: "100%",
|
|
12811
|
+
preserveAspectRatio: "none"
|
|
12812
|
+
}),
|
|
12813
|
+
tooltip && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($caf32827df861c4e$var$AxisTooltip, {
|
|
12814
|
+
x: tooltip.x,
|
|
12815
|
+
y: tooltip.y,
|
|
12816
|
+
info: tooltip.info
|
|
12817
|
+
})
|
|
12818
|
+
]
|
|
12819
|
+
});
|
|
12820
|
+
};
|
|
12821
|
+
// Position-fixed so it can escape the plot pane's clipping. Offset slightly
|
|
12822
|
+
// from the cursor and clamped to the viewport so it never spills off-screen.
|
|
12823
|
+
const $caf32827df861c4e$var$AxisTooltip = ({ x: x, y: y, info: info })=>{
|
|
12824
|
+
const ref = (0, $gXNCa$react.useRef)(null);
|
|
12825
|
+
const [pos, setPos] = (0, $gXNCa$react.useState)({
|
|
12826
|
+
left: x + 12,
|
|
12827
|
+
top: y + 12
|
|
12828
|
+
});
|
|
12829
|
+
(0, $gXNCa$react.useEffect)(()=>{
|
|
12830
|
+
const el = ref.current;
|
|
12831
|
+
if (!el) return;
|
|
12832
|
+
const w = el.offsetWidth;
|
|
12833
|
+
const h = el.offsetHeight;
|
|
12834
|
+
const vw = window.innerWidth;
|
|
12835
|
+
const vh = window.innerHeight;
|
|
12836
|
+
let left = x + 12;
|
|
12837
|
+
let top = y + 12;
|
|
12838
|
+
if (left + w > vw - 4) left = Math.max(4, x - 12 - w);
|
|
12839
|
+
if (top + h > vh - 4) top = Math.max(4, y - 12 - h);
|
|
12840
|
+
setPos({
|
|
12841
|
+
left: left,
|
|
12842
|
+
top: top
|
|
12843
|
+
});
|
|
12844
|
+
}, [
|
|
12845
|
+
x,
|
|
12846
|
+
y,
|
|
12847
|
+
info
|
|
12848
|
+
]);
|
|
12849
|
+
const { studyTitle: studyTitle, group: group, factors: factors, characteristics: characteristics } = info;
|
|
12850
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
12851
|
+
ref: ref,
|
|
12852
|
+
className: "exprviz-pc-tooltip",
|
|
12853
|
+
style: pos,
|
|
12854
|
+
children: [
|
|
12855
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
12856
|
+
children: [
|
|
12857
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
|
|
12858
|
+
className: "exprviz-pc-tip-key",
|
|
12859
|
+
children: "Study:"
|
|
12860
|
+
}),
|
|
12861
|
+
" ",
|
|
12862
|
+
studyTitle,
|
|
12863
|
+
group ? ` (${group})` : ''
|
|
12864
|
+
]
|
|
12865
|
+
}),
|
|
12866
|
+
factors.length > 0 && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactjsxruntime.Fragment), {
|
|
12867
|
+
children: [
|
|
12868
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
12869
|
+
className: "exprviz-pc-tip-section",
|
|
12870
|
+
children: "Factors"
|
|
12871
|
+
}),
|
|
12872
|
+
factors.map((p, i)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
12873
|
+
className: "exprviz-pc-tip-row",
|
|
12874
|
+
children: [
|
|
12875
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("span", {
|
|
12876
|
+
className: "exprviz-pc-tip-key",
|
|
12877
|
+
children: [
|
|
12878
|
+
p.name,
|
|
12879
|
+
":"
|
|
12880
|
+
]
|
|
12881
|
+
}),
|
|
12882
|
+
" ",
|
|
12883
|
+
p.value
|
|
12884
|
+
]
|
|
12885
|
+
}, `f-${i}`))
|
|
12886
|
+
]
|
|
12887
|
+
}),
|
|
12888
|
+
characteristics.length > 0 && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactjsxruntime.Fragment), {
|
|
12889
|
+
children: [
|
|
12890
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
12891
|
+
className: "exprviz-pc-tip-section",
|
|
12892
|
+
children: "Characteristics"
|
|
12893
|
+
}),
|
|
12894
|
+
characteristics.map((p, i)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
12895
|
+
className: "exprviz-pc-tip-row",
|
|
12896
|
+
children: [
|
|
12897
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("span", {
|
|
12898
|
+
className: "exprviz-pc-tip-key",
|
|
12899
|
+
children: [
|
|
12900
|
+
p.name,
|
|
12901
|
+
":"
|
|
12902
|
+
]
|
|
12903
|
+
}),
|
|
12904
|
+
" ",
|
|
12905
|
+
p.value
|
|
12906
|
+
]
|
|
12907
|
+
}, `c-${i}`))
|
|
12908
|
+
]
|
|
12909
|
+
})
|
|
12910
|
+
]
|
|
12911
|
+
});
|
|
12912
|
+
};
|
|
12913
|
+
var $caf32827df861c4e$export$2e2bcd8739ae039 = $caf32827df861c4e$var$ParallelCoordsPlot;
|
|
12914
|
+
|
|
12915
|
+
|
|
12916
|
+
|
|
12917
|
+
function $1fd2507769d5bd00$var$speciesTaxonId(tid) {
|
|
12918
|
+
const n = +tid;
|
|
12919
|
+
return n > 1000000 ? Math.floor(n / 1000) : n;
|
|
12920
|
+
}
|
|
12921
|
+
function $1fd2507769d5bd00$var$genomeName(grameneMaps, tid) {
|
|
12922
|
+
if (!grameneMaps) return tid;
|
|
12923
|
+
const direct = grameneMaps[tid];
|
|
12924
|
+
if (direct && direct.display_name) return direct.display_name;
|
|
12925
|
+
const sp = grameneMaps[$1fd2507769d5bd00$var$speciesTaxonId(tid)];
|
|
12926
|
+
if (sp && sp.display_name) return sp.display_name;
|
|
12927
|
+
return tid;
|
|
12928
|
+
}
|
|
12929
|
+
const $1fd2507769d5bd00$var$ExprVizViewCmp = (props)=>{
|
|
12930
|
+
const { exprVizPivot: pivot, exprViz: exprViz, exprVizActiveTaxon: activeTaxon, grameneMaps: grameneMaps, expressionStudies: expressionStudies, expressionSamples: expressionSamples, doSetExprVizActiveTaxon: doSetExprVizActiveTaxon, doToggleExprVizFieldsModal: doToggleExprVizFieldsModal, doFetchExprVizData: doFetchExprVizData } = props;
|
|
12931
|
+
const studiesFor = (tid)=>{
|
|
12932
|
+
if (!expressionStudies) return [];
|
|
12933
|
+
return expressionStudies[tid] || expressionStudies[$1fd2507769d5bd00$var$speciesTaxonId(tid)] || [];
|
|
12934
|
+
};
|
|
12935
|
+
const taxa = (0, $gXNCa$react.useMemo)(()=>{
|
|
12936
|
+
const ids = Object.keys(pivot.data || {});
|
|
12937
|
+
if (!grameneMaps) return ids;
|
|
12938
|
+
return ids.sort((a, b)=>{
|
|
12939
|
+
const ma = grameneMaps[a] || grameneMaps[$1fd2507769d5bd00$var$speciesTaxonId(a)];
|
|
12940
|
+
const mb = grameneMaps[b] || grameneMaps[$1fd2507769d5bd00$var$speciesTaxonId(b)];
|
|
12941
|
+
return (ma && ma.left_index || 0) - (mb && mb.left_index || 0);
|
|
12942
|
+
});
|
|
12943
|
+
}, [
|
|
12944
|
+
pivot.data,
|
|
12945
|
+
grameneMaps
|
|
12946
|
+
]);
|
|
12947
|
+
(0, $gXNCa$react.useEffect)(()=>{
|
|
12948
|
+
if (taxa.length === 0) return;
|
|
12949
|
+
if (!activeTaxon || !taxa.includes(String(activeTaxon))) doSetExprVizActiveTaxon(taxa[0]);
|
|
12950
|
+
}, [
|
|
12951
|
+
taxa,
|
|
12952
|
+
activeTaxon,
|
|
12953
|
+
doSetExprVizActiveTaxon
|
|
12954
|
+
]);
|
|
12955
|
+
if (pivot.status === 'loading') return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
12956
|
+
className: "exprviz-view",
|
|
12957
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("em", {
|
|
12958
|
+
children: "Loading studies\u2026"
|
|
12959
|
+
})
|
|
12960
|
+
});
|
|
12961
|
+
if (pivot.status === 'error') return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
12962
|
+
className: "exprviz-view",
|
|
12963
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("em", {
|
|
12964
|
+
children: [
|
|
12965
|
+
"Error: ",
|
|
12966
|
+
pivot.error
|
|
12967
|
+
]
|
|
12968
|
+
})
|
|
12969
|
+
});
|
|
12970
|
+
if (taxa.length === 0) return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
12971
|
+
className: "exprviz-view",
|
|
12972
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("em", {
|
|
12973
|
+
children: "No expression studies for current results."
|
|
12974
|
+
})
|
|
12975
|
+
});
|
|
12976
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
12977
|
+
className: "exprviz-view",
|
|
12978
|
+
children: [
|
|
12979
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Tabs), {
|
|
12980
|
+
activeKey: activeTaxon || taxa[0],
|
|
12981
|
+
onSelect: (k)=>doSetExprVizActiveTaxon(k),
|
|
12982
|
+
className: "exprviz-tabs",
|
|
12983
|
+
children: taxa.map((tid)=>{
|
|
12984
|
+
const studies = studiesFor(tid);
|
|
12985
|
+
const taxName = $1fd2507769d5bd00$var$genomeName(grameneMaps, tid);
|
|
12986
|
+
const geneCount = pivot.data[tid] || 0;
|
|
12987
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Tab), {
|
|
12988
|
+
eventKey: tid,
|
|
12989
|
+
title: `${taxName} (${studies.length} studies \xb7 ${geneCount} genes)`,
|
|
12990
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($1fd2507769d5bd00$var$TaxonPanel, {
|
|
12991
|
+
taxon: tid,
|
|
12992
|
+
studies: studies,
|
|
12993
|
+
expressionSamples: expressionSamples,
|
|
12994
|
+
tabState: exprViz.byTaxon[tid],
|
|
12995
|
+
onOpenFields: ()=>doToggleExprVizFieldsModal(tid, true),
|
|
12996
|
+
onLoad: ()=>doFetchExprVizData(tid),
|
|
12997
|
+
onReorder: (next)=>props.doReorderExprVizFields(tid, next),
|
|
12998
|
+
onAddRangeQuery: props.doAddGrameneRangeQuery
|
|
12999
|
+
})
|
|
13000
|
+
}, tid);
|
|
13001
|
+
})
|
|
13002
|
+
}),
|
|
13003
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $4d0c2e01f58b53b1$export$2e2bcd8739ae039), {})
|
|
13004
|
+
]
|
|
13005
|
+
});
|
|
13006
|
+
};
|
|
13007
|
+
// Compact axis labels for the parallel-coords plot. The raw Solr field name
|
|
13008
|
+
// (e.g. "E_CURD_148_g5__expr") is uninformative; we prefer the assay's
|
|
13009
|
+
// factor labels, falling back to "organism part" then to the group id.
|
|
13010
|
+
// `full` is exposed via an SVG <title> so the user can hover to see study,
|
|
13011
|
+
// group, and every factor/characteristic.
|
|
13012
|
+
const $1fd2507769d5bd00$var$AXIS_LABEL_MAX = 22;
|
|
13013
|
+
function $1fd2507769d5bd00$var$truncateLabel(s, n) {
|
|
13014
|
+
if (!s) return '';
|
|
13015
|
+
return s.length > n ? s.slice(0, n - 1) + "\u2026" : s;
|
|
13016
|
+
}
|
|
13017
|
+
function $1fd2507769d5bd00$var$compactAssayLabel(assay, group) {
|
|
13018
|
+
if (!assay) return group || '';
|
|
13019
|
+
const factorVals = (assay.factor || []).map((f)=>f && f.label).filter(Boolean);
|
|
13020
|
+
if (factorVals.length) return factorVals.join('; ');
|
|
13021
|
+
const chars = assay.characteristic || [];
|
|
13022
|
+
const organ = chars.find((c)=>c && c.type === 'organism part');
|
|
13023
|
+
if (organ && organ.label) return organ.label;
|
|
13024
|
+
const firstChar = chars.find((c)=>c && c.label);
|
|
13025
|
+
if (firstChar) return firstChar.label;
|
|
13026
|
+
return group || '';
|
|
13027
|
+
}
|
|
13028
|
+
function $1fd2507769d5bd00$var$assayPairs(list) {
|
|
13029
|
+
return (list || []).filter((x)=>x && x.label).map((x)=>({
|
|
13030
|
+
name: x.type || '',
|
|
13031
|
+
value: x.label
|
|
13032
|
+
}));
|
|
13033
|
+
}
|
|
13034
|
+
function $1fd2507769d5bd00$var$buildAxisLabels(fields, studies, expressionSamples) {
|
|
13035
|
+
const labels = {};
|
|
13036
|
+
if (!fields) return labels;
|
|
13037
|
+
const studyById = {};
|
|
13038
|
+
(studies || []).forEach((s)=>{
|
|
13039
|
+
if (s && s._id) studyById[s._id] = s;
|
|
13040
|
+
});
|
|
13041
|
+
const findAssay = (studyId, group)=>{
|
|
13042
|
+
const arr = expressionSamples && expressionSamples[studyId];
|
|
13043
|
+
return arr ? arr.find((a)=>a.group === group) : null;
|
|
13044
|
+
};
|
|
13045
|
+
for (const f of fields){
|
|
13046
|
+
const m = f.match(/^(.+?)_g(\d+)__expr$/);
|
|
13047
|
+
if (!m) {
|
|
13048
|
+
labels[f] = {
|
|
13049
|
+
short: $1fd2507769d5bd00$var$truncateLabel(f.replace(/__expr$/, ''), $1fd2507769d5bd00$var$AXIS_LABEL_MAX),
|
|
13050
|
+
structured: {
|
|
13051
|
+
studyTitle: f,
|
|
13052
|
+
group: '',
|
|
13053
|
+
factors: [],
|
|
13054
|
+
characteristics: []
|
|
13055
|
+
}
|
|
13056
|
+
};
|
|
13057
|
+
continue;
|
|
13058
|
+
}
|
|
13059
|
+
const expId = m[1].replace(/_/g, '-');
|
|
13060
|
+
const group = 'g' + m[2];
|
|
13061
|
+
const assay = findAssay(expId, group);
|
|
13062
|
+
const study = studyById[expId];
|
|
13063
|
+
const studyName = study && study.description || expId;
|
|
13064
|
+
labels[f] = {
|
|
13065
|
+
short: $1fd2507769d5bd00$var$truncateLabel($1fd2507769d5bd00$var$compactAssayLabel(assay, group), $1fd2507769d5bd00$var$AXIS_LABEL_MAX),
|
|
13066
|
+
structured: {
|
|
13067
|
+
studyTitle: studyName,
|
|
13068
|
+
group: group,
|
|
13069
|
+
factors: $1fd2507769d5bd00$var$assayPairs(assay && assay.factor),
|
|
13070
|
+
characteristics: $1fd2507769d5bd00$var$assayPairs(assay && assay.characteristic)
|
|
13071
|
+
}
|
|
13072
|
+
};
|
|
13073
|
+
}
|
|
13074
|
+
return labels;
|
|
13075
|
+
}
|
|
13076
|
+
function $1fd2507769d5bd00$var$rowMatchesSelections(row, selections) {
|
|
13077
|
+
for (const f of Object.keys(selections)){
|
|
13078
|
+
const v = row[f];
|
|
13079
|
+
if (v == null || Array.isArray(v)) return false;
|
|
13080
|
+
const n = +v;
|
|
13081
|
+
if (!Number.isFinite(n)) return false;
|
|
13082
|
+
const [lo, hi] = selections[f];
|
|
13083
|
+
if (n < lo || n > hi) return false;
|
|
13084
|
+
}
|
|
13085
|
+
return true;
|
|
13086
|
+
}
|
|
13087
|
+
function $1fd2507769d5bd00$var$fmt(n) {
|
|
13088
|
+
if (!Number.isFinite(n)) return String(n);
|
|
13089
|
+
const a = Math.abs(n);
|
|
13090
|
+
if (a !== 0 && (a < 0.001 || a >= 1e6)) return n.toExponential(3);
|
|
13091
|
+
return Number(n.toFixed(4)).toString();
|
|
13092
|
+
}
|
|
13093
|
+
function $1fd2507769d5bd00$var$tsvCell(v) {
|
|
13094
|
+
if (v == null) return '';
|
|
13095
|
+
if (Array.isArray(v)) return v.join(',');
|
|
13096
|
+
const s = typeof v === 'object' ? JSON.stringify(v) : String(v);
|
|
13097
|
+
return s.replace(/[\t\r\n]+/g, ' ');
|
|
13098
|
+
}
|
|
13099
|
+
// Mirror the on-screen table header in the TSV: one row per metadata level
|
|
13100
|
+
// the table is showing (Study, then one row per distinct factor type, then
|
|
13101
|
+
// one row per distinct characteristic type), followed by the leaf header
|
|
13102
|
+
// (Gene ID / Name / per-sample group). The first two columns are repurposed
|
|
13103
|
+
// to carry the row category and the row's specific name, matching the
|
|
13104
|
+
// pinned-column labels in ExprTable.
|
|
13105
|
+
function $1fd2507769d5bd00$var$downloadTsv(filename, rows, fields, studies, expressionSamples) {
|
|
13106
|
+
const cols = [
|
|
13107
|
+
'id',
|
|
13108
|
+
'name',
|
|
13109
|
+
...fields
|
|
13110
|
+
];
|
|
13111
|
+
const fieldInfo = (0, $4ab64e76c1caef59$export$7b242440eb2c300d)(fields, studies, expressionSamples);
|
|
13112
|
+
const factorTypes = new Set();
|
|
13113
|
+
const charTypes = new Set();
|
|
13114
|
+
for (const f of fields){
|
|
13115
|
+
const info = fieldInfo[f];
|
|
13116
|
+
if (!info) continue;
|
|
13117
|
+
Object.keys(info.factors || {}).forEach((t)=>factorTypes.add(t));
|
|
13118
|
+
Object.keys(info.characteristics || {}).forEach((t)=>charTypes.add(t));
|
|
13119
|
+
}
|
|
13120
|
+
const factorTypeList = Array.from(factorTypes).sort();
|
|
13121
|
+
const charTypeList = Array.from(charTypes).sort();
|
|
13122
|
+
const metaRow = (cat, label, getValue)=>{
|
|
13123
|
+
const cells = [
|
|
13124
|
+
cat,
|
|
13125
|
+
label
|
|
13126
|
+
];
|
|
13127
|
+
for (const f of fields)cells.push($1fd2507769d5bd00$var$tsvCell(getValue(fieldInfo[f] || {})));
|
|
13128
|
+
return cells.join('\t');
|
|
13129
|
+
};
|
|
13130
|
+
const lines = [];
|
|
13131
|
+
lines.push(metaRow('Study', 'Title', (info)=>info.studyDescription || ''));
|
|
13132
|
+
for (const t of factorTypeList)lines.push(metaRow('Factor', t, (info)=>info.factors && info.factors[t] || ''));
|
|
13133
|
+
for (const t of charTypeList)lines.push(metaRow('Characteristic', t, (info)=>info.characteristics && info.characteristics[t] || ''));
|
|
13134
|
+
// Leaf header — column ids for the data rows.
|
|
13135
|
+
lines.push([
|
|
13136
|
+
'Gene ID',
|
|
13137
|
+
'Name',
|
|
13138
|
+
...fields.map((f)=>{
|
|
13139
|
+
const info = fieldInfo[f];
|
|
13140
|
+
return info && info.group || f.replace(/__expr$/, '');
|
|
13141
|
+
})
|
|
13142
|
+
].join('\t'));
|
|
13143
|
+
for (const r of rows)lines.push(cols.map((c)=>$1fd2507769d5bd00$var$tsvCell(r[c])).join('\t'));
|
|
13144
|
+
const blob = new Blob([
|
|
13145
|
+
lines.join('\n') + '\n'
|
|
13146
|
+
], {
|
|
13147
|
+
type: 'text/tab-separated-values'
|
|
13148
|
+
});
|
|
13149
|
+
const url = URL.createObjectURL(blob);
|
|
13150
|
+
const a = document.createElement('a');
|
|
13151
|
+
a.href = url;
|
|
13152
|
+
a.download = filename;
|
|
13153
|
+
document.body.appendChild(a);
|
|
13154
|
+
a.click();
|
|
13155
|
+
document.body.removeChild(a);
|
|
13156
|
+
URL.revokeObjectURL(url);
|
|
13157
|
+
}
|
|
13158
|
+
const $1fd2507769d5bd00$var$TaxonPanel = ({ taxon: taxon, studies: studies, expressionSamples: expressionSamples, tabState: tabState, onOpenFields: onOpenFields, onLoad: onLoad, onReorder: onReorder, onAddRangeQuery: onAddRangeQuery })=>{
|
|
13159
|
+
const selected = tabState && tabState.selectedFields || [];
|
|
13160
|
+
const rows = tabState && tabState.rows || [];
|
|
13161
|
+
const fetchInfo = tabState && tabState.fetch || {
|
|
13162
|
+
status: 'idle',
|
|
13163
|
+
total: 0
|
|
13164
|
+
};
|
|
13165
|
+
const [scale, setScale] = (0, $gXNCa$react.useState)('linear');
|
|
13166
|
+
const [selections, setSelections] = (0, $gXNCa$react.useState)({});
|
|
13167
|
+
const [clearVersion, setClearVersion] = (0, $gXNCa$react.useState)(0);
|
|
13168
|
+
const [hoveredId, setHoveredId] = (0, $gXNCa$react.useState)(null);
|
|
13169
|
+
const [plotHeight, setPlotHeight] = (0, $gXNCa$react.useState)(320);
|
|
13170
|
+
const resizeStateRef = (0, $gXNCa$react.useRef)(null);
|
|
13171
|
+
// Drag the horizontal separator between the plot and the table to retune
|
|
13172
|
+
// their relative sizes. Bounded so neither pane disappears entirely.
|
|
13173
|
+
const startResize = (e)=>{
|
|
13174
|
+
e.preventDefault();
|
|
13175
|
+
resizeStateRef.current = {
|
|
13176
|
+
startY: e.clientY,
|
|
13177
|
+
startHeight: plotHeight
|
|
13178
|
+
};
|
|
13179
|
+
const onMove = (ev)=>{
|
|
13180
|
+
const s = resizeStateRef.current;
|
|
13181
|
+
if (!s) return;
|
|
13182
|
+
const next = Math.max(120, Math.min(1200, s.startHeight + (ev.clientY - s.startY)));
|
|
13183
|
+
setPlotHeight(next);
|
|
13184
|
+
};
|
|
13185
|
+
const onUp = ()=>{
|
|
13186
|
+
resizeStateRef.current = null;
|
|
13187
|
+
document.removeEventListener('mousemove', onMove);
|
|
13188
|
+
document.removeEventListener('mouseup', onUp);
|
|
13189
|
+
document.body.style.cursor = '';
|
|
13190
|
+
document.body.style.userSelect = '';
|
|
13191
|
+
};
|
|
13192
|
+
document.body.style.cursor = 'row-resize';
|
|
13193
|
+
document.body.style.userSelect = 'none';
|
|
13194
|
+
document.addEventListener('mousemove', onMove);
|
|
13195
|
+
document.addEventListener('mouseup', onUp);
|
|
13196
|
+
};
|
|
13197
|
+
const hasBrush = Object.keys(selections).length > 0;
|
|
13198
|
+
const filteredRows = (0, $gXNCa$react.useMemo)(()=>{
|
|
13199
|
+
if (!hasBrush) return rows;
|
|
13200
|
+
return rows.filter((r)=>$1fd2507769d5bd00$var$rowMatchesSelections(r, selections));
|
|
13201
|
+
}, [
|
|
13202
|
+
rows,
|
|
13203
|
+
selections,
|
|
13204
|
+
hasBrush
|
|
13205
|
+
]);
|
|
13206
|
+
// Drop fields with no numeric data in the loaded rows so empty axes/columns
|
|
13207
|
+
// don't clutter the visualization. Selected-but-empty fields stay in the
|
|
13208
|
+
// underlying selection so a future load can repopulate them.
|
|
13209
|
+
const visibleFields = (0, $gXNCa$react.useMemo)(()=>{
|
|
13210
|
+
if (rows.length === 0 || selected.length === 0) return selected;
|
|
13211
|
+
return selected.filter((f)=>rows.some((r)=>{
|
|
13212
|
+
const v = r[f];
|
|
13213
|
+
return v != null && !Array.isArray(v) && Number.isFinite(+v);
|
|
13214
|
+
}));
|
|
13215
|
+
}, [
|
|
13216
|
+
rows,
|
|
13217
|
+
selected
|
|
13218
|
+
]);
|
|
13219
|
+
const handleReorder = onReorder ? (newVisibleOrder)=>{
|
|
13220
|
+
const visibleSet = new Set(newVisibleOrder);
|
|
13221
|
+
const hidden = selected.filter((f)=>!visibleSet.has(f));
|
|
13222
|
+
onReorder([
|
|
13223
|
+
...newVisibleOrder,
|
|
13224
|
+
...hidden
|
|
13225
|
+
]);
|
|
13226
|
+
} : undefined;
|
|
13227
|
+
const axisLabels = (0, $gXNCa$react.useMemo)(()=>$1fd2507769d5bd00$var$buildAxisLabels(visibleFields, studies, expressionSamples), [
|
|
13228
|
+
visibleFields,
|
|
13229
|
+
studies,
|
|
13230
|
+
expressionSamples
|
|
13231
|
+
]);
|
|
13232
|
+
(0, $gXNCa$react.useEffect)(()=>{
|
|
13233
|
+
if (rows.length === 0 && hasBrush) {
|
|
13234
|
+
setSelections({});
|
|
13235
|
+
setClearVersion((v)=>v + 1);
|
|
13236
|
+
}
|
|
13237
|
+
}, [
|
|
13238
|
+
rows.length,
|
|
13239
|
+
hasBrush
|
|
13240
|
+
]);
|
|
13241
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
13242
|
+
className: "exprviz-tab-panel",
|
|
13243
|
+
children: [
|
|
13244
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
13245
|
+
className: "exprviz-toolbar",
|
|
13246
|
+
children: [
|
|
13247
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactbootstrap.Button), {
|
|
13248
|
+
size: "sm",
|
|
13249
|
+
onClick: onOpenFields,
|
|
13250
|
+
children: [
|
|
13251
|
+
"Select fields (",
|
|
13252
|
+
selected.length,
|
|
13253
|
+
" selected, ",
|
|
13254
|
+
studies.length,
|
|
13255
|
+
" studies)"
|
|
13256
|
+
]
|
|
13257
|
+
}),
|
|
13258
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
|
|
13259
|
+
size: "sm",
|
|
13260
|
+
variant: "primary",
|
|
13261
|
+
disabled: selected.length === 0 || fetchInfo.status === 'loading',
|
|
13262
|
+
onClick: onLoad,
|
|
13263
|
+
children: fetchInfo.status === 'loading' ? "Loading\u2026" : 'Load data'
|
|
13264
|
+
}),
|
|
13265
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactbootstrap.ToggleButtonGroup), {
|
|
13266
|
+
type: "radio",
|
|
13267
|
+
name: `exprviz-scale-${taxon}`,
|
|
13268
|
+
size: "sm",
|
|
13269
|
+
value: scale,
|
|
13270
|
+
onChange: setScale,
|
|
13271
|
+
children: [
|
|
13272
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.ToggleButton), {
|
|
13273
|
+
id: `exprviz-scale-${taxon}-lin`,
|
|
13274
|
+
value: "linear",
|
|
13275
|
+
variant: "outline-secondary",
|
|
13276
|
+
children: "Linear"
|
|
13277
|
+
}),
|
|
13278
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.ToggleButton), {
|
|
13279
|
+
id: `exprviz-scale-${taxon}-log`,
|
|
13280
|
+
value: "log",
|
|
13281
|
+
variant: "outline-secondary",
|
|
13282
|
+
children: "Log"
|
|
13283
|
+
})
|
|
13284
|
+
]
|
|
13285
|
+
}),
|
|
13286
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
|
|
13287
|
+
size: "sm",
|
|
13288
|
+
variant: "outline-secondary",
|
|
13289
|
+
disabled: !hasBrush,
|
|
13290
|
+
onClick: ()=>{
|
|
13291
|
+
setClearVersion((v)=>v + 1);
|
|
13292
|
+
setSelections({});
|
|
13293
|
+
},
|
|
13294
|
+
children: "Clear brushes"
|
|
13295
|
+
}),
|
|
13296
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
|
|
13297
|
+
size: "sm",
|
|
13298
|
+
variant: "outline-secondary",
|
|
13299
|
+
disabled: filteredRows.length === 0 || visibleFields.length === 0,
|
|
13300
|
+
onClick: ()=>$1fd2507769d5bd00$var$downloadTsv(`expression_${taxon}.tsv`, filteredRows, visibleFields, studies, expressionSamples),
|
|
13301
|
+
title: "Download the visible rows and columns as tab-delimited text",
|
|
13302
|
+
children: "Download TSV"
|
|
13303
|
+
}),
|
|
13304
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
|
|
13305
|
+
size: "sm",
|
|
13306
|
+
variant: "success",
|
|
13307
|
+
disabled: !hasBrush || !onAddRangeQuery,
|
|
13308
|
+
onClick: ()=>{
|
|
13309
|
+
const terms = Object.keys(selections).map((field)=>{
|
|
13310
|
+
const [lo, hi] = selections[field];
|
|
13311
|
+
return {
|
|
13312
|
+
category: 'Expression',
|
|
13313
|
+
name: `${field}: ${$1fd2507769d5bd00$var$fmt(lo)}\u{2013}${$1fd2507769d5bd00$var$fmt(hi)}`,
|
|
13314
|
+
fq_field: field,
|
|
13315
|
+
fq_value: `[${lo} TO ${hi}]`
|
|
13316
|
+
};
|
|
13317
|
+
});
|
|
13318
|
+
onAddRangeQuery(terms);
|
|
13319
|
+
},
|
|
13320
|
+
title: "Add brush ranges as an AND-conjunction filter on the search",
|
|
13321
|
+
children: "Apply as filter"
|
|
13322
|
+
}),
|
|
13323
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("span", {
|
|
13324
|
+
className: "exprviz-status",
|
|
13325
|
+
children: [
|
|
13326
|
+
hasBrush ? `${filteredRows.length} of ${rows.length}` : rows.length,
|
|
13327
|
+
fetchInfo.total ? ` / ${fetchInfo.total}` : '',
|
|
13328
|
+
" genes",
|
|
13329
|
+
hasBrush ? ' (brushed)' : ' loaded'
|
|
13330
|
+
]
|
|
13331
|
+
})
|
|
13332
|
+
]
|
|
13333
|
+
}),
|
|
13334
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
13335
|
+
className: "exprviz-body",
|
|
13336
|
+
children: [
|
|
13337
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
13338
|
+
className: "exprviz-plot",
|
|
13339
|
+
style: {
|
|
13340
|
+
height: plotHeight
|
|
13341
|
+
},
|
|
13342
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $caf32827df861c4e$export$2e2bcd8739ae039), {
|
|
13343
|
+
rows: rows,
|
|
13344
|
+
fields: visibleFields,
|
|
13345
|
+
scale: scale,
|
|
13346
|
+
onBrushChange: setSelections,
|
|
13347
|
+
onReorder: handleReorder,
|
|
13348
|
+
clearVersion: clearVersion,
|
|
13349
|
+
hoveredId: hoveredId,
|
|
13350
|
+
axisLabels: axisLabels
|
|
13351
|
+
})
|
|
13352
|
+
}),
|
|
13353
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
13354
|
+
className: "exprviz-resizer",
|
|
13355
|
+
role: "separator",
|
|
13356
|
+
"aria-orientation": "horizontal",
|
|
13357
|
+
"aria-label": "Resize plot",
|
|
13358
|
+
onMouseDown: startResize,
|
|
13359
|
+
title: "Drag to resize"
|
|
13360
|
+
}),
|
|
13361
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
13362
|
+
className: "exprviz-table",
|
|
13363
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $4ab64e76c1caef59$export$2e2bcd8739ae039), {
|
|
13364
|
+
rows: filteredRows,
|
|
13365
|
+
fields: visibleFields,
|
|
13366
|
+
onReorder: handleReorder,
|
|
13367
|
+
studies: studies,
|
|
13368
|
+
expressionSamples: expressionSamples,
|
|
13369
|
+
onHoverRow: setHoveredId
|
|
13370
|
+
})
|
|
13371
|
+
})
|
|
13372
|
+
]
|
|
13373
|
+
})
|
|
13374
|
+
]
|
|
13375
|
+
});
|
|
13376
|
+
};
|
|
13377
|
+
var $1fd2507769d5bd00$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.connect)('selectExprViz', 'selectExprVizPivot', 'selectExprVizActiveTaxon', 'selectGrameneMaps', 'selectExpressionStudies', 'selectExpressionSamples', 'doSetExprVizActiveTaxon', 'doToggleExprVizFieldsModal', 'doFetchExprVizData', 'doReorderExprVizFields', 'doAddGrameneRangeQuery', $1fd2507769d5bd00$var$ExprVizViewCmp);
|
|
13378
|
+
|
|
13379
|
+
|
|
13380
|
+
|
|
13381
|
+
|
|
13382
|
+
|
|
13383
|
+
|
|
13384
|
+
|
|
13385
|
+
|
|
13386
|
+
function $f511198465122338$var$speciesTaxonId(tid) {
|
|
13387
|
+
const n = +tid;
|
|
13388
|
+
return n > 1000000 ? Math.floor(n / 1000) : n;
|
|
13389
|
+
}
|
|
13390
|
+
function $f511198465122338$var$genomeName(grameneMaps, tid) {
|
|
13391
|
+
if (!grameneMaps) return String(tid);
|
|
13392
|
+
const direct = grameneMaps[tid];
|
|
13393
|
+
if (direct && direct.display_name) return direct.display_name;
|
|
13394
|
+
const sp = grameneMaps[$f511198465122338$var$speciesTaxonId(tid)];
|
|
13395
|
+
if (sp && sp.display_name) return sp.display_name;
|
|
13396
|
+
return String(tid);
|
|
13397
|
+
}
|
|
13398
|
+
function $f511198465122338$var$fmtP(p) {
|
|
13399
|
+
if (p == null) return '';
|
|
13400
|
+
if (p === 0) return '0';
|
|
13401
|
+
if (p < 1e-4) return p.toExponential(2);
|
|
13402
|
+
return p.toPrecision(3);
|
|
13403
|
+
}
|
|
13404
|
+
function $f511198465122338$var$fmtFold(f) {
|
|
13405
|
+
if (!isFinite(f)) return '';
|
|
13406
|
+
if (f >= 100) return f.toFixed(0);
|
|
13407
|
+
return f.toFixed(2);
|
|
13408
|
+
}
|
|
13409
|
+
// ---------- species tree helpers ----------
|
|
13410
|
+
function $f511198465122338$var$findRoots(tax) {
|
|
13411
|
+
return Object.values(tax).filter((n)=>!n.is_a || n.is_a.length === 0 || !n.is_a.some((p)=>tax[p]));
|
|
13412
|
+
}
|
|
13413
|
+
// Place each facet tid onto a taxonomy node id (fall back to species level
|
|
13414
|
+
// when the exact subspecies tid isn't in grameneTaxonomy).
|
|
13415
|
+
function $f511198465122338$var$placeTaxa(taxonomy, taxa) {
|
|
13416
|
+
const placement = {};
|
|
13417
|
+
const byPlace = {};
|
|
13418
|
+
for (const { tid: tid, count: count } of taxa){
|
|
13419
|
+
const place = taxonomy[tid] ? +tid : $f511198465122338$var$speciesTaxonId(tid);
|
|
13420
|
+
placement[tid] = place;
|
|
13421
|
+
if (!byPlace[place]) byPlace[place] = [];
|
|
13422
|
+
byPlace[place].push({
|
|
13423
|
+
tid: tid,
|
|
13424
|
+
count: count
|
|
13425
|
+
});
|
|
13426
|
+
}
|
|
13427
|
+
return {
|
|
13428
|
+
placement: placement,
|
|
13429
|
+
byPlace: byPlace
|
|
13430
|
+
};
|
|
13431
|
+
}
|
|
13432
|
+
// Set of taxonomy node ids on the path from any placed leaf back to its root.
|
|
13433
|
+
function $f511198465122338$var$relevantNodeIds(taxonomy, byPlace) {
|
|
13434
|
+
const out = new Set();
|
|
13435
|
+
for (const placeId of Object.keys(byPlace)){
|
|
13436
|
+
let cur = taxonomy[placeId];
|
|
13437
|
+
const seen = new Set();
|
|
13438
|
+
while(cur && !seen.has(+cur._id)){
|
|
13439
|
+
seen.add(+cur._id);
|
|
13440
|
+
out.add(+cur._id);
|
|
13441
|
+
const pid = cur.is_a && cur.is_a[0];
|
|
13442
|
+
cur = pid ? taxonomy[pid] : null;
|
|
13443
|
+
}
|
|
13444
|
+
}
|
|
13445
|
+
return out;
|
|
13446
|
+
}
|
|
13447
|
+
function $f511198465122338$var$relevantChildren(node, taxonomy, relevant) {
|
|
13448
|
+
return (node.children || []).map((cid)=>taxonomy[cid]).filter((c)=>c && relevant.has(+c._id));
|
|
13449
|
+
}
|
|
13450
|
+
// Walk down through single-relevant-child internal nodes to a branch / leaf.
|
|
13451
|
+
function $f511198465122338$var$compressChain(node, taxonomy, relevant, byPlace) {
|
|
13452
|
+
const chain = [
|
|
13453
|
+
node
|
|
13454
|
+
];
|
|
13455
|
+
let cur = node;
|
|
13456
|
+
while(true){
|
|
13457
|
+
if (byPlace[cur._id]) break; // node itself is a placed leaf
|
|
13458
|
+
const kids = $f511198465122338$var$relevantChildren(cur, taxonomy, relevant);
|
|
13459
|
+
if (kids.length !== 1) break;
|
|
13460
|
+
cur = kids[0];
|
|
13461
|
+
chain.push(cur);
|
|
13462
|
+
}
|
|
13463
|
+
return {
|
|
13464
|
+
chain: chain,
|
|
13465
|
+
terminal: cur
|
|
13466
|
+
};
|
|
13467
|
+
}
|
|
13468
|
+
const $f511198465122338$var$CHAIN_DISPLAY_MAX = 3;
|
|
13469
|
+
function $f511198465122338$var$renderChain(chain) {
|
|
13470
|
+
const nameOf = (n)=>n.short_name || n.name || String(n._id);
|
|
13471
|
+
if (chain.length <= $f511198465122338$var$CHAIN_DISPLAY_MAX) return chain.map((n, i)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, ($parcel$interopDefault($gXNCa$react))).Fragment, {
|
|
13472
|
+
children: [
|
|
13473
|
+
i > 0 && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
|
|
13474
|
+
className: "tax-sep",
|
|
13475
|
+
children: " \u203A "
|
|
13476
|
+
}),
|
|
13477
|
+
nameOf(n)
|
|
13478
|
+
]
|
|
13479
|
+
}, n._id));
|
|
13480
|
+
const first = chain[0];
|
|
13481
|
+
const last = chain[chain.length - 1];
|
|
13482
|
+
const middle = chain.slice(1, -1);
|
|
13483
|
+
const fullTitle = chain.map(nameOf).join(" \u203A ");
|
|
13484
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactjsxruntime.Fragment), {
|
|
13485
|
+
children: [
|
|
13486
|
+
nameOf(first),
|
|
13487
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
|
|
13488
|
+
className: "tax-sep",
|
|
13489
|
+
children: " \u203A "
|
|
13490
|
+
}),
|
|
13491
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("span", {
|
|
13492
|
+
className: "tax-ellipsis",
|
|
13493
|
+
title: fullTitle,
|
|
13494
|
+
children: [
|
|
13495
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
|
|
13496
|
+
className: "tax-ellipsis-short",
|
|
13497
|
+
children: "\u2026"
|
|
13498
|
+
}),
|
|
13499
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
|
|
13500
|
+
className: "tax-ellipsis-full",
|
|
13501
|
+
children: middle.map((n)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, ($parcel$interopDefault($gXNCa$react))).Fragment, {
|
|
13502
|
+
children: [
|
|
13503
|
+
nameOf(n),
|
|
13504
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
|
|
13505
|
+
className: "tax-sep",
|
|
13506
|
+
children: " \u203A "
|
|
13507
|
+
})
|
|
13508
|
+
]
|
|
13509
|
+
}, n._id))
|
|
13510
|
+
})
|
|
13511
|
+
]
|
|
13512
|
+
}),
|
|
13513
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
|
|
13514
|
+
className: "tax-sep",
|
|
13515
|
+
children: " \u203A "
|
|
13516
|
+
}),
|
|
13517
|
+
nameOf(last)
|
|
13518
|
+
]
|
|
12086
13519
|
});
|
|
13520
|
+
}
|
|
13521
|
+
function $f511198465122338$var$dedupAdjacent(chain) {
|
|
13522
|
+
const out = [];
|
|
13523
|
+
for (const n of chain)if (out.length && out[out.length - 1].name === n.name) out[out.length - 1] = n;
|
|
13524
|
+
else out.push(n);
|
|
13525
|
+
return out;
|
|
13526
|
+
}
|
|
13527
|
+
const $f511198465122338$var$SpeciesTreeNode = ({ node: node, depth: depth, taxonomy: taxonomy, relevant: relevant, byPlace: byPlace, grameneMaps: grameneMaps, expanded: expanded, onToggleExpand: onToggleExpand, activeTaxon: activeTaxon, onSelect: onSelect })=>{
|
|
13528
|
+
const { chain: rawChain, terminal: terminal } = $f511198465122338$var$compressChain(node, taxonomy, relevant, byPlace);
|
|
13529
|
+
const chain = $f511198465122338$var$dedupAdjacent(rawChain);
|
|
13530
|
+
const placed = byPlace[terminal._id] || [];
|
|
13531
|
+
const kids = $f511198465122338$var$relevantChildren(terminal, taxonomy, relevant);
|
|
13532
|
+
const hasKids = kids.length > 0;
|
|
13533
|
+
const isOpen = expanded.has(+terminal._id);
|
|
12087
13534
|
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
12088
|
-
|
|
12089
|
-
className: "exprviz-pc-container",
|
|
13535
|
+
className: "tax-node gsea-tree-node",
|
|
12090
13536
|
children: [
|
|
12091
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.
|
|
12092
|
-
|
|
12093
|
-
|
|
12094
|
-
|
|
12095
|
-
|
|
13537
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
13538
|
+
className: "tax-row",
|
|
13539
|
+
style: {
|
|
13540
|
+
paddingLeft: depth * 7
|
|
13541
|
+
},
|
|
13542
|
+
children: [
|
|
13543
|
+
hasKids ? /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
|
|
13544
|
+
className: "tax-chevron",
|
|
13545
|
+
onClick: ()=>onToggleExpand(+terminal._id),
|
|
13546
|
+
children: isOpen ? /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reacticonsbs.BsChevronDown), {}) : /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reacticonsbs.BsChevronRight), {})
|
|
13547
|
+
}) : /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
|
|
13548
|
+
className: "tax-chevron-spacer"
|
|
13549
|
+
}),
|
|
13550
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
|
|
13551
|
+
className: hasKids ? 'tax-label tax-label-internal' : 'tax-label',
|
|
13552
|
+
children: $f511198465122338$var$renderChain(chain)
|
|
13553
|
+
})
|
|
13554
|
+
]
|
|
12096
13555
|
}),
|
|
12097
|
-
|
|
12098
|
-
|
|
12099
|
-
|
|
12100
|
-
|
|
13556
|
+
placed.map(({ tid: tid, count: count })=>{
|
|
13557
|
+
const isActive = String(activeTaxon) === String(tid);
|
|
13558
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
13559
|
+
className: 'gsea-tree-leaf' + (isActive ? ' gsea-tree-leaf-active' : ''),
|
|
13560
|
+
style: {
|
|
13561
|
+
paddingLeft: (depth + 1) * 7 + 18
|
|
13562
|
+
},
|
|
13563
|
+
onClick: ()=>onSelect(tid),
|
|
13564
|
+
children: [
|
|
13565
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("input", {
|
|
13566
|
+
type: "radio",
|
|
13567
|
+
readOnly: true,
|
|
13568
|
+
checked: isActive,
|
|
13569
|
+
onChange: ()=>onSelect(tid)
|
|
13570
|
+
}),
|
|
13571
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
|
|
13572
|
+
className: "gsea-tree-leaf-name",
|
|
13573
|
+
children: $f511198465122338$var$genomeName(grameneMaps, tid)
|
|
13574
|
+
}),
|
|
13575
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
|
|
13576
|
+
className: "gsea-tree-leaf-count",
|
|
13577
|
+
children: count.toLocaleString()
|
|
13578
|
+
})
|
|
13579
|
+
]
|
|
13580
|
+
}, tid);
|
|
13581
|
+
}),
|
|
13582
|
+
hasKids && isOpen && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
13583
|
+
className: "tax-children",
|
|
13584
|
+
children: kids.map((c)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($f511198465122338$var$SpeciesTreeNode, {
|
|
13585
|
+
node: c,
|
|
13586
|
+
depth: depth + 1,
|
|
13587
|
+
taxonomy: taxonomy,
|
|
13588
|
+
relevant: relevant,
|
|
13589
|
+
byPlace: byPlace,
|
|
13590
|
+
grameneMaps: grameneMaps,
|
|
13591
|
+
expanded: expanded,
|
|
13592
|
+
onToggleExpand: onToggleExpand,
|
|
13593
|
+
activeTaxon: activeTaxon,
|
|
13594
|
+
onSelect: onSelect
|
|
13595
|
+
}, c._id))
|
|
12101
13596
|
})
|
|
12102
13597
|
]
|
|
12103
13598
|
});
|
|
12104
13599
|
};
|
|
12105
|
-
|
|
12106
|
-
|
|
12107
|
-
|
|
12108
|
-
|
|
12109
|
-
|
|
12110
|
-
|
|
12111
|
-
|
|
12112
|
-
|
|
13600
|
+
const $f511198465122338$var$SpeciesTree = ({ taxonomy: taxonomy, grameneMaps: grameneMaps, taxa: taxa, activeTaxon: activeTaxon, onSelect: onSelect })=>{
|
|
13601
|
+
const { placement: placement, byPlace: byPlace } = (0, $gXNCa$react.useMemo)(()=>$f511198465122338$var$placeTaxa(taxonomy, taxa), [
|
|
13602
|
+
taxonomy,
|
|
13603
|
+
taxa
|
|
13604
|
+
]);
|
|
13605
|
+
const relevant = (0, $gXNCa$react.useMemo)(()=>$f511198465122338$var$relevantNodeIds(taxonomy, byPlace), [
|
|
13606
|
+
taxonomy,
|
|
13607
|
+
byPlace
|
|
13608
|
+
]);
|
|
13609
|
+
const roots = (0, $gXNCa$react.useMemo)(()=>$f511198465122338$var$findRoots(taxonomy).filter((r)=>relevant.has(+r._id)), [
|
|
13610
|
+
taxonomy,
|
|
13611
|
+
relevant
|
|
13612
|
+
]);
|
|
13613
|
+
// Default: every relevant internal node expanded so the user sees the
|
|
13614
|
+
// full pruned tree on first paint.
|
|
13615
|
+
const [expanded, setExpanded] = (0, $gXNCa$react.useState)(()=>new Set(relevant));
|
|
12113
13616
|
(0, $gXNCa$react.useEffect)(()=>{
|
|
12114
|
-
|
|
12115
|
-
if (!el) return;
|
|
12116
|
-
const w = el.offsetWidth;
|
|
12117
|
-
const h = el.offsetHeight;
|
|
12118
|
-
const vw = window.innerWidth;
|
|
12119
|
-
const vh = window.innerHeight;
|
|
12120
|
-
let left = x + 12;
|
|
12121
|
-
let top = y + 12;
|
|
12122
|
-
if (left + w > vw - 4) left = Math.max(4, x - 12 - w);
|
|
12123
|
-
if (top + h > vh - 4) top = Math.max(4, y - 12 - h);
|
|
12124
|
-
setPos({
|
|
12125
|
-
left: left,
|
|
12126
|
-
top: top
|
|
12127
|
-
});
|
|
13617
|
+
setExpanded(new Set(relevant));
|
|
12128
13618
|
}, [
|
|
12129
|
-
|
|
12130
|
-
y,
|
|
12131
|
-
info
|
|
13619
|
+
relevant
|
|
12132
13620
|
]);
|
|
12133
|
-
const
|
|
12134
|
-
|
|
12135
|
-
|
|
12136
|
-
|
|
12137
|
-
|
|
13621
|
+
const handleToggle = (id)=>{
|
|
13622
|
+
setExpanded((prev)=>{
|
|
13623
|
+
const next = new Set(prev);
|
|
13624
|
+
next.has(id) ? next.delete(id) : next.add(id);
|
|
13625
|
+
return next;
|
|
13626
|
+
});
|
|
13627
|
+
};
|
|
13628
|
+
// Skip the root spine: if a root has only one relevant child and isn't
|
|
13629
|
+
// itself a placed leaf, render from its child instead.
|
|
13630
|
+
const topLevel = [];
|
|
13631
|
+
for (const r of roots){
|
|
13632
|
+
const { terminal: terminal } = $f511198465122338$var$compressChain(r, taxonomy, relevant, byPlace);
|
|
13633
|
+
if (byPlace[terminal._id]) topLevel.push(r);
|
|
13634
|
+
else {
|
|
13635
|
+
const kids = $f511198465122338$var$relevantChildren(terminal, taxonomy, relevant);
|
|
13636
|
+
kids.forEach((k)=>topLevel.push(k));
|
|
13637
|
+
}
|
|
13638
|
+
}
|
|
13639
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
13640
|
+
className: "gsea-tree",
|
|
13641
|
+
children: topLevel.map((n)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($f511198465122338$var$SpeciesTreeNode, {
|
|
13642
|
+
node: n,
|
|
13643
|
+
depth: 0,
|
|
13644
|
+
taxonomy: taxonomy,
|
|
13645
|
+
relevant: relevant,
|
|
13646
|
+
byPlace: byPlace,
|
|
13647
|
+
grameneMaps: grameneMaps,
|
|
13648
|
+
expanded: expanded,
|
|
13649
|
+
onToggleExpand: handleToggle,
|
|
13650
|
+
activeTaxon: activeTaxon,
|
|
13651
|
+
onSelect: onSelect
|
|
13652
|
+
}, n._id))
|
|
13653
|
+
});
|
|
13654
|
+
};
|
|
13655
|
+
// ---------- enrichment panel ----------
|
|
13656
|
+
const $f511198465122338$var$ControlsBar = ({ ui: ui, onChange: onChange })=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
13657
|
+
className: "gsea-controls",
|
|
12138
13658
|
children: [
|
|
12139
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)(
|
|
13659
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactbootstrap.Form).Group, {
|
|
13660
|
+
className: "gsea-control",
|
|
12140
13661
|
children: [
|
|
12141
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)(
|
|
12142
|
-
|
|
12143
|
-
children: "Study:"
|
|
13662
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Form).Label, {
|
|
13663
|
+
children: "p_adj \u2264"
|
|
12144
13664
|
}),
|
|
12145
|
-
|
|
12146
|
-
|
|
12147
|
-
|
|
13665
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Form).Control, {
|
|
13666
|
+
type: "number",
|
|
13667
|
+
step: "0.01",
|
|
13668
|
+
min: "0",
|
|
13669
|
+
max: "1",
|
|
13670
|
+
value: ui.pAdjCutoff,
|
|
13671
|
+
onChange: (e)=>onChange({
|
|
13672
|
+
pAdjCutoff: +e.target.value
|
|
13673
|
+
})
|
|
13674
|
+
})
|
|
12148
13675
|
]
|
|
12149
13676
|
}),
|
|
12150
|
-
|
|
13677
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactbootstrap.Form).Group, {
|
|
13678
|
+
className: "gsea-control",
|
|
12151
13679
|
children: [
|
|
12152
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)(
|
|
12153
|
-
|
|
12154
|
-
children: "Factors"
|
|
13680
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Form).Label, {
|
|
13681
|
+
children: "min k"
|
|
12155
13682
|
}),
|
|
12156
|
-
|
|
12157
|
-
|
|
12158
|
-
|
|
12159
|
-
|
|
12160
|
-
|
|
12161
|
-
|
|
12162
|
-
|
|
12163
|
-
|
|
12164
|
-
|
|
12165
|
-
}),
|
|
12166
|
-
" ",
|
|
12167
|
-
p.value
|
|
12168
|
-
]
|
|
12169
|
-
}, `f-${i}`))
|
|
13683
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Form).Control, {
|
|
13684
|
+
type: "number",
|
|
13685
|
+
step: "1",
|
|
13686
|
+
min: "1",
|
|
13687
|
+
value: ui.minK,
|
|
13688
|
+
onChange: (e)=>onChange({
|
|
13689
|
+
minK: Math.max(1, +e.target.value)
|
|
13690
|
+
})
|
|
13691
|
+
})
|
|
12170
13692
|
]
|
|
12171
13693
|
}),
|
|
12172
|
-
|
|
13694
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Form).Check, {
|
|
13695
|
+
className: "gsea-control",
|
|
13696
|
+
type: "switch",
|
|
13697
|
+
id: "gsea-most-specific",
|
|
13698
|
+
label: "Most-specific only",
|
|
13699
|
+
checked: !!ui.mostSpecific,
|
|
13700
|
+
onChange: (e)=>onChange({
|
|
13701
|
+
mostSpecific: e.target.checked
|
|
13702
|
+
})
|
|
13703
|
+
}),
|
|
13704
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactbootstrap.Form).Group, {
|
|
13705
|
+
className: "gsea-control gsea-control-grow",
|
|
12173
13706
|
children: [
|
|
12174
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)(
|
|
12175
|
-
|
|
12176
|
-
children: "Characteristics"
|
|
13707
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Form).Label, {
|
|
13708
|
+
children: "Filter terms"
|
|
12177
13709
|
}),
|
|
12178
|
-
|
|
12179
|
-
|
|
12180
|
-
|
|
12181
|
-
|
|
12182
|
-
|
|
12183
|
-
|
|
12184
|
-
|
|
12185
|
-
|
|
12186
|
-
|
|
12187
|
-
|
|
12188
|
-
|
|
12189
|
-
|
|
12190
|
-
|
|
12191
|
-
|
|
13710
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Form).Control, {
|
|
13711
|
+
type: "text",
|
|
13712
|
+
placeholder: "term id or name\u2026",
|
|
13713
|
+
value: ui.search || '',
|
|
13714
|
+
onChange: (e)=>onChange({
|
|
13715
|
+
search: e.target.value
|
|
13716
|
+
})
|
|
13717
|
+
})
|
|
13718
|
+
]
|
|
13719
|
+
})
|
|
13720
|
+
]
|
|
13721
|
+
});
|
|
13722
|
+
const $f511198465122338$var$TermRow = ({ row: row, showType: showType, onAddFilter: onAddFilter })=>{
|
|
13723
|
+
const handleClick = ()=>onAddFilter && onAddFilter(row);
|
|
13724
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("tr", {
|
|
13725
|
+
onClick: handleClick,
|
|
13726
|
+
title: "Click to add as a filter",
|
|
13727
|
+
children: [
|
|
13728
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
|
|
13729
|
+
className: "gsea-term-id",
|
|
13730
|
+
children: row.term_display_id
|
|
13731
|
+
}),
|
|
13732
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
|
|
13733
|
+
className: "gsea-term-name",
|
|
13734
|
+
children: row.term_name || /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("em", {
|
|
13735
|
+
children: "(loading\u2026)"
|
|
13736
|
+
})
|
|
13737
|
+
}),
|
|
13738
|
+
showType && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
|
|
13739
|
+
className: "gsea-term-type",
|
|
13740
|
+
children: row.term_namespace || ''
|
|
13741
|
+
}),
|
|
13742
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("td", {
|
|
13743
|
+
className: "gsea-num",
|
|
13744
|
+
children: [
|
|
13745
|
+
row.k,
|
|
13746
|
+
" / ",
|
|
13747
|
+
row.n
|
|
13748
|
+
]
|
|
13749
|
+
}),
|
|
13750
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("td", {
|
|
13751
|
+
className: "gsea-num",
|
|
13752
|
+
children: [
|
|
13753
|
+
row.K,
|
|
13754
|
+
" / ",
|
|
13755
|
+
row.N
|
|
12192
13756
|
]
|
|
13757
|
+
}),
|
|
13758
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
|
|
13759
|
+
className: "gsea-num",
|
|
13760
|
+
children: $f511198465122338$var$fmtFold(row.fold)
|
|
13761
|
+
}),
|
|
13762
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
|
|
13763
|
+
className: "gsea-num",
|
|
13764
|
+
children: $f511198465122338$var$fmtP(row.p)
|
|
13765
|
+
}),
|
|
13766
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
|
|
13767
|
+
className: "gsea-num",
|
|
13768
|
+
children: $f511198465122338$var$fmtP(row.pAdj)
|
|
12193
13769
|
})
|
|
12194
13770
|
]
|
|
12195
13771
|
});
|
|
12196
13772
|
};
|
|
12197
|
-
|
|
12198
|
-
|
|
12199
|
-
|
|
12200
|
-
|
|
12201
|
-
|
|
12202
|
-
|
|
12203
|
-
|
|
12204
|
-
|
|
12205
|
-
|
|
12206
|
-
|
|
12207
|
-
|
|
12208
|
-
|
|
12209
|
-
|
|
12210
|
-
|
|
12211
|
-
|
|
12212
|
-
|
|
12213
|
-
|
|
12214
|
-
|
|
12215
|
-
|
|
12216
|
-
|
|
12217
|
-
|
|
12218
|
-
|
|
12219
|
-
|
|
12220
|
-
|
|
12221
|
-
|
|
12222
|
-
|
|
12223
|
-
|
|
12224
|
-
|
|
12225
|
-
|
|
12226
|
-
|
|
13773
|
+
// InterPro entry types and pathway types are useful per-row context
|
|
13774
|
+
// (e.g. Domain vs Family vs Repeat for InterPro), and aren't reflected in
|
|
13775
|
+
// the section title the way GO namespaces are. Show a Type column for
|
|
13776
|
+
// those two ontologies only.
|
|
13777
|
+
const $f511198465122338$var$ONTS_WITH_TYPE_COLUMN = new Set([
|
|
13778
|
+
'domains',
|
|
13779
|
+
'pathways'
|
|
13780
|
+
]);
|
|
13781
|
+
const $f511198465122338$var$SORT_ACCESSORS = {
|
|
13782
|
+
term: (r)=>r.term_display_id || '',
|
|
13783
|
+
name: (r)=>(r.term_name || '').toLowerCase(),
|
|
13784
|
+
type: (r)=>(r.term_namespace || '').toLowerCase(),
|
|
13785
|
+
k: (r)=>r.k,
|
|
13786
|
+
K: (r)=>r.K,
|
|
13787
|
+
fold: (r)=>r.fold,
|
|
13788
|
+
p: (r)=>r.p,
|
|
13789
|
+
pAdj: (r)=>r.pAdj
|
|
13790
|
+
};
|
|
13791
|
+
// Defaults chosen so a single click does what the user usually wants:
|
|
13792
|
+
// numeric "more interesting" columns (k, K, fold) descend; p-values and
|
|
13793
|
+
// text columns ascend.
|
|
13794
|
+
const $f511198465122338$var$SORT_DEFAULT_DIR = {
|
|
13795
|
+
term: 'asc',
|
|
13796
|
+
name: 'asc',
|
|
13797
|
+
type: 'asc',
|
|
13798
|
+
k: 'desc',
|
|
13799
|
+
K: 'desc',
|
|
13800
|
+
fold: 'desc',
|
|
13801
|
+
p: 'asc',
|
|
13802
|
+
pAdj: 'asc'
|
|
13803
|
+
};
|
|
13804
|
+
const $f511198465122338$var$SortableTh = ({ label: label, sortKey: sortKey, activeKey: activeKey, activeDir: activeDir, onSort: onSort, numeric: numeric })=>{
|
|
13805
|
+
const active = activeKey === sortKey;
|
|
13806
|
+
const arrow = active ? activeDir === 'asc' ? " \u25B2" : " \u25BC" : '';
|
|
13807
|
+
const cls = 'gsea-sort-th' + (active ? ' gsea-sort-th-active' : '') + (numeric ? ' gsea-num' : '');
|
|
13808
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("th", {
|
|
13809
|
+
className: cls,
|
|
13810
|
+
onClick: ()=>onSort(sortKey),
|
|
13811
|
+
children: [
|
|
13812
|
+
label,
|
|
13813
|
+
arrow
|
|
13814
|
+
]
|
|
13815
|
+
});
|
|
13816
|
+
};
|
|
13817
|
+
const $f511198465122338$var$OntologySection = ({ block: block, search: search, onAddFilter: onAddFilter })=>{
|
|
13818
|
+
const filtered = (0, $gXNCa$react.useMemo)(()=>{
|
|
13819
|
+
if (!search) return block.rows;
|
|
13820
|
+
const needle = search.toLowerCase();
|
|
13821
|
+
return block.rows.filter((r)=>r.term_display_id && r.term_display_id.toLowerCase().includes(needle) || r.term_name && r.term_name.toLowerCase().includes(needle));
|
|
12227
13822
|
}, [
|
|
12228
|
-
|
|
12229
|
-
|
|
13823
|
+
block.rows,
|
|
13824
|
+
search
|
|
12230
13825
|
]);
|
|
12231
|
-
|
|
12232
|
-
|
|
12233
|
-
|
|
13826
|
+
const showType = $f511198465122338$var$ONTS_WITH_TYPE_COLUMN.has(block.ontology);
|
|
13827
|
+
const [sortKey, setSortKey] = (0, $gXNCa$react.useState)('pAdj');
|
|
13828
|
+
const [sortDir, setSortDir] = (0, $gXNCa$react.useState)('asc');
|
|
13829
|
+
const handleSort = (key)=>{
|
|
13830
|
+
if (key === sortKey) setSortDir((d)=>d === 'asc' ? 'desc' : 'asc');
|
|
13831
|
+
else {
|
|
13832
|
+
setSortKey(key);
|
|
13833
|
+
setSortDir($f511198465122338$var$SORT_DEFAULT_DIR[key] || 'asc');
|
|
13834
|
+
}
|
|
13835
|
+
};
|
|
13836
|
+
const sorted = (0, $gXNCa$react.useMemo)(()=>{
|
|
13837
|
+
const accessor = $f511198465122338$var$SORT_ACCESSORS[sortKey];
|
|
13838
|
+
if (!accessor) return filtered;
|
|
13839
|
+
const sign = sortDir === 'desc' ? -1 : 1;
|
|
13840
|
+
const arr = filtered.slice();
|
|
13841
|
+
arr.sort((a, b)=>{
|
|
13842
|
+
const va = accessor(a);
|
|
13843
|
+
const vb = accessor(b);
|
|
13844
|
+
if (typeof va === 'number' && typeof vb === 'number') {
|
|
13845
|
+
if (va === vb) return 0;
|
|
13846
|
+
return (va - vb) * sign;
|
|
13847
|
+
}
|
|
13848
|
+
return String(va).localeCompare(String(vb)) * sign;
|
|
13849
|
+
});
|
|
13850
|
+
return arr;
|
|
12234
13851
|
}, [
|
|
12235
|
-
|
|
12236
|
-
|
|
12237
|
-
|
|
13852
|
+
filtered,
|
|
13853
|
+
sortKey,
|
|
13854
|
+
sortDir
|
|
12238
13855
|
]);
|
|
12239
|
-
|
|
12240
|
-
|
|
13856
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactbootstrap.Accordion).Item, {
|
|
13857
|
+
eventKey: block.ontology,
|
|
13858
|
+
children: [
|
|
13859
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactbootstrap.Accordion).Header, {
|
|
13860
|
+
children: [
|
|
13861
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
|
|
13862
|
+
className: "gsea-ont-title",
|
|
13863
|
+
children: block.label
|
|
13864
|
+
}),
|
|
13865
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactbootstrap.Badge), {
|
|
13866
|
+
bg: "secondary",
|
|
13867
|
+
className: "gsea-ont-badge",
|
|
13868
|
+
children: [
|
|
13869
|
+
block.passing,
|
|
13870
|
+
" significant / ",
|
|
13871
|
+
block.tested,
|
|
13872
|
+
" tested"
|
|
13873
|
+
]
|
|
13874
|
+
})
|
|
13875
|
+
]
|
|
13876
|
+
}),
|
|
13877
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Accordion).Body, {
|
|
13878
|
+
children: sorted.length === 0 ? /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("em", {
|
|
13879
|
+
children: "No terms pass the current cutoffs."
|
|
13880
|
+
}) : /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("table", {
|
|
13881
|
+
className: "gsea-table",
|
|
13882
|
+
children: [
|
|
13883
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("thead", {
|
|
13884
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("tr", {
|
|
13885
|
+
children: [
|
|
13886
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($f511198465122338$var$SortableTh, {
|
|
13887
|
+
label: "Term",
|
|
13888
|
+
sortKey: "term",
|
|
13889
|
+
activeKey: sortKey,
|
|
13890
|
+
activeDir: sortDir,
|
|
13891
|
+
onSort: handleSort
|
|
13892
|
+
}),
|
|
13893
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($f511198465122338$var$SortableTh, {
|
|
13894
|
+
label: "Name",
|
|
13895
|
+
sortKey: "name",
|
|
13896
|
+
activeKey: sortKey,
|
|
13897
|
+
activeDir: sortDir,
|
|
13898
|
+
onSort: handleSort
|
|
13899
|
+
}),
|
|
13900
|
+
showType && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($f511198465122338$var$SortableTh, {
|
|
13901
|
+
label: "Type",
|
|
13902
|
+
sortKey: "type",
|
|
13903
|
+
activeKey: sortKey,
|
|
13904
|
+
activeDir: sortDir,
|
|
13905
|
+
onSort: handleSort
|
|
13906
|
+
}),
|
|
13907
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($f511198465122338$var$SortableTh, {
|
|
13908
|
+
label: "k / n",
|
|
13909
|
+
sortKey: "k",
|
|
13910
|
+
activeKey: sortKey,
|
|
13911
|
+
activeDir: sortDir,
|
|
13912
|
+
onSort: handleSort,
|
|
13913
|
+
numeric: true
|
|
13914
|
+
}),
|
|
13915
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($f511198465122338$var$SortableTh, {
|
|
13916
|
+
label: "K / N",
|
|
13917
|
+
sortKey: "K",
|
|
13918
|
+
activeKey: sortKey,
|
|
13919
|
+
activeDir: sortDir,
|
|
13920
|
+
onSort: handleSort,
|
|
13921
|
+
numeric: true
|
|
13922
|
+
}),
|
|
13923
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($f511198465122338$var$SortableTh, {
|
|
13924
|
+
label: "Fold",
|
|
13925
|
+
sortKey: "fold",
|
|
13926
|
+
activeKey: sortKey,
|
|
13927
|
+
activeDir: sortDir,
|
|
13928
|
+
onSort: handleSort,
|
|
13929
|
+
numeric: true
|
|
13930
|
+
}),
|
|
13931
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($f511198465122338$var$SortableTh, {
|
|
13932
|
+
label: "p",
|
|
13933
|
+
sortKey: "p",
|
|
13934
|
+
activeKey: sortKey,
|
|
13935
|
+
activeDir: sortDir,
|
|
13936
|
+
onSort: handleSort,
|
|
13937
|
+
numeric: true
|
|
13938
|
+
}),
|
|
13939
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($f511198465122338$var$SortableTh, {
|
|
13940
|
+
label: "p_adj",
|
|
13941
|
+
sortKey: "pAdj",
|
|
13942
|
+
activeKey: sortKey,
|
|
13943
|
+
activeDir: sortDir,
|
|
13944
|
+
onSort: handleSort,
|
|
13945
|
+
numeric: true
|
|
13946
|
+
})
|
|
13947
|
+
]
|
|
13948
|
+
})
|
|
13949
|
+
}),
|
|
13950
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("tbody", {
|
|
13951
|
+
children: sorted.map((r)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($f511198465122338$var$TermRow, {
|
|
13952
|
+
row: r,
|
|
13953
|
+
showType: showType,
|
|
13954
|
+
onAddFilter: onAddFilter
|
|
13955
|
+
}, `${r.ontology}:${r.term_id}`))
|
|
13956
|
+
})
|
|
13957
|
+
]
|
|
13958
|
+
})
|
|
13959
|
+
})
|
|
13960
|
+
]
|
|
13961
|
+
});
|
|
13962
|
+
};
|
|
13963
|
+
const $f511198465122338$var$TaxonPanel = ({ taxon: taxon, gsea: gsea, results: results, ui: ui, onUiChange: onUiChange, onAddFilter: onAddFilter })=>{
|
|
13964
|
+
if (!taxon) return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
13965
|
+
className: "gsea-panel",
|
|
12241
13966
|
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("em", {
|
|
12242
|
-
children: "
|
|
13967
|
+
children: "Select a species on the left."
|
|
12243
13968
|
})
|
|
12244
13969
|
});
|
|
12245
|
-
|
|
12246
|
-
|
|
12247
|
-
|
|
12248
|
-
|
|
12249
|
-
|
|
12250
|
-
pivot.error
|
|
12251
|
-
]
|
|
13970
|
+
const t = gsea.byTaxon[taxon];
|
|
13971
|
+
if (!t) return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
13972
|
+
className: "gsea-panel",
|
|
13973
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("em", {
|
|
13974
|
+
children: "Initializing\u2026"
|
|
12252
13975
|
})
|
|
12253
13976
|
});
|
|
12254
|
-
if (
|
|
12255
|
-
className: "
|
|
13977
|
+
if (t.fg.status === 'loading' || t.bg.status === 'loading' || t.fg.status === 'idle' || t.bg.status === 'idle') return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
13978
|
+
className: "gsea-panel gsea-loading",
|
|
12256
13979
|
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("em", {
|
|
12257
|
-
children: "
|
|
13980
|
+
children: "Loading enrichment\u2026"
|
|
12258
13981
|
})
|
|
12259
13982
|
});
|
|
12260
|
-
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.
|
|
12261
|
-
className: "
|
|
12262
|
-
children:
|
|
12263
|
-
|
|
12264
|
-
|
|
12265
|
-
|
|
12266
|
-
|
|
12267
|
-
|
|
12268
|
-
const studies = studiesFor(tid);
|
|
12269
|
-
const taxName = $1fd2507769d5bd00$var$genomeName(grameneMaps, tid);
|
|
12270
|
-
const geneCount = pivot.data[tid] || 0;
|
|
12271
|
-
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Tab), {
|
|
12272
|
-
eventKey: tid,
|
|
12273
|
-
title: `${taxName} (${studies.length} studies \xb7 ${geneCount} genes)`,
|
|
12274
|
-
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($1fd2507769d5bd00$var$TaxonPanel, {
|
|
12275
|
-
taxon: tid,
|
|
12276
|
-
studies: studies,
|
|
12277
|
-
expressionSamples: expressionSamples,
|
|
12278
|
-
tabState: exprViz.byTaxon[tid],
|
|
12279
|
-
onOpenFields: ()=>doToggleExprVizFieldsModal(tid, true),
|
|
12280
|
-
onLoad: ()=>doFetchExprVizData(tid),
|
|
12281
|
-
onReorder: (next)=>props.doReorderExprVizFields(tid, next),
|
|
12282
|
-
onAddRangeQuery: props.doAddGrameneRangeQuery
|
|
12283
|
-
})
|
|
12284
|
-
}, tid);
|
|
12285
|
-
})
|
|
12286
|
-
}),
|
|
12287
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $4d0c2e01f58b53b1$export$2e2bcd8739ae039), {})
|
|
12288
|
-
]
|
|
12289
|
-
});
|
|
12290
|
-
};
|
|
12291
|
-
// Compact axis labels for the parallel-coords plot. The raw Solr field name
|
|
12292
|
-
// (e.g. "E_CURD_148_g5__expr") is uninformative; we prefer the assay's
|
|
12293
|
-
// factor labels, falling back to "organism part" then to the group id.
|
|
12294
|
-
// `full` is exposed via an SVG <title> so the user can hover to see study,
|
|
12295
|
-
// group, and every factor/characteristic.
|
|
12296
|
-
const $1fd2507769d5bd00$var$AXIS_LABEL_MAX = 22;
|
|
12297
|
-
function $1fd2507769d5bd00$var$truncateLabel(s, n) {
|
|
12298
|
-
if (!s) return '';
|
|
12299
|
-
return s.length > n ? s.slice(0, n - 1) + "\u2026" : s;
|
|
12300
|
-
}
|
|
12301
|
-
function $1fd2507769d5bd00$var$compactAssayLabel(assay, group) {
|
|
12302
|
-
if (!assay) return group || '';
|
|
12303
|
-
const factorVals = (assay.factor || []).map((f)=>f && f.label).filter(Boolean);
|
|
12304
|
-
if (factorVals.length) return factorVals.join('; ');
|
|
12305
|
-
const chars = assay.characteristic || [];
|
|
12306
|
-
const organ = chars.find((c)=>c && c.type === 'organism part');
|
|
12307
|
-
if (organ && organ.label) return organ.label;
|
|
12308
|
-
const firstChar = chars.find((c)=>c && c.label);
|
|
12309
|
-
if (firstChar) return firstChar.label;
|
|
12310
|
-
return group || '';
|
|
12311
|
-
}
|
|
12312
|
-
function $1fd2507769d5bd00$var$assayPairs(list) {
|
|
12313
|
-
return (list || []).filter((x)=>x && x.label).map((x)=>({
|
|
12314
|
-
name: x.type || '',
|
|
12315
|
-
value: x.label
|
|
12316
|
-
}));
|
|
12317
|
-
}
|
|
12318
|
-
function $1fd2507769d5bd00$var$buildAxisLabels(fields, studies, expressionSamples) {
|
|
12319
|
-
const labels = {};
|
|
12320
|
-
if (!fields) return labels;
|
|
12321
|
-
const studyById = {};
|
|
12322
|
-
(studies || []).forEach((s)=>{
|
|
12323
|
-
if (s && s._id) studyById[s._id] = s;
|
|
13983
|
+
if (t.fg.status === 'error') return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
13984
|
+
className: "gsea-panel",
|
|
13985
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("em", {
|
|
13986
|
+
children: [
|
|
13987
|
+
"Foreground error: ",
|
|
13988
|
+
t.fg.error
|
|
13989
|
+
]
|
|
13990
|
+
})
|
|
12324
13991
|
});
|
|
12325
|
-
|
|
12326
|
-
|
|
12327
|
-
|
|
12328
|
-
|
|
12329
|
-
|
|
12330
|
-
|
|
12331
|
-
|
|
12332
|
-
|
|
12333
|
-
short: $1fd2507769d5bd00$var$truncateLabel(f.replace(/__expr$/, ''), $1fd2507769d5bd00$var$AXIS_LABEL_MAX),
|
|
12334
|
-
structured: {
|
|
12335
|
-
studyTitle: f,
|
|
12336
|
-
group: '',
|
|
12337
|
-
factors: [],
|
|
12338
|
-
characteristics: []
|
|
12339
|
-
}
|
|
12340
|
-
};
|
|
12341
|
-
continue;
|
|
12342
|
-
}
|
|
12343
|
-
const expId = m[1].replace(/_/g, '-');
|
|
12344
|
-
const group = 'g' + m[2];
|
|
12345
|
-
const assay = findAssay(expId, group);
|
|
12346
|
-
const study = studyById[expId];
|
|
12347
|
-
const studyName = study && study.description || expId;
|
|
12348
|
-
labels[f] = {
|
|
12349
|
-
short: $1fd2507769d5bd00$var$truncateLabel($1fd2507769d5bd00$var$compactAssayLabel(assay, group), $1fd2507769d5bd00$var$AXIS_LABEL_MAX),
|
|
12350
|
-
structured: {
|
|
12351
|
-
studyTitle: studyName,
|
|
12352
|
-
group: group,
|
|
12353
|
-
factors: $1fd2507769d5bd00$var$assayPairs(assay && assay.factor),
|
|
12354
|
-
characteristics: $1fd2507769d5bd00$var$assayPairs(assay && assay.characteristic)
|
|
12355
|
-
}
|
|
12356
|
-
};
|
|
12357
|
-
}
|
|
12358
|
-
return labels;
|
|
12359
|
-
}
|
|
12360
|
-
function $1fd2507769d5bd00$var$rowMatchesSelections(row, selections) {
|
|
12361
|
-
for (const f of Object.keys(selections)){
|
|
12362
|
-
const v = row[f];
|
|
12363
|
-
if (v == null || Array.isArray(v)) return false;
|
|
12364
|
-
const n = +v;
|
|
12365
|
-
if (!Number.isFinite(n)) return false;
|
|
12366
|
-
const [lo, hi] = selections[f];
|
|
12367
|
-
if (n < lo || n > hi) return false;
|
|
12368
|
-
}
|
|
12369
|
-
return true;
|
|
12370
|
-
}
|
|
12371
|
-
function $1fd2507769d5bd00$var$fmt(n) {
|
|
12372
|
-
if (!Number.isFinite(n)) return String(n);
|
|
12373
|
-
const a = Math.abs(n);
|
|
12374
|
-
if (a !== 0 && (a < 0.001 || a >= 1e6)) return n.toExponential(3);
|
|
12375
|
-
return Number(n.toFixed(4)).toString();
|
|
12376
|
-
}
|
|
12377
|
-
function $1fd2507769d5bd00$var$tsvCell(v) {
|
|
12378
|
-
if (v == null) return '';
|
|
12379
|
-
if (Array.isArray(v)) return v.join(',');
|
|
12380
|
-
const s = typeof v === 'object' ? JSON.stringify(v) : String(v);
|
|
12381
|
-
return s.replace(/[\t\r\n]+/g, ' ');
|
|
12382
|
-
}
|
|
12383
|
-
function $1fd2507769d5bd00$var$downloadTsv(filename, rows, fields) {
|
|
12384
|
-
const cols = [
|
|
12385
|
-
'id',
|
|
12386
|
-
'name',
|
|
12387
|
-
...fields
|
|
12388
|
-
];
|
|
12389
|
-
const headerLabels = [
|
|
12390
|
-
'id',
|
|
12391
|
-
'name',
|
|
12392
|
-
...fields.map((f)=>f.replace(/__expr$/, ''))
|
|
12393
|
-
];
|
|
12394
|
-
const lines = [
|
|
12395
|
-
headerLabels.join('\t')
|
|
12396
|
-
];
|
|
12397
|
-
for (const r of rows)lines.push(cols.map((c)=>$1fd2507769d5bd00$var$tsvCell(r[c])).join('\t'));
|
|
12398
|
-
const blob = new Blob([
|
|
12399
|
-
lines.join('\n') + '\n'
|
|
12400
|
-
], {
|
|
12401
|
-
type: 'text/tab-separated-values'
|
|
13992
|
+
if (t.bg.status === 'error') return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
13993
|
+
className: "gsea-panel",
|
|
13994
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("em", {
|
|
13995
|
+
children: [
|
|
13996
|
+
"Background error: ",
|
|
13997
|
+
t.bg.error
|
|
13998
|
+
]
|
|
13999
|
+
})
|
|
12402
14000
|
});
|
|
12403
|
-
|
|
12404
|
-
|
|
12405
|
-
|
|
12406
|
-
|
|
12407
|
-
|
|
12408
|
-
|
|
12409
|
-
|
|
12410
|
-
|
|
12411
|
-
|
|
12412
|
-
|
|
12413
|
-
const
|
|
12414
|
-
|
|
12415
|
-
|
|
12416
|
-
|
|
12417
|
-
|
|
12418
|
-
|
|
12419
|
-
|
|
12420
|
-
|
|
12421
|
-
|
|
12422
|
-
|
|
12423
|
-
|
|
12424
|
-
|
|
12425
|
-
|
|
12426
|
-
|
|
12427
|
-
|
|
14001
|
+
if (!results) return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
14002
|
+
className: "gsea-panel",
|
|
14003
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("em", {
|
|
14004
|
+
children: "No data."
|
|
14005
|
+
})
|
|
14006
|
+
});
|
|
14007
|
+
const allBlocks = ui.ontology === 'all' ? Object.values(results) : results[ui.ontology] ? [
|
|
14008
|
+
results[ui.ontology]
|
|
14009
|
+
] : [];
|
|
14010
|
+
// Hide ontologies that aren't used in this species at all.
|
|
14011
|
+
const blocks = allBlocks.filter((b)=>b.tested > 0);
|
|
14012
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
14013
|
+
className: "gsea-panel",
|
|
14014
|
+
children: [
|
|
14015
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
14016
|
+
className: "gsea-summary",
|
|
14017
|
+
children: [
|
|
14018
|
+
"Foreground: ",
|
|
14019
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("b", {
|
|
14020
|
+
children: t.fg.numFound.toLocaleString()
|
|
14021
|
+
}),
|
|
14022
|
+
" genes \xb7 Background: ",
|
|
14023
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("b", {
|
|
14024
|
+
children: t.bg.numFound.toLocaleString()
|
|
14025
|
+
}),
|
|
14026
|
+
" genes"
|
|
14027
|
+
]
|
|
14028
|
+
}),
|
|
14029
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($f511198465122338$var$ControlsBar, {
|
|
14030
|
+
ui: ui,
|
|
14031
|
+
onChange: onUiChange
|
|
14032
|
+
}),
|
|
14033
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Accordion), {
|
|
14034
|
+
alwaysOpen: true,
|
|
14035
|
+
defaultActiveKey: blocks.length === 1 ? blocks[0].ontology : undefined,
|
|
14036
|
+
children: blocks.map((b)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($f511198465122338$var$OntologySection, {
|
|
14037
|
+
block: b,
|
|
14038
|
+
search: ui.search,
|
|
14039
|
+
onAddFilter: onAddFilter
|
|
14040
|
+
}, b.ontology))
|
|
14041
|
+
})
|
|
14042
|
+
]
|
|
14043
|
+
});
|
|
14044
|
+
};
|
|
14045
|
+
const $f511198465122338$var$GseaViewCmp = (props)=>{
|
|
14046
|
+
const { grameneSearch: grameneSearch, grameneMaps: grameneMaps, grameneTaxonomy: grameneTaxonomy, gsea: gsea, gseaUI: ui, gseaResults: results, doSetGseaActiveTaxon: doSetGseaActiveTaxon, doSetGseaUI: doSetGseaUI, doFetchGseaForeground: doFetchGseaForeground, doFetchGseaBackground: doFetchGseaBackground, doAcceptGrameneSuggestion: doAcceptGrameneSuggestion } = props;
|
|
14047
|
+
const taxa = (0, $gXNCa$react.useMemo)(()=>{
|
|
14048
|
+
if (!grameneSearch || !grameneSearch.facet_counts) return [];
|
|
14049
|
+
const arr = grameneSearch.facet_counts.facet_fields.taxon_id || [];
|
|
14050
|
+
const ids = [];
|
|
14051
|
+
const counts = {};
|
|
14052
|
+
for(let i = 0; i < arr.length; i += 2){
|
|
14053
|
+
ids.push(arr[i]);
|
|
14054
|
+
counts[arr[i]] = +arr[i + 1];
|
|
14055
|
+
}
|
|
14056
|
+
if (grameneMaps) ids.sort((a, b)=>{
|
|
14057
|
+
const ma = grameneMaps[a] || grameneMaps[$f511198465122338$var$speciesTaxonId(a)];
|
|
14058
|
+
const mb = grameneMaps[b] || grameneMaps[$f511198465122338$var$speciesTaxonId(b)];
|
|
14059
|
+
return (ma && ma.left_index || 0) - (mb && mb.left_index || 0);
|
|
14060
|
+
});
|
|
14061
|
+
return ids.map((tid)=>({
|
|
14062
|
+
tid: tid,
|
|
14063
|
+
count: counts[tid]
|
|
14064
|
+
}));
|
|
14065
|
+
}, [
|
|
14066
|
+
grameneSearch,
|
|
14067
|
+
grameneMaps
|
|
14068
|
+
]);
|
|
14069
|
+
const activeTaxon = gsea.activeTaxon;
|
|
14070
|
+
const [treeWidth, setTreeWidth] = (0, $gXNCa$react.useState)(280);
|
|
14071
|
+
const beginResize = (e)=>{
|
|
12428
14072
|
e.preventDefault();
|
|
12429
|
-
|
|
12430
|
-
|
|
12431
|
-
startHeight: plotHeight
|
|
12432
|
-
};
|
|
14073
|
+
const startX = e.clientX;
|
|
14074
|
+
const startWidth = treeWidth;
|
|
12433
14075
|
const onMove = (ev)=>{
|
|
12434
|
-
const
|
|
12435
|
-
|
|
12436
|
-
const next = Math.max(120, Math.min(1200, s.startHeight + (ev.clientY - s.startY)));
|
|
12437
|
-
setPlotHeight(next);
|
|
14076
|
+
const next = Math.max(150, Math.min(800, startWidth + (ev.clientX - startX)));
|
|
14077
|
+
setTreeWidth(next);
|
|
12438
14078
|
};
|
|
12439
14079
|
const onUp = ()=>{
|
|
12440
|
-
resizeStateRef.current = null;
|
|
12441
14080
|
document.removeEventListener('mousemove', onMove);
|
|
12442
14081
|
document.removeEventListener('mouseup', onUp);
|
|
12443
|
-
document.body.style.cursor = '';
|
|
12444
14082
|
document.body.style.userSelect = '';
|
|
14083
|
+
document.body.style.cursor = '';
|
|
12445
14084
|
};
|
|
12446
|
-
document.body.style.cursor = 'row-resize';
|
|
12447
14085
|
document.body.style.userSelect = 'none';
|
|
14086
|
+
document.body.style.cursor = 'col-resize';
|
|
12448
14087
|
document.addEventListener('mousemove', onMove);
|
|
12449
14088
|
document.addEventListener('mouseup', onUp);
|
|
12450
14089
|
};
|
|
12451
|
-
|
|
12452
|
-
|
|
12453
|
-
if (!
|
|
12454
|
-
return rows.filter((r)=>$1fd2507769d5bd00$var$rowMatchesSelections(r, selections));
|
|
12455
|
-
}, [
|
|
12456
|
-
rows,
|
|
12457
|
-
selections,
|
|
12458
|
-
hasBrush
|
|
12459
|
-
]);
|
|
12460
|
-
// Drop fields with no numeric data in the loaded rows so empty axes/columns
|
|
12461
|
-
// don't clutter the visualization. Selected-but-empty fields stay in the
|
|
12462
|
-
// underlying selection so a future load can repopulate them.
|
|
12463
|
-
const visibleFields = (0, $gXNCa$react.useMemo)(()=>{
|
|
12464
|
-
if (rows.length === 0 || selected.length === 0) return selected;
|
|
12465
|
-
return selected.filter((f)=>rows.some((r)=>{
|
|
12466
|
-
const v = r[f];
|
|
12467
|
-
return v != null && !Array.isArray(v) && Number.isFinite(+v);
|
|
12468
|
-
}));
|
|
14090
|
+
(0, $gXNCa$react.useEffect)(()=>{
|
|
14091
|
+
if (taxa.length === 0) return;
|
|
14092
|
+
if (!activeTaxon || !taxa.find((t)=>String(t.tid) === String(activeTaxon))) doSetGseaActiveTaxon(taxa[0].tid);
|
|
12469
14093
|
}, [
|
|
12470
|
-
|
|
12471
|
-
|
|
12472
|
-
|
|
12473
|
-
const handleReorder = onReorder ? (newVisibleOrder)=>{
|
|
12474
|
-
const visibleSet = new Set(newVisibleOrder);
|
|
12475
|
-
const hidden = selected.filter((f)=>!visibleSet.has(f));
|
|
12476
|
-
onReorder([
|
|
12477
|
-
...newVisibleOrder,
|
|
12478
|
-
...hidden
|
|
12479
|
-
]);
|
|
12480
|
-
} : undefined;
|
|
12481
|
-
const axisLabels = (0, $gXNCa$react.useMemo)(()=>$1fd2507769d5bd00$var$buildAxisLabels(visibleFields, studies, expressionSamples), [
|
|
12482
|
-
visibleFields,
|
|
12483
|
-
studies,
|
|
12484
|
-
expressionSamples
|
|
14094
|
+
taxa,
|
|
14095
|
+
activeTaxon,
|
|
14096
|
+
doSetGseaActiveTaxon
|
|
12485
14097
|
]);
|
|
12486
14098
|
(0, $gXNCa$react.useEffect)(()=>{
|
|
12487
|
-
if (
|
|
12488
|
-
|
|
12489
|
-
|
|
12490
|
-
|
|
14099
|
+
if (!activeTaxon) return;
|
|
14100
|
+
const t = gsea.byTaxon[activeTaxon];
|
|
14101
|
+
if (!t) return;
|
|
14102
|
+
if (t.fg.status === 'idle') doFetchGseaForeground(activeTaxon);
|
|
14103
|
+
if (t.bg.status === 'idle') doFetchGseaBackground(activeTaxon);
|
|
12491
14104
|
}, [
|
|
12492
|
-
|
|
12493
|
-
|
|
14105
|
+
activeTaxon,
|
|
14106
|
+
gsea,
|
|
14107
|
+
doFetchGseaForeground,
|
|
14108
|
+
doFetchGseaBackground
|
|
12494
14109
|
]);
|
|
14110
|
+
if (taxa.length === 0) return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
14111
|
+
className: "gsea-view",
|
|
14112
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("em", {
|
|
14113
|
+
children: "No species in the current results."
|
|
14114
|
+
})
|
|
14115
|
+
});
|
|
14116
|
+
if (!grameneTaxonomy) return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
14117
|
+
className: "gsea-view",
|
|
14118
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("em", {
|
|
14119
|
+
children: "Loading taxonomy\u2026"
|
|
14120
|
+
})
|
|
14121
|
+
});
|
|
14122
|
+
const handleAddFilter = (row)=>{
|
|
14123
|
+
if (!doAcceptGrameneSuggestion) return;
|
|
14124
|
+
const label = row.term_name ? `${row.term_display_id} ${row.term_name}` : row.term_display_id;
|
|
14125
|
+
doAcceptGrameneSuggestion({
|
|
14126
|
+
fq_field: row.field,
|
|
14127
|
+
fq_value: String(row.term_id),
|
|
14128
|
+
name: label,
|
|
14129
|
+
category: row.ontology_label
|
|
14130
|
+
});
|
|
14131
|
+
};
|
|
12495
14132
|
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
12496
|
-
className: "
|
|
14133
|
+
className: "gsea-view gsea-layout",
|
|
12497
14134
|
children: [
|
|
12498
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.
|
|
12499
|
-
className: "
|
|
12500
|
-
|
|
12501
|
-
|
|
12502
|
-
|
|
12503
|
-
|
|
12504
|
-
|
|
12505
|
-
|
|
12506
|
-
|
|
12507
|
-
|
|
12508
|
-
|
|
12509
|
-
|
|
12510
|
-
]
|
|
12511
|
-
}),
|
|
12512
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
|
|
12513
|
-
size: "sm",
|
|
12514
|
-
variant: "primary",
|
|
12515
|
-
disabled: selected.length === 0 || fetchInfo.status === 'loading',
|
|
12516
|
-
onClick: onLoad,
|
|
12517
|
-
children: fetchInfo.status === 'loading' ? "Loading\u2026" : 'Load data'
|
|
12518
|
-
}),
|
|
12519
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactbootstrap.ToggleButtonGroup), {
|
|
12520
|
-
type: "radio",
|
|
12521
|
-
name: `exprviz-scale-${taxon}`,
|
|
12522
|
-
size: "sm",
|
|
12523
|
-
value: scale,
|
|
12524
|
-
onChange: setScale,
|
|
12525
|
-
children: [
|
|
12526
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.ToggleButton), {
|
|
12527
|
-
id: `exprviz-scale-${taxon}-lin`,
|
|
12528
|
-
value: "linear",
|
|
12529
|
-
variant: "outline-secondary",
|
|
12530
|
-
children: "Linear"
|
|
12531
|
-
}),
|
|
12532
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.ToggleButton), {
|
|
12533
|
-
id: `exprviz-scale-${taxon}-log`,
|
|
12534
|
-
value: "log",
|
|
12535
|
-
variant: "outline-secondary",
|
|
12536
|
-
children: "Log"
|
|
12537
|
-
})
|
|
12538
|
-
]
|
|
12539
|
-
}),
|
|
12540
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
|
|
12541
|
-
size: "sm",
|
|
12542
|
-
variant: "outline-secondary",
|
|
12543
|
-
disabled: !hasBrush,
|
|
12544
|
-
onClick: ()=>{
|
|
12545
|
-
setClearVersion((v)=>v + 1);
|
|
12546
|
-
setSelections({});
|
|
12547
|
-
},
|
|
12548
|
-
children: "Clear brushes"
|
|
12549
|
-
}),
|
|
12550
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
|
|
12551
|
-
size: "sm",
|
|
12552
|
-
variant: "outline-secondary",
|
|
12553
|
-
disabled: filteredRows.length === 0 || visibleFields.length === 0,
|
|
12554
|
-
onClick: ()=>$1fd2507769d5bd00$var$downloadTsv(`expression_${taxon}.tsv`, filteredRows, visibleFields),
|
|
12555
|
-
title: "Download the visible rows and columns as tab-delimited text",
|
|
12556
|
-
children: "Download TSV"
|
|
12557
|
-
}),
|
|
12558
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
|
|
12559
|
-
size: "sm",
|
|
12560
|
-
variant: "success",
|
|
12561
|
-
disabled: !hasBrush || !onAddRangeQuery,
|
|
12562
|
-
onClick: ()=>{
|
|
12563
|
-
const terms = Object.keys(selections).map((field)=>{
|
|
12564
|
-
const [lo, hi] = selections[field];
|
|
12565
|
-
return {
|
|
12566
|
-
category: 'Expression',
|
|
12567
|
-
name: `${field}: ${$1fd2507769d5bd00$var$fmt(lo)}\u{2013}${$1fd2507769d5bd00$var$fmt(hi)}`,
|
|
12568
|
-
fq_field: field,
|
|
12569
|
-
fq_value: `[${lo} TO ${hi}]`
|
|
12570
|
-
};
|
|
12571
|
-
});
|
|
12572
|
-
onAddRangeQuery(terms);
|
|
12573
|
-
},
|
|
12574
|
-
title: "Add brush ranges as an AND-conjunction filter on the search",
|
|
12575
|
-
children: "Apply as filter"
|
|
12576
|
-
}),
|
|
12577
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("span", {
|
|
12578
|
-
className: "exprviz-status",
|
|
12579
|
-
children: [
|
|
12580
|
-
hasBrush ? `${filteredRows.length} of ${rows.length}` : rows.length,
|
|
12581
|
-
fetchInfo.total ? ` / ${fetchInfo.total}` : '',
|
|
12582
|
-
" genes",
|
|
12583
|
-
hasBrush ? ' (brushed)' : ' loaded'
|
|
12584
|
-
]
|
|
12585
|
-
})
|
|
12586
|
-
]
|
|
14135
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
14136
|
+
className: "gsea-layout-tree",
|
|
14137
|
+
style: {
|
|
14138
|
+
flex: `0 0 ${treeWidth}px`
|
|
14139
|
+
},
|
|
14140
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($f511198465122338$var$SpeciesTree, {
|
|
14141
|
+
taxonomy: grameneTaxonomy,
|
|
14142
|
+
grameneMaps: grameneMaps,
|
|
14143
|
+
taxa: taxa,
|
|
14144
|
+
activeTaxon: activeTaxon,
|
|
14145
|
+
onSelect: (tid)=>doSetGseaActiveTaxon(String(tid))
|
|
14146
|
+
})
|
|
12587
14147
|
}),
|
|
12588
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.
|
|
12589
|
-
className: "
|
|
12590
|
-
|
|
12591
|
-
|
|
12592
|
-
|
|
12593
|
-
|
|
12594
|
-
|
|
12595
|
-
|
|
12596
|
-
|
|
12597
|
-
|
|
12598
|
-
|
|
12599
|
-
|
|
12600
|
-
|
|
12601
|
-
|
|
12602
|
-
|
|
12603
|
-
hoveredId: hoveredId,
|
|
12604
|
-
axisLabels: axisLabels
|
|
12605
|
-
})
|
|
12606
|
-
}),
|
|
12607
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
12608
|
-
className: "exprviz-resizer",
|
|
12609
|
-
role: "separator",
|
|
12610
|
-
"aria-orientation": "horizontal",
|
|
12611
|
-
"aria-label": "Resize plot",
|
|
12612
|
-
onMouseDown: startResize,
|
|
12613
|
-
title: "Drag to resize"
|
|
12614
|
-
}),
|
|
12615
|
-
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
12616
|
-
className: "exprviz-table",
|
|
12617
|
-
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $4ab64e76c1caef59$export$2e2bcd8739ae039), {
|
|
12618
|
-
rows: filteredRows,
|
|
12619
|
-
fields: visibleFields,
|
|
12620
|
-
onReorder: handleReorder,
|
|
12621
|
-
studies: studies,
|
|
12622
|
-
expressionSamples: expressionSamples,
|
|
12623
|
-
onHoverRow: setHoveredId
|
|
12624
|
-
})
|
|
12625
|
-
})
|
|
12626
|
-
]
|
|
14148
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
14149
|
+
className: "gsea-splitter",
|
|
14150
|
+
onMouseDown: beginResize,
|
|
14151
|
+
title: "Drag to resize"
|
|
14152
|
+
}),
|
|
14153
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
14154
|
+
className: "gsea-layout-panel",
|
|
14155
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($f511198465122338$var$TaxonPanel, {
|
|
14156
|
+
taxon: activeTaxon ? String(activeTaxon) : null,
|
|
14157
|
+
gsea: gsea,
|
|
14158
|
+
results: results,
|
|
14159
|
+
ui: ui,
|
|
14160
|
+
onUiChange: doSetGseaUI,
|
|
14161
|
+
onAddFilter: handleAddFilter
|
|
14162
|
+
})
|
|
12627
14163
|
})
|
|
12628
14164
|
]
|
|
12629
14165
|
});
|
|
12630
14166
|
};
|
|
12631
|
-
var $
|
|
14167
|
+
var $f511198465122338$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.connect)('selectGrameneSearch', 'selectGrameneMaps', 'selectGrameneTaxonomy', 'selectGsea', 'selectGseaUI', 'selectGseaResults', 'doSetGseaActiveTaxon', 'doSetGseaUI', 'doFetchGseaForeground', 'doFetchGseaBackground', 'doAcceptGrameneSuggestion', $f511198465122338$var$GseaViewCmp);
|
|
12632
14168
|
|
|
12633
14169
|
|
|
12634
14170
|
|
|
@@ -12749,6 +14285,7 @@ const $693dd8c7a5607c3a$var$inventory = {
|
|
|
12749
14285
|
attribs: (0, $67bf5a43401bffdc$export$2e2bcd8739ae039),
|
|
12750
14286
|
expression: (0, $261baeb81c4d4d8a$export$2e2bcd8739ae039),
|
|
12751
14287
|
exprViz: (0, $1fd2507769d5bd00$export$2e2bcd8739ae039),
|
|
14288
|
+
gsea: (0, $f511198465122338$export$2e2bcd8739ae039),
|
|
12752
14289
|
userLists: (0, $0f50f369018a42ef$export$2e2bcd8739ae039),
|
|
12753
14290
|
export: (0, $37b3bb0145d266b0$export$2e2bcd8739ae039)
|
|
12754
14291
|
};
|