gramene-search 2.38.2 → 2.39.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -6351,6 +6351,9 @@ var $d365d8c287ab0c94$export$2e2bcd8739ae039 = $d365d8c287ab0c94$var$ontologyEnr
6351
6351
  // - expandedDetail: which detail tab is open in the gene-list card
6352
6352
  // - fullscreen: whether the expanded detail is full-screened
6353
6353
  // - homology.viewer: 'treevis' | 'tbrowse'
6354
+ // - homology.tree: which of the gene's trees is shown — the homology field
6355
+ // holding it ('gene_tree', or a tree set such as 'wheat'); unset = the
6356
+ // first (gene_tree when the gene has one)
6354
6357
  // - homology.height: drag-resize height of the homology detail pane
6355
6358
  // - homology.tbrowse: the tbrowse ViewState (collapsedNodeIds, prunedNodeIds,
6356
6359
  // swappedNodeIds, compressedNodeIds, nodeOfInterestId, zones, zoneStates,
@@ -6480,6 +6483,14 @@ const $7f865ea0feda21af$var$uiViewState = {
6480
6483
  return $7f865ea0feda21af$var$setHomology(state, payload.geneId, {
6481
6484
  viewer: payload.viewer
6482
6485
  });
6486
+ case 'UI_HOMOLOGY_TREE_SET':
6487
+ // payload: { geneId, tree }. The tbrowse ViewState belongs to one tree
6488
+ // (its node ids), so a switch drops it and Homology re-seeds the new
6489
+ // tree pivoted on the gene.
6490
+ return $7f865ea0feda21af$var$setHomology(state, payload.geneId, {
6491
+ tree: payload.tree,
6492
+ tbrowse: undefined
6493
+ });
6483
6494
  case 'UI_HOMOLOGY_HEIGHT_SET':
6484
6495
  // payload: { geneId, height }
6485
6496
  return $7f865ea0feda21af$var$setHomology(state, payload.geneId, {
@@ -6542,6 +6553,15 @@ const $7f865ea0feda21af$var$uiViewState = {
6542
6553
  }
6543
6554
  });
6544
6555
  },
