gramene-search 1.6.46 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,13 +1,16 @@
1
1
  require("./index.css");
2
+ var $gXNCa$reactjsxruntime = require("react/jsx-runtime");
3
+ var $gXNCa$react = require("react");
4
+ var $gXNCa$reduxbundlerreact = require("redux-bundler-react");
5
+ var $gXNCa$aggridreact = require("ag-grid-react");
6
+ require("ag-grid-community/styles/ag-grid.css");
7
+ require("ag-grid-community/styles/ag-theme-quartz.css");
2
8
  var $gXNCa$reduxbundler = require("redux-bundler");
3
9
  var $gXNCa$lodash = require("lodash");
4
10
  var $gXNCa$gramenebinsclient = require("gramene-bins-client");
5
11
  var $gXNCa$gramenetreesclient = require("gramene-trees-client");
6
12
  var $gXNCa$gramenetaxonomywithgenomes = require("gramene-taxonomy-with-genomes");
7
13
  var $gXNCa$reactga4 = require("react-ga4");
8
- var $gXNCa$reactjsxruntime = require("react/jsx-runtime");
9
- var $gXNCa$reduxbundlerreact = require("redux-bundler-react");
10
- var $gXNCa$react = require("react");
11
14
  var $gXNCa$reactbootstrap = require("react-bootstrap");
12
15
  var $gXNCa$reactswitch = require("react-switch");
13
16
  var $gXNCa$reacticonsio5 = require("react-icons/io5");
@@ -22,9 +25,6 @@ var $gXNCa$lodashget = require("lodash/get");
22
25
  var $gXNCa$lodashisEqual = require("lodash/isEqual");
23
26
  var $gXNCa$flattonested = require("flat-to-nested");
24
27
  var $gXNCa$reactsimpletreemenu = require("react-simple-tree-menu");
25
- var $gXNCa$aggridreact = require("ag-grid-react");
26
- require("ag-grid-community/styles/ag-grid.css");
27
- require("ag-grid-community/styles/ag-theme-quartz.css");
28
28
  require("@fortawesome/fontawesome-free/css/all.min.css");
29
29
  var $gXNCa$gramenedbxrefs = require("gramene-dbxrefs");
30
30
  var $gXNCa$reacticonsai = require("react-icons/ai");
@@ -33,6 +33,10 @@ var $gXNCa$numeral = require("numeral");
33
33
  var $gXNCa$firebaseauth = require("firebase/auth");
34
34
 
35
35
 
36
+ function $parcel$defineInteropFlag(a) {
37
+ Object.defineProperty(a, '__esModule', {value: true, configurable: true});
38
+ }
39
+
36
40
  function $parcel$export(e, n, v, s) {
37
41
  Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
38
42
  }
@@ -74,8 +78,133 @@ if (parcelRequire == null) {
74
78
  }
75
79
 
76
80
  var parcelRegister = parcelRequire.register;
77
- parcelRegister("7u0Mi", function(module, exports) {
78
- module.exports = Promise.resolve(require("./Study.826d318c.js")).then(()=>parcelRequire('7zuJ6'));
81
+ parcelRegister("7zuJ6", function(module, exports) {
82
+
83
+ $parcel$defineInteropFlag(module.exports);
84
+
85
+ $parcel$export(module.exports, "default", () => $5833a2eeefc77457$export$2e2bcd8739ae039);
86
+
87
+
88
+
89
+
90
+
91
+
92
+ const $5833a2eeefc77457$var$metaRenderer = (params)=>{
93
+ if (params.value.ontology) return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("a", {
94
+ href: `http://purl.obolibrary.org/obo/${params.value.id.replace(":", "_")}`,
95
+ target: "_blank",
96
+ children: params.value.label
97
+ });
98
+ return params.value.label;
99
+ };
100
+ const $5833a2eeefc77457$var$sampleRenderer = (params)=>{
101
+ const sampleMeta = params.value;
102
+ return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("label", {
103
+ children: [
104
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("input", {
105
+ type: "checkbox",
106
+ checked: params.desiredSamples.hasOwnProperty(sampleMeta._id),
107
+ onChange: ()=>params.doToggleExpressionSample(sampleMeta._id)
108
+ }),
109
+ "\xa0",
110
+ sampleMeta.experiment,
111
+ "-",
112
+ sampleMeta.group
113
+ ]
114
+ });
115
+ // return JSON.stringify(sampleMeta,null,2);
116
+ };
117
+ const $5833a2eeefc77457$var$connectedSampleRenderer = (0, $gXNCa$reduxbundlerreact.connect)('selectDesiredSamples', 'doToggleExpressionSample', $5833a2eeefc77457$var$sampleRenderer);
118
+ const $5833a2eeefc77457$var$Study = (props)=>{
119
+ let samples = props.expressionSamples[props.id];
120
+ let sampleMetadata = [];
121
+ let metadataFields = [
122
+ {
123
+ field: "sampleId",
124
+ cellRenderer: $5833a2eeefc77457$var$connectedSampleRenderer
125
+ }
126
+ ];
127
+ let isFactor = {};
128
+ samples.forEach((sample, idx)=>{
129
+ if (idx === 0) {
130
+ let factors = {
131
+ headerName: 'Experimental Variables',
132
+ children: []
133
+ };
134
+ sample.factor.forEach((factor)=>{
135
+ factors.children.push({
136
+ field: factor.type,
137
+ cellRenderer: $5833a2eeefc77457$var$metaRenderer
138
+ });
139
+ isFactor[factor.type] = true;
140
+ });
141
+ metadataFields.push(factors);
142
+ let characteristics = {
143
+ headerName: 'Sample Characteristics',
144
+ children: []
145
+ };
146
+ sample.characteristic.forEach((ch)=>{
147
+ if (!isFactor[ch.type]) characteristics.children.push({
148
+ field: ch.type,
149
+ cellRenderer: $5833a2eeefc77457$var$metaRenderer
150
+ });
151
+ });
152
+ metadataFields.push(characteristics);
153
+ }
154
+ let s_info = {
155
+ sampleId: sample
156
+ };
157
+ sample.factor.forEach((factor)=>{
158
+ s_info[factor.type] = {
159
+ label: factor.label
160
+ };
161
+ if (factor.ontology) {
162
+ s_info[factor.type]['ontology'] = factor.ontology;
163
+ s_info[factor.type]['id'] = factor.id;
164
+ }
165
+ });
166
+ sample.characteristic.forEach((ch)=>{
167
+ s_info[ch.type] = {
168
+ label: ch.label
169
+ };
170
+ if (ch.ontology) {
171
+ s_info[ch.type]['ontology'] = ch.ontology;
172
+ s_info[ch.type]['id'] = ch.id;
173
+ }
174
+ });
175
+ sampleMetadata.push(s_info);
176
+ });
177
+ const [rowData, setRowData] = (0, $gXNCa$react.useState)(sampleMetadata);
178
+ const [colDefs, setColDefs] = (0, $gXNCa$react.useState)(metadataFields);
179
+ const defaultColDef = (0, $gXNCa$react.useMemo)(()=>{
180
+ return {
181
+ filter: true
182
+ };
183
+ }, []);
184
+ return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
185
+ children: [
186
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
187
+ className: "ag-theme-quartz",
188
+ style: {
189
+ height: `${44 * (samples.length + 2)}px`
190
+ },
191
+ children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$aggridreact.AgGridReact), {
192
+ rowData: rowData,
193
+ columnDefs: colDefs,
194
+ defaultColDef: defaultColDef
195
+ })
196
+ }),
197
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("a", {
198
+ href: `https://www.ebi.ac.uk/gxa/experiments/${props.id}`,
199
+ children: [
200
+ "EBI Atlas Experiment: ",
201
+ props.id
202
+ ]
203
+ })
204
+ ]
205
+ });
206
+ };
207
+ var $5833a2eeefc77457$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.connect)('selectExpressionSamples', $5833a2eeefc77457$var$Study);
79
208
 
