gramene-search 2.20.2 → 2.21.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.css +44 -0
- package/dist/index.css.map +1 -1
- package/dist/index.js +265 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -849,6 +849,7 @@ function $af4441dd29af05df$var$markSubtree(node, source, invert) {
|
|
|
849
849
|
$af4441dd29af05df$var$markSubtree(child, source, invert);
|
|
850
850
|
});
|
|
851
851
|
}
|
|
852
|
+
const $af4441dd29af05df$export$6b95404109a3e2ec = 'Genomic intervals';
|
|
852
853
|
const $af4441dd29af05df$export$da3188ffd2da2525 = {
|
|
853
854
|
orthologs: {
|
|
854
855
|
label: 'orthologs',
|
|
@@ -1037,6 +1038,52 @@ const $af4441dd29af05df$var$grameneFilters = {
|
|
|
1037
1038
|
return newState;
|
|
1038
1039
|
}
|
|
1039
1040
|
break;
|
|
1041
|
+
case 'GRAMENE_FILTER_INTERVAL_ADDED':
|
|
1042
|
+
{
|
|
1043
|
+
// Intervals accumulate into a single OR group, because ANDing two
|
|
1044
|
+
// disjoint intervals matches nothing — no gene sits in both. The group
|
|
1045
|
+
// is tagged with `category`, one of the keys viewSnapshot keeps, so a
|
|
1046
|
+
// restored view merges into it instead of starting a second group; were
|
|
1047
|
+
// that tag ever lost the worst case is an extra group, never a corrupt
|
|
1048
|
+
// tree.
|
|
1049
|
+
newState = Object.assign({}, state, {
|
|
1050
|
+
status: 'search',
|
|
1051
|
+
showMarked: true,
|
|
1052
|
+
searchOffset: 0
|
|
1053
|
+
});
|
|
1054
|
+
const { map: map, mapLabel: mapLabel, region: region, start: start, end: end } = payload;
|
|
1055
|
+
// One leaf per interval, not four. getQuery has a raw-passthrough branch
|
|
1056
|
+
// for a `location` leaf whose value starts with "(map:" — every other
|
|
1057
|
+
// branch would escape the colons — so the whole clause rides in one node
|
|
1058
|
+
// and the Filters panel shows one readable row per interval.
|
|
1059
|
+
//
|
|
1060
|
+
// Overlap, not containment: start <= interval end AND end >= interval
|
|
1061
|
+
// start, so a gene that merely crosses the boundary still matches.
|
|
1062
|
+
const intervalNode = {
|
|
1063
|
+
fq_field: 'location',
|
|
1064
|
+
fq_value: `(map:${map} AND region:${region}` + ` AND start:[* TO ${end}] AND end:[${start} TO *])`,
|
|
1065
|
+
name: `${mapLabel} ${region}:${start.toLocaleString()}-${end.toLocaleString()}`,
|
|
1066
|
+
category: 'Genomic interval',
|
|
1067
|
+
negate: false,
|
|
1068
|
+
showMenu: false
|
|
1069
|
+
};
|
|
1070
|
+
let group = (newState.children || []).find((c)=>c && c.category === $af4441dd29af05df$export$6b95404109a3e2ec && Array.isArray(c.children));
|
|
1071
|
+
if (group) group.children.push(intervalNode);
|
|
1072
|
+
else newState.children.push({
|
|
1073
|
+
operation: 'OR',
|
|
1074
|
+
category: $af4441dd29af05df$export$6b95404109a3e2ec,
|
|
1075
|
+
negate: false,
|
|
1076
|
+
showMenu: false,
|
|
1077
|
+
children: [
|
|
1078
|
+
intervalNode
|
|
1079
|
+
]
|
|
1080
|
+
});
|
|
1081
|
+
// Inserting a nested subtree invalidates the hand-computed indices the
|
|
1082
|
+
// append actions rely on, so renumber the whole tree.
|
|
1083
|
+
$af4441dd29af05df$var$reindexTree(newState, 0);
|
|
1084
|
+
$af4441dd29af05df$var$markSubtree(newState, newState, false);
|
|
1085
|
+
return newState;
|
|
1086
|
+
}
|
|
1040
1087
|
case 'GRAMENE_FILTER_EXPANSION_SET':
|
|
1041
1088
|
{
|
|
1042
1089
|
// Setting or clearing an expansion is just a field on the node — the tree
|
|
@@ -1353,6 +1400,25 @@ const $af4441dd29af05df$var$grameneFilters = {
|
|
|
1353
1400
|
]
|
|
1354
1401
|
});
|
|
1355
1402
|
},
|
|
1403
|
+
// Add one genomic interval. Accumulates into a single OR group; see the
|
|
1404
|
+
// GRAMENE_FILTER_INTERVAL_ADDED reducer for why they cannot be ANDed.
|
|
1405
|
+
doAddGrameneInterval: (interval)=>({ dispatch: dispatch })=>{
|
|
1406
|
+
dispatch({
|
|
1407
|
+
type: 'BATCH_ACTIONS',
|
|
1408
|
+
actions: [
|
|
1409
|
+
{
|
|
1410
|
+
type: 'GRAMENE_SEARCH_CLEARED'
|
|
1411
|
+
},
|
|
1412
|
+
{
|
|
1413
|
+
type: 'GRAMENE_TAXONOMY_CLEARED'
|
|
1414
|
+
},
|
|
1415
|
+
{
|
|
1416
|
+
type: 'GRAMENE_FILTER_INTERVAL_ADDED',
|
|
1417
|
+
payload: interval
|
|
1418
|
+
}
|
|
1419
|
+
]
|
|
1420
|
+
});
|
|
1421
|
+
},
|
|
1356
1422
|
doToggleGrameneFilterMenu: (node)=>({ dispatch: dispatch })=>{
|
|
1357
1423
|
dispatch({
|
|
1358
1424
|
type: 'GRAMENE_FILTER_MENU_TOGGLED',
|
|
@@ -20789,6 +20855,181 @@ var $7d7b7dad5e71dfd3$export$2e2bcd8739ae039 = $7d7b7dad5e71dfd3$var$Facets;
|
|
|
20789
20855
|
|
|
20790
20856
|
|
|
20791
20857
|
|
|
20858
|
+
// Sequences that aren't a placed chromosome. Excluded from the dropdown because
|
|
20859
|
+
// an interval on them is not something a user can reason about positionally.
|
|
20860
|
+
// Organelles (C, M, Mt, Pt, mitochondrion_genome) are deliberately kept — they
|
|
20861
|
+
// are real, coordinate-addressable sequences.
|
|
20862
|
+
const $909272efb41be16f$var$UNPLACED = /^(unanchored|u)$/i;
|
|
20863
|
+
function $909272efb41be16f$export$ac97d17982e0cb21(grameneMaps, targetTaxonId) {
|
|
20864
|
+
const genomes = Object.values(grameneMaps || {}).filter((m)=>m && m._id && m.regions);
|
|
20865
|
+
const byLabel = (a, b)=>String(a.display_name || '').localeCompare(String(b.display_name || ''));
|
|
20866
|
+
const reference = genomes.filter((m)=>String(m.taxon_id) === String(targetTaxonId));
|
|
20867
|
+
const refIds = new Set(reference.map((m)=>m.taxon_id));
|
|
20868
|
+
const anchors = genomes.filter((m)=>m.is_anchor && !refIds.has(m.taxon_id)).sort(byLabel);
|
|
20869
|
+
const anchorIds = new Set(anchors.map((m)=>m.taxon_id));
|
|
20870
|
+
const rest = genomes.filter((m)=>!refIds.has(m.taxon_id) && !anchorIds.has(m.taxon_id)).sort(byLabel);
|
|
20871
|
+
return {
|
|
20872
|
+
reference: reference,
|
|
20873
|
+
anchors: anchors,
|
|
20874
|
+
rest: rest
|
|
20875
|
+
};
|
|
20876
|
+
}
|
|
20877
|
+
function $909272efb41be16f$export$94955a075dcb14b2(genome) {
|
|
20878
|
+
const regions = genome && genome.regions || {};
|
|
20879
|
+
const names = regions.names || [];
|
|
20880
|
+
const lengths = regions.lengths || [];
|
|
20881
|
+
return names.map((name, i)=>({
|
|
20882
|
+
name: name,
|
|
20883
|
+
length: lengths[i]
|
|
20884
|
+
})).filter((r)=>!$909272efb41be16f$var$UNPLACED.test(String(r.name)));
|
|
20885
|
+
}
|
|
20886
|
+
const $909272efb41be16f$var$GenomicIntervalForm = ({ grameneMaps: grameneMaps, targetTaxonId: targetTaxonId, onAdd: onAdd })=>{
|
|
20887
|
+
const [open, setOpen] = (0, $gXNCa$react.useState)(false);
|
|
20888
|
+
const [taxonId, setTaxonId] = (0, $gXNCa$react.useState)('');
|
|
20889
|
+
const [region, setRegion] = (0, $gXNCa$react.useState)('');
|
|
20890
|
+
const [start, setStart] = (0, $gXNCa$react.useState)('');
|
|
20891
|
+
const [end, setEnd] = (0, $gXNCa$react.useState)('');
|
|
20892
|
+
const { reference: reference, anchors: anchors, rest: rest } = (0, $gXNCa$react.useMemo)(()=>$909272efb41be16f$export$ac97d17982e0cb21(grameneMaps, targetTaxonId), [
|
|
20893
|
+
grameneMaps,
|
|
20894
|
+
targetTaxonId
|
|
20895
|
+
]);
|
|
20896
|
+
// Default to the site's reference genome once maps have loaded.
|
|
20897
|
+
const effectiveTaxon = taxonId || reference[0] && String(reference[0].taxon_id) || '';
|
|
20898
|
+
const genome = effectiveTaxon ? (grameneMaps || {})[effectiveTaxon] : null;
|
|
20899
|
+
const chromosomes = (0, $gXNCa$react.useMemo)(()=>$909272efb41be16f$export$94955a075dcb14b2(genome), [
|
|
20900
|
+
genome
|
|
20901
|
+
]);
|
|
20902
|
+
const effectiveRegion = region || chromosomes[0] && chromosomes[0].name || '';
|
|
20903
|
+
const chrLength = (chromosomes.find((c)=>String(c.name) === String(effectiveRegion)) || {}).length;
|
|
20904
|
+
const s = start === '' ? null : Number(start);
|
|
20905
|
+
const e = end === '' ? null : Number(end);
|
|
20906
|
+
// Validated against the assembly's own region lengths, so the message can name
|
|
20907
|
+
// the actual limit rather than just refusing.
|
|
20908
|
+
const error = (()=>{
|
|
20909
|
+
if (!genome) return null;
|
|
20910
|
+
if (s === null || e === null) return null;
|
|
20911
|
+
if (!Number.isFinite(s) || !Number.isFinite(e)) return 'Positions must be numbers.';
|
|
20912
|
+
if (s < 1 || e < 1) return 'Positions start at 1.';
|
|
20913
|
+
if (s > e) return 'Start must not be greater than end.';
|
|
20914
|
+
if (chrLength && e > chrLength) return `${effectiveRegion} is ${chrLength.toLocaleString()} bp; end is beyond it.`;
|
|
20915
|
+
return null;
|
|
20916
|
+
})();
|
|
20917
|
+
const ready = !!genome && !!effectiveRegion && s !== null && e !== null && !error;
|
|
20918
|
+
const submit = ()=>{
|
|
20919
|
+
if (!ready) return;
|
|
20920
|
+
onAdd({
|
|
20921
|
+
map: genome._id,
|
|
20922
|
+
mapLabel: genome.display_name || genome._id,
|
|
20923
|
+
region: effectiveRegion,
|
|
20924
|
+
start: s,
|
|
20925
|
+
end: e
|
|
20926
|
+
});
|
|
20927
|
+
setStart('');
|
|
20928
|
+
setEnd('');
|
|
20929
|
+
};
|
|
20930
|
+
const genomeOption = (m)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("option", {
|
|
20931
|
+
value: m.taxon_id,
|
|
20932
|
+
children: m.display_name || m.system_name
|
|
20933
|
+
}, m.taxon_id);
|
|
20934
|
+
return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
20935
|
+
className: "gramene-interval",
|
|
20936
|
+
children: [
|
|
20937
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
20938
|
+
className: "gramene-interval-toggle",
|
|
20939
|
+
onClick: ()=>setOpen(!open),
|
|
20940
|
+
children: [
|
|
20941
|
+
open ? /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reacticonsbs.BsChevronDown), {}) : /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reacticonsbs.BsChevronRight), {}),
|
|
20942
|
+
" Add genomic interval"
|
|
20943
|
+
]
|
|
20944
|
+
}),
|
|
20945
|
+
open && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
20946
|
+
className: "gramene-interval-form",
|
|
20947
|
+
children: [
|
|
20948
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)((0, $gXNCa$reactbootstrap.Form).Select, {
|
|
20949
|
+
size: "sm",
|
|
20950
|
+
className: "mb-1",
|
|
20951
|
+
value: effectiveTaxon,
|
|
20952
|
+
onChange: (ev)=>{
|
|
20953
|
+
setTaxonId(ev.target.value);
|
|
20954
|
+
setRegion('');
|
|
20955
|
+
},
|
|
20956
|
+
children: [
|
|
20957
|
+
reference.map(genomeOption),
|
|
20958
|
+
anchors.length > 0 && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("optgroup", {
|
|
20959
|
+
label: "Reference genomes",
|
|
20960
|
+
children: anchors.map(genomeOption)
|
|
20961
|
+
}),
|
|
20962
|
+
rest.length > 0 && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("optgroup", {
|
|
20963
|
+
label: "Other genomes",
|
|
20964
|
+
children: rest.map(genomeOption)
|
|
20965
|
+
})
|
|
20966
|
+
]
|
|
20967
|
+
}),
|
|
20968
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Form).Select, {
|
|
20969
|
+
size: "sm",
|
|
20970
|
+
className: "mb-1",
|
|
20971
|
+
value: effectiveRegion,
|
|
20972
|
+
onChange: (ev)=>setRegion(ev.target.value),
|
|
20973
|
+
children: chromosomes.map((c)=>/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("option", {
|
|
20974
|
+
value: c.name,
|
|
20975
|
+
children: [
|
|
20976
|
+
c.name,
|
|
20977
|
+
c.length ? ` (${Math.round(c.length / 1e6)} Mb)` : ''
|
|
20978
|
+
]
|
|
20979
|
+
}, c.name))
|
|
20980
|
+
}),
|
|
20981
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)("div", {
|
|
20982
|
+
className: "gramene-interval-range",
|
|
20983
|
+
children: [
|
|
20984
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Form).Control, {
|
|
20985
|
+
size: "sm",
|
|
20986
|
+
type: "number",
|
|
20987
|
+
min: "1",
|
|
20988
|
+
placeholder: "start",
|
|
20989
|
+
value: start,
|
|
20990
|
+
onChange: (ev)=>setStart(ev.target.value)
|
|
20991
|
+
}),
|
|
20992
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
|
|
20993
|
+
className: "gramene-interval-dash",
|
|
20994
|
+
children: "\u2013"
|
|
20995
|
+
}),
|
|
20996
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Form).Control, {
|
|
20997
|
+
size: "sm",
|
|
20998
|
+
type: "number",
|
|
20999
|
+
min: "1",
|
|
21000
|
+
placeholder: "end",
|
|
21001
|
+
value: end,
|
|
21002
|
+
onChange: (ev)=>setEnd(ev.target.value),
|
|
21003
|
+
onKeyDown: (ev)=>{
|
|
21004
|
+
if (ev.key === 'Enter') submit();
|
|
21005
|
+
}
|
|
21006
|
+
})
|
|
21007
|
+
]
|
|
21008
|
+
}),
|
|
21009
|
+
error && /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
21010
|
+
className: "gramene-interval-error",
|
|
21011
|
+
children: error
|
|
21012
|
+
}),
|
|
21013
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reactbootstrap.Button), {
|
|
21014
|
+
size: "sm",
|
|
21015
|
+
variant: "primary",
|
|
21016
|
+
className: "gramene-interval-submit",
|
|
21017
|
+
disabled: !ready,
|
|
21018
|
+
onClick: submit,
|
|
21019
|
+
children: "Add interval"
|
|
21020
|
+
})
|
|
21021
|
+
]
|
|
21022
|
+
})
|
|
21023
|
+
]
|
|
21024
|
+
});
|
|
21025
|
+
};
|
|
21026
|
+
var $909272efb41be16f$export$2e2bcd8739ae039 = $909272efb41be16f$var$GenomicIntervalForm;
|
|
21027
|
+
|
|
21028
|
+
|
|
21029
|
+
|
|
21030
|
+
|
|
21031
|
+
|
|
21032
|
+
|
|
20792
21033
|
|
|
20793
21034
|
|
|
20794
21035
|
|
|
@@ -21423,10 +21664,15 @@ const $693dd8c7a5607c3a$var$FiltersCmp = (props)=>{
|
|
|
21423
21664
|
unmarkTargets: props.doUnmarkGrameneFilterTargets,
|
|
21424
21665
|
toggleMenu: props.doToggleGrameneFilterMenu
|
|
21425
21666
|
};
|
|
21667
|
+
const intervalForm = /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $909272efb41be16f$export$2e2bcd8739ae039), {
|
|
21668
|
+
grameneMaps: props.grameneMaps,
|
|
21669
|
+
targetTaxonId: props.targetTaxonId,
|
|
21670
|
+
onAdd: props.doAddGrameneInterval
|
|
21671
|
+
});
|
|
21426
21672
|
const containerClass = props.configuration.id === 'sorghum' ? 'sorghumbase-filter-container' : 'gramene-filter-container';
|
|
21427
21673
|
if (props.grameneFilters.rightIdx > 1) return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
21428
21674
|
className: containerClass,
|
|
21429
|
-
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.
|
|
21675
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)($693dd8c7a5607c3a$var$CollapsibleSection, {
|
|
21430
21676
|
title: "Filters",
|
|
21431
21677
|
extra: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("span", {
|
|
21432
21678
|
style: {
|
|
@@ -21439,26 +21685,32 @@ const $693dd8c7a5607c3a$var$FiltersCmp = (props)=>{
|
|
|
21439
21685
|
},
|
|
21440
21686
|
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)((0, $gXNCa$reacticonsbs.BsTrash), {})
|
|
21441
21687
|
}),
|
|
21442
|
-
children:
|
|
21443
|
-
|
|
21444
|
-
|
|
21445
|
-
|
|
21446
|
-
|
|
21447
|
-
|
|
21688
|
+
children: [
|
|
21689
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)($693dd8c7a5607c3a$var$Filter, {
|
|
21690
|
+
node: props.grameneFilters,
|
|
21691
|
+
moveCopyMode: props.grameneFilters.moveCopyMode,
|
|
21692
|
+
showMarked: props.grameneFilters.showMarked,
|
|
21693
|
+
actions: actions
|
|
21694
|
+
}),
|
|
21695
|
+
intervalForm
|
|
21696
|
+
]
|
|
21448
21697
|
})
|
|
21449
21698
|
});
|
|
21450
21699
|
else return /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
21451
21700
|
className: containerClass,
|
|
21452
|
-
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.
|
|
21701
|
+
children: /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsxs)($693dd8c7a5607c3a$var$CollapsibleSection, {
|
|
21453
21702
|
title: "Filters",
|
|
21454
|
-
children:
|
|
21455
|
-
|
|
21456
|
-
|
|
21457
|
-
|
|
21703
|
+
children: [
|
|
21704
|
+
/*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|
|
21705
|
+
className: "gramene-filter gramene-filter-AND",
|
|
21706
|
+
children: "No filters defined"
|
|
21707
|
+
}),
|
|
21708
|
+
intervalForm
|
|
21709
|
+
]
|
|
21458
21710
|
})
|
|
21459
21711
|
});
|
|
21460
21712
|
};
|
|
21461
|
-
const $693dd8c7a5607c3a$export$92a576f896a9bf72 = (0, $gXNCa$reduxbundlerreact.connect)('selectGrameneFilters', 'selectConfiguration', 'doNegateGrameneFilter', 'doDeleteGrameneFilter', 'doChangeGrameneFilterOperation', 'doExpandGrameneFilter', 'doRemoveGrameneExpansion', 'doMoveOrCopyGrameneFilter', 'doMarkGrameneFilterTargets', 'doUnmarkGrameneFilterTargets', 'doToggleGrameneFilterMenu', 'doClearGrameneFilters', $693dd8c7a5607c3a$var$FiltersCmp);
|
|
21713
|
+
const $693dd8c7a5607c3a$export$92a576f896a9bf72 = (0, $gXNCa$reduxbundlerreact.connect)('selectGrameneFilters', 'selectConfiguration', 'doNegateGrameneFilter', 'doDeleteGrameneFilter', 'doChangeGrameneFilterOperation', 'doExpandGrameneFilter', 'doRemoveGrameneExpansion', 'doMoveOrCopyGrameneFilter', 'doMarkGrameneFilterTargets', 'doUnmarkGrameneFilterTargets', 'doToggleGrameneFilterMenu', 'selectGrameneMaps', 'selectTargetTaxonId', 'doAddGrameneInterval', 'doClearGrameneFilters', $693dd8c7a5607c3a$var$FiltersCmp);
|
|
21462
21714
|
const $693dd8c7a5607c3a$var$ResultsCmp = (props)=>{
|
|
21463
21715
|
let activeViews = props.grameneViews.options;
|
|
21464
21716
|
return props.grameneFilters.rightIdx > 0 ? /*#__PURE__*/ (0, $gXNCa$reactjsxruntime.jsx)("div", {
|