gramene-search 2.38.1 → 2.39.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
@@ -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;
@@ -9074,6 +9094,38 @@ const $64fad37f770d2bfe$var$TBROWSE_BASE_ZONES = [
9074
9094
  (0, $gXNCa$tbrowse.msaZone),
9075
9095
  (0, $gXNCa$tbrowse.neighborhoodZone)
9076
9096
  ];
9097
+ // A gene's trees: the main Compara tree (homology.gene_tree) and/or trees in
9098
+ // clade-specific tree sets, homology.<tree_set> — e.g. a wheat gene may carry
9099
+ // gene_tree, homology.wheat = {id: 'EplWheatGT_…'} and homology.barley. Solr
9100
+ // indexes each tree id under the same name (gene_tree, wheat, barley, …), so
9101
+ // `field` is also the fq field. gene_tree comes first; empty when the gene
9102
+ // has homologues but no tree at all.
9103
+ const $64fad37f770d2bfe$var$NOT_TREE_KEYS = [
9104
+ 'homologous_genes',
9105
+ 'supertree'
9106
+ ];
9107
+ function $64fad37f770d2bfe$var$geneTreeRefs(gene) {
9108
+ const h = gene && gene.homology;
9109
+ if (!h) return [];
9110
+ const isTree = (k)=>!$64fad37f770d2bfe$var$NOT_TREE_KEYS.includes(k) && h[k] && typeof h[k] === 'object' && typeof h[k].id === 'string';
9111
+ const keys = Object.keys(h).filter(isTree);
9112
+ keys.sort((a, b)=>a === 'gene_tree' ? -1 : b === 'gene_tree' ? 1 : 0);
9113
+ return keys.map((field)=>({
9114
+ field: field,
9115
+ id: h[field].id,
9116
+ rootTaxonName: h[field].root_taxon_name
9117
+ }));
9118
+ }
9119
+ // The tree to show: the one picked in the switcher (`field`), else the first.
9120
+ function $64fad37f770d2bfe$var$geneTreeRef(gene, field) {
9121
+ const refs = $64fad37f770d2bfe$var$geneTreeRefs(gene);
9122
+ return refs.find((r)=>r.field === field) || refs[0] || null;
9123
+ }
9124
+ // Switcher label: the tree set and the clade the tree is rooted at.
9125
+ const $64fad37f770d2bfe$var$treeLabel = (ref)=>{
9126
+ const set = ref.field === 'gene_tree' ? 'Compara' : ref.field.charAt(0).toUpperCase() + ref.field.slice(1);
9127
+ return ref.rootTaxonName ? `${set} \xb7 ${ref.rootTaxonName}` : set;
9128
+ };
9077
9129
  class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$react))).Component {
9078
9130
  constructor(props){
9079
9131
  super(props);
@@ -9110,6 +9162,10 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9110
9162
  getViewer() {
9111
9163
  return this.getHomologySlice().viewer || 'tbrowse';
9112
9164
  }
9165
+ // The gene's selected tree (see the tree switcher in renderViewerToggle).
9166
+ selectedTreeRef(gene) {
9167
+ return $64fad37f770d2bfe$var$geneTreeRef(gene, this.getHomologySlice().tree);
9168
+ }
9113
9169
  // The genome (gene-structure) zone is opt-in per site via
9114
9170
  // `enable_tbrowse_genome_zone` (defaults to false).
9115
9171
  isGenomeZoneEnabled() {
@@ -9133,6 +9189,12 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9133
9189
  const h = this.getHomologySlice().height;
9134
9190
  return typeof h === 'number' ? h : 600;
9135
9191
  }
9192
+ setTree(field) {
9193
+ this.props.doSetHomologyTree({
9194
+ geneId: this.getGeneId(),
9195
+ tree: field
9196
+ });
9197
+ }
9136
9198
  setViewer(viewer) {
9137
9199
  this.props.doSetHomologyViewer({
9138
9200
  geneId: this.getGeneId(),
@@ -9196,8 +9258,9 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9196
9258
  const id = this.getGeneId();
9197
9259
  if (!this.props.geneDocs.hasOwnProperty(id)) return;
9198
9260
  const gene = this.props.geneDocs[id];
9199
- if (!gene.homology) return;
9200
- const treeId = gene.homology.gene_tree.id;
9261
+ const ref = this.selectedTreeRef(gene);
9262
+ if (!ref) return;
9263
+ const treeId = ref.id;
9201
9264
  const raw = this.props.grameneTrees[treeId];
9202
9265
  if (!raw || !raw.taxon_id) return;
9203
9266
  const adapted = (0, $gXNCa$tbrowse.fromGrameneGenetree)([
@@ -9247,8 +9310,9 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9247
9310
  const id = this.getGeneId();
9248
9311
  if (!this.props.geneDocs.hasOwnProperty(id)) return;
9249
9312
  const gene = this.props.geneDocs[id];
9250
- if (!gene.homology) return;
9251
- const treeId = gene.homology.gene_tree.id;
9313
+ const ref = this.selectedTreeRef(gene);
9314
+ if (!ref) return;
9315
+ const treeId = ref.id;
9252
9316
  const raw = this.props.grameneTrees[treeId];
9253
9317
  if (!raw || !raw.taxon_id) return;
9254
9318
  // Lazily compute the adapted tbrowse data the same way renderTBrowse
@@ -9260,13 +9324,13 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9260
9324
  raw
9261
9325
  ]);
9262
9326
  }
9263
- this.fetchNeighborhood(treeId);
9327
+ this.fetchNeighborhood(treeId, ref.field);
9264
9328
  // Only pay for gene-structure data when the genome zone is actually enabled.
9265
9329
  if (this.isGenomeZoneEnabled()) this.fetchGeneStructures(treeId, this._tbrowseData.tree);
9266
9330
  // Same for the per-gene expression attributes zone.
9267
- if (this.isExpressionZoneEnabled()) this.fetchExprAttrs(treeId, this._tbrowseData.tree);
9331
+ if (this.isExpressionZoneEnabled()) this.fetchExprAttrs(treeId, this._tbrowseData.tree, ref.field);
9268
9332
  }
9269
- fetchNeighborhood(treeId) {
9333
+ fetchNeighborhood(treeId, field = 'gene_tree') {
9270
9334
  if (this._neighborhoodFetchedFor === treeId) return;
9271
9335
  this._neighborhoodFetchedFor = treeId;
9272
9336
  this.setState({
@@ -9274,8 +9338,13 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9274
9338
  });
9275
9339
  const api = this.props.grameneAPI;
9276
9340
  const url = new URL(`${api}/search`);
9277
- url.searchParams.set('fl', 'id,name,gene_tree,gene_idx,region,start,end,strand,biotype,system_name,description');
9278
- url.searchParams.set('fq', `{!graph from=compara_neighbors_10 to=compara_idx_multi maxDepth=1}gene_tree:${treeId}`);
9341
+ const fl = 'id,name,gene_tree,gene_idx,region,start,end,strand,biotype,system_name,description';
9342
+ url.searchParams.set('fl', field === 'gene_tree' ? fl : `${fl},${field}`);
9343
+ // cache=false: as a cached fq the graph query caches its seed inside its own
9344
+ // filterCache computeIfAbsent, and Solr's FastLRUCache throws "Recursive
9345
+ // update" (HTTP 500) whenever the two keys collide — for some trees, until
9346
+ // the seed happens to be cached by another request.
9347
+ url.searchParams.set('fq', `{!graph from=compara_neighbors_10 to=compara_idx_multi maxDepth=1 cache=false}${field}:${treeId}`);
9279
9348
  url.searchParams.set('rows', '100000');
9280
9349
  url.searchParams.set('start', '0');
9281
9350
  fetch(url.toString(), {
@@ -9287,6 +9356,11 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9287
9356
  return res.json();
9288
9357
  }).then((json)=>{
9289
9358
  if (this._neighborhoodFetchedFor !== treeId) return;
9359
+ // The neighborhood zone colours genes by family from doc.gene_tree; in
9360
+ // a clade tree set the family id lives under the set's own field.
9361
+ if (field !== 'gene_tree' && json && json.response && Array.isArray(json.response.docs)) json.response.docs.forEach((d)=>{
9362
+ if (d[field] && !d.gene_tree) d.gene_tree = d[field];
9363
+ });
9290
9364
  this.setState({
9291
9365
  neighborhood: (0, $gXNCa$tbrowse.fromGrameneNeighborhood)(json),
9292
9366
  neighborhoodTreeId: treeId,
@@ -9344,13 +9418,13 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9344
9418
  });
9345
9419
  }
9346
9420
  // Fetch the expression attributes (expr_*__attr_*) for this tree's genes in a
9347
- // single query: scope by gene_tree and the `expression_attributes` capability
9421
+ // single query: scope by the tree's field and the `expression_attributes` capability
9348
9422
  // so only genes that actually have the data come back (rows high enough to
9349
9423
  // cover the whole tree). Uses /search (not /genes, whose trimmed docs omit the
9350
9424
  // attr fields) with an fl glob so the columns are discovered from the data
9351
9425
  // rather than hard-coded. `tree` is still needed to map gene ids to leaf node
9352
9426
  // ids (see buildExprByNode).
9353
- fetchExprAttrs(treeId, tree) {
9427
+ fetchExprAttrs(treeId, tree, field = 'gene_tree') {
9354
9428
  if (this._exprAttrsFetchedFor === treeId) return;
9355
9429
  this._exprAttrsFetchedFor = treeId;
9356
9430
  this.setState({
@@ -9359,7 +9433,7 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9359
9433
  const api = this.props.grameneAPI;
9360
9434
  const url = new URL(`${api}/search`);
9361
9435
  url.searchParams.set('q', '*:*');
9362
- url.searchParams.append('fq', `gene_tree:${treeId}`);
9436
+ url.searchParams.append('fq', `${field}:${treeId}`);
9363
9437
  url.searchParams.append('fq', 'capabilities:expression_attributes');
9364
9438
  url.searchParams.set('fl', 'id,expr_*__attr_*');
9365
9439
  url.searchParams.set('rows', '10000');
@@ -9436,7 +9510,7 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9436
9510
  });
9437
9511
  }
9438
9512
  renderTBrowse() {
9439
- const treeId = this.gene.homology.gene_tree.id;
9513
+ const treeId = this.treeRef.id;
9440
9514
  // Adapted tbrowse data is computed lazily in maybeFetchTbrowseData
9441
9515
  // (called from lifecycle). If the user just flipped to tbrowse and
9442
9516
  // the lifecycle hasn't fired yet, compute it once here without
@@ -9532,20 +9606,59 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9532
9606
  },
9533
9607
  children: label
9534
9608
  }, id);
9609
+ // A second row when the gene sits in more than one tree (e.g. a wheat
9610
+ // gene in the Compara, wheat and barley trees).
9611
+ const refs = $64fad37f770d2bfe$var$geneTreeRefs(this.gene);
9612
+ const treeBtn = (ref)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("button", {
9613
+ type: "button",
9614
+ title: ref.id,
9615
+ onClick: ()=>this.setTree(ref.field),
9616
+ style: {
9617
+ padding: '4px 10px',
9618
+ marginRight: 4,
9619
+ fontSize: 12,
9620
+ border: '1px solid #ccc',
9621
+ background: this.treeRef.field === ref.field ? '#2878dc' : '#fff',
9622
+ color: this.treeRef.field === ref.field ? '#fff' : '#222',
9623
+ cursor: 'pointer',
9624
+ borderRadius: 3
9625
+ },
9626
+ children: $64fad37f770d2bfe$var$treeLabel(ref)
9627
+ }, ref.field);
9535
9628
  return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
9536
9629
  style: {
9537
9630
  margin: '8px 0'
9538
9631
  },
9539
9632
  children: [
9540
- btn('tbrowse', 'TBrowse'),
9541
- btn('treevis', 'TreeVis')
9633
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
9634
+ children: [
9635
+ btn('tbrowse', 'TBrowse'),
9636
+ btn('treevis', 'TreeVis')
9637
+ ]
9638
+ }),
9639
+ refs.length > 1 && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
9640
+ className: "homology-tree-switcher",
9641
+ style: {
9642
+ marginTop: 6
9643
+ },
9644
+ children: [
9645
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
9646
+ style: {
9647
+ fontSize: 12,
9648
+ marginRight: 6
9649
+ },
9650
+ children: "Gene tree:"
9651
+ }),
9652
+ refs.map(treeBtn)
9653
+ ]
9654
+ })
9542
9655
  ]