6556
+ doSetHomologyTree: ({ geneId: geneId, tree: tree })=>({ dispatch: dispatch })=>{
6557
+ dispatch({
6558
+ type: 'UI_HOMOLOGY_TREE_SET',
6559
+ payload: {
6560
+ geneId: geneId,
6561
+ tree: tree
6562
+ }
6563
+ });
6564
+ },
6545
6565
  doSetHomologyHeight: ({ geneId: geneId, height: height })=>({ dispatch: dispatch })=>{
6546
6566
  dispatch({
6547
6567
  type: 'UI_HOMOLOGY_HEIGHT_SET',
@@ -6676,7 +6696,7 @@ var $6048209b532f201d$export$2e2bcd8739ae039 = $6048209b532f201d$var$taxTreeView
6676
6696
  // { geneId,
6677
6697
  // expandedDetail: string|null,
6678
6698
  // fullscreen: boolean,
6679
- // homology: { viewer, height, tbrowse: <ViewState> } | undefined,
6699
+ // homology: { viewer, tree, height, tbrowse: <ViewState> } | undefined,
6680
6700
  // sequences: { tab, tid, upstream, downstream } | undefined,
6681
6701
  // expression: { activeTab, atlasExperiment, jgiExperiment,
6682
6702
  // jgiAxes: { [jgiExperiment]: { rowFactor, columnFactor } },
@@ -6734,7 +6754,7 @@ const $472fe3745b238881$var$isMeaningfulGene = (entry)=>{
6734
6754
  if (!entry) return false;
6735
6755
  if (entry.expandedDetail) return true;
6736
6756
  if (entry.fullscreen) return true;
6737
- if (entry.homology && (entry.homology.viewer !== undefined || entry.homology.height !== undefined || entry.homology.tbrowse !== undefined)) return true;
6757
+ if (entry.homology && (entry.homology.viewer !== undefined || entry.homology.tree !== undefined || entry.homology.height !== undefined || entry.homology.tbrowse !== undefined)) return true;
6738
6758
  if (entry.sequences && Object.keys(entry.sequences).length) return true;
6739
6759
  if (entry.expression && Object.keys(entry.expression).length) return true;
6740
6760
  if (entry.primers && Object.keys(entry.primers).length) return true;
@@ -8336,6 +8356,18 @@ const $9e29a4f60318db7a$var$Detail = (props)=>{
8336
8356
  studies,
8337
8357
  geneStudyIds
8338
8358
  ]);
8359
+ // Without a baseline study the EBI Studies heatmap has nothing to draw (its
8360
+ // request fails rather than coming back empty), so the tab says so and
8361
+ // points at the differential EBI studies the gene does appear in -- e.g.
8362
+ // Medicago truncatula, whose studies are all differential.
8363
+ const ebiDifferential = (0, $gXNCa$react.useMemo)(()=>{
8364
+ if (!geneStudyIds || !studies) return [];
8365
+ const mine = new Set(geneStudyIds);
8366
+ return studies.filter((e)=>mine.has(e._id) && $9e29a4f60318db7a$var$isDifferential(e) && !$9e29a4f60318db7a$var$isJgiStudy(e)).sort((a, b)=>$9e29a4f60318db7a$var$studyLabel(a) < $9e29a4f60318db7a$var$studyLabel(b) ? -1 : 1);
8367
+ }, [
8368
+ studies,
8369
+ geneStudyIds
8370
+ ]);
8339
8371
  const allJgiKey = JSON.stringify(allJgiStudies.map((e)=>[
8340
8372
  e._id,
8341
8373
  e.name
@@ -8434,7 +8466,43 @@ const $9e29a4f60318db7a$var$Detail = (props)=>{
8434
8466
  role: "status",
8435
8467
  children: "Loading expression studies\u2026"
8436
8468
  }),
8437
- activeTab === "gene" && studiesSettled && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$grameneatlasheatmap.ExpressionAtlasHeatmap), {
8469
+ activeTab === "gene" && studiesSettled && !hasEbiBaseline && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
8470
+ className: "text-muted small",
8471
+ role: "status",
8472
+ children: [
8473
+ gene.name || gene._id,
8474
+ " is not in any baseline expression study, so there is no heatmap here.",
8475
+ ebiDifferential.length > 0 && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactjsxruntime.Fragment), {
8476
+ children: [
8477
+ ' ',
8478
+ "It has results in ",
8479
+ ebiDifferential.length === 1 ? 'a differential study' : `${ebiDifferential.length} differential studies`,
8480
+ " at Expression Atlas:",
8481
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("ul", {
8482
+ className: "mt-1 mb-0",
8483
+ children: ebiDifferential.map((e)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("li", {
8484
+ children: [
8485
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("a", {
8486
+ href: `${$9e29a4f60318db7a$var$EBI_GXA}experiments/${encodeURIComponent(e._id)}/Results?geneQuery=${encodeURIComponent(JSON.stringify([
8487
+ {
8488
+ value: geneQuery
8489
+ }
8490
+ ]))}`,
8491
+ target: "_blank",
8492
+ rel: "noopener noreferrer",
8493
+ children: e.description || e._id
8494
+ }),
8495
+ " (",
8496
+ e._id,
8497
+ ")"
8498
+ ]
8499
+ }, e._id))
8500
+ })
8501
+ ]
8502
+ })
8503
+ ]
8504
+ }),
8505
+ activeTab === "gene" && studiesSettled && hasEbiBaseline && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$grameneatlasheatmap.ExpressionAtlasHeatmap), {
8438
8506
  ...$9e29a4f60318db7a$var$HEATMAP_OPTIONS,
8439
8507
  resolveUrl: resolveUrl,
8440
8508
  atlasUrl: atlasUrl,
@@ -9074,28 +9142,38 @@ const $64fad37f770d2bfe$var$TBROWSE_BASE_ZONES = [
9074
9142
  (0, $gXNCa$tbrowse.msaZone),
9075
9143
  (0, $gXNCa$tbrowse.neighborhoodZone)
9076
9144
  ];
9077
- // A gene's tree is either the main Compara tree (homology.gene_tree) or, for
9078
- // genomes in a clade-specific tree set, homology.<tree_set> — e.g. wheat genes
9079
- // carry homology.wheat = {id: 'EplWheatGT_…'}. Solr indexes the tree id under
9080
- // the same name (gene_tree, wheat, oat, …), so `field` is also the fq field.
9081
- // Null when the gene has homologues but no tree at all.
9145
+ // A gene's trees: the main Compara tree (homology.gene_tree) and/or trees in
9146
+ // clade-specific tree sets, homology.<tree_set> — e.g. a wheat gene may carry
9147
+ // gene_tree, homology.wheat = {id: 'EplWheatGT_…'} and homology.barley. Solr
9148
+ // indexes each tree id under the same name (gene_tree, wheat, barley, …), so
9149
+ // `field` is also the fq field. gene_tree comes first; empty when the gene
9150
+ // has homologues but no tree at all.
9082
9151
  const $64fad37f770d2bfe$var$NOT_TREE_KEYS = [
9083
9152
  'homologous_genes',
9084
9153
  'supertree'
9085
9154
  ];
9086
- function $64fad37f770d2bfe$var$geneTreeRef(gene) {
9155
+ function $64fad37f770d2bfe$var$geneTreeRefs(gene) {
9087
9156
  const h = gene && gene.homology;
9088
- if (!h) return null;
9089
- if (h.gene_tree && h.gene_tree.id) return {
9090
- field: 'gene_tree',
9091
- id: h.gene_tree.id
9092
- };
9093
- const key = Object.keys(h).find((k)=>!$64fad37f770d2bfe$var$NOT_TREE_KEYS.includes(k) && h[k] && typeof h[k] === 'object' && typeof h[k].id === 'string');
9094
- return key ? {
9095
- field: key,
9096
- id: h[key].id
9097
- } : null;
9157
+ if (!h) return [];
9158
+ const isTree = (k)=>!$64fad37f770d2bfe$var$NOT_TREE_KEYS.includes(k) && h[k] && typeof h[k] === 'object' && typeof h[k].id === 'string';
9159
+ const keys = Object.keys(h).filter(isTree);
9160
+ keys.sort((a, b)=>a === 'gene_tree' ? -1 : b === 'gene_tree' ? 1 : 0);
9161
+ return keys.map((field)=>({
9162
+ field: field,
9163
+ id: h[field].id,
9164
+ rootTaxonName: h[field].root_taxon_name
9165
+ }));
9166
+ }
9167
+ // The tree to show: the one picked in the switcher (`field`), else the first.
9168
+ function $64fad37f770d2bfe$var$geneTreeRef(gene, field) {
9169
+ const refs = $64fad37f770d2bfe$var$geneTreeRefs(gene);
9170
+ return refs.find((r)=>r.field === field) || refs[0] || null;
9098
9171
  }
9172
+ // Switcher label: the tree set and the clade the tree is rooted at.
9173
+ const $64fad37f770d2bfe$var$treeLabel = (ref)=>{
9174
+ const set = ref.field === 'gene_tree' ? 'Compara' : ref.field.charAt(0).toUpperCase() + ref.field.slice(1);
9175
+ return ref.rootTaxonName ? `${set} \xb7 ${ref.rootTaxonName}` : set;
9176
+ };
9099
9177
  class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$react))).Component {
9100
9178
  constructor(props){
9101
9179
  super(props);
@@ -9132,6 +9210,10 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9132
9210
  getViewer() {
9133
9211
  return this.getHomologySlice().viewer || 'tbrowse';
9134
9212
  }
9213
+ // The gene's selected tree (see the tree switcher in renderViewerToggle).
9214
+ selectedTreeRef(gene) {
9215
+ return $64fad37f770d2bfe$var$geneTreeRef(gene, this.getHomologySlice().tree);
9216
+ }
9135
9217
  // The genome (gene-structure) zone is opt-in per site via
9136
9218
  // `enable_tbrowse_genome_zone` (defaults to false).
9137
9219
  isGenomeZoneEnabled() {
@@ -9155,6 +9237,12 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9155
9237
  const h = this.getHomologySlice().height;
9156
9238
  return typeof h === 'number' ? h : 600;
9157
9239
  }
9240
+ setTree(field) {
9241
+ this.props.doSetHomologyTree({
9242
+ geneId: this.getGeneId(),
9243
+ tree: field
9244
+ });
9245
+ }
9158
9246
  setViewer(viewer) {
9159
9247
  this.props.doSetHomologyViewer({
9160
9248
  geneId: this.getGeneId(),
@@ -9218,7 +9306,7 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9218
9306
  const id = this.getGeneId();
9219
9307
  if (!this.props.geneDocs.hasOwnProperty(id)) return;
9220
9308
  const gene = this.props.geneDocs[id];
9221
- const ref = $64fad37f770d2bfe$var$geneTreeRef(gene);
9309
+ const ref = this.selectedTreeRef(gene);
9222
9310
  if (!ref) return;
9223
9311
  const treeId = ref.id;
9224
9312
  const raw = this.props.grameneTrees[treeId];
@@ -9270,7 +9358,7 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9270
9358
  const id = this.getGeneId();
9271
9359
  if (!this.props.geneDocs.hasOwnProperty(id)) return;
9272
9360
  const gene = this.props.geneDocs[id];
9273
- const ref = $64fad37f770d2bfe$var$geneTreeRef(gene);
9361
+ const ref = this.selectedTreeRef(gene);
9274
9362
  if (!ref) return;
9275
9363
  const treeId = ref.id;
9276
9364
  const raw = this.props.grameneTrees[treeId];
@@ -9566,13 +9654,52 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9566
9654
  },
9567
9655
  children: label
9568
9656
  }, id);
9657
+ // A second row when the gene sits in more than one tree (e.g. a wheat
9658
+ // gene in the Compara, wheat and barley trees).
9659
+ const refs = $64fad37f770d2bfe$var$geneTreeRefs(this.gene);
9660
+ const treeBtn = (ref)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("button", {
9661
+ type: "button",
9662
+ title: ref.id,
9663
+ onClick: ()=>this.setTree(ref.field),
9664
+ style: {
9665
+ padding: '4px 10px',
9666
+ marginRight: 4,
9667
+ fontSize: 12,
9668
+ border: '1px solid #ccc',
9669
+ background: this.treeRef.field === ref.field ? '#2878dc' : '#fff',
9670
+ color: this.treeRef.field === ref.field ? '#fff' : '#222',
9671
+ cursor: 'pointer',
9672
+ borderRadius: 3
9673
+ },
9674
+ children: $64fad37f770d2bfe$var$treeLabel(ref)
9675
+ }, ref.field);
9569
9676
  return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
9570
9677
  style: {
9571
9678
  margin: '8px 0'
9572
9679
  },
9573
9680
  children: [
9574
- btn('tbrowse', 'TBrowse'),
9575
- btn('treevis', 'TreeVis')
9681
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
9682
+ children: [
9683
+ btn('tbrowse', 'TBrowse'),
9684
+ btn('treevis', 'TreeVis')
9685
+ ]
9686
+ }),
9687
+ refs.length > 1 && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
9688
+ className: "homology-tree-switcher",
9689
+ style: {
9690
+ marginTop: 6
9691
+ },
9692
+ children: [
9693
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
9694
+ style: {
9695
+ fontSize: 12,
9696
+ marginRight: 6
9697
+ },
9698
+ children: "Gene tree:"
9699
+ }),
9700
+ refs.map(treeBtn)
9701
+ ]
9702
+ })
9576
9703
  ]
