gramene-search 1.6.4 → 1.6.6

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.
Files changed (46) hide show
  1. package/.parcel-cache/4987902b3f9787cc-BundleGraph-0 +0 -0
  2. package/.parcel-cache/70f1f7555dda250d-AssetGraph-0 +0 -0
  3. package/.parcel-cache/7b8e4611c0f03524-AssetGraph-0 +0 -0
  4. package/.parcel-cache/adb9e64d5da6fbba-AssetGraph-0 +0 -0
  5. package/.parcel-cache/d48c91545c145068-BundleGraph-0 +0 -0
  6. package/.parcel-cache/data.mdb +0 -0
  7. package/.parcel-cache/lock.mdb +0 -0
  8. package/.parcel-cache/requestGraph-369948a06d23ec44-0 +0 -0
  9. package/.parcel-cache/requestGraph-524f09471ce7017b-0 +0 -0
  10. package/.parcel-cache/requestGraph-nodes-0-369948a06d23ec44-0 +0 -0
  11. package/.parcel-cache/requestGraph-nodes-0-524f09471ce7017b-0 +0 -0
  12. package/.parcel-cache/snapshot-369948a06d23ec44.txt +2 -2
  13. package/.parcel-cache/snapshot-524f09471ce7017b.txt +2 -2
  14. package/dist/index.js +251 -86
  15. package/dist/index.js.map +1 -1
  16. package/package.json +1 -1
  17. package/src/components/results/details/VEP.js +228 -42
  18. package/.parcel-cache/12c2ac26a83b0e33 +0 -0
  19. package/.parcel-cache/13241643a33ce8ed +0 -0
  20. package/.parcel-cache/3d581284675046c6 +0 -0
  21. package/.parcel-cache/43baead379789480 +0 -0
  22. package/.parcel-cache/56ba3face9690f8b-BundleGraph-0 +0 -0
  23. package/.parcel-cache/5b4f2c99ec04bf49-AssetGraph-0 +0 -0
  24. package/.parcel-cache/75917750f148582a +0 -0
  25. package/.parcel-cache/7c54988bfe0947ac +0 -0
  26. package/.parcel-cache/7f973df67467291d-AssetGraph-0 +0 -0
  27. package/.parcel-cache/8882a8f68ea22235 +0 -0
  28. package/.parcel-cache/9ed3c0dffa18099e +0 -0
  29. package/.parcel-cache/aea3b3f00e39e7d7 +0 -0
  30. package/.parcel-cache/b4a7d80971a57169-BundleGraph-0 +0 -0
  31. package/.parcel-cache/baeab7b2fd8ed441 +0 -0
  32. package/.parcel-cache/c0a6f93df69d20be +0 -0
  33. package/.parcel-cache/cadf66668af753d0 +0 -0
  34. package/.parcel-cache/d3d5a0c046bd2fee +0 -0
  35. package/.parcel-cache/e382ef13c33de3db-AssetGraph-0 +0 -0
  36. package/.parcel-cache/e80b459410ade898 +0 -0
  37. package/.parcel-cache/ef56c415264d359e +0 -0
  38. package/.parcel-cache/f1471b5a88ba6716 +0 -0
  39. package/.parcel-cache/fa1c0991a1e3d246 +0 -0
  40. package/.parcel-cache/fa7f3db05903caf2 +0 -0
  41. package/.parcel-cache/requestGraph-2b56c4c5947cf88b-0 +0 -0
  42. package/.parcel-cache/requestGraph-62897db56b555037-0 +0 -0
  43. package/.parcel-cache/requestGraph-nodes-0-2b56c4c5947cf88b-0 +0 -0
  44. package/.parcel-cache/requestGraph-nodes-0-62897db56b555037-0 +0 -0
  45. package/.parcel-cache/snapshot-2b56c4c5947cf88b.txt +0 -2
  46. package/.parcel-cache/snapshot-62897db56b555037.txt +0 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gramene-search",
3
- "version": "1.6.4",
3
+ "version": "1.6.6",
4
4
  "description": "search wrapper for gramene",
5
5
  "source": "src/index.js",
6
6
  "main": "dist/index.js",
@@ -1,7 +1,8 @@
1
- import React, {useState, useEffect, useMemo} from 'react';
1
+ import React, {useState, useEffect, useRef, useCallback} from 'react';
2
2
  import {connect} from "redux-bundler-react";
3
- import {Button} from 'react-bootstrap';
3
+ import {Button, Accordion, AccordionHeader} from 'react-bootstrap';
4
4
  import { AgGridReact } from "ag-grid-react";
5
+ import _ from 'lodash';
5
6
  import "ag-grid-community/styles/ag-grid.css";