9543
9656
  });
9544
9657
  }
9545
9658
  filterAllHomologs() {
9546
9659
  this.props.doReplaceGrameneFilters((0, $047461923b1badda$export$964d88edb00bbcaa)({
9547
9660
  category: 'Gene Tree',
9548
- fq_field: 'gene_tree',
9661
+ fq_field: this.treeRef.field,
9549
9662
  fq_value: this.tree._id,
9550
9663
  name: `Homologs of ${this.gene.name}`
9551
9664
  }));
@@ -9598,14 +9711,14 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9598
9711
  }
9599
9712
  }
9600
9713
  explorations() {
9601
- let x = [
9714
+ let x = this.tree ? [
9602
9715
  {
9603
9716
  name: 'Homologs',
9604
9717
  category: 'Gene Tree',
9605
9718
  count: this.tree.geneCount,
9606
9719
  handleClick: this.filterAllHomologs.bind(this)
9607
9720
  }
9608
- ];
9721
+ ] : [];
9609
9722
  if (this.orthologs) x.push({
9610
9723
  name: 'Orthologs',
9611
9724
  category: 'Gene Tree',
@@ -9643,7 +9756,32 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9643
9756
  const id = this.props.searchResult.id;
9644
9757
  if (!this.props.geneDocs.hasOwnProperty(id)) return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Spinner), {});
9645
9758
  this.gene = this.props.geneDocs[id];
9646
- const treeId = this.gene.homology.gene_tree.id;
9759
+ this.treeRef = this.selectedTreeRef(this.gene);
9760
+ // Recomputed below only once the selected tree has loaded, so a switch to
9761
+ // a tree still in flight never draws the previous one.
9762
+ this.tree = undefined;
9763
+ if (!this.treeRef) {
9764
+ // Homologues but no tree (some pan-genome assemblies): offer the
9765
+ // ortholog/paralog searches instead of a phylogram.
9766
+ this.tree = undefined;
9767
+ this.orthologs = this.orthologList();
9768
+ this.paralogs = this.paralogList();
9769
+ const explorations = this.explorations();
9770
+ return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $5c2c79352d3d7b81$export$47eb42ff093406d4), {
9771
+ children: [
9772
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $5c2c79352d3d7b81$export$393edc798c47379d), {
9773
+ children: "No gene tree is available for this gene."
9774
+ }, "description"),
9775
+ explorations.length > 0 && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $5c2c79352d3d7b81$export$900f1bfcd1cb6476), {
9776
+ explorations: explorations
9777
+ }, "explore"),
9778
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $5c2c79352d3d7b81$export$b2e089eb3692b073), {
9779
+ links: this.links()
9780
+ }, "links")
9781
+ ]
9782
+ });
9783
+ }
9784
+ const treeId = this.treeRef.id;
9647
9785
  if (!this.props.grameneTrees.hasOwnProperty(treeId)) this.props.doRequestGrameneTree(treeId);