9577
9704
  });
9578
9705
  }
@@ -9677,7 +9804,10 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9677
9804
  const id = this.props.searchResult.id;
9678
9805
  if (!this.props.geneDocs.hasOwnProperty(id)) return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Spinner), {});
9679
9806
  this.gene = this.props.geneDocs[id];
9680
- this.treeRef = $64fad37f770d2bfe$var$geneTreeRef(this.gene);
9807
+ this.treeRef = this.selectedTreeRef(this.gene);
9808
+ // Recomputed below only once the selected tree has loaded, so a switch to
9809
+ // a tree still in flight never draws the previous one.
9810
+ this.tree = undefined;
9681
9811
  if (!this.treeRef) {
9682
9812
  // Homologues but no tree (some pan-genome assemblies): offer the
9683
9813
  // ortholog/paralog searches instead of a phylogram.
@@ -9716,10 +9846,10 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9716
9846
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $5c2c79352d3d7b81$export$393edc798c47379d), {
9717
9847
  children: "This phylogram shows the relationships between this gene and others similar to it, as determined by Ensembl Compara."
9718
9848
  }, "description"),
9719
- this.tree && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $5c2c79352d3d7b81$export$7c6e2c02157bb7d2), {
9849
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $5c2c79352d3d7b81$export$7c6e2c02157bb7d2), {
9720
9850
  children: [
9721
9851
  this.renderViewerToggle(),
9722
- this.getViewer() === 'tbrowse' ? this.renderTBrowse() : this.renderTreeVis()
9852
+ !this.tree ? /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Spinner), {}) : this.getViewer() === 'tbrowse' ? this.renderTBrowse() : this.renderTreeVis()
9723
9853
  ]