80
209
  });
81
210
 
@@ -95,10 +224,11 @@ $parcel$export(module.exports, "Views", () => $693dd8c7a5607c3a$export$5cb791131
95
224
 
96
225
  const $9d9aeaf9299e61a1$var$facets = [
97
226
  "{!facet.limit='300' facet.mincount='1' key='taxon_id'}taxon_id",
98
- "{!facet.limit='100' facet.mincount='1' key='genetree'}gene_tree",
99
- "{!facet.limit='100' facet.mincount='1' key='pathways'}pathways__ancestors",
100
- "{!facet.limit='100' facet.mincount='1' key='domains'}domain_roots",
101
- "{!facet.limit='-1' facet.mincount='1' key='fixed_1000__bin'}fixed_1000__bin"
227
+ // "{!facet.limit='100' facet.mincount='1' key='genetree'}gene_tree",
228
+ // "{!facet.limit='100' facet.mincount='1' key='pathways'}pathways__ancestors",
229
+ // "{!facet.limit='100' facet.mincount='1' key='domains'}domain_roots",
230
+ "{!facet.limit='-1' facet.mincount='1' key='fixed_1000__bin'}fixed_1000__bin",
231
+ "{!facet.limit='100' facet.mincount='0' key='AED' type='range' start=0 end=1.0 gap=0.01}MAKER__AED__attr_f"
102
232
  ];
103
233
  const $9d9aeaf9299e61a1$var$genomesOfInterest = '(taxon_id:2769) OR (taxon_id:3055) OR (taxon_id:3218) OR (taxon_id:3702) OR (taxon_id:3847) OR (taxon_id:4555) OR (taxon_id:4558) OR (taxon_id:4577) OR (taxon_id:13333) OR (taxon_id:15368) OR (taxon_id:29760) OR (taxon_id:39947) OR (taxon_id:55577) OR (taxon_id:88036) OR (taxon_id:214687)';
104
234
  const $9d9aeaf9299e61a1$var$sites = [
@@ -314,138 +444,80 @@ $9d9aeaf9299e61a1$var$grameneGermplasm.reactGrameneGermplasm = (0, $gXNCa$reduxb
314
444
  // }
315
445
  // }
316
446
  // );
317
- const $9d9aeaf9299e61a1$var$attribFacetFields = [
318
- "{!facet.limit='10' facet.mincount='1' key='age'}panset_age_attr_s",
319
- "{!facet.limit='100' facet.mincount='1' key='taxa'}panset_ntaxa_attr_i",
320
- "{!facet.limit='100' facet.mincount='1' key='AED' type='range' start=0 end=1.0 gap=0.25}MAKER_AED_attr_f",
321
- "{!facet.limit='100' facet.mincount='1' key='QI2' type='range' start=0 end=1.0 gap=0.25}MAKER_QI2_attr_f",
322
- "{!facet.limit='100' facet.mincount='1' key='QI3' type='range' start=0 end=1.0 gap=0.25}MAKER_QI3_attr_f",
323
- "{!facet.limit='100' facet.mincount='1' key='QI4' type='range' start=0 end=1.0 gap=0.25}MAKER_QI4_attr_f",
324
- "{!facet.limit='100' facet.mincount='1' key='QI5' type='range' start=0 end=1.0 gap=0.25}MAKER_QI5_attr_f",
325
- "{!facet.limit='100' facet.mincount='1' key='QI6' type='range' start=0 end=1.0 gap=0.25}MAKER_QI6_attr_f"
447
+ const $9d9aeaf9299e61a1$var$MAKERAttribs = [
448
+ 'MAKER__AED__attr_f',
449
+ 'MAKER__QI1__attr_i',
450
+ 'MAKER__QI2__attr_f',
451
+ 'MAKER__QI3__attr_f',
452
+ 'MAKER__QI4__attr_f',
453
+ 'MAKER__QI5__attr_f',
454
+ 'MAKER__QI6__attr_f',
455
+ 'MAKER__QI7__attr_i',
456
+ 'MAKER__QI8__attr_i',
457
+ 'MAKER__QI9__attr_i'
326
458
  ];
327
- const $9d9aeaf9299e61a1$var$attribFacets = {
328
- "age": {
329
- "type": "terms",
330
- "field": "panset_age_attr_s"
331
- },
332
- "nTaxa": {
333
- "type": "terms",
334
- "field": "panset_ntaxa_attr_i",
335
- "limit": 100
336
- },
337
- "AED": {
338
- "type": "range",
339
- "field": "MAKER_AED_attr_f",
340
- "start": 0.0,
341
- "end": 1.0,
342
- "gap": 0.25
343
- },
344
- "QI2": {
345
- "type": "range",
346
- "field": "MAKER_QI2_attr_f",
347
- "start": 0.0,
348
- "end": 1.0,
349
- "gap": 0.25
350
- },
351
- "QI3": {
352
- "type": "range",
353
- "field": "MAKER_QI3_attr_f",
354
- "start": 0.0,
355
- "end": 1.0,
356
- "gap": 0.25
357
- },
358
- "QI4": {
359
- "type": "range",
360
- "field": "MAKER_QI4_attr_f",
361
- "start": 0.0,
362
- "end": 1.0,
363
- "gap": 0.25
364
- },
365
- "QI5": {
366
- "type": "range",
367
- "field": "MAKER_QI5_attr_f",
368
- "start": 0.0,
369
- "end": 1.0,
370
- "gap": 0.25
371
- },
372
- "QI6": {
373
- "type": "range",
374
- "field": "MAKER_QI6_attr_f",
375
- "start": 0.0,
376
- "end": 1.0,
377
- "gap": 0.25
378
- },
379
- "byAge": {
380
- "type": "terms",
381
- "field": "panset_age_attr_s",
382
- "facet": {
383
- "nTaxa": {
384
- "type": "terms",
385
- "field": "panset_ntaxa_attr_i",
386
- "limit": 100
387
- },
388
- "AED": {
389
- "type": "range",
390
- "field": "MAKER_AED_attr_f",
391
- "start": 0.0,
392
- "end": 1.0,
393
- "gap": 0.25
394
- },
395
- "QI2": {
396
- "type": "range",
397
- "field": "MAKER_QI2_attr_f",
398
- "start": 0.0,
399
- "end": 1.0,
400
- "gap": 0.25
401
- },
402
- "QI3": {
403
- "type": "range",
404
- "field": "MAKER_QI3_attr_f",
405
- "start": 0.0,
406
- "end": 1.0,
407
- "gap": 0.25
408
- },
409
- "QI4": {
410
- "type": "range",
411
- "field": "MAKER_QI4_attr_f",
412
- "start": 0.0,
413
- "end": 1.0,
414
- "gap": 0.25
415
- },
416
- "QI5": {
417
- "type": "range",
418
- "field": "MAKER_QI5_attr_f",
419
- "start": 0.0,
420
- "end": 1.0,
421
- "gap": 0.25
422
- },
423
- "QI6": {
424
- "type": "range",
425
- "field": "MAKER_QI6_attr_f",
426
- "start": 0.0,
427
- "end": 1.0,
428
- "gap": 0.25
429
- }
459
+ const $9d9aeaf9299e61a1$var$geneAttribs = {
460
+ "MAKER transcript metrics": [
461
+ {
462
+ name: "AED",
463
+ description: "Annotation Edit Distance",
464
+ dtype: "f",
465
+ fieldName: "MAKER__AED__attr_f"
466
+ },
467
+ {
468
+ name: "QI1",
469
+ description: "Length of the 5' UTR",
470
+ dtype: "i",
471
+ fieldName: "MAKER__QI1__attr_i"
472
+ },
473
+ {
474
+ name: "QI2",
475
+ description: "Fraction of splice sites confirmed by an EST alignment",
476
+ dtype: "f",
477
+ fieldName: "MAKER__QI2__attr_f"
478
+ },
479
+ {
480
+ name: "QI3",
481
+ description: "Fraction of exons that overlap an EST alignment",
482
+ dtype: "f",
483
+ fieldName: "MAKER__QI3__attr_f"
484
+ },
485
+ {
486
+ name: "QI4",
487
+ description: "Fraction of exons that overlap EST or Protein alignments",
488
+ dtype: "f",
489
+ fieldName: "MAKER__QI4__attr_f"
490
+ },
491
+ // { name: "QI5", description: "Fraction of splice sites confirmed by a SNAP prediction", dtype: "f", fieldName: "MAKER__QI5__attr_f" },
492
+ // { name: "QI6", description: "Fraction of exons that overlap a SNAP prediction", dtype: "f", fieldName: "MAKER__QI6__attr_f" },
493
+ {
494
+ name: "QI7",
495
+ description: "Number of exons in the mRNA",
496
+ dtype: "i",
497
+ fieldName: "MAKER__QI7__attr_i"
498
+ },
499
+ {
500
+ name: "QI8",
501
+ description: "Length of the 3' UTR",
502
+ dtype: "i",
503
+ fieldName: "MAKER__QI8__attr_i"
504
+ },
505
+ {
506
+ name: "QI9",
507
+ description: "Length of the protein sequence produced by the mRNA",
508
+ dtype: "i",
509
+ fieldName: "MAKER__QI9__attr_i"
430
510
  }
431
- }
511
+ ]
432
512
  };
513
+ const $9d9aeaf9299e61a1$var$statsFields = $9d9aeaf9299e61a1$var$geneAttribs['MAKER transcript metrics'].map(// (f) => `stats.field={!min=true max=true count=true mean=true stddev=true percentiles='20,40,60,80,90,95,99'}${f}`
514
+ (f)=>`stats.field={!min=true max=true count=true mean=true stddev=true percentiles='10,20,30,40,50,60,70,80,90,99.99'}${f.fieldName}`);
433
515
  const $9d9aeaf9299e61a1$var$grameneGeneAttribs = (0, $gXNCa$reduxbundler.createAsyncResourceBundle)({
434
516
  name: 'grameneGeneAttribs',
435
517
  actionBaseType: 'GRAMENE_GENE_ATTRIBS',
436
518
  persist: false,
437
519
  getPromise: ({ store: store })=>{
438
- const g = store.selectGrameneGenomes();
439
- const taxa = Object.keys(g.active);
440
- let fq = '';
441
- if (taxa.length) {
442
- console.log('search add a fq for ', taxa);
443
- fq = `&fq=taxon_id:(${taxa.join(' OR ')})`;
444
- }
445
- return fetch(`${store.selectGrameneAPI()}/search?q=${store.selectGrameneFiltersQueryString()}&json.facet=${JSON.stringify($9d9aeaf9299e61a1$var$attribFacets)}&rows=0${fq}`)// return fetch(`${store.selectGrameneAPI()}/search?rows=1&q=MAKER_AED_attr_f:*&json.facet=${JSON.stringify(attribFacets)}`)
446
- .then((res)=>res.json()).then((res)=>{
447
- return res.facets;
448
- });
520
+ return fetch(`${store.selectGrameneAPI()}/geneAttributes`).then((res)=>$9d9aeaf9299e61a1$var$geneAttribs);
449
521
  }
450
522
  });
451
523
  $9d9aeaf9299e61a1$var$grameneGeneAttribs.reactGrameneGeneAttribs = (0, $gXNCa$reduxbundler.createSelector)('selectGrameneGeneAttribsShouldUpdate', 'selectGrameneFiltersStatus', 'selectGrameneViews', (shouldUpdate, status, views)=>{
@@ -470,7 +542,7 @@ const $9d9aeaf9299e61a1$var$grameneSearch = (0, $gXNCa$reduxbundler.createAsyncR
470
542
  console.log('search add a fq for ', taxa);
471
543
  fq = `&fq=taxon_id:(${taxa.join(' OR ')})`;
472
544
  }
473
- return fetch(`${store.selectGrameneAPI()}/search?q=${store.selectGrameneFiltersQueryString()}&facet.field=${$9d9aeaf9299e61a1$var$facets}&rows=${rows}&start=${offset}${fq}`).then((res)=>res.json()).then((res)=>{
545
+ return fetch(`${store.selectGrameneAPI()}/search?q=${store.selectGrameneFiltersQueryString()}&facet.field=${$9d9aeaf9299e61a1$var$facets}&rows=${rows}&start=${offset}${fq}&stats=true&${$9d9aeaf9299e61a1$var$statsFields.join('&')}`).then((res)=>res.json()).then((res)=>{
474
546
  res.response.docs.forEach((d)=>{
475
547
  d.can_show = {};
476
548
  d.capabilities.forEach((c)=>{
@@ -603,9 +675,11 @@ const $9d9aeaf9299e61a1$var$grameneParalogs = {
603
675
  });
604
676
  const API = store.selectGrameneAPI();
605
677
  const q = supertree ? `supertree_attr_s:${supertree}` : `homology__within_species_paralog:${geneId}`;
606
- fetch(`${API}/search?q=${q}&rows=100&fq=taxon_id:${taxon_id}`).then((res)=>res.json()).then((res)=>{
678
+ fetch(`${API}/search?q=${q}&rows=1000&fq=taxon_id:${taxon_id}`).then((res)=>res.json()).then((res)=>{
607
679
  let newParalogs = {};
608
- newParalogs[geneId] = res.response.docs.map((d)=>d.id);
680
+ newParalogs[geneId] = res.response.numFound > 0 ? res.response.docs.map((d)=>d.id) : [
681
+ geneId
682
+ ];
609
683
  dispatch({
610
684
  type: 'GRAMENE_PARALOGS_RECEIVED',
611
685
  payload: newParalogs
@@ -671,6 +745,7 @@ var // function selectFacetIDs(store, field) {
671
745
  $9d9aeaf9299e61a1$export$2e2bcd8739ae039 = [
672
746
  $9d9aeaf9299e61a1$var$grameneSuggestions,
673
747
  $9d9aeaf9299e61a1$var$grameneSearch,
748
+ $9d9aeaf9299e61a1$var$grameneGeneAttribs,
674
749
  $9d9aeaf9299e61a1$var$grameneMaps,
675
750
  $9d9aeaf9299e61a1$var$grameneTaxonomy,
676
751
  $9d9aeaf9299e61a1$var$grameneTaxDist,
@@ -678,7 +753,6 @@ $9d9aeaf9299e61a1$export$2e2bcd8739ae039 = [
678
753
  $9d9aeaf9299e61a1$var$grameneParalogs,
679
754
  $9d9aeaf9299e61a1$var$curatedGenes,
680
755
  $9d9aeaf9299e61a1$var$grameneGermplasm,
681
- $9d9aeaf9299e61a1$var$grameneGeneAttribs,
682
756
  $9d9aeaf9299e61a1$var$expressionSamples,
683
757
  $9d9aeaf9299e61a1$var$expressionStudies
684
758
  ];
@@ -1370,7 +1444,7 @@ const $24971af0a229e0e3$var$grameneViews = {
1370
1444
  {
1371
1445
  id: 'attribs',
1372
1446
  name: 'Gene attributes',
1373
- show: 'disabled',
1447
+ show: 'off',
1374
1448
  shouldScroll: false
1375
1449
  }
1376
1450
  ]
@@ -1556,6 +1630,7 @@ const $671312b287158a8a$var$grameneDocs = {
1556
1630
  else newState.desiredSamples[payload] = {
1557
1631
  status: 'need'
1558
1632
  };
1633
+ return newState;
1559
1634
  }
1560
1635
  return state;
1561
1636
  };
@@ -2356,6 +2431,7 @@ const $9e29a4f60318db7a$var$Detail = (props)=>{
2356
2431
  const gene = props.geneDocs[props.searchResult.id];
2357
2432
  const [atlasExperiment, setAtlasExperiment] = (0, $gXNCa$react.useState)(null);
2358
2433
  const [atlasExperimentList, setAtlasExperimentList] = (0, $gXNCa$react.useState)([]);
2434
+ const [atlasFacets, setAtlasFacets] = (0, $gXNCa$react.useState)(null);
2359
2435
  const [isLocal, setIsLocal] = (0, $gXNCa$react.useState)(false);
2360
2436
  const [activeTab, setActiveTab] = (0, $gXNCa$react.useState)('gene');
2361
2437
  const handleLocalAPIChange = (event)=>{
@@ -2364,6 +2440,10 @@ const $9e29a4f60318db7a$var$Detail = (props)=>{
2364
2440
  (0, $gXNCa$react.useEffect)(()=>{
2365
2441
  const tid = Math.floor(gene.taxon_id / 1000);
2366
2442
  if (props.expressionStudies[tid]) {
2443
+ let facets = {
2444
+ Differential: {},
2445
+ Baseline: {}
2446
+ };
2367
2447
  let eList = props.expressionStudies[tid].sort((a, b)=>{
2368
2448
  const a_name = `${a.type}:${a.description || a._id}`;
2369
2449
  const b_name = `${b.type}:${b.description || b._id}`;
@@ -2373,7 +2453,11 @@ const $9e29a4f60318db7a$var$Detail = (props)=>{
2373
2453
  const in_gxa = new Set(props.searchResult.expressed_in_gxa_attr_ss);
2374
2454
  eList = eList.filter((e)=>in_gxa.has(e._id));
2375
2455
  }
2456
+ eList.forEach((e)=>{
2457
+ e.factors.forEach((factor)=>facets[e.type][factor] = 1);
2458
+ });
2376
2459
  setAtlasExperimentList(eList);
2460
+ setAtlasFacets(facets);
2377
2461
  let refExp = eList.filter((e)=>e.isRef);
2378
2462
  if (refExp.length === 1) setAtlasExperiment(refExp[0]._id);
2379
2463
  else // no reference experiment - choose first
@@ -2390,7 +2474,7 @@ const $9e29a4f60318db7a$var$Detail = (props)=>{
2390
2474
  // if (gene.homology && gene.homology.homologous_genes && gene.homology.homologous_genes.within_species_paralog) {
2391
2475
  // paralogs = gene.homology.homologous_genes.within_species_paralog;
2392
2476
  // }
2393
- if (paralogs.length > 1 && atlasExperiment) paralogs_url = `https://dev.gramene.org/static/atlasWidget.html?genes=${paralogs.join(' ')}&experiment=${atlasExperiment}&localAPI=${isLocal}`;
2477
+ if (paralogs.length > 0 && atlasExperiment) paralogs_url = `https://dev.gramene.org/static/atlasWidget.html?genes=${paralogs.join(' ')}&experiment=${atlasExperiment}&localAPI=${isLocal}`;
2394
2478
  return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactbootstrap.Tabs), {
2395
2479
  activeKey: activeTab,
2396
2480
  onSelect: (k)=>setActiveTab(k),
@@ -5243,7 +5327,8 @@ class $a67cad486021eb32$var$TaxDist extends (0, ($parcel$interopDefault($gXNCa$r
5243
5327
  constructor(props){
5244
5328
  super(props);
5245
5329
  this.state = {
5246
- collapseEmpties: true
5330
+ collapseEmpties: true,
5331
+ comparaOnly: true
5247
5332
  };
5248
5333
  }
5249
5334
  handleSelection(selections) {
@@ -5266,22 +5351,44 @@ class $a67cad486021eb32$var$TaxDist extends (0, ($parcel$interopDefault($gXNCa$r
5266
5351
  collapseEmpties: !this.state.collapseEmpties
5267
5352
  });
5268
5353
  }
5354
+ toggleCompara() {
5355
+ this.setState({
5356
+ comparaOnly: !this.state.comparaOnly
5357
+ });
5358
+ }
5269
5359
  render() {
5270
5360
  let selectedTaxa = {};
5271
5361
  if (this.props.grameneSearch && this.state.collapseEmpties) this.props.grameneSearch.facet_counts.facet_fields.taxon_id.filter((tid, idx)=>idx % 2 === 0).forEach((tid)=>{
5272
5362
  selectedTaxa[tid] = true;
5273
5363
  });
5364
+ else if (Object.keys(this.props.grameneGenomes.active).length === 0 && this.props.grameneMaps) Object.keys(this.props.grameneMaps).forEach((tid)=>selectedTaxa[tid] = true);
5274
5365
  else selectedTaxa = this.props.grameneGenomes.active;
5366
+ if (this.state.comparaOnly && this.props.grameneMaps) Object.keys(selectedTaxa).forEach((tid)=>{
5367
+ if (!this.props.grameneMaps[tid].in_compara) delete selectedTaxa[tid];
5368
+ });
5275
5369
  return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
5276
5370
  className: "results-vis big-vis",
5277
5371
  children: [
5278
- this.props.grameneTaxDist && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("button", {
5279
- type: "button",
5280
- className: "btn btn-primary btn-sm",
5281
- onClick: this.toggleEmpties.bind(this),
5372
+ this.props.grameneTaxDist && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("span", {
5282
5373
  children: [
5283
- this.state.collapseEmpties ? 'Expand' : 'Collapse',
5284
- " empty branches"
5374
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("button", {
5375
+ type: "button",
5376
+ className: "btn btn-outline-primary btn-sm",
5377
+ onClick: this.toggleEmpties.bind(this),
5378
+ children: [
5379
+ this.state.collapseEmpties ? 'Expand' : 'Collapse',
5380
+ " empty branches"
5381
+ ]
5382
+ }),
5383
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("button", {
5384
+ type: "button",
5385
+ className: "btn btn-outline-success btn-sm",
5386
+ onClick: this.toggleCompara.bind(this),
5387
+ children: [
5388
+ "Show ",
5389
+ this.state.comparaOnly ? 'all genomes' : 'compara only'
5390
+ ]
5391
+ })
5285
5392
  ]
5286
5393
  }),
5287
5394
  this.props.grameneTaxDist && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, ($parcel$interopDefault($gXNCa$gramenesearchvis))), {
@@ -5303,7 +5410,7 @@ class $a67cad486021eb32$var$TaxDist extends (0, ($parcel$interopDefault($gXNCa$r
5303
5410
  });
5304
5411
  }
5305
5412
  }
5306
- var $a67cad486021eb32$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.connect)('selectGrameneTaxDist', 'selectGrameneGenomes', 'selectGrameneSearch', $a67cad486021eb32$var$TaxDist);
5413
+ var $a67cad486021eb32$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.connect)('selectGrameneTaxDist', 'selectGrameneGenomes', 'selectGrameneSearch', 'selectGrameneMaps', $a67cad486021eb32$var$TaxDist);
5307
5414
 
5308
5415
 
5309
5416
 
@@ -5493,21 +5600,461 @@ var $b36244140732570a$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.conn
5493
5600
 
5494
5601
 
5495
5602
 
5603
+
5604
+
5605
+ function $dbdedae66c619d9b$export$2e2bcd8739ae039({ groups: groups, stats: stats }) {
5606
+ const fields = stats?.stats_fields || {};
5607
+ return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
5608
+ style: {
5609
+ fontFamily: "system-ui, -apple-system, Segoe UI, Roboto, sans-serif",
5610
+ lineHeight: 1.35
5611
+ },
5612
+ children: Object.entries(groups).map(([groupName, attrs])=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($dbdedae66c619d9b$var$GroupTable, {
5613
+ groupName: groupName,
5614
+ attributes: attrs,
5615
+ fields: fields
5616
+ }, groupName))
5617
+ });
5618
+ }
5619
+ function $dbdedae66c619d9b$var$GroupTable({ groupName: groupName, attributes: attributes, fields: fields }) {
5620
+ const hasAny = attributes?.some((a)=>fields[a.fieldName]);
5621
+ const columns = (0, $gXNCa$react.useMemo)(()=>[
5622
+ {
5623
+ key: "attr",
5624
+ label: "Attribute",
5625
+ min: 120
5626
+ },
5627
+ {
5628
+ key: "desc",
5629
+ label: "Description",
5630
+ min: 380,
5631
+ flex: true
5632
+ },
5633
+ {
5634
+ key: "mean",
5635
+ label: "Mean",
5636
+ min: 100
5637
+ },
5638
+ {
5639
+ key: "stddev",
5640
+ label: "Std Dev",
5641
+ min: 110
5642
+ },
5643
+ {
5644
+ key: "min",
5645
+ label: "Min",
5646
+ min: 90
5647
+ },
5648
+ {
5649
+ key: "max",
5650
+ label: "Max",
5651
+ min: 90
5652
+ },
5653
+ {
5654
+ key: "count",
5655
+ label: "Count",
5656
+ min: 90
5657
+ },
5658
+ {
5659
+ key: "dist",
5660
+ label: "Distribution",
5661
+ min: 220
5662
+ }
5663
+ ], []);
5664
+ const initial = (0, $gXNCa$react.useMemo)(()=>columns.map((c)=>c.flex ? Math.max(380, c.min) : c.min), [
5665
+ columns
5666
+ ]);
5667
+ const { colWidths: colWidths, startResize: startResize, resizing: resizing } = $dbdedae66c619d9b$var$useResizableColumns({
5668
+ initialWidths: initial,
5669
+ minWidths: columns.map((c)=>c.min || 60)
5670
+ });
5671
+ const nfInt = (0, $gXNCa$react.useMemo)(()=>new Intl.NumberFormat("en-US", {
5672
+ maximumFractionDigits: 0
5673
+ }), []);
5674
+ const nfFloat = (0, $gXNCa$react.useMemo)(()=>new Intl.NumberFormat("en-US", {
5675
+ minimumFractionDigits: 0,
5676
+ maximumFractionDigits: 3
5677
+ }), []);
5678
+ return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("section", {
5679
+ style: {
5680
+ marginBottom: 24
5681
+ },
5682
+ children: [
5683
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("header", {
5684
+ style: {
5685
+ display: "flex",
5686
+ alignItems: "baseline",
5687
+ gap: 12,
5688
+ marginBottom: 8
5689
+ },
5690
+ children: [
5691
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("h2", {
5692
+ style: {
5693
+ margin: 0,
5694
+ fontSize: 18
5695
+ },
5696
+ children: groupName
5697
+ }),
5698
+ !hasAny && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
5699
+ style: {
5700
+ fontSize: 12,
5701
+ color: "#666"
5702
+ },
5703
+ children: "No stats available for this group."
5704
+ })
5705
+ ]
5706
+ }),
5707
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
5708
+ style: {
5709
+ overflowX: "auto",
5710
+ border: "1px solid #eee",
5711
+ borderRadius: 8,
5712
+ boxShadow: "0 1px 2px rgba(0,0,0,0.04)"
5713
+ },
5714
+ children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("table", {
5715
+ style: $dbdedae66c619d9b$var$tableStyle,
5716
+ children: [
5717
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("colgroup", {
5718
+ children: colWidths.map((w, i)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("col", {
5719
+ style: {
5720
+ width: w
5721
+ }
5722
+ }, i))
5723
+ }),
5724
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("thead", {
5725
+ children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("tr", {
5726
+ children: columns.map((col, i)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($dbdedae66c619d9b$var$ResizableTh, {
5727
+ label: col.label,
5728
+ index: i,
5729
+ onResizeStart: startResize
5730
+ }, col.key))
5731
+ })
5732
+ }),
5733
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("tbody", {
5734
+ children: attributes.map((a)=>{
5735
+ const s = fields[a.fieldName] || {};
5736
+ return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("tr", {
5737
+ children: [
5738
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($dbdedae66c619d9b$var$Td, {
5739
+ mono: true,
5740
+ title: a.fieldName,
5741
+ children: a.name
5742
+ }),
5743
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($dbdedae66c619d9b$var$Td, {
5744
+ title: a.description,
5745
+ children: a.description
5746
+ }),
5747
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($dbdedae66c619d9b$var$Td, {
5748
+ align: "right",
5749
+ children: $dbdedae66c619d9b$var$fmtValue(s.mean, a.dtype, true, nfInt, nfFloat)
5750
+ }),
5751
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($dbdedae66c619d9b$var$Td, {
5752
+ align: "right",
5753
+ children: $dbdedae66c619d9b$var$fmtValue(s.stddev, a.dtype, true, nfInt, nfFloat)
5754
+ }),
5755
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($dbdedae66c619d9b$var$Td, {
5756
+ align: "right",
5757
+ children: $dbdedae66c619d9b$var$fmtValue(s.min, a.dtype, false, nfInt, nfFloat)
5758
+ }),
5759
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($dbdedae66c619d9b$var$Td, {
5760
+ align: "right",
5761
+ children: $dbdedae66c619d9b$var$fmtValue(s.max, a.dtype, false, nfInt, nfFloat)
5762
+ }),
5763
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($dbdedae66c619d9b$var$Td, {
5764
+ align: "right",
5765
+ children: $dbdedae66c619d9b$var$fmtCount(s.count, nfInt)
5766
+ }),
5767
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($dbdedae66c619d9b$var$Td, {
5768
+ children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($dbdedae66c619d9b$var$PercentileHeatmapNormalized, {
5769
+ percentilesArr: s.percentiles,
5770
+ min: s.min,
5771
+ max: s.max
5772
+ })
5773
+ })
5774
+ ]
5775
+ }, a.fieldName);
5776
+ })
5777
+ })
5778
+ ]
5779
+ })
5780
+ }),
5781
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
5782
+ style: {
5783
+ marginTop: 6,
5784
+ fontSize: 12,
5785
+ color: "#666"
5786
+ },
5787
+ children: [
5788
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("em", {
5789
+ children: "Tip:"
5790
+ }),
5791
+ " Drag the divider at the right edge of any header to resize.",
5792
+ resizing && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
5793
+ style: {
5794
+ marginLeft: 8,
5795
+ color: "#999"
5796
+ },
5797
+ children: "(resizing\u2026)"
5798
+ })
5799
+ ]
5800
+ })
5801
+ ]
5802
+ });
5803
+ }
5804
+ /* ===================== Percentiles / Heatmap ===================== */ /**
5805
+ * Convert alternating array into ordered pairs: [["10.0", v10], ["20.0", v20], ...]
5806
+ * - Preserves the exact order provided by Solr
5807
+ */ function $dbdedae66c619d9b$var$percentilesArrayToPairs(arr) {
5808
+ if (!Array.isArray(arr)) return [];
5809
+ const out = [];
5810
+ for(let i = 0; i < arr.length - 1; i += 2)out.push([
5811
+ String(arr[i]),
5812
+ arr[i + 1]
5813
+ ]);
5814
+ return out;
5815
+ }
5816
+ function $dbdedae66c619d9b$var$normalizeBetween(value, min, max) {
5817
+ if (!isFinite(min) || !isFinite(max) || max <= min || !isFinite(value)) return null;
5818
+ return (value - min) / (max - min);
5819
+ }
5820
+ // White -> Blue (0 -> 1)
5821
+ function $dbdedae66c619d9b$var$rgbWhiteToBlue(vNorm) {
5822
+ const t = $dbdedae66c619d9b$var$clamp01(vNorm);
5823
+ const rg = Math.round(255 * (1 - t));
5824
+ return `rgb(${rg}, ${rg}, 255)`;
5825
+ }
5826
+ function $dbdedae66c619d9b$var$clamp01(x) {
5827
+ if (typeof x !== "number" || !isFinite(x)) return 0;
5828
+ return Math.max(0, Math.min(1, x));
5829
+ }
5830
+ function $dbdedae66c619d9b$var$fmtFloat(v) {
5831
+ if (v == null || !isFinite(v)) return "n/a";
5832
+ return v.toFixed(3);
5833
+ }
5834
+ /**
5835
+ * PercentileHeatmapNormalized
5836
+ * - Infers bins from percentilesArr (order preserved)
5837
+ * - Colors normalized by row min/max
5838
+ */ function $dbdedae66c619d9b$var$PercentileHeatmapNormalized({ percentilesArr: percentilesArr, min: min, max: max }) {
5839
+ const pairs = (0, $gXNCa$react.useMemo)(()=>$dbdedae66c619d9b$var$percentilesArrayToPairs(percentilesArr), [
5840
+ percentilesArr
5841
+ ]);
5842
+ const n = pairs.length || 1; // avoid zero columns
5843
+ const validScale = isFinite(min) && isFinite(max) && max > min;
5844
+ return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
5845
+ style: {
5846
+ ...$dbdedae66c619d9b$var$heatRowDynamic,
5847
+ gridTemplateColumns: `repeat(${n}, 1fr)`
5848
+ },
5849
+ children: pairs.map(([pStr, raw], idx)=>{
5850
+ const rawNum = typeof raw === "number" && isFinite(raw) ? raw : null;
5851
+ const norm = rawNum == null ? null : validScale ? $dbdedae66c619d9b$var$normalizeBetween(rawNum, min, max) : null;
5852
+ const bg = norm == null ? "#f2f2f2" : $dbdedae66c619d9b$var$rgbWhiteToBlue(norm);
5853
+ const label = `${pStr} \u{2192} raw ${$dbdedae66c619d9b$var$fmtFloat(rawNum)} (norm ${$dbdedae66c619d9b$var$fmtFloat(norm)})`;
5854
+ return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($dbdedae66c619d9b$var$HeatCell, {
5855
+ background: bg,
5856
+ label: label
5857
+ }, `${pStr}-${idx}`);
5858
+ })
5859
+ });
5860
+ }
5861
+ function $dbdedae66c619d9b$var$HeatCell({ background: background, label: label }) {
5862
+ const [hover, setHover] = (0, $gXNCa$react.useState)(false);
5863
+ return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
5864
+ style: {
5865
+ ...$dbdedae66c619d9b$var$heatCell,
5866
+ background: background
5867
+ },
5868
+ onMouseEnter: ()=>setHover(true),
5869
+ onMouseLeave: ()=>setHover(false),
5870
+ title: label,
5871
+ children: hover && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
5872
+ style: $dbdedae66c619d9b$var$popover,
5873
+ children: label
5874
+ })
5875
+ });
5876
+ }
5877
+ /* ===================== Resizable columns ===================== */ function $dbdedae66c619d9b$var$useResizableColumns({ initialWidths: initialWidths, minWidths: minWidths }) {
5878
+ const [colWidths, setColWidths] = (0, $gXNCa$react.useState)(initialWidths);
5879
+ const [resizing, setResizing] = (0, $gXNCa$react.useState)(false);
5880
+ const activeRef = (0, $gXNCa$react.useRef)(null); // { index, startX, startW }
5881
+ (0, $gXNCa$react.useEffect)(()=>{
5882
+ if (initialWidths?.length) setColWidths(initialWidths);
5883
+ }, [
5884
+ initialWidths?.length
5885
+ ]); // eslint-disable-line react-hooks/exhaustive-deps
5886
+ const onMouseMove = (e)=>{
5887
+ if (!activeRef.current) return;
5888
+ const { index: index, startX: startX, startW: startW } = activeRef.current;
5889
+ const dx = e.clientX - startX;
5890
+ const next = [
5891
+ ...colWidths
5892
+ ];
5893
+ const minW = minWidths?.[index] ?? 60;
5894
+ next[index] = Math.max(minW, startW + dx);
5895
+ setColWidths(next);
5896
+ };
5897
+ const endResize = ()=>{
5898
+ activeRef.current = null;
5899
+ setResizing(false);
5900
+ document.body.style.cursor = "";
5901
+ document.body.style.userSelect = "";
5902
+ window.removeEventListener("mousemove", onMouseMove);
5903
+ window.removeEventListener("mouseup", endResize);
5904
+ };
5905
+ const startResize = (index, ev)=>{
5906
+ const startX = ev.clientX;
5907
+ const startW = colWidths[index];
5908
+ activeRef.current = {
5909
+ index: index,
5910
+ startX: startX,
5911
+ startW: startW
5912
+ };
5913
+ setResizing(true);
5914
+ document.body.style.cursor = "col-resize";
5915
+ document.body.style.userSelect = "none";
5916
+ window.addEventListener("mousemove", onMouseMove);
5917
+ window.addEventListener("mouseup", endResize);
5918
+ };
5919
+ (0, $gXNCa$react.useEffect)(()=>{
5920
+ return ()=>{
5921
+ window.removeEventListener("mousemove", onMouseMove);
5922
+ window.removeEventListener("mouseup", endResize);
5923
+ };
5924
+ }, []); // eslint-disable-line react-hooks/exhaustive-deps
5925
+ return {
5926
+ colWidths: colWidths,
5927
+ setColWidths: setColWidths,
5928
+ startResize: startResize,
5929
+ resizing: resizing
5930
+ };
5931
+ }
5932
+ function $dbdedae66c619d9b$var$ResizableTh({ label: label, index: index, onResizeStart: onResizeStart }) {
5933
+ return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("th", {
5934
+ style: $dbdedae66c619d9b$var$thStyle,
5935
+ children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
5936
+ style: {
5937
+ position: "relative",
5938
+ width: "100%"
5939
+ },
5940
+ children: [
5941
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
5942
+ children: label
5943
+ }),
5944
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
5945
+ onMouseDown: (e)=>onResizeStart(index, e),
5946
+ role: "separator",
5947
+ "aria-orientation": "vertical",
5948
+ title: "Drag to resize column",
5949
+ style: $dbdedae66c619d9b$var$resizerStyle
5950
+ })
5951
+ ]
5952
+ })
5953
+ });
5954
+ }
5955
+ /* ===================== Formatting helpers ===================== */ function $dbdedae66c619d9b$var$fmtCount(v, nfInt) {
5956
+ if (v === null || v === undefined) return "\u2014";
5957
+ return nfInt.format(v);
5958
+ }
5959
+ function $dbdedae66c619d9b$var$fmtValue(v, dtype = "f", isStat = false, nfInt, nfFloat) {
5960
+ if (v === null || v === undefined || Number.isNaN(v)) return "\u2014";
5961
+ const isIntType = dtype === "i";
5962
+ return isIntType && !isStat ? nfInt.format(v) : nfFloat.format(v);
5963
+ }
5964
+ /* ===================== Cells & Styles ===================== */ function $dbdedae66c619d9b$var$Td({ children: children, align: align = "left", mono: mono = false, title: title }) {
5965
+ return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
5966
+ title: title,
5967
+ style: {
5968
+ ...$dbdedae66c619d9b$var$cellBase,
5969
+ textAlign: align,
5970
+ borderBottom: "1px solid #eee",
5971
+ padding: "8px 10px",
5972
+ fontFamily: mono ? "ui-monospace, SFMono-Regular, Menlo, monospace" : undefined,
5973
+ whiteSpace: "nowrap",
5974
+ overflow: "hidden",
5975
+ textOverflow: "ellipsis",
5976
+ verticalAlign: "top"
5977
+ },
5978
+ children: children
5979
+ });
5980
+ }
5981
+ const $dbdedae66c619d9b$var$tableStyle = {
5982
+ width: "100%",
5983
+ borderCollapse: "collapse",
5984
+ tableLayout: "fixed",
5985
+ minWidth: 980
5986
+ };
5987
+ const $dbdedae66c619d9b$var$cellBase = {
5988
+ fontSize: 13,
5989
+ lineHeight: 1.35,
5990
+ whiteSpace: "nowrap",
5991
+ overflow: "hidden",
5992
+ textOverflow: "ellipsis"
5993
+ };
5994
+ const $dbdedae66c619d9b$var$thStyle = {
5995
+ ...$dbdedae66c619d9b$var$cellBase,
5996
+ textAlign: "left",
5997
+ borderBottom: "1px solid #ddd",
5998
+ background: "#fafafa",
5999
+ fontWeight: 600,
6000
+ padding: "10px 10px",
6001
+ position: "relative"
6002
+ };
6003
+ const $dbdedae66c619d9b$var$resizerStyle = {
6004
+ position: "absolute",
6005
+ right: -5,
6006
+ top: 0,
6007
+ height: "100%",
6008
+ width: 10,
6009
+ cursor: "col-resize",
6010
+ boxShadow: "inset -1px 0 0 rgba(0,0,0,0.08)"
6011
+ };
6012
+ const $dbdedae66c619d9b$var$heatRowDynamic = {
6013
+ display: "grid",
6014
+ gap: 2,
6015
+ alignItems: "center",
6016
+ width: "100%",
6017
+ minWidth: 200
6018
+ };
6019
+ const $dbdedae66c619d9b$var$heatCell = {
6020
+ height: 16,
6021
+ borderRadius: 3,
6022
+ position: "relative",
6023
+ boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.06)"
6024
+ };
6025
+ const $dbdedae66c619d9b$var$popover = {
6026
+ position: "absolute",
6027
+ left: "50%",
6028
+ top: -26,
6029
+ transform: "translateX(-50%)",
6030
+ padding: "2px 6px",
6031
+ fontSize: 11,
6032
+ background: "rgba(0,0,0,0.8)",
6033
+ color: "#fff",
6034
+ borderRadius: 4,
6035
+ whiteSpace: "nowrap",
6036
+ pointerEvents: "none"
6037
+ };
6038
+
6039
+
5496
6040
  class $67bf5a43401bffdc$var$GeneAttribs extends (0, ($parcel$interopDefault($gXNCa$react))).Component {
5497
6041
  constructor(props){
5498
6042
  super(props);
5499
6043
  this.state = {};
5500
6044
  }
5501
6045
  render() {
5502
- return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
5503
- className: "gramene-attribs",
5504
- children: this.props.grameneGeneAttribs && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("pre", {
5505
- children: "hi"
5506
- })
5507
- });
6046
+ if (this.props.grameneGeneAttribs && this.props.grameneSearch) {
6047
+ const groups = this.props.grameneGeneAttribs;
6048
+ const stats = this.props.grameneSearch.stats;
6049
+ return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $dbdedae66c619d9b$export$2e2bcd8739ae039), {
6050
+ groups: groups,
6051
+ stats: stats
6052
+ });
6053
+ }
6054
+ return null;
5508
6055
  }
5509
6056
  }
5510
- var $67bf5a43401bffdc$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.connect)('selectGrameneGeneAttribs', $67bf5a43401bffdc$var$GeneAttribs);
6057
+ var $67bf5a43401bffdc$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.connect)('selectGrameneSearch', 'selectGrameneGeneAttribs', $67bf5a43401bffdc$var$GeneAttribs);
5511
6058
 
5512
6059
 
5513
6060
 
@@ -5635,7 +6182,9 @@ var $76e15aea9236bd47$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.conn
5635
6182
 
5636
6183
 
5637
6184
 
5638
- const $261baeb81c4d4d8a$var$LazyStudy = /*#__PURE__*/ (0, ($parcel$interopDefault($gXNCa$react))).lazy(()=>(parcelRequire("7u0Mi")));
6185
+ var $7zuJ6 = parcelRequire("7zuJ6");
6186
+
6187
+ const $261baeb81c4d4d8a$var$LazyStudy = /*#__PURE__*/ (0, ($parcel$interopDefault($gXNCa$react))).lazy(()=>Promise.resolve((parcelRequire("7zuJ6"))));
5639
6188
  const $261baeb81c4d4d8a$var$StudyList = (props)=>{
5640
6189
  return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Accordion), {
5641
6190
  alwaysOpen: true,
@@ -5648,13 +6197,8 @@ const $261baeb81c4d4d8a$var$StudyList = (props)=>{
5648
6197
  children: study.description
5649
6198
  }),
5650
6199
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Accordion).Body, {
5651
- children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$react.Suspense), {
5652
- fallback: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
5653
- children: "Loading..."
5654
- }),
5655
- children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($261baeb81c4d4d8a$var$LazyStudy, {
5656
- id: study._id
5657
- })
6200
+ children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $7zuJ6.default), {
6201
+ id: study._id
5658
6202
  })