9648
9786
  else {
9649
9787
  const tree = this.props.grameneTrees[treeId];
@@ -9660,10 +9798,10 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9660
9798
  /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $5c2c79352d3d7b81$export$393edc798c47379d), {
9661
9799
  children: "This phylogram shows the relationships between this gene and others similar to it, as determined by Ensembl Compara."
9662
9800
  }, "description"),
9663
- this.tree && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $5c2c79352d3d7b81$export$7c6e2c02157bb7d2), {
9801
+ /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $5c2c79352d3d7b81$export$7c6e2c02157bb7d2), {
9664
9802
  children: [
9665
9803
  this.renderViewerToggle(),
9666
- this.getViewer() === 'tbrowse' ? this.renderTBrowse() : this.renderTreeVis()
9804
+ !this.tree ? /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Spinner), {}) : this.getViewer() === 'tbrowse' ? this.renderTBrowse() : this.renderTreeVis()
9667
9805
  ]
9668
9806
  }, "content"),
9669
9807
  this.tree && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $5c2c79352d3d7b81$export$900f1bfcd1cb6476), {
@@ -9676,7 +9814,7 @@ class $64fad37f770d2bfe$var$Homology extends (0, ($parcel$interopDefault($gXNCa$
9676
9814
  });
9677
9815
  }
9678
9816
  }
9679
- var $64fad37f770d2bfe$export$2e2bcd8739ae039 = (0, $gXNCa$reduxbundlerreact.connect)('selectGrameneTaxonomy', 'selectGrameneTrees', 'selectGrameneGenomes', 'selectGrameneAPI', 'selectConfiguration', 'selectCuration', 'selectUiViewState', 'doRequestGrameneTree', 'doSetHomologyViewer', 'doSetHomologyHeight', 'doSetHomologyTbrowseViewState', 'doAcceptGrameneSuggestion', 'doReplaceGrameneFilters', $64fad37f770d2bfe$var$Homology);
9817
+ 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);
9680
9818
 
9681
9819
 
9682
9820