9724
9854
  }, "content"),
9725
9855
  this.tree && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $5c2c79352d3d7b81$export$900f1bfcd1cb6476), {
@@ -9732,7 +9862,7 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9732
9862
  });
9733
9863
  }
9734
9864
  }
9735
- var $64fad37f770d2bfe$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.connect)('selectGrameneTaxonomy', 'selectGrameneTrees', 'selectGrameneGenomes', 'selectGrameneAPI', 'selectConfiguration', 'selectCuration', 'selectUiViewState', 'doRequestGrameneTree', 'doSetHomologyViewer', 'doSetHomologyHeight', 'doSetHomologyTbrowseViewState', 'doAcceptGrameneSuggestion', 'doReplaceGrameneFilters', $64fad37f770d2bfe$var$Homology);
9865
+ var $64fad37f770d2bfe$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.connect)('selectGrameneTaxonomy', 'selectGrameneTrees', 'selectGrameneGenomes', 'selectGrameneAPI', 'selectConfiguration', 'selectCuration', 'selectUiViewState', 'doRequestGrameneTree', 'doSetHomologyViewer', 'doSetHomologyTree', 'doSetHomologyHeight', 'doSetHomologyTbrowseViewState', 'doAcceptGrameneSuggestion', 'doReplaceGrameneFilters', $64fad37f770d2bfe$var$Homology);
9736
9866
 
9737
9867
 
9738
9868