5659
6203
  })
5660
6204
  ]
@@ -5666,15 +6210,21 @@ const $261baeb81c4d4d8a$var$Expression = (props)=>{
5666
6210
  let searchTaxa = {};
5667
6211
  if (props.grameneSearch) {
5668
6212
  const taxon_id_facet = props.grameneSearch.facet_counts.facet_fields.taxon_id;
5669
- taxon_id_facet.filter((tid, idx)=>idx % 2 === 0).forEach((tid)=>searchTaxa[tid] = true);
6213
+ taxon_id_facet.filter((tid, idx)=>idx % 2 === 0).forEach((tid)=>{
6214
+ if (tid > 1000000) {
6215
+ const tid2 = Math.floor(tid / 1000);
6216
+ if (props.expressionStudies[tid2]) searchTaxa[tid2] = tid;
6217
+ } else searchTaxa[tid] = tid;
6218
+ });
5670
6219
  }
5671
- const availableTaxa = Object.keys(props.expressionStudies).filter((tid)=>searchTaxa[tid] || searchTaxa[tid + '001']).sort((a, b)=>props.grameneMaps[a + '001'].left_index - props.grameneMaps[b + '001'].left_index);
6220
+ const availableTaxa = Object.keys(props.expressionStudies).filter((tid)=>searchTaxa[tid]).sort((a, b)=>props.grameneMaps[searchTaxa[a]].left_index - props.grameneMaps[searchTaxa[b]].left_index);
5672
6221
  return availableTaxa && props.grameneTaxonomy && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
5673
6222
  children: [
5674
6223
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
5675
6224
  children: [
5676
6225
  "This is where you can launch a component for the selected samples. props.desiredSamples lists them. This component can request the data from the API organize samples by factor metadata? One big table with all the studies?",
5677
6226
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactbootstrap.Button), {
6227
+ onClick: console.log(Object.keys(props.desiredSamples)),
5678
6228
  children: [
5679
6229
  "Show Samples (",
5680
6230
  Object.keys(props.desiredSamples).length,
@@ -5687,7 +6237,8 @@ const $261baeb81c4d4d8a$var$Expression = (props)=>{
5687
6237
  alwaysOpen: true,
5688
6238
  defaultActiveKey: availableTaxa.length === 1 ? "tax_0" : undefined,
5689
6239
  children: availableTaxa.map((tid, idx)=>{
5690
- const n = props.expressionStudies[tid].length;
6240
+ const baselineStudies = props.expressionStudies[tid].filter((study)=>study.type === 'Baseline');
6241
+ const n = baselineStudies.length;
5691
6242
  return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactbootstrap.Accordion).Item, {
5692
6243
  eventKey: 'tax_' + idx,
5693
6244
  children: [
@@ -5702,7 +6253,7 @@ const $261baeb81c4d4d8a$var$Expression = (props)=>{
5702
6253
  }),
5703
6254
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Accordion).Body, {
5704
6255
  children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($261baeb81c4d4d8a$var$StudyList, {
5705
- studies: props.expressionStudies[tid]
6256
+ studies: baselineStudies
5706
6257
  })
5707
6258
  })
5708
6259
  ]
@@ -5761,6 +6312,28 @@ const $0f50f369018a42ef$var$GeneListDisplayComponent = (props)=>{
5761
6312
  setError('Failed to fetch gene lists. Please try again later.');
5762
6313
  }
5763
6314
  };
6315
+ // Example functions for viewing and deleting lists
6316
+ const viewGeneList = (list)=>{
6317
+ alert(`Viewing gene list: ${list.label}`);
6318
+ props.addFilter({
6319
+ category: 'Gene List',
6320
+ fq_field: 'saved_search',
6321
+ fq_value: list.hash,
6322
+ name: list.label
6323
+ });
6324
+ };
6325
+ const deleteGeneList = async (api, listId)=>{
6326
+ if (window.confirm('Are you sure you want to delete this gene list?')) // Replace with the actual delete request
6327
+ try {
6328
+ await fetch(`${api}/gene_lists/${listId}`, {
6329
+ method: 'DELETE'
6330
+ });
6331
+ alert('Gene list deleted!');
6332
+ // Optionally refetch the updated list
6333
+ } catch (err) {
6334
+ alert('Failed to delete gene list.');
6335
+ }
6336
+ };
5764
6337
  // Fetch data when the component is mounted
5765
6338
  (0, $gXNCa$react.useEffect)(()=>{
5766
6339
  fetchPublicGeneLists();
@@ -5786,20 +6359,28 @@ const $0f50f369018a42ef$var$GeneListDisplayComponent = (props)=>{
5786
6359
  hover: true,
5787
6360
  className: "mt-4",
5788
6361
  children: [
5789
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("thead", {
5790
- children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("tr", {
5791
- children: [
5792
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("th", {
5793
- children: "List Name"
5794
- }),
5795
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("th", {
5796
- children: "Number of Genes"
5797
- }),
5798
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("th", {
5799
- children: "Actions"
6362
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("thead", {
6363
+ children: [
6364
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("tr", {
6365
+ children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("th", {
6366
+ colspan: 3,
6367
+ children: "My gene lists"
5800
6368
  })
5801
- ]
5802
- })
6369
+ }),
6370
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("tr", {
6371
+ children: [
6372
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("th", {
6373
+ children: "List Name"
6374
+ }),
6375
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("th", {
6376
+ children: "Number of Genes"
6377
+ }),
6378
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("th", {
6379
+ children: "Actions"
6380
+ })
6381
+ ]
6382
+ })
6383
+ ]
5803
6384
  }),
5804
6385
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("tbody", {
5805
6386
  children: privateGeneLists.map((list, index)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("tr", {
@@ -5808,18 +6389,18 @@ const $0f50f369018a42ef$var$GeneListDisplayComponent = (props)=>{
5808
6389
  children: list.label
5809
6390
  }),
5810
6391
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
5811
- children: list.hash
6392
+ children: list.n_genes || 0
5812
6393
  }),
5813
6394
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("td", {
5814
6395
  children: [
5815
6396
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
5816
6397
  variant: "info",
5817
- onClick: ()=>$0f50f369018a42ef$var$viewGeneList(list),
6398
+ onClick: ()=>viewGeneList(list),
5818
6399
  children: "View"
5819
6400
  }),
5820
6401
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
5821
6402
  variant: "danger",
5822
- onClick: ()=>$0f50f369018a42ef$var$deleteGeneList(props.api, list._id),
6403
+ onClick: ()=>deleteGeneList(props.api, list._id),
5823
6404
  className: "ml-2",
5824
6405
  children: "Delete"
5825
6406
  })
@@ -5836,20 +6417,28 @@ const $0f50f369018a42ef$var$GeneListDisplayComponent = (props)=>{
5836
6417
  hover: true,
5837
6418
  className: "mt-4",
5838
6419
  children: [
5839
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("thead", {
5840
- children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("tr", {
5841
- children: [
5842
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("th", {
5843
- children: "List Name"
5844
- }),
5845
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("th", {
5846
- children: "Number of Genes"
5847
- }),
5848
- /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("th", {
5849
- children: "Actions"
6420
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("thead", {
6421
+ children: [
6422
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("tr", {
6423
+ children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("th", {
6424
+ colSpan: 3,
6425
+ children: "Public gene lists"
5850
6426
  })
5851
- ]
5852
- })
6427
+ }),
6428
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("tr", {
6429
+ children: [
6430
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("th", {
6431
+ children: "List Name"
6432
+ }),
6433
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("th", {
6434
+ children: "Number of Genes"
6435
+ }),
6436
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("th", {
6437
+ children: "Actions"
6438
+ })
6439
+ ]
6440
+ })
6441
+ ]
5853
6442
  }),
5854
6443
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("tbody", {
5855
6444
  children: publicGeneLists.map((list, index)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("tr", {
@@ -5858,18 +6447,18 @@ const $0f50f369018a42ef$var$GeneListDisplayComponent = (props)=>{
5858
6447
  children: list.label
5859
6448
  }),
5860
6449
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("td", {
5861
- children: list.hash
6450
+ children: list.n_genes || 0
5862
6451
  }),
5863
6452
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("td", {
5864
6453
  children: [
5865
6454
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
5866
6455
  variant: "info",
5867
- onClick: ()=>$0f50f369018a42ef$var$viewGeneList(list),
6456
+ onClick: ()=>viewGeneList(list),
5868
6457
  children: "View"
5869
6458
  }),
5870
6459
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
5871
6460
  variant: "danger",
5872
- onClick: ()=>$0f50f369018a42ef$var$deleteGeneList(props.api, list._id),
6461
+ onClick: ()=>deleteGeneList(props.api, list._id),
5873
6462
  className: "ml-2",
5874
6463
  children: "Delete"
5875
6464
  })
@@ -5887,22 +6476,6 @@ const $0f50f369018a42ef$var$GeneListDisplayComponent = (props)=>{
5887
6476
  ]
5888
6477
  });
5889
6478
  };
5890
- // Example functions for viewing and deleting lists
5891
- const $0f50f369018a42ef$var$viewGeneList = (list)=>{
5892
- alert(`Viewing gene list: ${list.name}\nGenes: ${list.genes.join(', ')}`);
5893
- };
5894
- const $0f50f369018a42ef$var$deleteGeneList = async (api, listId)=>{
5895
- if (window.confirm('Are you sure you want to delete this gene list?')) // Replace with the actual delete request
5896
- try {
5897
- await fetch(`${api}/gene_lists/${listId}`, {
5898
- method: 'DELETE'
5899
- });
5900
- alert('Gene list deleted!');
5901
- // Optionally refetch the updated list
5902
- } catch (err) {
5903
- alert('Failed to delete gene list.');
5904
- }
5905
- };
5906
6479
  const $0f50f369018a42ef$var$GeneListComponent = (props)=>{
5907
6480
  const [geneList, setGeneList] = (0, $gXNCa$react.useState)('');
5908
6481
  const [listHash, setListHash] = (0, $gXNCa$react.useState)(null);
@@ -5964,6 +6537,7 @@ const $0f50f369018a42ef$var$GeneListComponent = (props)=>{
5964
6537
  label: listName,
5965
6538
  hash: listHash,
5966
6539
  site: props.site,
6540
+ n_genes: validatedList.length,
5967
6541
  isPublic: listIsPublic
5968
6542
  };
5969
6543
  const queryString = new URLSearchParams(queryParams).toString();
@@ -6124,14 +6698,15 @@ const $0f50f369018a42ef$var$UserGeneListsComponent = (props)=>{
6124
6698
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Col), {
6125
6699
  children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($0f50f369018a42ef$var$GeneListDisplayComponent, {
6126
6700
  api: props.configuration.grameneData,
6127
- site: props.configuration.id
6701
+ site: props.configuration.id,
6702
+ addFilter: props.doAcceptGrameneSuggestion
6128
6703
  })
6129
6704
  })
6130
6705
  ]
6131
6706
  })
6132
6707
  });
6133
6708
  };
6134
- var $0f50f369018a42ef$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.connect)('selectConfiguration', $0f50f369018a42ef$var$UserGeneListsComponent);
6709
+ var $0f50f369018a42ef$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.connect)('selectConfiguration', 'doAcceptGrameneSuggestion', $0f50f369018a42ef$var$UserGeneListsComponent);
6135
6710
 
6136
6711
 
6137
6712