@teselagen/ove 0.8.39 → 0.8.41
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/AlignmentView/AlignmentSearchBar.d.ts +2 -0
- package/AlignmentView/Mismatches.d.ts +2 -20
- package/AlignmentView/findAlignmentDifferences.d.ts +53 -0
- package/AlignmentView/utils.d.ts +31 -0
- package/index.cjs.js +1063 -164
- package/index.es.js +1063 -164
- package/index.umd.js +1063 -164
- package/ove.css +138 -54
- package/package.json +1 -1
- package/src/AlignmentView/AlignmentSearchBar.js +810 -0
- package/src/AlignmentView/AlignmentVisibilityTool.js +9 -11
- package/src/AlignmentView/Minimap.js +21 -3
- package/src/AlignmentView/Mismatches.js +201 -123
- package/src/AlignmentView/findAlignmentDifferences.js +116 -0
- package/src/AlignmentView/findAlignmentDifferences.test.js +208 -0
- package/src/AlignmentView/index.js +30 -2
- package/src/AlignmentView/style.css +84 -0
- package/src/AlignmentView/utils.js +30 -0
- package/src/PropertySidePanel/index.js +89 -28
- package/src/redux/alignments.js +58 -20
package/index.es.js
CHANGED
|
@@ -95492,14 +95492,34 @@ function addHighlightedDifferences(alignmentTracks) {
|
|
|
95492
95492
|
track.alignmentData.sequence
|
|
95493
95493
|
);
|
|
95494
95494
|
const mismatches = matchHighlightRanges.filter(({ isMatch }) => !isMatch);
|
|
95495
|
+
const alignedSeq = track.alignmentData.sequence;
|
|
95496
|
+
const seqLen = alignedSeq.length;
|
|
95497
|
+
const startIndex = seqLen - alignedSeq.replace(/^-+/, "").length;
|
|
95498
|
+
const endIndex = alignedSeq.replace(/-+$/, "").length;
|
|
95499
|
+
const gapRanges = [
|
|
95500
|
+
startIndex > 0 && {
|
|
95501
|
+
start: 0,
|
|
95502
|
+
end: startIndex - 1,
|
|
95503
|
+
differenceType: "gap"
|
|
95504
|
+
},
|
|
95505
|
+
endIndex < seqLen && {
|
|
95506
|
+
start: endIndex,
|
|
95507
|
+
end: seqLen - 1,
|
|
95508
|
+
differenceType: "gap"
|
|
95509
|
+
}
|
|
95510
|
+
].filter(Boolean);
|
|
95495
95511
|
return __spreadProps(__spreadValues({}, track), {
|
|
95496
95512
|
sequenceData: sequenceData2,
|
|
95497
95513
|
matchHighlightRanges,
|
|
95498
|
-
additionalSelectionLayers:
|
|
95499
|
-
|
|
95514
|
+
additionalSelectionLayers: [
|
|
95515
|
+
...matchHighlightRanges.filter(({ isMatch }) => !isMatch).map((range2) => __spreadProps(__spreadValues(__spreadValues({}, range2), highlightRangeProps), {
|
|
95500
95516
|
className: "veAlignmentMismatch"
|
|
95501
|
-
})
|
|
95502
|
-
|
|
95517
|
+
})),
|
|
95518
|
+
...gapRanges.map((range2) => __spreadProps(__spreadValues(__spreadValues({}, range2), highlightRangeProps), {
|
|
95519
|
+
className: "veAlignmentMismatch"
|
|
95520
|
+
}))
|
|
95521
|
+
],
|
|
95522
|
+
gapRanges,
|
|
95503
95523
|
mismatches
|
|
95504
95524
|
});
|
|
95505
95525
|
});
|
|
@@ -95633,23 +95653,30 @@ function getRangeMatchesBetweenTemplateAndNonTemplate(tempSeq, nonTempSeq) {
|
|
|
95633
95653
|
const startIndex = seqLength - nonTempSeqWithoutLeadingDashes.length;
|
|
95634
95654
|
const endIndex = seqLength - (seqLength - nonTempSeqWithoutTrailingDashes.length);
|
|
95635
95655
|
for (let index2 = startIndex; index2 < endIndex; index2++) {
|
|
95636
|
-
const
|
|
95637
|
-
const
|
|
95638
|
-
|
|
95639
|
-
|
|
95640
|
-
|
|
95656
|
+
const tempBase = tempSeq[index2].toLowerCase();
|
|
95657
|
+
const nonTempBase = nonTempSeq[index2].toLowerCase();
|
|
95658
|
+
const isMatch = tempBase === nonTempBase;
|
|
95659
|
+
let differenceType = null;
|
|
95660
|
+
if (!isMatch) {
|
|
95661
|
+
if (tempBase === "-") {
|
|
95662
|
+
differenceType = "insertion";
|
|
95663
|
+
} else if (nonTempBase === "-") {
|
|
95664
|
+
differenceType = "deletion";
|
|
95641
95665
|
} else {
|
|
95642
|
-
|
|
95643
|
-
start: index2,
|
|
95644
|
-
end: index2,
|
|
95645
|
-
isMatch
|
|
95646
|
-
});
|
|
95666
|
+
differenceType = "mismatch";
|
|
95647
95667
|
}
|
|
95668
|
+
}
|
|
95669
|
+
const previousRange = ranges[ranges.length - 1];
|
|
95670
|
+
if (previousRange && previousRange.isMatch === isMatch && previousRange.differenceType === differenceType) {
|
|
95671
|
+
previousRange.end++;
|
|
95672
|
+
} else if (previousRange) {
|
|
95673
|
+
ranges.push({ start: index2, end: index2, isMatch, differenceType });
|
|
95648
95674
|
} else {
|
|
95649
95675
|
ranges.push({
|
|
95650
95676
|
start: startIndex,
|
|
95651
95677
|
end: startIndex,
|
|
95652
|
-
isMatch
|
|
95678
|
+
isMatch,
|
|
95679
|
+
differenceType
|
|
95653
95680
|
});
|
|
95654
95681
|
}
|
|
95655
95682
|
}
|
|
@@ -117227,7 +117254,7 @@ function showFileDialog({ multiple = false, onSelect }) {
|
|
|
117227
117254
|
input.click();
|
|
117228
117255
|
}
|
|
117229
117256
|
__name(showFileDialog, "showFileDialog");
|
|
117230
|
-
const version = "0.8.
|
|
117257
|
+
const version = "0.8.41";
|
|
117231
117258
|
const packageJson = {
|
|
117232
117259
|
version
|
|
117233
117260
|
};
|
|
@@ -125096,11 +125123,13 @@ const _Minimap = class _Minimap extends React__default.Component {
|
|
|
125096
125123
|
dimensions: { width = 200 },
|
|
125097
125124
|
laneHeight,
|
|
125098
125125
|
laneSpacing = 1,
|
|
125099
|
-
isTrackSelected = []
|
|
125126
|
+
isTrackSelected = [],
|
|
125127
|
+
activeFilterType = "all"
|
|
125100
125128
|
} = this.props;
|
|
125101
125129
|
const charWidth2 = this.getCharWidth();
|
|
125102
125130
|
const {
|
|
125103
125131
|
matchHighlightRanges: _matchHighlightRanges,
|
|
125132
|
+
gapRanges = [],
|
|
125104
125133
|
alignmentData: { trimmedRange } = {}
|
|
125105
125134
|
} = alignmentTracks[i];
|
|
125106
125135
|
const matchHighlightRanges = !trimmedRange ? _matchHighlightRanges : flatMap(_matchHighlightRanges, (r2) => {
|
|
@@ -125127,10 +125156,19 @@ const _Minimap = class _Minimap extends React__default.Component {
|
|
|
125127
125156
|
charWidth2
|
|
125128
125157
|
);
|
|
125129
125158
|
const toAdd = `M${xStart},${y2} L${xStart + width2},${y2} L${xStart + width2},${y2 + height} L${xStart},${y2 + height}`;
|
|
125130
|
-
if (!range2.isMatch) {
|
|
125159
|
+
if (!range2.isMatch && (activeFilterType === "all" || range2.differenceType === activeFilterType)) {
|
|
125131
125160
|
redPath += toAdd;
|
|
125132
125161
|
}
|
|
125133
125162
|
});
|
|
125163
|
+
if (activeFilterType === "gap") {
|
|
125164
|
+
gapRanges.forEach((range2) => {
|
|
125165
|
+
const { xStart, width: width2 } = getXStartAndWidthFromNonCircularRange(
|
|
125166
|
+
range2,
|
|
125167
|
+
charWidth2
|
|
125168
|
+
);
|
|
125169
|
+
redPath += `M${xStart},${y2} L${xStart + width2},${y2} L${xStart + width2},${y2 + height} L${xStart},${y2 + height}`;
|
|
125170
|
+
});
|
|
125171
|
+
}
|
|
125134
125172
|
return /* @__PURE__ */ React__default.createElement(
|
|
125135
125173
|
"div",
|
|
125136
125174
|
{
|
|
@@ -125160,7 +125198,8 @@ const _Minimap = class _Minimap extends React__default.Component {
|
|
|
125160
125198
|
"scrollAlignmentView",
|
|
125161
125199
|
"laneHeight",
|
|
125162
125200
|
"laneSpacing",
|
|
125163
|
-
"isTrackSelected"
|
|
125201
|
+
"isTrackSelected",
|
|
125202
|
+
"activeFilterType"
|
|
125164
125203
|
].some((key) => props[key] !== newProps[key]))
|
|
125165
125204
|
return true;
|
|
125166
125205
|
return false;
|
|
@@ -125438,6 +125477,899 @@ function getTrimmedRangesToDisplay({ trimmedRange, seqLen }) {
|
|
|
125438
125477
|
return splitRangeIntoTwoPartsIfItIsCircular(inverted, seqLen);
|
|
125439
125478
|
}
|
|
125440
125479
|
__name(getTrimmedRangesToDisplay, "getTrimmedRangesToDisplay");
|
|
125480
|
+
function groupConsecutiveDifferences(differences) {
|
|
125481
|
+
const grouped = [];
|
|
125482
|
+
for (const diff of differences) {
|
|
125483
|
+
if (diff.type === "mismatch") {
|
|
125484
|
+
grouped.push(__spreadProps(__spreadValues({}, diff), { start: diff.position, end: diff.position }));
|
|
125485
|
+
continue;
|
|
125486
|
+
}
|
|
125487
|
+
const last2 = grouped[grouped.length - 1];
|
|
125488
|
+
if (last2 && last2.type === diff.type && last2.end === diff.position - 1) {
|
|
125489
|
+
grouped[grouped.length - 1] = __spreadProps(__spreadValues({}, last2), { end: diff.position });
|
|
125490
|
+
} else {
|
|
125491
|
+
grouped.push(__spreadProps(__spreadValues({}, diff), { start: diff.position, end: diff.position }));
|
|
125492
|
+
}
|
|
125493
|
+
}
|
|
125494
|
+
return grouped;
|
|
125495
|
+
}
|
|
125496
|
+
__name(groupConsecutiveDifferences, "groupConsecutiveDifferences");
|
|
125497
|
+
function findAlignmentDifferences(alignedSeqs) {
|
|
125498
|
+
var _a2;
|
|
125499
|
+
if (alignedSeqs.length < 2 || !((_a2 = alignedSeqs[0]) == null ? void 0 : _a2.length)) return [];
|
|
125500
|
+
const template = alignedSeqs[0].toLowerCase();
|
|
125501
|
+
const nonTemplates = alignedSeqs.slice(1).map((s2) => s2.toLowerCase());
|
|
125502
|
+
const trackBounds = nonTemplates.map((seq) => {
|
|
125503
|
+
const withoutLeading = seq.replace(/^-+/, "");
|
|
125504
|
+
const withoutTrailing = seq.replace(/-+$/, "");
|
|
125505
|
+
const start2 = seq.length - withoutLeading.length;
|
|
125506
|
+
const end2 = seq.length - (seq.length - withoutTrailing.length);
|
|
125507
|
+
return { start: start2, end: end2 };
|
|
125508
|
+
});
|
|
125509
|
+
const differences = [];
|
|
125510
|
+
for (let i = 0; i < template.length; i++) {
|
|
125511
|
+
const templateBase = template[i];
|
|
125512
|
+
const allNonTemplateBases = nonTemplates.map((seq) => seq[i]);
|
|
125513
|
+
const bases = [templateBase, ...allNonTemplateBases];
|
|
125514
|
+
const alignedIndices = trackBounds.reduce((acc, { start: start2, end: end2 }, idx) => {
|
|
125515
|
+
if (i >= start2 && i < end2) acc.push(idx);
|
|
125516
|
+
return acc;
|
|
125517
|
+
}, []);
|
|
125518
|
+
if (alignedIndices.length === 0) {
|
|
125519
|
+
differences.push({ position: i, type: "gap", bases });
|
|
125520
|
+
continue;
|
|
125521
|
+
}
|
|
125522
|
+
const alignedBases = alignedIndices.map((idx) => allNonTemplateBases[idx]);
|
|
125523
|
+
const templateIsGap = templateBase === "-";
|
|
125524
|
+
const nonTemplateHasBase = alignedBases.some((b3) => b3 !== "-");
|
|
125525
|
+
const nonTemplateHasGap = alignedBases.some((b3) => b3 === "-");
|
|
125526
|
+
if (templateIsGap && nonTemplateHasBase) {
|
|
125527
|
+
differences.push({ position: i, type: "insertion", bases });
|
|
125528
|
+
} else if (!templateIsGap && nonTemplateHasGap) {
|
|
125529
|
+
differences.push({ position: i, type: "deletion", bases });
|
|
125530
|
+
} else if (!templateIsGap) {
|
|
125531
|
+
const uniqueBases = /* @__PURE__ */ new Set([templateBase, ...alignedBases]);
|
|
125532
|
+
if (uniqueBases.size > 1) {
|
|
125533
|
+
differences.push({ position: i, type: "mismatch", bases });
|
|
125534
|
+
}
|
|
125535
|
+
}
|
|
125536
|
+
}
|
|
125537
|
+
return differences;
|
|
125538
|
+
}
|
|
125539
|
+
__name(findAlignmentDifferences, "findAlignmentDifferences");
|
|
125540
|
+
function scrollToAlignmentSelection() {
|
|
125541
|
+
const el = document.querySelector(".veCaret");
|
|
125542
|
+
if (el) {
|
|
125543
|
+
el.scrollIntoView({ inline: "center", block: "nearest" });
|
|
125544
|
+
}
|
|
125545
|
+
}
|
|
125546
|
+
__name(scrollToAlignmentSelection, "scrollToAlignmentSelection");
|
|
125547
|
+
function updateCaretPosition({ start: start2, end: end2 }) {
|
|
125548
|
+
if (window.updateAlignmentSelection) {
|
|
125549
|
+
window.updateAlignmentSelection({ start: start2, end: end2 });
|
|
125550
|
+
}
|
|
125551
|
+
}
|
|
125552
|
+
__name(updateCaretPosition, "updateCaretPosition");
|
|
125553
|
+
const FILTER_OPTIONS = [
|
|
125554
|
+
{ value: "all", label: "All" },
|
|
125555
|
+
{ value: "mismatch", label: "Mismatches" },
|
|
125556
|
+
{ value: "insertion", label: "Insertions" },
|
|
125557
|
+
{ value: "deletion", label: "Deletions" },
|
|
125558
|
+
{ value: "gap", label: "Gaps" }
|
|
125559
|
+
];
|
|
125560
|
+
function FindMismatches(props) {
|
|
125561
|
+
var _a2;
|
|
125562
|
+
const { alignmentJson, id: id2, onFilterChange } = props;
|
|
125563
|
+
const alignedSeqs = useMemo$1(
|
|
125564
|
+
() => alignmentJson.map((t2) => {
|
|
125565
|
+
var _a3;
|
|
125566
|
+
return ((_a3 = t2.alignmentData) == null ? void 0 : _a3.sequence) || "";
|
|
125567
|
+
}),
|
|
125568
|
+
[alignmentJson]
|
|
125569
|
+
);
|
|
125570
|
+
const [activeFilter, setActiveFilter] = React__default.useState("all");
|
|
125571
|
+
const allDifferences = useMemo$1(
|
|
125572
|
+
() => groupConsecutiveDifferences(findAlignmentDifferences(alignedSeqs)),
|
|
125573
|
+
[alignedSeqs]
|
|
125574
|
+
);
|
|
125575
|
+
const countsByType = useMemo$1(() => {
|
|
125576
|
+
const counts = { all: 0, mismatch: 0, insertion: 0, deletion: 0, gap: 0 };
|
|
125577
|
+
allDifferences.forEach((d2) => {
|
|
125578
|
+
counts[d2.type] = (counts[d2.type] || 0) + 1;
|
|
125579
|
+
counts.all++;
|
|
125580
|
+
});
|
|
125581
|
+
return counts;
|
|
125582
|
+
}, [allDifferences]);
|
|
125583
|
+
const differences = useMemo$1(() => {
|
|
125584
|
+
const filtered = activeFilter === "all" ? allDifferences : allDifferences.filter((d2) => d2.type === activeFilter);
|
|
125585
|
+
return [{ position: -1, start: -1, end: -1, bases: [""] }, ...filtered];
|
|
125586
|
+
}, [allDifferences, activeFilter]);
|
|
125587
|
+
const currentCaretPosition = useSelector(
|
|
125588
|
+
(state2) => {
|
|
125589
|
+
var _a3;
|
|
125590
|
+
return (_a3 = state2.VectorEditor.__allEditorsOptions.alignments[id2]) == null ? void 0 : _a3.caretPosition;
|
|
125591
|
+
}
|
|
125592
|
+
);
|
|
125593
|
+
const [currentIdx, setCurrentIdx] = React__default.useState(0);
|
|
125594
|
+
const currentDiff = differences[currentIdx];
|
|
125595
|
+
const disablePrev = currentIdx <= 1;
|
|
125596
|
+
const disableNext = currentIdx >= differences.length - 1;
|
|
125597
|
+
useEffect(() => {
|
|
125598
|
+
setCurrentIdx(0);
|
|
125599
|
+
}, [activeFilter]);
|
|
125600
|
+
useEffect(() => {
|
|
125601
|
+
onFilterChange == null ? void 0 : onFilterChange({ activeFilter });
|
|
125602
|
+
}, [activeFilter, onFilterChange]);
|
|
125603
|
+
useEffect(() => {
|
|
125604
|
+
if (currentCaretPosition !== -1) {
|
|
125605
|
+
const diffIdx = differences.findIndex(
|
|
125606
|
+
(d2, i) => i > 0 && currentCaretPosition >= d2.start && currentCaretPosition <= d2.end + 1
|
|
125607
|
+
);
|
|
125608
|
+
if (diffIdx !== -1 && diffIdx !== currentIdx) {
|
|
125609
|
+
setCurrentIdx(diffIdx);
|
|
125610
|
+
}
|
|
125611
|
+
}
|
|
125612
|
+
}, [currentCaretPosition, differences, currentIdx]);
|
|
125613
|
+
const updateView = /* @__PURE__ */ __name((diff) => {
|
|
125614
|
+
const idx = differences.indexOf(diff);
|
|
125615
|
+
const { start: start2, end: end2 } = diff;
|
|
125616
|
+
setCurrentIdx(idx);
|
|
125617
|
+
updateCaretPosition({ start: start2, end: end2 });
|
|
125618
|
+
setTimeout(() => {
|
|
125619
|
+
scrollToAlignmentSelection();
|
|
125620
|
+
}, 0);
|
|
125621
|
+
}, "updateView");
|
|
125622
|
+
const prevDifference = /* @__PURE__ */ __name(() => {
|
|
125623
|
+
var _a3, _b2;
|
|
125624
|
+
const pivot = currentCaretPosition >= 0 ? currentCaretPosition : (_b2 = (_a3 = differences[currentIdx]) == null ? void 0 : _a3.start) != null ? _b2 : 0;
|
|
125625
|
+
const prev = [...differences].reverse().find((d2) => d2.start >= 0 && d2.start < pivot);
|
|
125626
|
+
if (prev) updateView(prev);
|
|
125627
|
+
}, "prevDifference");
|
|
125628
|
+
const nextDifference = /* @__PURE__ */ __name(() => {
|
|
125629
|
+
var _a3, _b2;
|
|
125630
|
+
const pivot = currentCaretPosition >= 0 ? currentCaretPosition : (_b2 = (_a3 = differences[currentIdx]) == null ? void 0 : _a3.start) != null ? _b2 : -1;
|
|
125631
|
+
const next = differences.find((d2) => d2.start > pivot && d2.start >= 0);
|
|
125632
|
+
if (next) updateView(next);
|
|
125633
|
+
}, "nextDifference");
|
|
125634
|
+
const noDifferences = differences.length <= 1;
|
|
125635
|
+
const activeOption = FILTER_OPTIONS.find((o2) => o2.value === activeFilter);
|
|
125636
|
+
const activeLabel = (_a2 = activeOption == null ? void 0 : activeOption.label) != null ? _a2 : "Differences";
|
|
125637
|
+
const filterMenu = /* @__PURE__ */ React__default.createElement(Menu, null, FILTER_OPTIONS.map(({ value, label }) => {
|
|
125638
|
+
var _a3;
|
|
125639
|
+
const count2 = (_a3 = countsByType[value]) != null ? _a3 : 0;
|
|
125640
|
+
const isActive2 = activeFilter === value;
|
|
125641
|
+
return /* @__PURE__ */ React__default.createElement(
|
|
125642
|
+
MenuItem,
|
|
125643
|
+
{
|
|
125644
|
+
key: value,
|
|
125645
|
+
active: isActive2,
|
|
125646
|
+
onClick: /* @__PURE__ */ __name(() => setActiveFilter(value), "onClick"),
|
|
125647
|
+
text: /* @__PURE__ */ React__default.createElement("span", { className: "veDiffMenuItem-inner" }, label, /* @__PURE__ */ React__default.createElement(Tag, { round: true, minimal: true, style: { marginLeft: 6 } }, count2))
|
|
125648
|
+
}
|
|
125649
|
+
);
|
|
125650
|
+
}));
|
|
125651
|
+
return /* @__PURE__ */ React__default.createElement("div", { className: "veDiffNavigator" }, /* @__PURE__ */ React__default.createElement(
|
|
125652
|
+
Popover,
|
|
125653
|
+
{
|
|
125654
|
+
minimal: true,
|
|
125655
|
+
position: Position.BOTTOM_LEFT,
|
|
125656
|
+
content: filterMenu,
|
|
125657
|
+
target: /* @__PURE__ */ React__default.createElement(
|
|
125658
|
+
Button,
|
|
125659
|
+
{
|
|
125660
|
+
minimal: true,
|
|
125661
|
+
"data-tip": "Filter Difference Type",
|
|
125662
|
+
small: true,
|
|
125663
|
+
rightIcon: "caret-down",
|
|
125664
|
+
className: "veDiffFilter-trigger"
|
|
125665
|
+
},
|
|
125666
|
+
activeLabel
|
|
125667
|
+
)
|
|
125668
|
+
}
|
|
125669
|
+
), noDifferences ? /* @__PURE__ */ React__default.createElement("span", { className: "veDiffNav-empty" }, "no", " ", activeFilter === "all" ? "differences" : activeLabel.toLowerCase()) : /* @__PURE__ */ React__default.createElement("div", { className: "veDiffNav" }, /* @__PURE__ */ React__default.createElement(
|
|
125670
|
+
Button,
|
|
125671
|
+
{
|
|
125672
|
+
minimal: true,
|
|
125673
|
+
small: true,
|
|
125674
|
+
"data-tip": "Previous Difference",
|
|
125675
|
+
icon: "arrow-left",
|
|
125676
|
+
intent: Intent.PRIMARY,
|
|
125677
|
+
onClick: prevDifference,
|
|
125678
|
+
disabled: disablePrev
|
|
125679
|
+
}
|
|
125680
|
+
), /* @__PURE__ */ React__default.createElement("div", { className: "veDiffNav-center" }, /* @__PURE__ */ React__default.createElement("span", { className: "veDiffNav-fraction" }, currentIdx, /* @__PURE__ */ React__default.createElement("span", { className: "veDiffNav-sep" }, "/"), differences.length - 1), (currentDiff == null ? void 0 : currentDiff.start) > -1 && /* @__PURE__ */ React__default.createElement("span", { className: "veDiffNav-pos" }, ":", currentDiff.start + 1)), /* @__PURE__ */ React__default.createElement(
|
|
125681
|
+
Button,
|
|
125682
|
+
{
|
|
125683
|
+
minimal: true,
|
|
125684
|
+
small: true,
|
|
125685
|
+
"data-tip": "Next Difference",
|
|
125686
|
+
icon: "arrow-right",
|
|
125687
|
+
intent: Intent.PRIMARY,
|
|
125688
|
+
onClick: nextDifference,
|
|
125689
|
+
disabled: disableNext
|
|
125690
|
+
}
|
|
125691
|
+
)));
|
|
125692
|
+
}
|
|
125693
|
+
__name(FindMismatches, "FindMismatches");
|
|
125694
|
+
function getGapMap(sequence2) {
|
|
125695
|
+
const gapMap = [0];
|
|
125696
|
+
sequence2.split("").forEach((char) => {
|
|
125697
|
+
if (char === "-") {
|
|
125698
|
+
gapMap[Math.max(0, gapMap.length - 1)] = (gapMap[Math.max(0, gapMap.length - 1)] || 0) + 1;
|
|
125699
|
+
} else {
|
|
125700
|
+
gapMap.push(gapMap[gapMap.length - 1] || 0);
|
|
125701
|
+
}
|
|
125702
|
+
});
|
|
125703
|
+
return gapMap;
|
|
125704
|
+
}
|
|
125705
|
+
__name(getGapMap, "getGapMap");
|
|
125706
|
+
const MATCH_COLOR = "gold";
|
|
125707
|
+
const CURRENT_MATCH_COLOR = "green";
|
|
125708
|
+
const MISMATCH_COLOR = "red";
|
|
125709
|
+
const ANNOTATION_TYPES = ["features", "parts", "primers"];
|
|
125710
|
+
const initialSearchState = {
|
|
125711
|
+
searchText: "",
|
|
125712
|
+
matches: [],
|
|
125713
|
+
currentMatchIndex: 0,
|
|
125714
|
+
searched: false,
|
|
125715
|
+
featureMatches: [],
|
|
125716
|
+
dnaOrAA: "DNA",
|
|
125717
|
+
ambiguousOrLiteral: "LITERAL",
|
|
125718
|
+
mismatchesAllowed: 0
|
|
125719
|
+
};
|
|
125720
|
+
function searchReducer(state2, action2) {
|
|
125721
|
+
switch (action2.type) {
|
|
125722
|
+
case "SET_SEARCH_TEXT":
|
|
125723
|
+
return __spreadProps(__spreadValues({}, state2), { searchText: action2.payload });
|
|
125724
|
+
case "SET_MATCHES":
|
|
125725
|
+
return __spreadProps(__spreadValues({}, state2), {
|
|
125726
|
+
matches: action2.payload.matches,
|
|
125727
|
+
currentMatchIndex: action2.payload.currentMatchIndex
|
|
125728
|
+
});
|
|
125729
|
+
case "SET_CURRENT_MATCH_INDEX":
|
|
125730
|
+
return __spreadProps(__spreadValues({}, state2), { currentMatchIndex: action2.payload });
|
|
125731
|
+
case "SET_SEARCHED":
|
|
125732
|
+
return __spreadProps(__spreadValues({}, state2), { searched: action2.payload });
|
|
125733
|
+
case "SEARCH_COMPLETE":
|
|
125734
|
+
return __spreadProps(__spreadValues({}, state2), {
|
|
125735
|
+
matches: action2.payload.matches,
|
|
125736
|
+
currentMatchIndex: action2.payload.currentMatchIndex,
|
|
125737
|
+
searched: action2.payload.searched
|
|
125738
|
+
});
|
|
125739
|
+
case "SET_FEATURE_MATCHES":
|
|
125740
|
+
return __spreadProps(__spreadValues({}, state2), { featureMatches: action2.payload });
|
|
125741
|
+
case "SET_DNA_OR_AA":
|
|
125742
|
+
return __spreadProps(__spreadValues({}, state2), { dnaOrAA: action2.payload });
|
|
125743
|
+
case "SET_AMBIGUOUS_OR_LITERAL":
|
|
125744
|
+
return __spreadProps(__spreadValues({}, state2), { ambiguousOrLiteral: action2.payload });
|
|
125745
|
+
case "SET_MISMATCHES_ALLOWED":
|
|
125746
|
+
return __spreadProps(__spreadValues({}, state2), { mismatchesAllowed: Math.max(0, action2.payload) });
|
|
125747
|
+
case "RESET":
|
|
125748
|
+
return __spreadValues({}, initialSearchState);
|
|
125749
|
+
default:
|
|
125750
|
+
return state2;
|
|
125751
|
+
}
|
|
125752
|
+
}
|
|
125753
|
+
__name(searchReducer, "searchReducer");
|
|
125754
|
+
function AlignmentSearchBar(props) {
|
|
125755
|
+
const { alignmentTracks = [], setSearchMatchLayers } = props;
|
|
125756
|
+
const [searchState, dispatch] = useReducer(searchReducer, initialSearchState);
|
|
125757
|
+
const {
|
|
125758
|
+
searchText,
|
|
125759
|
+
matches,
|
|
125760
|
+
currentMatchIndex,
|
|
125761
|
+
searched,
|
|
125762
|
+
featureMatches,
|
|
125763
|
+
dnaOrAA,
|
|
125764
|
+
ambiguousOrLiteral,
|
|
125765
|
+
mismatchesAllowed
|
|
125766
|
+
} = searchState;
|
|
125767
|
+
const debouncedSearch = useRef(
|
|
125768
|
+
debounce$1((text2, search2, featureSearch) => {
|
|
125769
|
+
search2(text2);
|
|
125770
|
+
featureSearch(text2);
|
|
125771
|
+
}, 50)
|
|
125772
|
+
).current;
|
|
125773
|
+
useEffect(() => {
|
|
125774
|
+
return () => {
|
|
125775
|
+
debouncedSearch.cancel();
|
|
125776
|
+
};
|
|
125777
|
+
}, [debouncedSearch]);
|
|
125778
|
+
const [highlightAll, setHighlightAll] = useState(false);
|
|
125779
|
+
const [isExpanded, setIsExpanded] = useState(false);
|
|
125780
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
125781
|
+
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
|
125782
|
+
const handleToggleExpanded = useCallback$1(() => {
|
|
125783
|
+
setIsExpanded((prev) => {
|
|
125784
|
+
const next = !prev;
|
|
125785
|
+
if (!next) setIsPopoverOpen(true);
|
|
125786
|
+
return next;
|
|
125787
|
+
});
|
|
125788
|
+
}, [setIsPopoverOpen]);
|
|
125789
|
+
useEffect(() => {
|
|
125790
|
+
dispatch({ type: "RESET" });
|
|
125791
|
+
if (setSearchMatchLayers) setSearchMatchLayers([]);
|
|
125792
|
+
}, [setSearchMatchLayers]);
|
|
125793
|
+
const buildMatchLayers = useCallback$1(
|
|
125794
|
+
(allMatches, activeIndex) => {
|
|
125795
|
+
if (!setSearchMatchLayers) return;
|
|
125796
|
+
if (!allMatches.length) {
|
|
125797
|
+
setSearchMatchLayers([]);
|
|
125798
|
+
return;
|
|
125799
|
+
}
|
|
125800
|
+
const makeMismatchLayers = /* @__PURE__ */ __name((match) => (match.mismatchAlignmentPositions || []).map((pos) => ({
|
|
125801
|
+
start: pos,
|
|
125802
|
+
end: pos,
|
|
125803
|
+
color: MISMATCH_COLOR,
|
|
125804
|
+
className: "veSearchMismatch",
|
|
125805
|
+
ignoreGaps: true,
|
|
125806
|
+
hideCarets: true
|
|
125807
|
+
})), "makeMismatchLayers");
|
|
125808
|
+
const layers = highlightAll ? allMatches.flatMap((match, i) => [
|
|
125809
|
+
{
|
|
125810
|
+
start: match.alignmentStart,
|
|
125811
|
+
end: match.alignmentEnd,
|
|
125812
|
+
color: i === activeIndex ? CURRENT_MATCH_COLOR : MATCH_COLOR,
|
|
125813
|
+
className: i === activeIndex ? "veSearchLayerActive" : "veSearchLayer",
|
|
125814
|
+
ignoreGaps: true
|
|
125815
|
+
},
|
|
125816
|
+
...makeMismatchLayers(match)
|
|
125817
|
+
]) : [
|
|
125818
|
+
{
|
|
125819
|
+
start: allMatches[activeIndex].alignmentStart,
|
|
125820
|
+
end: allMatches[activeIndex].alignmentEnd,
|
|
125821
|
+
color: CURRENT_MATCH_COLOR,
|
|
125822
|
+
className: "veSearchLayerActive",
|
|
125823
|
+
ignoreGaps: true
|
|
125824
|
+
},
|
|
125825
|
+
...makeMismatchLayers(allMatches[activeIndex])
|
|
125826
|
+
];
|
|
125827
|
+
setSearchMatchLayers(layers);
|
|
125828
|
+
},
|
|
125829
|
+
[setSearchMatchLayers, highlightAll]
|
|
125830
|
+
);
|
|
125831
|
+
const navigateTo = useCallback$1(
|
|
125832
|
+
(allMatches, index2) => {
|
|
125833
|
+
const match = allMatches[index2];
|
|
125834
|
+
if (!match) return;
|
|
125835
|
+
updateCaretPosition({
|
|
125836
|
+
start: match.alignmentStart,
|
|
125837
|
+
end: match.alignmentEnd
|
|
125838
|
+
});
|
|
125839
|
+
setTimeout(() => {
|
|
125840
|
+
scrollToAlignmentSelection();
|
|
125841
|
+
}, 0);
|
|
125842
|
+
buildMatchLayers(allMatches, index2);
|
|
125843
|
+
},
|
|
125844
|
+
[buildMatchLayers]
|
|
125845
|
+
);
|
|
125846
|
+
const runSearch = useCallback$1(
|
|
125847
|
+
(text2) => {
|
|
125848
|
+
const query = text2.trim();
|
|
125849
|
+
if (!query) {
|
|
125850
|
+
dispatch({
|
|
125851
|
+
type: "SEARCH_COMPLETE",
|
|
125852
|
+
payload: { matches: [], currentMatchIndex: 0, searched: false }
|
|
125853
|
+
});
|
|
125854
|
+
if (setSearchMatchLayers) setSearchMatchLayers([]);
|
|
125855
|
+
return;
|
|
125856
|
+
}
|
|
125857
|
+
const allMatches = [];
|
|
125858
|
+
alignmentTracks.slice(0, 1).forEach((track, trackIndex) => {
|
|
125859
|
+
var _a2, _b2;
|
|
125860
|
+
const rawSeq = ((_a2 = track.sequenceData) == null ? void 0 : _a2.sequence) || "";
|
|
125861
|
+
const alignedSeq = ((_b2 = track.alignmentData) == null ? void 0 : _b2.sequence) || "";
|
|
125862
|
+
const gapMap = getGapMap(alignedSeq);
|
|
125863
|
+
const gapOffset = /* @__PURE__ */ __name((n2) => {
|
|
125864
|
+
var _a3, _b3;
|
|
125865
|
+
return (_b3 = (_a3 = gapMap[n2]) != null ? _a3 : gapMap[gapMap.length - 1]) != null ? _b3 : 0;
|
|
125866
|
+
}, "gapOffset");
|
|
125867
|
+
let seqMatches = [];
|
|
125868
|
+
if (dnaOrAA === "DNA" && ambiguousOrLiteral === "LITERAL" && mismatchesAllowed > 0) {
|
|
125869
|
+
const approxMatches = findApproxMatches(
|
|
125870
|
+
query.toLowerCase(),
|
|
125871
|
+
rawSeq.toLowerCase(),
|
|
125872
|
+
mismatchesAllowed,
|
|
125873
|
+
false
|
|
125874
|
+
);
|
|
125875
|
+
seqMatches = approxMatches.map((m2) => ({
|
|
125876
|
+
start: m2.index,
|
|
125877
|
+
end: m2.index + m2.match.length - 1,
|
|
125878
|
+
mismatchPositions: m2.mismatchPositions
|
|
125879
|
+
}));
|
|
125880
|
+
} else {
|
|
125881
|
+
seqMatches = findSequenceMatches(rawSeq, query, {
|
|
125882
|
+
isCircular: false,
|
|
125883
|
+
isAmbiguous: ambiguousOrLiteral === "AMBIGUOUS",
|
|
125884
|
+
isProteinSearch: dnaOrAA !== "DNA",
|
|
125885
|
+
searchReverseStrand: dnaOrAA === "DNA"
|
|
125886
|
+
});
|
|
125887
|
+
}
|
|
125888
|
+
const hitsToProcess = query.length < 2 ? seqMatches.slice(0, 1) : seqMatches;
|
|
125889
|
+
hitsToProcess.forEach(({ start: start2, end: end2, mismatchPositions }) => {
|
|
125890
|
+
const alignmentStart = start2 + gapOffset(start2);
|
|
125891
|
+
const alignmentEnd = end2 + gapOffset(end2);
|
|
125892
|
+
const mismatchAlignmentPositions = (mismatchPositions || []).map(
|
|
125893
|
+
(p2) => {
|
|
125894
|
+
const absPos = start2 + p2;
|
|
125895
|
+
return absPos + gapOffset(absPos);
|
|
125896
|
+
}
|
|
125897
|
+
);
|
|
125898
|
+
allMatches.push({
|
|
125899
|
+
trackIndex,
|
|
125900
|
+
alignmentStart,
|
|
125901
|
+
alignmentEnd,
|
|
125902
|
+
mismatchAlignmentPositions
|
|
125903
|
+
});
|
|
125904
|
+
});
|
|
125905
|
+
});
|
|
125906
|
+
const results = query.length < 2 ? allMatches.slice(0, 1) : allMatches;
|
|
125907
|
+
dispatch({
|
|
125908
|
+
type: "SEARCH_COMPLETE",
|
|
125909
|
+
payload: { matches: results, currentMatchIndex: 0, searched: true }
|
|
125910
|
+
});
|
|
125911
|
+
if (results.length) {
|
|
125912
|
+
navigateTo(results, 0);
|
|
125913
|
+
} else {
|
|
125914
|
+
if (setSearchMatchLayers) setSearchMatchLayers([]);
|
|
125915
|
+
}
|
|
125916
|
+
},
|
|
125917
|
+
[
|
|
125918
|
+
alignmentTracks,
|
|
125919
|
+
navigateTo,
|
|
125920
|
+
dnaOrAA,
|
|
125921
|
+
ambiguousOrLiteral,
|
|
125922
|
+
mismatchesAllowed,
|
|
125923
|
+
setSearchMatchLayers
|
|
125924
|
+
]
|
|
125925
|
+
);
|
|
125926
|
+
const runFeatureSearch = useCallback$1(
|
|
125927
|
+
(text2) => {
|
|
125928
|
+
const query = text2.trim().toLowerCase();
|
|
125929
|
+
if (!query) {
|
|
125930
|
+
dispatch({ type: "SET_FEATURE_MATCHES", payload: [] });
|
|
125931
|
+
return;
|
|
125932
|
+
}
|
|
125933
|
+
const allMatches = [];
|
|
125934
|
+
alignmentTracks.slice(0, 1).forEach((track, trackIndex) => {
|
|
125935
|
+
const { sequenceData: sequenceData2, alignmentData } = track;
|
|
125936
|
+
const alignedSeq = (alignmentData == null ? void 0 : alignmentData.sequence) || "";
|
|
125937
|
+
const gapMap = getGapMap(alignedSeq);
|
|
125938
|
+
const gapOffset = /* @__PURE__ */ __name((n2) => {
|
|
125939
|
+
var _a2, _b2;
|
|
125940
|
+
return (_b2 = (_a2 = gapMap[n2]) != null ? _a2 : gapMap[gapMap.length - 1]) != null ? _b2 : 0;
|
|
125941
|
+
}, "gapOffset");
|
|
125942
|
+
const trackName = (alignmentData == null ? void 0 : alignmentData.name) || (sequenceData2 == null ? void 0 : sequenceData2.name) || (sequenceData2 == null ? void 0 : sequenceData2.id) || "";
|
|
125943
|
+
ANNOTATION_TYPES.forEach((type2) => {
|
|
125944
|
+
const anns = sequenceData2 == null ? void 0 : sequenceData2[type2];
|
|
125945
|
+
if (!anns) return;
|
|
125946
|
+
const annsArray = Array.isArray(anns) ? anns : Object.values(anns);
|
|
125947
|
+
annsArray.forEach((ann) => {
|
|
125948
|
+
if (!ann.name) return;
|
|
125949
|
+
if (ann.name.toLowerCase().includes(query)) {
|
|
125950
|
+
const alignmentStart = ann.start + gapOffset(ann.start);
|
|
125951
|
+
const alignmentEnd = ann.end + gapOffset(ann.end);
|
|
125952
|
+
allMatches.push({
|
|
125953
|
+
trackIndex,
|
|
125954
|
+
trackName,
|
|
125955
|
+
type: type2,
|
|
125956
|
+
annotation: ann,
|
|
125957
|
+
alignmentStart,
|
|
125958
|
+
alignmentEnd
|
|
125959
|
+
});
|
|
125960
|
+
}
|
|
125961
|
+
});
|
|
125962
|
+
});
|
|
125963
|
+
});
|
|
125964
|
+
dispatch({ type: "SET_FEATURE_MATCHES", payload: allMatches });
|
|
125965
|
+
},
|
|
125966
|
+
[alignmentTracks]
|
|
125967
|
+
);
|
|
125968
|
+
const goToPrev = useCallback$1(() => {
|
|
125969
|
+
if (!matches.length) return;
|
|
125970
|
+
const newIndex = currentMatchIndex === 0 ? matches.length - 1 : currentMatchIndex - 1;
|
|
125971
|
+
dispatch({ type: "SET_CURRENT_MATCH_INDEX", payload: newIndex });
|
|
125972
|
+
navigateTo(matches, newIndex);
|
|
125973
|
+
}, [matches, currentMatchIndex, navigateTo]);
|
|
125974
|
+
const goToNext = useCallback$1(() => {
|
|
125975
|
+
if (!matches.length) return;
|
|
125976
|
+
const newIndex = currentMatchIndex === matches.length - 1 ? 0 : currentMatchIndex + 1;
|
|
125977
|
+
dispatch({ type: "SET_CURRENT_MATCH_INDEX", payload: newIndex });
|
|
125978
|
+
navigateTo(matches, newIndex);
|
|
125979
|
+
}, [matches, currentMatchIndex, navigateTo]);
|
|
125980
|
+
const handleKeyDown = useCallback$1(
|
|
125981
|
+
(e) => {
|
|
125982
|
+
if (e.key === "Escape") {
|
|
125983
|
+
setIsOpen(false);
|
|
125984
|
+
}
|
|
125985
|
+
if (e.key === "Enter") {
|
|
125986
|
+
if (e.shiftKey) {
|
|
125987
|
+
goToPrev();
|
|
125988
|
+
} else {
|
|
125989
|
+
goToNext();
|
|
125990
|
+
}
|
|
125991
|
+
e.preventDefault();
|
|
125992
|
+
e.stopPropagation();
|
|
125993
|
+
}
|
|
125994
|
+
},
|
|
125995
|
+
[goToPrev, goToNext]
|
|
125996
|
+
);
|
|
125997
|
+
useEffect(() => {
|
|
125998
|
+
if (!searched || !searchText.trim()) return;
|
|
125999
|
+
runSearch(searchText);
|
|
126000
|
+
runFeatureSearch(searchText);
|
|
126001
|
+
}, [
|
|
126002
|
+
dnaOrAA,
|
|
126003
|
+
ambiguousOrLiteral,
|
|
126004
|
+
mismatchesAllowed,
|
|
126005
|
+
runSearch,
|
|
126006
|
+
runFeatureSearch,
|
|
126007
|
+
searched,
|
|
126008
|
+
searchText
|
|
126009
|
+
]);
|
|
126010
|
+
useEffect(() => {
|
|
126011
|
+
if (searchText.trim().length < 1) setHighlightAll(false);
|
|
126012
|
+
}, [searchText]);
|
|
126013
|
+
const prevHighlightAll = useRef(highlightAll);
|
|
126014
|
+
useEffect(() => {
|
|
126015
|
+
if (prevHighlightAll.current !== highlightAll) {
|
|
126016
|
+
prevHighlightAll.current = highlightAll;
|
|
126017
|
+
if (matches.length) buildMatchLayers(matches, currentMatchIndex);
|
|
126018
|
+
}
|
|
126019
|
+
}, [highlightAll, matches, currentMatchIndex, buildMatchLayers]);
|
|
126020
|
+
const hasMatches = matches.length > 0;
|
|
126021
|
+
const handleChange = useCallback$1(
|
|
126022
|
+
(e) => {
|
|
126023
|
+
const value = e.target.value;
|
|
126024
|
+
dispatch({ type: "SET_SEARCH_TEXT", payload: value });
|
|
126025
|
+
debouncedSearch(value, runSearch, runFeatureSearch);
|
|
126026
|
+
},
|
|
126027
|
+
[debouncedSearch, runSearch, runFeatureSearch]
|
|
126028
|
+
);
|
|
126029
|
+
const handleFeatureClick = useCallback$1((featureMatch) => {
|
|
126030
|
+
updateCaretPosition({
|
|
126031
|
+
start: featureMatch.alignmentStart,
|
|
126032
|
+
end: featureMatch.alignmentEnd
|
|
126033
|
+
});
|
|
126034
|
+
setTimeout(() => {
|
|
126035
|
+
scrollToAlignmentSelection();
|
|
126036
|
+
}, 0);
|
|
126037
|
+
}, []);
|
|
126038
|
+
const matchCounter = /* @__PURE__ */ React__default.createElement(
|
|
126039
|
+
"span",
|
|
126040
|
+
{
|
|
126041
|
+
style: {
|
|
126042
|
+
marginRight: 3,
|
|
126043
|
+
color: "lightgrey",
|
|
126044
|
+
fontSize: "0.9em",
|
|
126045
|
+
whiteSpace: "nowrap"
|
|
126046
|
+
}
|
|
126047
|
+
},
|
|
126048
|
+
hasMatches ? currentMatchIndex + 1 : 0,
|
|
126049
|
+
"/",
|
|
126050
|
+
matches.length
|
|
126051
|
+
);
|
|
126052
|
+
const inlineNavEl = /* @__PURE__ */ React__default.createElement("span", { style: { display: "flex", alignItems: "center" } }, !isExpanded && /* @__PURE__ */ React__default.createElement(
|
|
126053
|
+
Popover,
|
|
126054
|
+
{
|
|
126055
|
+
autoFocus: false,
|
|
126056
|
+
enforceFocus: false,
|
|
126057
|
+
isOpen: isPopoverOpen,
|
|
126058
|
+
onInteraction: setIsPopoverOpen,
|
|
126059
|
+
position: Position.TOP,
|
|
126060
|
+
content: /* @__PURE__ */ React__default.createElement(
|
|
126061
|
+
"div",
|
|
126062
|
+
{
|
|
126063
|
+
className: "ve-find-options-popover",
|
|
126064
|
+
style: {
|
|
126065
|
+
display: "flex",
|
|
126066
|
+
flexDirection: "column",
|
|
126067
|
+
paddingLeft: 20,
|
|
126068
|
+
paddingBottom: 10,
|
|
126069
|
+
paddingTop: 10,
|
|
126070
|
+
paddingRight: 20,
|
|
126071
|
+
gap: 6
|
|
126072
|
+
}
|
|
126073
|
+
},
|
|
126074
|
+
/* @__PURE__ */ React__default.createElement(
|
|
126075
|
+
FindOptionsPanel,
|
|
126076
|
+
{
|
|
126077
|
+
dnaOrAA,
|
|
126078
|
+
ambiguousOrLiteral,
|
|
126079
|
+
mismatchesAllowed,
|
|
126080
|
+
searchText,
|
|
126081
|
+
matches,
|
|
126082
|
+
dispatch,
|
|
126083
|
+
highlightAll,
|
|
126084
|
+
setHighlightAll,
|
|
126085
|
+
isExpanded,
|
|
126086
|
+
onToggleExpanded: handleToggleExpanded
|
|
126087
|
+
}
|
|
126088
|
+
)
|
|
126089
|
+
),
|
|
126090
|
+
target: /* @__PURE__ */ React__default.createElement(Button, { minimal: true, icon: "wrench", "data-tip": "Options" })
|
|
126091
|
+
}
|
|
126092
|
+
), matchCounter, /* @__PURE__ */ React__default.createElement(
|
|
126093
|
+
Button,
|
|
126094
|
+
{
|
|
126095
|
+
minimal: true,
|
|
126096
|
+
small: true,
|
|
126097
|
+
icon: "caret-left",
|
|
126098
|
+
"data-tip": "Previous",
|
|
126099
|
+
disabled: !hasMatches,
|
|
126100
|
+
onClick: goToPrev
|
|
126101
|
+
}
|
|
126102
|
+
), /* @__PURE__ */ React__default.createElement(
|
|
126103
|
+
Button,
|
|
126104
|
+
{
|
|
126105
|
+
minimal: true,
|
|
126106
|
+
small: true,
|
|
126107
|
+
icon: "caret-right",
|
|
126108
|
+
"data-tip": "Next",
|
|
126109
|
+
disabled: !hasMatches,
|
|
126110
|
+
onClick: goToNext
|
|
126111
|
+
}
|
|
126112
|
+
), /* @__PURE__ */ React__default.createElement(
|
|
126113
|
+
Button,
|
|
126114
|
+
{
|
|
126115
|
+
minimal: true,
|
|
126116
|
+
small: true,
|
|
126117
|
+
"data-tip": "Close (Esc)",
|
|
126118
|
+
icon: "small-cross",
|
|
126119
|
+
onClick: /* @__PURE__ */ __name(() => setIsOpen(false), "onClick")
|
|
126120
|
+
}
|
|
126121
|
+
));
|
|
126122
|
+
const expandedNavEl = /* @__PURE__ */ React__default.createElement("span", { style: { display: "flex", alignItems: "center" } }, matchCounter, /* @__PURE__ */ React__default.createElement(
|
|
126123
|
+
Button,
|
|
126124
|
+
{
|
|
126125
|
+
minimal: true,
|
|
126126
|
+
small: true,
|
|
126127
|
+
icon: "caret-up",
|
|
126128
|
+
disabled: !hasMatches,
|
|
126129
|
+
onClick: goToPrev
|
|
126130
|
+
}
|
|
126131
|
+
), /* @__PURE__ */ React__default.createElement(
|
|
126132
|
+
Button,
|
|
126133
|
+
{
|
|
126134
|
+
minimal: true,
|
|
126135
|
+
small: true,
|
|
126136
|
+
icon: "caret-down",
|
|
126137
|
+
disabled: !hasMatches,
|
|
126138
|
+
onClick: goToNext
|
|
126139
|
+
}
|
|
126140
|
+
));
|
|
126141
|
+
if (!isOpen) {
|
|
126142
|
+
return /* @__PURE__ */ React__default.createElement("div", null, /* @__PURE__ */ React__default.createElement(
|
|
126143
|
+
Button,
|
|
126144
|
+
{
|
|
126145
|
+
minimal: true,
|
|
126146
|
+
small: true,
|
|
126147
|
+
intent: "primary",
|
|
126148
|
+
icon: "search",
|
|
126149
|
+
rightIcon: "caret-right",
|
|
126150
|
+
"data-tip": "Search",
|
|
126151
|
+
onClick: /* @__PURE__ */ __name(() => setIsOpen(true), "onClick")
|
|
126152
|
+
}
|
|
126153
|
+
));
|
|
126154
|
+
}
|
|
126155
|
+
const annotationPopoverOpen = searched && featureMatches.length > 0;
|
|
126156
|
+
const inputEl = /* @__PURE__ */ React__default.createElement(
|
|
126157
|
+
InputGroup,
|
|
126158
|
+
{
|
|
126159
|
+
className: "tg-find-tool-input alignment-search-bar",
|
|
126160
|
+
leftIcon: "search",
|
|
126161
|
+
placeholder: "Search...",
|
|
126162
|
+
autoFocus: true,
|
|
126163
|
+
value: searchText,
|
|
126164
|
+
onChange: handleChange,
|
|
126165
|
+
onKeyDown: handleKeyDown,
|
|
126166
|
+
rightElement: inlineNavEl
|
|
126167
|
+
}
|
|
126168
|
+
);
|
|
126169
|
+
return /* @__PURE__ */ React__default.createElement("div", { style: { position: "relative" } }, !isExpanded && /* @__PURE__ */ React__default.createElement(
|
|
126170
|
+
Popover,
|
|
126171
|
+
{
|
|
126172
|
+
autoFocus: false,
|
|
126173
|
+
enforceFocus: false,
|
|
126174
|
+
modifiers: {
|
|
126175
|
+
arrow: false
|
|
126176
|
+
},
|
|
126177
|
+
position: Position.BOTTOM,
|
|
126178
|
+
isOpen: annotationPopoverOpen,
|
|
126179
|
+
content: /* @__PURE__ */ React__default.createElement(
|
|
126180
|
+
AnnotationResultsComp,
|
|
126181
|
+
{
|
|
126182
|
+
featureMatches,
|
|
126183
|
+
onClickMatch: handleFeatureClick
|
|
126184
|
+
}
|
|
126185
|
+
),
|
|
126186
|
+
target: inputEl
|
|
126187
|
+
}
|
|
126188
|
+
), isExpanded && /* @__PURE__ */ React__default.createElement(
|
|
126189
|
+
"div",
|
|
126190
|
+
{
|
|
126191
|
+
style: {
|
|
126192
|
+
position: "absolute",
|
|
126193
|
+
top: 0,
|
|
126194
|
+
left: 0,
|
|
126195
|
+
padding: 10,
|
|
126196
|
+
paddingBottom: 25,
|
|
126197
|
+
display: "flex",
|
|
126198
|
+
alignItems: "flex-start",
|
|
126199
|
+
gap: 10,
|
|
126200
|
+
zIndex: 5e4,
|
|
126201
|
+
background: "white",
|
|
126202
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.2)",
|
|
126203
|
+
borderRadius: 3
|
|
126204
|
+
}
|
|
126205
|
+
},
|
|
126206
|
+
/* @__PURE__ */ React__default.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 6 } }, /* @__PURE__ */ React__default.createElement(
|
|
126207
|
+
TextArea,
|
|
126208
|
+
{
|
|
126209
|
+
autoFocus: true,
|
|
126210
|
+
placeholder: "Search sequences and annotations...",
|
|
126211
|
+
value: searchText,
|
|
126212
|
+
onChange: handleChange,
|
|
126213
|
+
onKeyDown: handleKeyDown,
|
|
126214
|
+
style: { resize: "vertical", width: 350, height: 190 }
|
|
126215
|
+
}
|
|
126216
|
+
), annotationPopoverOpen && /* @__PURE__ */ React__default.createElement(
|
|
126217
|
+
AnnotationResultsComp,
|
|
126218
|
+
{
|
|
126219
|
+
featureMatches,
|
|
126220
|
+
onClickMatch: handleFeatureClick
|
|
126221
|
+
}
|
|
126222
|
+
)),
|
|
126223
|
+
/* @__PURE__ */ React__default.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 5 } }, expandedNavEl, /* @__PURE__ */ React__default.createElement(
|
|
126224
|
+
FindOptionsPanel,
|
|
126225
|
+
{
|
|
126226
|
+
dnaOrAA,
|
|
126227
|
+
ambiguousOrLiteral,
|
|
126228
|
+
mismatchesAllowed,
|
|
126229
|
+
searchText,
|
|
126230
|
+
matches,
|
|
126231
|
+
dispatch,
|
|
126232
|
+
highlightAll,
|
|
126233
|
+
setHighlightAll,
|
|
126234
|
+
isExpanded,
|
|
126235
|
+
onToggleExpanded: handleToggleExpanded
|
|
126236
|
+
}
|
|
126237
|
+
)),
|
|
126238
|
+
/* @__PURE__ */ React__default.createElement(
|
|
126239
|
+
Button,
|
|
126240
|
+
{
|
|
126241
|
+
minimal: true,
|
|
126242
|
+
style: { position: "absolute", bottom: 0, right: 0 },
|
|
126243
|
+
onClick: /* @__PURE__ */ __name(() => setIsOpen(false), "onClick"),
|
|
126244
|
+
icon: "cross"
|
|
126245
|
+
}
|
|
126246
|
+
)
|
|
126247
|
+
));
|
|
126248
|
+
}
|
|
126249
|
+
__name(AlignmentSearchBar, "AlignmentSearchBar");
|
|
126250
|
+
function AnnotationResultsComp({ featureMatches, onClickMatch }) {
|
|
126251
|
+
const byType = {};
|
|
126252
|
+
ANNOTATION_TYPES.forEach((type2) => {
|
|
126253
|
+
byType[type2] = [];
|
|
126254
|
+
});
|
|
126255
|
+
featureMatches.forEach((match) => {
|
|
126256
|
+
if (byType[match.type]) {
|
|
126257
|
+
byType[match.type].push(match);
|
|
126258
|
+
}
|
|
126259
|
+
});
|
|
126260
|
+
const featureColorMap = getFeatureToColorMap({ includeHidden: true });
|
|
126261
|
+
return /* @__PURE__ */ React__default.createElement("div", { className: "veAnnotationFindMatches" }, ANNOTATION_TYPES.map((type2) => {
|
|
126262
|
+
const anns = byType[type2];
|
|
126263
|
+
if (!anns.length) return null;
|
|
126264
|
+
const showing = anns.slice(0, 10);
|
|
126265
|
+
return /* @__PURE__ */ React__default.createElement("div", { key: type2 }, /* @__PURE__ */ React__default.createElement("div", { className: "veAnnotationFoundType" }, anns.length, " ", getSingular(type2), " match", anns.length > 1 ? "es" : null, anns.length > 10 ? ` (only showing 10)` : null, ":"), /* @__PURE__ */ React__default.createElement("div", null, showing.map((match, i) => {
|
|
126266
|
+
const { annotation } = match;
|
|
126267
|
+
const annotationColor = type2 === "parts" ? "#ac68cc" : annotation.color || featureColorMap[annotation.type];
|
|
126268
|
+
return /* @__PURE__ */ React__default.createElement(
|
|
126269
|
+
"div",
|
|
126270
|
+
{
|
|
126271
|
+
key: i,
|
|
126272
|
+
onClick: /* @__PURE__ */ __name(() => onClickMatch(match), "onClick"),
|
|
126273
|
+
className: "veAnnotationFoundResult"
|
|
126274
|
+
},
|
|
126275
|
+
/* @__PURE__ */ React__default.createElement("div", { style: { display: "flex", alignItems: "center" } }, /* @__PURE__ */ React__default.createElement(
|
|
126276
|
+
"div",
|
|
126277
|
+
{
|
|
126278
|
+
style: {
|
|
126279
|
+
background: annotationColor,
|
|
126280
|
+
height: 15,
|
|
126281
|
+
width: 15,
|
|
126282
|
+
marginRight: 3
|
|
126283
|
+
}
|
|
126284
|
+
}
|
|
126285
|
+
), annotation.name),
|
|
126286
|
+
/* @__PURE__ */ React__default.createElement("div", { className: "veAnnotationFoundResultRange" }, annotation.start + 1, "-", annotation.end + 1)
|
|
126287
|
+
);
|
|
126288
|
+
})));
|
|
126289
|
+
}));
|
|
126290
|
+
}
|
|
126291
|
+
__name(AnnotationResultsComp, "AnnotationResultsComp");
|
|
126292
|
+
function FindOptionsPanel({
|
|
126293
|
+
dnaOrAA,
|
|
126294
|
+
ambiguousOrLiteral,
|
|
126295
|
+
mismatchesAllowed,
|
|
126296
|
+
searchText,
|
|
126297
|
+
matches,
|
|
126298
|
+
dispatch,
|
|
126299
|
+
highlightAll,
|
|
126300
|
+
setHighlightAll,
|
|
126301
|
+
isExpanded,
|
|
126302
|
+
onToggleExpanded
|
|
126303
|
+
}) {
|
|
126304
|
+
return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(
|
|
126305
|
+
TgHTMLSelect,
|
|
126306
|
+
{
|
|
126307
|
+
options: [
|
|
126308
|
+
{ label: "DNA", value: "DNA" },
|
|
126309
|
+
{ label: "Amino Acids", value: "AA" }
|
|
126310
|
+
],
|
|
126311
|
+
value: dnaOrAA,
|
|
126312
|
+
onChange: /* @__PURE__ */ __name((e) => dispatch({ type: "SET_DNA_OR_AA", payload: e.target.value }), "onChange")
|
|
126313
|
+
}
|
|
126314
|
+
), /* @__PURE__ */ React__default.createElement("div", { style: { display: "flex" } }, /* @__PURE__ */ React__default.createElement(
|
|
126315
|
+
TgHTMLSelect,
|
|
126316
|
+
{
|
|
126317
|
+
options: [
|
|
126318
|
+
{ label: "Literal", value: "LITERAL" },
|
|
126319
|
+
{ label: "Ambiguous", value: "AMBIGUOUS" }
|
|
126320
|
+
],
|
|
126321
|
+
value: ambiguousOrLiteral,
|
|
126322
|
+
onChange: /* @__PURE__ */ __name((e) => dispatch({
|
|
126323
|
+
type: "SET_AMBIGUOUS_OR_LITERAL",
|
|
126324
|
+
payload: e.target.value
|
|
126325
|
+
}), "onChange")
|
|
126326
|
+
}
|
|
126327
|
+
), /* @__PURE__ */ React__default.createElement(InfoHelper, { style: { marginLeft: 10 } }, /* @__PURE__ */ React__default.createElement("div", null, "Ambiguous substitutions:", /* @__PURE__ */ React__default.createElement("div", { style: { display: "flex", fontSize: 12 } }, /* @__PURE__ */ React__default.createElement("div", { style: { marginRight: 20 } }, /* @__PURE__ */ React__default.createElement("div", { style: { fontSize: 14, marginBottom: 4, marginTop: 5 } }, "DNA:"), /* @__PURE__ */ React__default.createElement("div", null, "M: AC"), /* @__PURE__ */ React__default.createElement("div", null, "R: AG"), /* @__PURE__ */ React__default.createElement("div", null, "W: AT"), /* @__PURE__ */ React__default.createElement("div", null, "S: CG"), /* @__PURE__ */ React__default.createElement("div", null, "Y: CT"), /* @__PURE__ */ React__default.createElement("div", null, "K: GT"), /* @__PURE__ */ React__default.createElement("div", null, "V: ACG"), /* @__PURE__ */ React__default.createElement("div", null, "H: ACT"), /* @__PURE__ */ React__default.createElement("div", null, "D: AGT"), /* @__PURE__ */ React__default.createElement("div", null, "B: CGT"), /* @__PURE__ */ React__default.createElement("div", null, "X: GATC"), /* @__PURE__ */ React__default.createElement("div", null, "N: GATC"), /* @__PURE__ */ React__default.createElement("div", null, "*: any")), /* @__PURE__ */ React__default.createElement("div", null, /* @__PURE__ */ React__default.createElement("div", { style: { fontSize: 14, marginBottom: 4, marginTop: 5 } }, "AA:"), /* @__PURE__ */ React__default.createElement("div", null, "B: ND"), /* @__PURE__ */ React__default.createElement("div", null, "J: IL"), /* @__PURE__ */ React__default.createElement("div", null, "X: ACDEFGHIKLMNPQRSTVWY"), /* @__PURE__ */ React__default.createElement("div", null, "Z: QE"), /* @__PURE__ */ React__default.createElement("div", null, "*: any")))))), /* @__PURE__ */ React__default.createElement(
|
|
126328
|
+
"div",
|
|
126329
|
+
{
|
|
126330
|
+
style: {
|
|
126331
|
+
marginTop: "8px",
|
|
126332
|
+
display: "flex",
|
|
126333
|
+
flexDirection: "row",
|
|
126334
|
+
gap: "3px",
|
|
126335
|
+
alignItems: "center"
|
|
126336
|
+
}
|
|
126337
|
+
},
|
|
126338
|
+
/* @__PURE__ */ React__default.createElement("label", null, "Mismatches Allowed:"),
|
|
126339
|
+
/* @__PURE__ */ React__default.createElement(
|
|
126340
|
+
NumericInput,
|
|
126341
|
+
{
|
|
126342
|
+
min: 0,
|
|
126343
|
+
max: 10,
|
|
126344
|
+
className: "tg-mismatches-allowed-input",
|
|
126345
|
+
style: { width: "60px" },
|
|
126346
|
+
value: mismatchesAllowed,
|
|
126347
|
+
disabled: dnaOrAA !== "DNA" || ambiguousOrLiteral !== "LITERAL",
|
|
126348
|
+
onValueChange: /* @__PURE__ */ __name((value) => dispatch({
|
|
126349
|
+
type: "SET_MISMATCHES_ALLOWED",
|
|
126350
|
+
payload: Number.parseInt(value, 10) || 0
|
|
126351
|
+
}), "onValueChange")
|
|
126352
|
+
}
|
|
126353
|
+
),
|
|
126354
|
+
/* @__PURE__ */ React__default.createElement(InfoHelper, { style: { marginLeft: 10 } }, /* @__PURE__ */ React__default.createElement("div", null, "Number of mismatches allowed when searching DNA sequences with literal matching.", /* @__PURE__ */ React__default.createElement("br", null), /* @__PURE__ */ React__default.createElement("br", null), "Higher values may slow down search performance."))
|
|
126355
|
+
), /* @__PURE__ */ React__default.createElement(
|
|
126356
|
+
Switch,
|
|
126357
|
+
{
|
|
126358
|
+
checked: highlightAll,
|
|
126359
|
+
onChange: /* @__PURE__ */ __name(() => setHighlightAll((v2) => !v2), "onChange"),
|
|
126360
|
+
disabled: searchText.trim().length < 2 || matches.length > MAX_MATCHES_DISPLAYED
|
|
126361
|
+
},
|
|
126362
|
+
/* @__PURE__ */ React__default.createElement(
|
|
126363
|
+
Tooltip,
|
|
126364
|
+
{
|
|
126365
|
+
disabled: matches.length <= MAX_MATCHES_DISPLAYED,
|
|
126366
|
+
content: `Disabled because there are >${MAX_MATCHES_DISPLAYED} matches`
|
|
126367
|
+
},
|
|
126368
|
+
"Highlight All"
|
|
126369
|
+
)
|
|
126370
|
+
), /* @__PURE__ */ React__default.createElement(Switch, { checked: isExpanded, onChange: onToggleExpanded }, "Expanded"));
|
|
126371
|
+
}
|
|
126372
|
+
__name(FindOptionsPanel, "FindOptionsPanel");
|
|
125441
126373
|
const AlignmentVisibilityTool = pure(/* @__PURE__ */ __name(function AlignmentVisibilityTool2(props) {
|
|
125442
126374
|
return /* @__PURE__ */ React__default.createElement(
|
|
125443
126375
|
Popover,
|
|
@@ -125445,17 +126377,18 @@ const AlignmentVisibilityTool = pure(/* @__PURE__ */ __name(function AlignmentVi
|
|
|
125445
126377
|
minimal: true,
|
|
125446
126378
|
position: "bottom",
|
|
125447
126379
|
content: /* @__PURE__ */ React__default.createElement(VisibilityOptions$2, __spreadValues({}, props)),
|
|
125448
|
-
target: /* @__PURE__ */ React__default.createElement(
|
|
126380
|
+
target: /* @__PURE__ */ React__default.createElement(
|
|
125449
126381
|
Button,
|
|
125450
126382
|
{
|
|
125451
126383
|
className: "tg-alignment-visibility-toggle",
|
|
125452
126384
|
small: true,
|
|
126385
|
+
"data-tip": "Visibility Options",
|
|
125453
126386
|
rightIcon: "caret-down",
|
|
125454
126387
|
intent: Intent.PRIMARY,
|
|
125455
126388
|
minimal: true,
|
|
125456
126389
|
icon: "eye-open"
|
|
125457
126390
|
}
|
|
125458
|
-
)
|
|
126391
|
+
)
|
|
125459
126392
|
}
|
|
125460
126393
|
);
|
|
125461
126394
|
}, "AlignmentVisibilityTool"));
|
|
@@ -138621,7 +139554,6 @@ const aminoAcidShortNames = {
|
|
|
138621
139554
|
const PropertySidePanel = /* @__PURE__ */ __name(({ properties: properties2, setProperties, style: style2 }) => {
|
|
138622
139555
|
const sidebarRef = React__default.useRef(null);
|
|
138623
139556
|
const [mismatchesCount, setMismatchesCount] = React__default.useState(0);
|
|
138624
|
-
const [mismatchesInRange, setMismatchesInRange] = React__default.useState(0);
|
|
138625
139557
|
const { track, isOpen, selection, isPairwise } = properties2;
|
|
138626
139558
|
const getSequenceInRegion = useCallback$1(() => {
|
|
138627
139559
|
var _a2, _b2;
|
|
@@ -138640,6 +139572,30 @@ const PropertySidePanel = /* @__PURE__ */ __name(({ properties: properties2, set
|
|
|
138640
139572
|
if (!Array.isArray(tr)) return [];
|
|
138641
139573
|
return isPairwise ? tr.filter((m2) => (m2 == null ? void 0 : m2.color) === "red") : tr;
|
|
138642
139574
|
}, [track, mismatchKey, isPairwise]);
|
|
139575
|
+
const mismatchSchema = useMemo$1(
|
|
139576
|
+
() => ({
|
|
139577
|
+
fields: [
|
|
139578
|
+
{
|
|
139579
|
+
path: "start",
|
|
139580
|
+
type: "number",
|
|
139581
|
+
displayName: "Start",
|
|
139582
|
+
render: /* @__PURE__ */ __name((val2) => val2 + 1, "render")
|
|
139583
|
+
},
|
|
139584
|
+
{
|
|
139585
|
+
path: "end",
|
|
139586
|
+
type: "number",
|
|
139587
|
+
displayName: "End",
|
|
139588
|
+
render: /* @__PURE__ */ __name((val2) => val2 + 1, "render")
|
|
139589
|
+
}
|
|
139590
|
+
]
|
|
139591
|
+
}),
|
|
139592
|
+
[]
|
|
139593
|
+
);
|
|
139594
|
+
const mismatchEntities = useMemo$1(() => {
|
|
139595
|
+
return (trackMismatches || []).map((m2, i) => __spreadProps(__spreadValues({}, m2), {
|
|
139596
|
+
id: i.toString()
|
|
139597
|
+
}));
|
|
139598
|
+
}, [trackMismatches]);
|
|
138643
139599
|
useEffect(() => {
|
|
138644
139600
|
if (!isOpen || sidebarRef.current === null || !track) {
|
|
138645
139601
|
return;
|
|
@@ -138657,21 +139613,6 @@ const PropertySidePanel = /* @__PURE__ */ __name(({ properties: properties2, set
|
|
|
138657
139613
|
}
|
|
138658
139614
|
});
|
|
138659
139615
|
setMismatchesCount(mismatchCount);
|
|
138660
|
-
setMismatchesInRange(mismatchCount);
|
|
138661
|
-
if (selection && selection.start > -1 && selection.end > -1) {
|
|
138662
|
-
let count2 = 0;
|
|
138663
|
-
trackMismatches == null ? void 0 : trackMismatches.forEach((tm) => {
|
|
138664
|
-
if (tm === null || tm.start === null || tm.end === null) {
|
|
138665
|
-
return;
|
|
138666
|
-
}
|
|
138667
|
-
const overlapStart = Math.max(tm.start, selection.start);
|
|
138668
|
-
const overlapEnd = Math.min(tm.end, selection.end);
|
|
138669
|
-
if (overlapEnd >= overlapStart) {
|
|
138670
|
-
count2 += overlapEnd - overlapStart + 1;
|
|
138671
|
-
}
|
|
138672
|
-
});
|
|
138673
|
-
setMismatchesInRange(count2);
|
|
138674
|
-
}
|
|
138675
139616
|
}, [isOpen, track, selection, trackMismatches]);
|
|
138676
139617
|
const aminoFreq = useMemo$1(() => {
|
|
138677
139618
|
var _a2, _b2;
|
|
@@ -138707,7 +139648,7 @@ const PropertySidePanel = /* @__PURE__ */ __name(({ properties: properties2, set
|
|
|
138707
139648
|
width: "100%"
|
|
138708
139649
|
}
|
|
138709
139650
|
}
|
|
138710
|
-
), /* @__PURE__ */ React__default.createElement(
|
|
139651
|
+
), /* @__PURE__ */ React__default.createElement(HeaderItem, { title: "Track Properties" }), /* @__PURE__ */ React__default.createElement("div", { className: "bp3-tab-panel" }, /* @__PURE__ */ React__default.createElement(RowItem, { item: name2, title: "Name" }), /* @__PURE__ */ React__default.createElement(RowItem, { item: isProtein2 ? proteinSize : size, title: "Length" }), /* @__PURE__ */ React__default.createElement(
|
|
138711
139652
|
RowItem,
|
|
138712
139653
|
{
|
|
138713
139654
|
item: molecularWeight == null ? void 0 : molecularWeight.toFixed(2),
|
|
@@ -138721,18 +139662,45 @@ const PropertySidePanel = /* @__PURE__ */ __name(({ properties: properties2, set
|
|
|
138721
139662
|
title: "Extinction Coefficient"
|
|
138722
139663
|
}
|
|
138723
139664
|
)), /* @__PURE__ */ React__default.createElement(
|
|
138724
|
-
RowItem,
|
|
138725
|
-
{
|
|
138726
|
-
item: `${mismatchesInRange}/${mismatchesCount}`,
|
|
138727
|
-
title: "Mismatches"
|
|
138728
|
-
}
|
|
138729
|
-
), /* @__PURE__ */ React__default.createElement(
|
|
138730
139665
|
RowItem,
|
|
138731
139666
|
{
|
|
138732
139667
|
item: selection && selection.start > -1 ? /* @__PURE__ */ React__default.createElement("span", null, selection.start + 1, " - ", selection.end + 1) : /* @__PURE__ */ React__default.createElement("span", null, "1 - ", isProtein2 ? proteinSize : size),
|
|
138733
139668
|
title: "Region"
|
|
138734
139669
|
}
|
|
138735
|
-
)
|
|
139670
|
+
), /* @__PURE__ */ React__default.createElement(HeaderItem, { title: `Mismatches (${mismatchesCount})` }), trackMismatches && trackMismatches.length > 0 && /* @__PURE__ */ React__default.createElement(
|
|
139671
|
+
"div",
|
|
139672
|
+
{
|
|
139673
|
+
style: {
|
|
139674
|
+
margin: "0px 10px"
|
|
139675
|
+
}
|
|
139676
|
+
},
|
|
139677
|
+
/* @__PURE__ */ React__default.createElement(
|
|
139678
|
+
WrappedDT,
|
|
139679
|
+
{
|
|
139680
|
+
formName: "mismatchesTable",
|
|
139681
|
+
isSimple: true,
|
|
139682
|
+
noHeader: true,
|
|
139683
|
+
noFooter: true,
|
|
139684
|
+
withSearch: false,
|
|
139685
|
+
noPadding: true,
|
|
139686
|
+
compact: true,
|
|
139687
|
+
maxHeight: 150,
|
|
139688
|
+
entities: mismatchEntities,
|
|
139689
|
+
schema: mismatchSchema,
|
|
139690
|
+
onRowClick: /* @__PURE__ */ __name((e, row) => {
|
|
139691
|
+
updateCaretPosition({ start: row.start, end: row.end });
|
|
139692
|
+
setTimeout(() => {
|
|
139693
|
+
scrollToAlignmentSelection();
|
|
139694
|
+
}, 0);
|
|
139695
|
+
}, "onRowClick")
|
|
139696
|
+
}
|
|
139697
|
+
)
|
|
139698
|
+
)), /* @__PURE__ */ React__default.createElement(
|
|
139699
|
+
HeaderItem,
|
|
139700
|
+
{
|
|
139701
|
+
title: `${isProtein2 ? "Amino Acid" : "Base Pair"} Frequencies`
|
|
139702
|
+
}
|
|
139703
|
+
), /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-table" }, /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-row" }, /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-cell" }, isProtein2 ? "Amino Acid" : "Base"), /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-cell" }, "Count"), /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-cell" }, "Percentage")), frequencyEntries.map(([aa, data], idx) => {
|
|
138736
139704
|
return /* @__PURE__ */ React__default.createElement("div", { className: `sidebar-row property-amino-acid-${idx}` }, /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-cell" }, aa, " ", isProtein2 ? `(${aminoAcidShortNames[aa]})` : ""), /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-cell" }, data.count), /* @__PURE__ */ React__default.createElement("div", { className: "sidebar-cell" }, data.percentage.toFixed(1), "%"));
|
|
138737
139705
|
})));
|
|
138738
139706
|
} else {
|
|
@@ -138789,11 +139757,29 @@ const PropertySidePanel = /* @__PURE__ */ __name(({ properties: properties2, set
|
|
|
138789
139757
|
);
|
|
138790
139758
|
}, "PropertySidePanel");
|
|
138791
139759
|
function RowItem({ item, title, units }) {
|
|
138792
|
-
if (
|
|
139760
|
+
if (item == null) {
|
|
139761
|
+
return null;
|
|
139762
|
+
}
|
|
138793
139763
|
const propertyClass = title.split(" ").join("-").toLowerCase();
|
|
138794
|
-
return /* @__PURE__ */ React__default.createElement("div", { className: `ve-flex-row property-${propertyClass}` }, /* @__PURE__ */ React__default.createElement("div", { className: "ve-column-left" }, title), /* @__PURE__ */ React__default.createElement("div", { className: "ve-column-right" }, item, " ", units != null ? units : ""));
|
|
139764
|
+
return /* @__PURE__ */ React__default.createElement("div", { className: `ve-flex-row property-${propertyClass}` }, /* @__PURE__ */ React__default.createElement("div", { style: { fontWeight: "bold" }, className: "ve-column-left" }, title), /* @__PURE__ */ React__default.createElement("div", { className: "ve-column-right" }, item, " ", units != null ? units : ""));
|
|
138795
139765
|
}
|
|
138796
139766
|
__name(RowItem, "RowItem");
|
|
139767
|
+
const HeaderItem = /* @__PURE__ */ __name(({ title }) => {
|
|
139768
|
+
return /* @__PURE__ */ React__default.createElement(
|
|
139769
|
+
"h5",
|
|
139770
|
+
{
|
|
139771
|
+
style: {
|
|
139772
|
+
margin: 0,
|
|
139773
|
+
fontSize: 15,
|
|
139774
|
+
fontWeight: "bold",
|
|
139775
|
+
textAlign: "center",
|
|
139776
|
+
padding: "5px 0",
|
|
139777
|
+
borderBottom: "1px solid #f1f1f1"
|
|
139778
|
+
}
|
|
139779
|
+
},
|
|
139780
|
+
title
|
|
139781
|
+
);
|
|
139782
|
+
}, "HeaderItem");
|
|
138797
139783
|
function calculatePairwiseIdentity(seq1, seq2, excludeGaps = true) {
|
|
138798
139784
|
if (seq1.length !== seq2.length) {
|
|
138799
139785
|
throw new Error("Sequences must be aligned (same length)");
|
|
@@ -139189,6 +140175,11 @@ const AlignmentView = /* @__PURE__ */ __name((props) => {
|
|
|
139189
140175
|
const [tempTrimBefore, setTempTrimBefore] = useState({});
|
|
139190
140176
|
const [tempTrimAfter, setTempTrimAfter] = useState({});
|
|
139191
140177
|
const [tempTrimmingCaret, setTempTrimmingCaret] = useState({});
|
|
140178
|
+
const [searchMatchLayers, setSearchMatchLayers] = React__default.useState([]);
|
|
140179
|
+
const [activeFilterType, setActiveFilterType] = useState("all");
|
|
140180
|
+
const handleFilterChange = useCallback$1(({ activeFilter }) => {
|
|
140181
|
+
setActiveFilterType(activeFilter);
|
|
140182
|
+
}, []);
|
|
139192
140183
|
const bindOutsideChangeHelper = useRef({});
|
|
139193
140184
|
const alignmentHolder = useRef(null);
|
|
139194
140185
|
const alignmentHolderTop = useRef(null);
|
|
@@ -139913,7 +140904,12 @@ ${seqDataToCopy}\r
|
|
|
139913
140904
|
alignmentData,
|
|
139914
140905
|
chromatogramData
|
|
139915
140906
|
}) : linearViewOptions)), {
|
|
139916
|
-
additionalSelectionLayers
|
|
140907
|
+
additionalSelectionLayers: [
|
|
140908
|
+
...i !== 0 ? (additionalSelectionLayers || []).filter(
|
|
140909
|
+
(layer) => activeFilterType === "all" ? layer.differenceType !== "gap" : layer.differenceType === activeFilterType
|
|
140910
|
+
) : additionalSelectionLayers || [],
|
|
140911
|
+
...searchMatchLayers || []
|
|
140912
|
+
],
|
|
139917
140913
|
dimensions: {
|
|
139918
140914
|
width: linearViewWidth
|
|
139919
140915
|
},
|
|
@@ -140441,7 +141437,7 @@ ${seqDataToCopy}\r
|
|
|
140441
141437
|
display: "flex",
|
|
140442
141438
|
minHeight: "32px",
|
|
140443
141439
|
width: "100%",
|
|
140444
|
-
flexWrap: "
|
|
141440
|
+
flexWrap: "wrap",
|
|
140445
141441
|
flexDirection: "row",
|
|
140446
141442
|
flex: "0 0 auto"
|
|
140447
141443
|
},
|
|
@@ -140562,6 +141558,22 @@ ${seqDataToCopy}\r
|
|
|
140562
141558
|
currentPairwiseAlignmentIndex
|
|
140563
141559
|
}, alignmentVisibilityToolOptions)
|
|
140564
141560
|
),
|
|
141561
|
+
/* @__PURE__ */ React__default.createElement(
|
|
141562
|
+
AlignmentSearchBar,
|
|
141563
|
+
{
|
|
141564
|
+
alignmentTracks,
|
|
141565
|
+
id: id2,
|
|
141566
|
+
setSearchMatchLayers
|
|
141567
|
+
}
|
|
141568
|
+
),
|
|
141569
|
+
/* @__PURE__ */ React__default.createElement(
|
|
141570
|
+
FindMismatches,
|
|
141571
|
+
{
|
|
141572
|
+
alignmentJson: alignmentTracks,
|
|
141573
|
+
id: id2,
|
|
141574
|
+
onFilterChange: handleFilterChange
|
|
141575
|
+
}
|
|
141576
|
+
),
|
|
140565
141577
|
additionalTopEl,
|
|
140566
141578
|
saveMessage && /* @__PURE__ */ React__default.createElement(
|
|
140567
141579
|
"div",
|
|
@@ -140662,6 +141674,7 @@ ${seqDataToCopy}\r
|
|
|
140662
141674
|
}
|
|
140663
141675
|
)),
|
|
140664
141676
|
alignmentTracks,
|
|
141677
|
+
activeFilterType,
|
|
140665
141678
|
dimensions: {
|
|
140666
141679
|
width: Math.max(width, 10) || 10
|
|
140667
141680
|
},
|
|
@@ -145851,108 +146864,6 @@ const schema = {
|
|
|
145851
146864
|
]
|
|
145852
146865
|
};
|
|
145853
146866
|
const DigestTool$1 = withEditorInteractions(DigestTool);
|
|
145854
|
-
const _Mismatches = class _Mismatches extends React__default.Component {
|
|
145855
|
-
constructor() {
|
|
145856
|
-
super(...arguments);
|
|
145857
|
-
__publicField(this, "getGapMap", /* @__PURE__ */ __name((sequence2) => {
|
|
145858
|
-
const gapMap = [0];
|
|
145859
|
-
sequence2.split("").forEach((char) => {
|
|
145860
|
-
if (char === "-") {
|
|
145861
|
-
gapMap[Math.max(0, gapMap.length - 1)] = (gapMap[Math.max(0, gapMap.length - 1)] || 0) + 1;
|
|
145862
|
-
} else {
|
|
145863
|
-
gapMap.push(gapMap[gapMap.length - 1] || 0);
|
|
145864
|
-
}
|
|
145865
|
-
});
|
|
145866
|
-
return gapMap;
|
|
145867
|
-
}, "getGapMap"));
|
|
145868
|
-
__publicField(this, "getMismatchList", /* @__PURE__ */ __name((alignmentData, mismatches) => {
|
|
145869
|
-
const mismatchList = [];
|
|
145870
|
-
let getGaps2 = /* @__PURE__ */ __name(() => ({
|
|
145871
|
-
gapsBefore: 0,
|
|
145872
|
-
gapsInside: 0
|
|
145873
|
-
}), "getGaps");
|
|
145874
|
-
const gapMap = this.getGapMap(alignmentData.sequence);
|
|
145875
|
-
getGaps2 = /* @__PURE__ */ __name((rangeOrCaretPosition) => {
|
|
145876
|
-
if (typeof rangeOrCaretPosition !== "object") {
|
|
145877
|
-
return {
|
|
145878
|
-
gapsBefore: gapMap[Math.min(rangeOrCaretPosition, gapMap.length - 1)]
|
|
145879
|
-
};
|
|
145880
|
-
}
|
|
145881
|
-
const { start: start2, end: end2 } = rangeOrCaretPosition;
|
|
145882
|
-
const toReturn = {
|
|
145883
|
-
gapsBefore: gapMap[start2],
|
|
145884
|
-
gapsInside: gapMap[Math.min(end2, gapMap.length - 1)] - gapMap[Math.min(start2, gapMap.length - 1)]
|
|
145885
|
-
};
|
|
145886
|
-
return toReturn;
|
|
145887
|
-
}, "getGaps");
|
|
145888
|
-
const gapsBeforeSequence = getGaps2(0).gapsBefore;
|
|
145889
|
-
for (let mismatchI = 0; mismatchI < mismatches.length; mismatchI++) {
|
|
145890
|
-
const mismatchEnd = mismatches[mismatchI].end;
|
|
145891
|
-
const mismatchStart = mismatches[mismatchI].start;
|
|
145892
|
-
const mismatchDifference = mismatchEnd - mismatchStart;
|
|
145893
|
-
if (mismatchDifference === 0) {
|
|
145894
|
-
mismatchList.push({
|
|
145895
|
-
mismatches: mismatchStart + 1 - gapsBeforeSequence,
|
|
145896
|
-
start: mismatchStart - gapsBeforeSequence,
|
|
145897
|
-
end: mismatchStart - gapsBeforeSequence
|
|
145898
|
-
});
|
|
145899
|
-
} else {
|
|
145900
|
-
for (let innerI = 0; innerI <= mismatchDifference; innerI++) {
|
|
145901
|
-
mismatchList.push({
|
|
145902
|
-
mismatches: mismatchStart + innerI + 1 - gapsBeforeSequence,
|
|
145903
|
-
start: mismatchStart + innerI - gapsBeforeSequence,
|
|
145904
|
-
end: mismatchStart + innerI - gapsBeforeSequence
|
|
145905
|
-
});
|
|
145906
|
-
}
|
|
145907
|
-
}
|
|
145908
|
-
}
|
|
145909
|
-
return mismatchList;
|
|
145910
|
-
}, "getMismatchList"));
|
|
145911
|
-
}
|
|
145912
|
-
UNSAFE_componentWillMount() {
|
|
145913
|
-
const { alignmentData, mismatches } = this.props;
|
|
145914
|
-
const mismatchList = this.getMismatchList(alignmentData, mismatches);
|
|
145915
|
-
const schema2 = {
|
|
145916
|
-
fields: [{ path: "mismatches", type: "number" }]
|
|
145917
|
-
};
|
|
145918
|
-
this.setState({ mismatchList, schema: schema2 });
|
|
145919
|
-
}
|
|
145920
|
-
render() {
|
|
145921
|
-
const { mismatchList, schema: schema2 } = this.state;
|
|
145922
|
-
let tableOfMismatches;
|
|
145923
|
-
if (mismatchList.length === 0) {
|
|
145924
|
-
tableOfMismatches = null;
|
|
145925
|
-
} else {
|
|
145926
|
-
tableOfMismatches = /* @__PURE__ */ React__default.createElement(
|
|
145927
|
-
WrappedDT,
|
|
145928
|
-
{
|
|
145929
|
-
maxHeight: 168,
|
|
145930
|
-
formName: "mismatchesTable",
|
|
145931
|
-
isSimple: true,
|
|
145932
|
-
compact: true,
|
|
145933
|
-
noRouter: true,
|
|
145934
|
-
schema: schema2,
|
|
145935
|
-
entities: mismatchList
|
|
145936
|
-
}
|
|
145937
|
-
);
|
|
145938
|
-
}
|
|
145939
|
-
return /* @__PURE__ */ React__default.createElement("div", { style: { maxHeight: 180.8, overflowY: "scroll" } }, /* @__PURE__ */ React__default.createElement(
|
|
145940
|
-
"div",
|
|
145941
|
-
{
|
|
145942
|
-
style: {
|
|
145943
|
-
// margin: 10,
|
|
145944
|
-
display: "flex",
|
|
145945
|
-
flexDirection: "column",
|
|
145946
|
-
alignItems: "center"
|
|
145947
|
-
}
|
|
145948
|
-
},
|
|
145949
|
-
/* @__PURE__ */ React__default.createElement("div", { style: { width: 100, margin: 4 } }, tableOfMismatches)
|
|
145950
|
-
));
|
|
145951
|
-
}
|
|
145952
|
-
};
|
|
145953
|
-
__name(_Mismatches, "Mismatches");
|
|
145954
|
-
let Mismatches = _Mismatches;
|
|
145955
|
-
const Mismatches$1 = withSelectedEntities("mismatchesTable")(Mismatches);
|
|
145956
146867
|
function PCRTool(props) {
|
|
145957
146868
|
const {
|
|
145958
146869
|
sequenceData: sequenceData2,
|
|
@@ -146124,7 +147035,7 @@ const _panelMap = {
|
|
|
146124
147035
|
comp: PropertiesDialog$1,
|
|
146125
147036
|
panelSpecificProps: ["PropertiesProps"]
|
|
146126
147037
|
},
|
|
146127
|
-
mismatches:
|
|
147038
|
+
mismatches: FindMismatches
|
|
146128
147039
|
};
|
|
146129
147040
|
const reorder = /* @__PURE__ */ __name((list2, startIndex, endIndex) => {
|
|
146130
147041
|
const result = Array.from(list2);
|
|
@@ -148954,18 +149865,6 @@ __name(createAlignmentView, "createAlignmentView");
|
|
|
148954
149865
|
window.createVectorEditor = createVectorEditor;
|
|
148955
149866
|
window.createAlignmentView = createAlignmentView;
|
|
148956
149867
|
window.createVersionHistoryView = createVersionHistoryView;
|
|
148957
|
-
function getGapMap(sequence2) {
|
|
148958
|
-
const gapMap = [0];
|
|
148959
|
-
sequence2.split("").forEach((char) => {
|
|
148960
|
-
if (char === "-") {
|
|
148961
|
-
gapMap[Math.max(0, gapMap.length - 1)] = (gapMap[Math.max(0, gapMap.length - 1)] || 0) + 1;
|
|
148962
|
-
} else {
|
|
148963
|
-
gapMap.push(gapMap[gapMap.length - 1] || 0);
|
|
148964
|
-
}
|
|
148965
|
-
});
|
|
148966
|
-
return gapMap;
|
|
148967
|
-
}
|
|
148968
|
-
__name(getGapMap, "getGapMap");
|
|
148969
149868
|
let getGaps = /* @__PURE__ */ __name(() => ({
|
|
148970
149869
|
gapsBefore: 0,
|
|
148971
149870
|
gapsInside: 0
|