6
7
  import "ag-grid-community/styles/ag-theme-quartz.css";
7
8
  import "./VEP.css";
@@ -10,9 +11,21 @@ import {suggestionToFilters} from "../../utils";
10
11
  const ggURL = {
11
12
  IRRI: 'https://gringlobal.irri.org/gringlobal/accessiondetail?id=',
12
13
  ARS: 'https://npgsweb.ars-grin.gov/gringlobal/accessiondetail.aspx?id=',
14
+ ICRISAT: 'https://genebank.icrisat.org/IND/PassportSummary?ID=',
13
15
  sorbmutdb: 'https://www.depts.ttu.edu/igcast/sorbmutdb.php'
14
16
  };
15
17
  const metaRenderer = params => {
18
+ if (params.value.field === "accessions") {
19
+ const accs = params.value.accessions;
20
+ return <Accordion>
21
+ <Accordion.Item>
22
+ <Accordion.Header>{accs.length}</Accordion.Header>
23
+ <Accordion.Body>
24
+ <p>This is where the "table" goes</p>
25
+ </Accordion.Body>
26
+ </Accordion.Item>
27
+ </Accordion>
28
+ }
16
29
  if (params.value.field === "germplasm") { // link to stock center
17
30
  const genebank = params.value.stock_center;
18
31
  const url = ggURL[genebank];
@@ -54,7 +67,9 @@ const study_info = {
54
67
  '2': {label: 'USDA Lubbock EMS', type: 'EMS'},
55
68
  '3': {label: 'Lozano', type: 'NAT'},
56
69
  '4': {label: 'USDA Lubbock EMS', type: 'EMS'},
57
- '5': {label: 'Boatwright SAP', type: 'NAT'}
70
+ '5': {label: 'Boatwright SAP', type: 'NAT'},
71
+ '7': {label: 'Kumar BAP', type: 'NAT'},
72
+ '8': {label: 'Lasky landraces', type: 'NAT'}
58
73
  },
59
74
  'oryza_sativa': {
60
75
  '7': {label: 'Rice 3K', type: 'NAT'},
@@ -69,54 +84,225 @@ const study_info = {
69
84
  'oryza_sativamh63': rice_studies,
70
85
  'oryza_sativazs97': rice_studies
71
86
  };
72
- const Detail = props => {
73
- const gene = props.geneDocs[props.searchResult.id];
74
- if (props.grameneConsequences && props.grameneConsequences[gene._id] && props.grameneGermplasm) {
75
- const germplasmLUT = props.grameneGermplasm;
76
- const vep_obj = props.grameneConsequences[gene._id];
77
- let accessionTable = [];
78
- let tableFields = [
79
- { field: 'Order Germplasm', cellRenderer: metaRenderer, comparator: sortByLabel},
80
- { field: 'Synonyms', cellRenderer: metaRenderer, comparator: sortByLabel},
81
- { field: 'Study/Population', cellRenderer: metaRenderer, comparator: sortByLabel},
82
- { field: 'VEP consequence', cellRenderer: metaRenderer, comparator: sortByLabel},
83
- { field: 'Allele Status', cellRenderer: metaRenderer, comparator: sortByLabel},
84
- { field: 'All LOF Genes', cellRenderer: metaRenderer, comparator: sortByLabel}
85
- ];
86
- Object.entries(vep_obj).forEach(([key,accessions]) => {
87
- const parts = key.split("__");
88
- if (parts[0] === "VEP") {
89
- if (parts[1] !== "merged") {
90
- accessions.forEach(ens_id => {
91
- const germplasm = germplasmLUT[ens_id][0];
92
- const accInfo = {
93
- 'Study/Population': {label: study_info[parts[3]][parts[4]].label},
94
- 'VEP consequence': {label: parts[1].replaceAll("_"," ")},
95
- 'Allele Status': {label: parts[2] === "het" ? "heterozygous" : "homozygous"},
96
- 'Order Germplasm': {field: 'germplasm', gene_id: props.searchResult.id, label: germplasm.pub_id, ...germplasm},
97
- 'All LOF Genes': {field: 'search', label: germplasm.ens_id, pop_type: study_info[parts[3]][parts[4]].type, ...germplasm},
98
- 'Synonyms': {label: germplasm.ens_id}
99
- };
100
- accessionTable.push(accInfo);
101
- });
87
+ const AccessionLink = ({germplasm, gene_id}) => {
88
+ if (germplasm.germplasm_dbid) { // link to stock center
89
+ const germ_id = germplasm.germplasm_dbid;
90
+ const genebank = germplasm.stock_center;
91
+ const url = ggURL[genebank];
92
+ if (germ_id && url && germ_id !== "0") {
93
+ return <a target="_blank" href={`${url}${germ_id}`}>
94
+ {germplasm.pub_id} ({genebank})</a>;
95
+ }
96
+ if (genebank === "sorbmutdb") {
97
+ return (
98
+ <form id={germplasm.pub_id} action={url} method="post" target="_blank">
99
+ <input type="hidden" name="search" value={gene_id.replace('SORBI_3','Sobic.')} />
100
+ <input type="hidden" name="submit" value="Search" />
101
+ <button type="submit" className="button-like-link">SorbMutDB</button>
102
+ </form>
103
+ );
104
+ }
105
+ }
106
+ return <span>{germplasm.pub_id}</span>
107
+ }
108
+ function group_germplasm(gene, germplasmLUT, vep_obj) {
109
+ let accessionTable = [];
110
+ Object.entries(vep_obj).forEach(([key,accessions]) => {
111
+ const parts = key.split("__");
112
+ if (parts[0] === "VEP") {
113
+ if (parts[1] !== "merged") {
114
+ accessions.forEach(ens_id => {
115
+ const germplasm = germplasmLUT[ens_id][0];
116
+ const pop = study_info[parts[3]][parts[4]];
117
+ const conseq = parts[1].replaceAll("_"," ");
118
+ const status = parts[2] === "het" ? "heterozygous" : "homozygous";
119
+ const accInfo = {
120
+ key: [pop.label,conseq,status].join('%%%'),
121
+ germplasm: germplasm,
122
+ pop: pop
123
+ };
124
+ accessionTable.push(accInfo);
125
+ });
126
+ }
127
+ }
128
+ });
129
+ // group accessionTable by key field
130
+ const groups = _.groupBy(accessionTable, 'key');
131
+ let grouped = [];
132
+ let id=0;
133
+ Object.keys(groups).sort().forEach((group) => {
134
+ const [pop,conseq,status] = group.split('%%%');
135
+ id++;
136
+ const tally = groups[group].length;
137
+ grouped.push({
138
+ id: id,
139
+ group: group,
140
+ summary: true,
141
+ pop: pop,
142
+ conseq: conseq,
143
+ status: status,
144
+ tally: tally
145
+ });
146
+ groups[group].forEach(acc => {
147
+ id++;
148
+ grouped.push({
149
+ id: id,
150
+ group: group,
151
+ summary: false,
152
+ pop:pop,
153
+ conseq: conseq,
154
+ status: status,
155
+ accession: acc,
156
+ tally: tally
157
+ })
158
+ })
159
+ })
160
+ return grouped;
161
+ }
162
+ const THRESHOLD = 5;
163
+ const GridWithGroups = ({groups,gene_id}) => {
164
+ const [rowData, setRowData] = useState(groups);
165
+
166
+ const initialExpanded = {};
167
+ rowData.forEach((row) => {
168
+ if (row.summary) {
169
+ initialExpanded[row.group] = (row.tally < THRESHOLD);
170
+ }
171
+ });
172
+ const [expandedGroups, setExpandedGroups] = useState(initialExpanded);
173
+
174
+ // const gridRef = useRef();
175
+
176
+ // Toggle group visibility
177
+ const toggleGroup = (group) => {
178
+ setExpandedGroups((prevExpandedGroups) => ({
179
+ ...prevExpandedGroups,
180
+ [group]: !prevExpandedGroups[group], // Toggle the group's state
181
+ }));
182
+ };
183
+
184
+ // Filter the data to show/hide rows based on the expanded group state
185
+ const getVisibleRowData = () => {
186
+ const visibleRows = [];
187
+ rowData.forEach((row) => {
188
+ if (row.summary) {
189
+ if (row.tally > 1) {
190
+ visibleRows.push(row);
102
191
  }
192
+ } else if (expandedGroups[row.group]) {
193
+ visibleRows.push(row); // Show non-summary rows if the group is expanded
103
194
  }
104
195
  });
105
- // const [rowData, setRowData] = useState(accessionTable);
106
- // const [colDefs, setColDefs] = useState(tableFields);
107
- const defaultColDef = useMemo(() => {
108
- return {
109
- filter: true
196
+ return visibleRows;
197
+ };
198
+
199
+ // Define columns with a custom renderer for the summary rows
200
+ const columnDefs = [
201
+ { field: 'pop', headerName: 'Study',
202
+ cellRenderer: (params) => {
203
+ if (params.data.summary || params.data.tally === 1) {
204
+ return params.value;
205
+ }
206
+ return null;
207
+ }
208
+ },
209
+ { field: 'conseq', headerName: 'VEP consequence',
210
+ cellRenderer: (params) => {
211
+ if (params.data.summary || params.data.tally === 1) {
212
+ return params.value;
213
+ }
214
+ return null;
215
+ }
216
+ },
217
+ { field: 'status', headerName: 'Allele status',
218
+ cellRenderer: (params) => {
219
+ if (params.data.summary || params.data.tally === 1) {
220
+ return params.value;
221
+ }
222
+ return null;
223
+ }
224
+ },
225
+ { field: 'accession', headerName: 'Order Germplasm',
226
+ cellRenderer: (params) => {
227
+ if (params.value) {
228
+ return <AccessionLink germplasm={params.value.germplasm} gene_id={gene_id} />;
229
+ }
230
+ if (params.data.summary) {
231
+ return (
232
+ <span
233
+ onClick={() => toggleGroup(params.data.group)}
234
+ >
235
+ {params.data.tally} Accessions {expandedGroups[params.data.group] ? '▼' : '▶'}
236
+ </span>
237
+ );
238
+ }
239
+ return null;
240
+ }
241
+ },
242
+ { field: 'search', headerName: 'All LOF Genes',
243
+ cellRenderer: (params) => {
244
+ if (params.data.accession) {
245
+ const currentURL = new URL(window.location.href);
246
+ const accession = params.data.accession;
247
+ currentURL.search = '';
248
+ currentURL.searchParams.set('category', 'Germplasm');
249
+ currentURL.searchParams.set('fq_field', `VEP__merged__${accession.pop.type}__attr_ss`);
250
+ currentURL.searchParams.set('fq_value', accession.germplasm.ens_id);
251
+ currentURL.searchParams.set('name', accession.germplasm.ens_id);
252
+
253
+ return <Button size='sm' href={currentURL.toString()}>Search</Button>
254
+
255
+ }
256
+ return null;
110
257
  }
111
- }, []);
258
+ }
259
+ ];
260
+
261
+ const defaultColDef = {
262
+ sortable: false,
263
+ cellStyle: (params) => {
264
+ // if (!params.data.summary) {
265
+ // return {paddingLeft: '30px'};
266
+ // }
267
+ if (params.data.summary) {
268
+ return {cursor: 'pointer'};
269
+ }
270
+ return null;
271
+ }
272
+ };
273
+
274
+ const nVisible = getVisibleRowData().length;
275
+ const tableHeight = 50 + Math.min(nVisible, 10) * 42;
276
+ return (
277
+ <div
278
+ className="ag-theme-quartz"
279
+ style={{ height: tableHeight, width: "100%" }}
280
+ >
281
+ <AgGridReact
282
+ rowData={getVisibleRowData()}
283
+ columnDefs={columnDefs}
284
+ getRowNodeId={(data) => data.id}
285
+ animateRows={true}
286
+ defaultColDef={defaultColDef}
287
+ />
288
+ </div>
289
+ );
290
+ };
291
+
292
+ const Detail = props => {
293
+ const gene = props.geneDocs[props.searchResult.id];
294
+ if (props.grameneConsequences && props.grameneConsequences[gene._id] && props.grameneGermplasm) {
295
+ const groups = group_germplasm(gene, props.grameneGermplasm, props.grameneConsequences[gene._id]);
296
+
112
297
  return <div>
113
298
  <h5>Predicted loss-of-function alleles were detected in these germplasm.</h5>
114
299
  <div >Explore other variants within this gene in the <a target="_blank"
115
300
  href={`${props.configuration.ensemblURL}/${gene.system_name}/Gene/Variation_Gene/Image?db=core;g=${props.searchResult.id}`}>
116
301
  Variant image</a> page in the Ensembl genome browser.</div>
117
- <div className="ag-theme-quartz" style={{height: `${44 * (accessionTable.length + 2)}px`}}>
118
- <AgGridReact rowData={accessionTable} columnDefs={tableFields} defaultColDef={defaultColDef}/>
119
- </div>
302
+ <GridWithGroups groups={...groups} gene_id={gene._id}/>
303
+ {/*<div className="ag-theme-quartz" style={{height: `${rowHeight * (rows2show + 1)}px`}}>*/}
304
+ {/* /!*<AgGridReact rowHeight={rowHeight} rowData={rowData} columnDefs={tableFields} defaultColDef={defaultColDef}/>*!/*/}
305
+ {/*</div>*/}
120
306
  </div>
121
307
  } else {
122
308
  props.doRequestVEP(gene._id);
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -1,2 +0,0 @@
1
- 143878288
2
- 1728587320560471000
@@ -1,2 +0,0 @@
1
- 135678894
2
- 1728491020709461000