@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.umd.js
CHANGED
|
@@ -124411,14 +124411,34 @@ ${seq.sequence}
|
|
|
124411
124411
|
track.alignmentData.sequence
|
|
124412
124412
|
);
|
|
124413
124413
|
const mismatches = matchHighlightRanges.filter(({ isMatch }) => !isMatch);
|
|
124414
|
+
const alignedSeq = track.alignmentData.sequence;
|
|
124415
|
+
const seqLen = alignedSeq.length;
|
|
124416
|
+
const startIndex = seqLen - alignedSeq.replace(/^-+/, "").length;
|
|
124417
|
+
const endIndex = alignedSeq.replace(/-+$/, "").length;
|
|
124418
|
+
const gapRanges = [
|
|
124419
|
+
startIndex > 0 && {
|
|
124420
|
+
start: 0,
|
|
124421
|
+
end: startIndex - 1,
|
|
124422
|
+
differenceType: "gap"
|
|
124423
|
+
},
|
|
124424
|
+
endIndex < seqLen && {
|
|
124425
|
+
start: endIndex,
|
|
124426
|
+
end: seqLen - 1,
|
|
124427
|
+
differenceType: "gap"
|
|
124428
|
+
}
|
|
124429
|
+
].filter(Boolean);
|
|
124414
124430
|
return __spreadProps(__spreadValues({}, track), {
|
|
124415
124431
|
sequenceData: sequenceData2,
|
|
124416
124432
|
matchHighlightRanges,
|
|
124417
|
-
additionalSelectionLayers:
|
|
124418
|
-
|
|
124433
|
+
additionalSelectionLayers: [
|
|
124434
|
+
...matchHighlightRanges.filter(({ isMatch }) => !isMatch).map((range2) => __spreadProps(__spreadValues(__spreadValues({}, range2), highlightRangeProps), {
|
|
124419
124435
|
className: "veAlignmentMismatch"
|
|
124420
|
-
})
|
|
124421
|
-
|
|
124436
|
+
})),
|
|
124437
|
+
...gapRanges.map((range2) => __spreadProps(__spreadValues(__spreadValues({}, range2), highlightRangeProps), {
|
|
124438
|
+
className: "veAlignmentMismatch"
|
|
124439
|
+
}))
|
|
124440
|
+
],
|
|
124441
|
+
gapRanges,
|
|
124422
124442
|
mismatches
|
|
124423
124443
|
});
|
|
124424
124444
|
});
|
|
@@ -124552,23 +124572,30 @@ ${seq.sequence}
|
|
|
124552
124572
|
const startIndex = seqLength - nonTempSeqWithoutLeadingDashes.length;
|
|
124553
124573
|
const endIndex = seqLength - (seqLength - nonTempSeqWithoutTrailingDashes.length);
|
|
124554
124574
|
for (let index2 = startIndex; index2 < endIndex; index2++) {
|
|
124555
|
-
const
|
|
124556
|
-
const
|
|
124557
|
-
|
|
124558
|
-
|
|
124559
|
-
|
|
124575
|
+
const tempBase = tempSeq[index2].toLowerCase();
|
|
124576
|
+
const nonTempBase = nonTempSeq[index2].toLowerCase();
|
|
124577
|
+
const isMatch = tempBase === nonTempBase;
|
|
124578
|
+
let differenceType = null;
|
|
124579
|
+
if (!isMatch) {
|
|
124580
|
+
if (tempBase === "-") {
|
|
124581
|
+
differenceType = "insertion";
|
|
124582
|
+
} else if (nonTempBase === "-") {
|
|
124583
|
+
differenceType = "deletion";
|
|
124560
124584
|
} else {
|
|
124561
|
-
|
|
124562
|
-
start: index2,
|
|
124563
|
-
end: index2,
|
|
124564
|
-
isMatch
|
|
124565
|
-
});
|
|
124585
|
+
differenceType = "mismatch";
|
|
124566
124586
|
}
|
|
124587
|
+
}
|
|
124588
|
+
const previousRange = ranges[ranges.length - 1];
|
|
124589
|
+
if (previousRange && previousRange.isMatch === isMatch && previousRange.differenceType === differenceType) {
|
|
124590
|
+
previousRange.end++;
|
|
124591
|
+
} else if (previousRange) {
|
|
124592
|
+
ranges.push({ start: index2, end: index2, isMatch, differenceType });
|
|
124567
124593
|
} else {
|
|
124568
124594
|
ranges.push({
|
|
124569
124595
|
start: startIndex,
|
|
124570
124596
|
end: startIndex,
|
|
124571
|
-
isMatch
|
|
124597
|
+
isMatch,
|
|
124598
|
+
differenceType
|
|
124572
124599
|
});
|
|
124573
124600
|
}
|
|
124574
124601
|
}
|
|
@@ -145343,7 +145370,7 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
|
|
|
145343
145370
|
input.click();
|
|
145344
145371
|
}
|
|
145345
145372
|
__name(showFileDialog, "showFileDialog");
|
|
145346
|
-
const version = "0.8.
|
|
145373
|
+
const version = "0.8.41";
|
|
145347
145374
|
const packageJson = {
|
|
145348
145375
|
version
|
|
145349
145376
|
};
|
|
@@ -151610,11 +151637,13 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
|
|
|
151610
151637
|
dimensions: { width = 200 },
|
|
151611
151638
|
laneHeight,
|
|
151612
151639
|
laneSpacing = 1,
|
|
151613
|
-
isTrackSelected = []
|
|
151640
|
+
isTrackSelected = [],
|
|
151641
|
+
activeFilterType = "all"
|
|
151614
151642
|
} = this.props;
|
|
151615
151643
|
const charWidth2 = this.getCharWidth();
|
|
151616
151644
|
const {
|
|
151617
151645
|
matchHighlightRanges: _matchHighlightRanges,
|
|
151646
|
+
gapRanges = [],
|
|
151618
151647
|
alignmentData: { trimmedRange } = {}
|
|
151619
151648
|
} = alignmentTracks[i2];
|
|
151620
151649
|
const matchHighlightRanges = !trimmedRange ? _matchHighlightRanges : flatMap(_matchHighlightRanges, (r2) => {
|
|
@@ -151641,10 +151670,19 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
|
|
|
151641
151670
|
charWidth2
|
|
151642
151671
|
);
|
|
151643
151672
|
const toAdd = `M${xStart},${y2} L${xStart + width2},${y2} L${xStart + width2},${y2 + height} L${xStart},${y2 + height}`;
|
|
151644
|
-
if (!range2.isMatch) {
|
|
151673
|
+
if (!range2.isMatch && (activeFilterType === "all" || range2.differenceType === activeFilterType)) {
|
|
151645
151674
|
redPath += toAdd;
|
|
151646
151675
|
}
|
|
151647
151676
|
});
|
|
151677
|
+
if (activeFilterType === "gap") {
|
|
151678
|
+
gapRanges.forEach((range2) => {
|
|
151679
|
+
const { xStart, width: width2 } = getXStartAndWidthFromNonCircularRange(
|
|
151680
|
+
range2,
|
|
151681
|
+
charWidth2
|
|
151682
|
+
);
|
|
151683
|
+
redPath += `M${xStart},${y2} L${xStart + width2},${y2} L${xStart + width2},${y2 + height} L${xStart},${y2 + height}`;
|
|
151684
|
+
});
|
|
151685
|
+
}
|
|
151648
151686
|
return /* @__PURE__ */ React.createElement(
|
|
151649
151687
|
"div",
|
|
151650
151688
|
{
|
|
@@ -151674,7 +151712,8 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
|
|
|
151674
151712
|
"scrollAlignmentView",
|
|
151675
151713
|
"laneHeight",
|
|
151676
151714
|
"laneSpacing",
|
|
151677
|
-
"isTrackSelected"
|
|
151715
|
+
"isTrackSelected",
|
|
151716
|
+
"activeFilterType"
|
|
151678
151717
|
].some((key) => props[key] !== newProps[key]))
|
|
151679
151718
|
return true;
|
|
151680
151719
|
return false;
|
|
@@ -151952,6 +151991,899 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
|
|
|
151952
151991
|
return splitRangeIntoTwoPartsIfItIsCircular(inverted, seqLen);
|
|
151953
151992
|
}
|
|
151954
151993
|
__name(getTrimmedRangesToDisplay, "getTrimmedRangesToDisplay");
|
|
151994
|
+
function groupConsecutiveDifferences(differences) {
|
|
151995
|
+
const grouped = [];
|
|
151996
|
+
for (const diff of differences) {
|
|
151997
|
+
if (diff.type === "mismatch") {
|
|
151998
|
+
grouped.push(__spreadProps(__spreadValues({}, diff), { start: diff.position, end: diff.position }));
|
|
151999
|
+
continue;
|
|
152000
|
+
}
|
|
152001
|
+
const last2 = grouped[grouped.length - 1];
|
|
152002
|
+
if (last2 && last2.type === diff.type && last2.end === diff.position - 1) {
|
|
152003
|
+
grouped[grouped.length - 1] = __spreadProps(__spreadValues({}, last2), { end: diff.position });
|
|
152004
|
+
} else {
|
|
152005
|
+
grouped.push(__spreadProps(__spreadValues({}, diff), { start: diff.position, end: diff.position }));
|
|
152006
|
+
}
|
|
152007
|
+
}
|
|
152008
|
+
return grouped;
|
|
152009
|
+
}
|
|
152010
|
+
__name(groupConsecutiveDifferences, "groupConsecutiveDifferences");
|
|
152011
|
+
function findAlignmentDifferences(alignedSeqs) {
|
|
152012
|
+
var _a2;
|
|
152013
|
+
if (alignedSeqs.length < 2 || !((_a2 = alignedSeqs[0]) == null ? void 0 : _a2.length)) return [];
|
|
152014
|
+
const template = alignedSeqs[0].toLowerCase();
|
|
152015
|
+
const nonTemplates = alignedSeqs.slice(1).map((s2) => s2.toLowerCase());
|
|
152016
|
+
const trackBounds = nonTemplates.map((seq) => {
|
|
152017
|
+
const withoutLeading = seq.replace(/^-+/, "");
|
|
152018
|
+
const withoutTrailing = seq.replace(/-+$/, "");
|
|
152019
|
+
const start2 = seq.length - withoutLeading.length;
|
|
152020
|
+
const end2 = seq.length - (seq.length - withoutTrailing.length);
|
|
152021
|
+
return { start: start2, end: end2 };
|
|
152022
|
+
});
|
|
152023
|
+
const differences = [];
|
|
152024
|
+
for (let i2 = 0; i2 < template.length; i2++) {
|
|
152025
|
+
const templateBase = template[i2];
|
|
152026
|
+
const allNonTemplateBases = nonTemplates.map((seq) => seq[i2]);
|
|
152027
|
+
const bases = [templateBase, ...allNonTemplateBases];
|
|
152028
|
+
const alignedIndices = trackBounds.reduce((acc, { start: start2, end: end2 }, idx) => {
|
|
152029
|
+
if (i2 >= start2 && i2 < end2) acc.push(idx);
|
|
152030
|
+
return acc;
|
|
152031
|
+
}, []);
|
|
152032
|
+
if (alignedIndices.length === 0) {
|
|
152033
|
+
differences.push({ position: i2, type: "gap", bases });
|
|
152034
|
+
continue;
|
|
152035
|
+
}
|
|
152036
|
+
const alignedBases = alignedIndices.map((idx) => allNonTemplateBases[idx]);
|
|
152037
|
+
const templateIsGap = templateBase === "-";
|
|
152038
|
+
const nonTemplateHasBase = alignedBases.some((b3) => b3 !== "-");
|
|
152039
|
+
const nonTemplateHasGap = alignedBases.some((b3) => b3 === "-");
|
|
152040
|
+
if (templateIsGap && nonTemplateHasBase) {
|
|
152041
|
+
differences.push({ position: i2, type: "insertion", bases });
|
|
152042
|
+
} else if (!templateIsGap && nonTemplateHasGap) {
|
|
152043
|
+
differences.push({ position: i2, type: "deletion", bases });
|
|
152044
|
+
} else if (!templateIsGap) {
|
|
152045
|
+
const uniqueBases = /* @__PURE__ */ new Set([templateBase, ...alignedBases]);
|
|
152046
|
+
if (uniqueBases.size > 1) {
|
|
152047
|
+
differences.push({ position: i2, type: "mismatch", bases });
|
|
152048
|
+
}
|
|
152049
|
+
}
|
|
152050
|
+
}
|
|
152051
|
+
return differences;
|
|
152052
|
+
}
|
|
152053
|
+
__name(findAlignmentDifferences, "findAlignmentDifferences");
|
|
152054
|
+
function scrollToAlignmentSelection() {
|
|
152055
|
+
const el = document.querySelector(".veCaret");
|
|
152056
|
+
if (el) {
|
|
152057
|
+
el.scrollIntoView({ inline: "center", block: "nearest" });
|
|
152058
|
+
}
|
|
152059
|
+
}
|
|
152060
|
+
__name(scrollToAlignmentSelection, "scrollToAlignmentSelection");
|
|
152061
|
+
function updateCaretPosition({ start: start2, end: end2 }) {
|
|
152062
|
+
if (window.updateAlignmentSelection) {
|
|
152063
|
+
window.updateAlignmentSelection({ start: start2, end: end2 });
|
|
152064
|
+
}
|
|
152065
|
+
}
|
|
152066
|
+
__name(updateCaretPosition, "updateCaretPosition");
|
|
152067
|
+
const FILTER_OPTIONS = [
|
|
152068
|
+
{ value: "all", label: "All" },
|
|
152069
|
+
{ value: "mismatch", label: "Mismatches" },
|
|
152070
|
+
{ value: "insertion", label: "Insertions" },
|
|
152071
|
+
{ value: "deletion", label: "Deletions" },
|
|
152072
|
+
{ value: "gap", label: "Gaps" }
|
|
152073
|
+
];
|
|
152074
|
+
function FindMismatches(props) {
|
|
152075
|
+
var _a2;
|
|
152076
|
+
const { alignmentJson, id: id2, onFilterChange } = props;
|
|
152077
|
+
const alignedSeqs = reactExports.useMemo(
|
|
152078
|
+
() => alignmentJson.map((t2) => {
|
|
152079
|
+
var _a3;
|
|
152080
|
+
return ((_a3 = t2.alignmentData) == null ? void 0 : _a3.sequence) || "";
|
|
152081
|
+
}),
|
|
152082
|
+
[alignmentJson]
|
|
152083
|
+
);
|
|
152084
|
+
const [activeFilter, setActiveFilter] = React.useState("all");
|
|
152085
|
+
const allDifferences = reactExports.useMemo(
|
|
152086
|
+
() => groupConsecutiveDifferences(findAlignmentDifferences(alignedSeqs)),
|
|
152087
|
+
[alignedSeqs]
|
|
152088
|
+
);
|
|
152089
|
+
const countsByType = reactExports.useMemo(() => {
|
|
152090
|
+
const counts = { all: 0, mismatch: 0, insertion: 0, deletion: 0, gap: 0 };
|
|
152091
|
+
allDifferences.forEach((d2) => {
|
|
152092
|
+
counts[d2.type] = (counts[d2.type] || 0) + 1;
|
|
152093
|
+
counts.all++;
|
|
152094
|
+
});
|
|
152095
|
+
return counts;
|
|
152096
|
+
}, [allDifferences]);
|
|
152097
|
+
const differences = reactExports.useMemo(() => {
|
|
152098
|
+
const filtered = activeFilter === "all" ? allDifferences : allDifferences.filter((d2) => d2.type === activeFilter);
|
|
152099
|
+
return [{ position: -1, start: -1, end: -1, bases: [""] }, ...filtered];
|
|
152100
|
+
}, [allDifferences, activeFilter]);
|
|
152101
|
+
const currentCaretPosition = useSelector(
|
|
152102
|
+
(state2) => {
|
|
152103
|
+
var _a3;
|
|
152104
|
+
return (_a3 = state2.VectorEditor.__allEditorsOptions.alignments[id2]) == null ? void 0 : _a3.caretPosition;
|
|
152105
|
+
}
|
|
152106
|
+
);
|
|
152107
|
+
const [currentIdx, setCurrentIdx] = React.useState(0);
|
|
152108
|
+
const currentDiff = differences[currentIdx];
|
|
152109
|
+
const disablePrev = currentIdx <= 1;
|
|
152110
|
+
const disableNext = currentIdx >= differences.length - 1;
|
|
152111
|
+
reactExports.useEffect(() => {
|
|
152112
|
+
setCurrentIdx(0);
|
|
152113
|
+
}, [activeFilter]);
|
|
152114
|
+
reactExports.useEffect(() => {
|
|
152115
|
+
onFilterChange == null ? void 0 : onFilterChange({ activeFilter });
|
|
152116
|
+
}, [activeFilter, onFilterChange]);
|
|
152117
|
+
reactExports.useEffect(() => {
|
|
152118
|
+
if (currentCaretPosition !== -1) {
|
|
152119
|
+
const diffIdx = differences.findIndex(
|
|
152120
|
+
(d2, i2) => i2 > 0 && currentCaretPosition >= d2.start && currentCaretPosition <= d2.end + 1
|
|
152121
|
+
);
|
|
152122
|
+
if (diffIdx !== -1 && diffIdx !== currentIdx) {
|
|
152123
|
+
setCurrentIdx(diffIdx);
|
|
152124
|
+
}
|
|
152125
|
+
}
|
|
152126
|
+
}, [currentCaretPosition, differences, currentIdx]);
|
|
152127
|
+
const updateView = /* @__PURE__ */ __name((diff) => {
|
|
152128
|
+
const idx = differences.indexOf(diff);
|
|
152129
|
+
const { start: start2, end: end2 } = diff;
|
|
152130
|
+
setCurrentIdx(idx);
|
|
152131
|
+
updateCaretPosition({ start: start2, end: end2 });
|
|
152132
|
+
setTimeout(() => {
|
|
152133
|
+
scrollToAlignmentSelection();
|
|
152134
|
+
}, 0);
|
|
152135
|
+
}, "updateView");
|
|
152136
|
+
const prevDifference = /* @__PURE__ */ __name(() => {
|
|
152137
|
+
var _a3, _b2;
|
|
152138
|
+
const pivot = currentCaretPosition >= 0 ? currentCaretPosition : (_b2 = (_a3 = differences[currentIdx]) == null ? void 0 : _a3.start) != null ? _b2 : 0;
|
|
152139
|
+
const prev = [...differences].reverse().find((d2) => d2.start >= 0 && d2.start < pivot);
|
|
152140
|
+
if (prev) updateView(prev);
|
|
152141
|
+
}, "prevDifference");
|
|
152142
|
+
const nextDifference = /* @__PURE__ */ __name(() => {
|
|
152143
|
+
var _a3, _b2;
|
|
152144
|
+
const pivot = currentCaretPosition >= 0 ? currentCaretPosition : (_b2 = (_a3 = differences[currentIdx]) == null ? void 0 : _a3.start) != null ? _b2 : -1;
|
|
152145
|
+
const next = differences.find((d2) => d2.start > pivot && d2.start >= 0);
|
|
152146
|
+
if (next) updateView(next);
|
|
152147
|
+
}, "nextDifference");
|
|
152148
|
+
const noDifferences = differences.length <= 1;
|
|
152149
|
+
const activeOption = FILTER_OPTIONS.find((o2) => o2.value === activeFilter);
|
|
152150
|
+
const activeLabel = (_a2 = activeOption == null ? void 0 : activeOption.label) != null ? _a2 : "Differences";
|
|
152151
|
+
const filterMenu = /* @__PURE__ */ React.createElement(Menu, null, FILTER_OPTIONS.map(({ value, label }) => {
|
|
152152
|
+
var _a3;
|
|
152153
|
+
const count2 = (_a3 = countsByType[value]) != null ? _a3 : 0;
|
|
152154
|
+
const isActive2 = activeFilter === value;
|
|
152155
|
+
return /* @__PURE__ */ React.createElement(
|
|
152156
|
+
MenuItem,
|
|
152157
|
+
{
|
|
152158
|
+
key: value,
|
|
152159
|
+
active: isActive2,
|
|
152160
|
+
onClick: /* @__PURE__ */ __name(() => setActiveFilter(value), "onClick"),
|
|
152161
|
+
text: /* @__PURE__ */ React.createElement("span", { className: "veDiffMenuItem-inner" }, label, /* @__PURE__ */ React.createElement(Tag, { round: true, minimal: true, style: { marginLeft: 6 } }, count2))
|
|
152162
|
+
}
|
|
152163
|
+
);
|
|
152164
|
+
}));
|
|
152165
|
+
return /* @__PURE__ */ React.createElement("div", { className: "veDiffNavigator" }, /* @__PURE__ */ React.createElement(
|
|
152166
|
+
Popover,
|
|
152167
|
+
{
|
|
152168
|
+
minimal: true,
|
|
152169
|
+
position: Position.BOTTOM_LEFT,
|
|
152170
|
+
content: filterMenu,
|
|
152171
|
+
target: /* @__PURE__ */ React.createElement(
|
|
152172
|
+
Button,
|
|
152173
|
+
{
|
|
152174
|
+
minimal: true,
|
|
152175
|
+
"data-tip": "Filter Difference Type",
|
|
152176
|
+
small: true,
|
|
152177
|
+
rightIcon: "caret-down",
|
|
152178
|
+
className: "veDiffFilter-trigger"
|
|
152179
|
+
},
|
|
152180
|
+
activeLabel
|
|
152181
|
+
)
|
|
152182
|
+
}
|
|
152183
|
+
), noDifferences ? /* @__PURE__ */ React.createElement("span", { className: "veDiffNav-empty" }, "no", " ", activeFilter === "all" ? "differences" : activeLabel.toLowerCase()) : /* @__PURE__ */ React.createElement("div", { className: "veDiffNav" }, /* @__PURE__ */ React.createElement(
|
|
152184
|
+
Button,
|
|
152185
|
+
{
|
|
152186
|
+
minimal: true,
|
|
152187
|
+
small: true,
|
|
152188
|
+
"data-tip": "Previous Difference",
|
|
152189
|
+
icon: "arrow-left",
|
|
152190
|
+
intent: Intent.PRIMARY,
|
|
152191
|
+
onClick: prevDifference,
|
|
152192
|
+
disabled: disablePrev
|
|
152193
|
+
}
|
|
152194
|
+
), /* @__PURE__ */ React.createElement("div", { className: "veDiffNav-center" }, /* @__PURE__ */ React.createElement("span", { className: "veDiffNav-fraction" }, currentIdx, /* @__PURE__ */ React.createElement("span", { className: "veDiffNav-sep" }, "/"), differences.length - 1), (currentDiff == null ? void 0 : currentDiff.start) > -1 && /* @__PURE__ */ React.createElement("span", { className: "veDiffNav-pos" }, ":", currentDiff.start + 1)), /* @__PURE__ */ React.createElement(
|
|
152195
|
+
Button,
|
|
152196
|
+
{
|
|
152197
|
+
minimal: true,
|
|
152198
|
+
small: true,
|
|
152199
|
+
"data-tip": "Next Difference",
|
|
152200
|
+
icon: "arrow-right",
|
|
152201
|
+
intent: Intent.PRIMARY,
|
|
152202
|
+
onClick: nextDifference,
|
|
152203
|
+
disabled: disableNext
|
|
152204
|
+
}
|
|
152205
|
+
)));
|
|
152206
|
+
}
|
|
152207
|
+
__name(FindMismatches, "FindMismatches");
|
|
152208
|
+
function getGapMap(sequence2) {
|
|
152209
|
+
const gapMap = [0];
|
|
152210
|
+
sequence2.split("").forEach((char) => {
|
|
152211
|
+
if (char === "-") {
|
|
152212
|
+
gapMap[Math.max(0, gapMap.length - 1)] = (gapMap[Math.max(0, gapMap.length - 1)] || 0) + 1;
|
|
152213
|
+
} else {
|
|
152214
|
+
gapMap.push(gapMap[gapMap.length - 1] || 0);
|
|
152215
|
+
}
|
|
152216
|
+
});
|
|
152217
|
+
return gapMap;
|
|
152218
|
+
}
|
|
152219
|
+
__name(getGapMap, "getGapMap");
|
|
152220
|
+
const MATCH_COLOR = "gold";
|
|
152221
|
+
const CURRENT_MATCH_COLOR = "green";
|
|
152222
|
+
const MISMATCH_COLOR = "red";
|
|
152223
|
+
const ANNOTATION_TYPES = ["features", "parts", "primers"];
|
|
152224
|
+
const initialSearchState = {
|
|
152225
|
+
searchText: "",
|
|
152226
|
+
matches: [],
|
|
152227
|
+
currentMatchIndex: 0,
|
|
152228
|
+
searched: false,
|
|
152229
|
+
featureMatches: [],
|
|
152230
|
+
dnaOrAA: "DNA",
|
|
152231
|
+
ambiguousOrLiteral: "LITERAL",
|
|
152232
|
+
mismatchesAllowed: 0
|
|
152233
|
+
};
|
|
152234
|
+
function searchReducer(state2, action2) {
|
|
152235
|
+
switch (action2.type) {
|
|
152236
|
+
case "SET_SEARCH_TEXT":
|
|
152237
|
+
return __spreadProps(__spreadValues({}, state2), { searchText: action2.payload });
|
|
152238
|
+
case "SET_MATCHES":
|
|
152239
|
+
return __spreadProps(__spreadValues({}, state2), {
|
|
152240
|
+
matches: action2.payload.matches,
|
|
152241
|
+
currentMatchIndex: action2.payload.currentMatchIndex
|
|
152242
|
+
});
|
|
152243
|
+
case "SET_CURRENT_MATCH_INDEX":
|
|
152244
|
+
return __spreadProps(__spreadValues({}, state2), { currentMatchIndex: action2.payload });
|
|
152245
|
+
case "SET_SEARCHED":
|
|
152246
|
+
return __spreadProps(__spreadValues({}, state2), { searched: action2.payload });
|
|
152247
|
+
case "SEARCH_COMPLETE":
|
|
152248
|
+
return __spreadProps(__spreadValues({}, state2), {
|
|
152249
|
+
matches: action2.payload.matches,
|
|
152250
|
+
currentMatchIndex: action2.payload.currentMatchIndex,
|
|
152251
|
+
searched: action2.payload.searched
|
|
152252
|
+
});
|
|
152253
|
+
case "SET_FEATURE_MATCHES":
|
|
152254
|
+
return __spreadProps(__spreadValues({}, state2), { featureMatches: action2.payload });
|
|
152255
|
+
case "SET_DNA_OR_AA":
|
|
152256
|
+
return __spreadProps(__spreadValues({}, state2), { dnaOrAA: action2.payload });
|
|
152257
|
+
case "SET_AMBIGUOUS_OR_LITERAL":
|
|
152258
|
+
return __spreadProps(__spreadValues({}, state2), { ambiguousOrLiteral: action2.payload });
|
|
152259
|
+
case "SET_MISMATCHES_ALLOWED":
|
|
152260
|
+
return __spreadProps(__spreadValues({}, state2), { mismatchesAllowed: Math.max(0, action2.payload) });
|
|
152261
|
+
case "RESET":
|
|
152262
|
+
return __spreadValues({}, initialSearchState);
|
|
152263
|
+
default:
|
|
152264
|
+
return state2;
|
|
152265
|
+
}
|
|
152266
|
+
}
|
|
152267
|
+
__name(searchReducer, "searchReducer");
|
|
152268
|
+
function AlignmentSearchBar(props) {
|
|
152269
|
+
const { alignmentTracks = [], setSearchMatchLayers } = props;
|
|
152270
|
+
const [searchState, dispatch] = reactExports.useReducer(searchReducer, initialSearchState);
|
|
152271
|
+
const {
|
|
152272
|
+
searchText,
|
|
152273
|
+
matches,
|
|
152274
|
+
currentMatchIndex,
|
|
152275
|
+
searched,
|
|
152276
|
+
featureMatches,
|
|
152277
|
+
dnaOrAA,
|
|
152278
|
+
ambiguousOrLiteral,
|
|
152279
|
+
mismatchesAllowed
|
|
152280
|
+
} = searchState;
|
|
152281
|
+
const debouncedSearch = reactExports.useRef(
|
|
152282
|
+
debounce((text2, search2, featureSearch) => {
|
|
152283
|
+
search2(text2);
|
|
152284
|
+
featureSearch(text2);
|
|
152285
|
+
}, 50)
|
|
152286
|
+
).current;
|
|
152287
|
+
reactExports.useEffect(() => {
|
|
152288
|
+
return () => {
|
|
152289
|
+
debouncedSearch.cancel();
|
|
152290
|
+
};
|
|
152291
|
+
}, [debouncedSearch]);
|
|
152292
|
+
const [highlightAll, setHighlightAll] = reactExports.useState(false);
|
|
152293
|
+
const [isExpanded, setIsExpanded] = reactExports.useState(false);
|
|
152294
|
+
const [isOpen2, setIsOpen] = reactExports.useState(false);
|
|
152295
|
+
const [isPopoverOpen, setIsPopoverOpen] = reactExports.useState(false);
|
|
152296
|
+
const handleToggleExpanded = reactExports.useCallback(() => {
|
|
152297
|
+
setIsExpanded((prev) => {
|
|
152298
|
+
const next = !prev;
|
|
152299
|
+
if (!next) setIsPopoverOpen(true);
|
|
152300
|
+
return next;
|
|
152301
|
+
});
|
|
152302
|
+
}, [setIsPopoverOpen]);
|
|
152303
|
+
reactExports.useEffect(() => {
|
|
152304
|
+
dispatch({ type: "RESET" });
|
|
152305
|
+
if (setSearchMatchLayers) setSearchMatchLayers([]);
|
|
152306
|
+
}, [setSearchMatchLayers]);
|
|
152307
|
+
const buildMatchLayers = reactExports.useCallback(
|
|
152308
|
+
(allMatches, activeIndex) => {
|
|
152309
|
+
if (!setSearchMatchLayers) return;
|
|
152310
|
+
if (!allMatches.length) {
|
|
152311
|
+
setSearchMatchLayers([]);
|
|
152312
|
+
return;
|
|
152313
|
+
}
|
|
152314
|
+
const makeMismatchLayers = /* @__PURE__ */ __name((match) => (match.mismatchAlignmentPositions || []).map((pos) => ({
|
|
152315
|
+
start: pos,
|
|
152316
|
+
end: pos,
|
|
152317
|
+
color: MISMATCH_COLOR,
|
|
152318
|
+
className: "veSearchMismatch",
|
|
152319
|
+
ignoreGaps: true,
|
|
152320
|
+
hideCarets: true
|
|
152321
|
+
})), "makeMismatchLayers");
|
|
152322
|
+
const layers = highlightAll ? allMatches.flatMap((match, i2) => [
|
|
152323
|
+
{
|
|
152324
|
+
start: match.alignmentStart,
|
|
152325
|
+
end: match.alignmentEnd,
|
|
152326
|
+
color: i2 === activeIndex ? CURRENT_MATCH_COLOR : MATCH_COLOR,
|
|
152327
|
+
className: i2 === activeIndex ? "veSearchLayerActive" : "veSearchLayer",
|
|
152328
|
+
ignoreGaps: true
|
|
152329
|
+
},
|
|
152330
|
+
...makeMismatchLayers(match)
|
|
152331
|
+
]) : [
|
|
152332
|
+
{
|
|
152333
|
+
start: allMatches[activeIndex].alignmentStart,
|
|
152334
|
+
end: allMatches[activeIndex].alignmentEnd,
|
|
152335
|
+
color: CURRENT_MATCH_COLOR,
|
|
152336
|
+
className: "veSearchLayerActive",
|
|
152337
|
+
ignoreGaps: true
|
|
152338
|
+
},
|
|
152339
|
+
...makeMismatchLayers(allMatches[activeIndex])
|
|
152340
|
+
];
|
|
152341
|
+
setSearchMatchLayers(layers);
|
|
152342
|
+
},
|
|
152343
|
+
[setSearchMatchLayers, highlightAll]
|
|
152344
|
+
);
|
|
152345
|
+
const navigateTo = reactExports.useCallback(
|
|
152346
|
+
(allMatches, index2) => {
|
|
152347
|
+
const match = allMatches[index2];
|
|
152348
|
+
if (!match) return;
|
|
152349
|
+
updateCaretPosition({
|
|
152350
|
+
start: match.alignmentStart,
|
|
152351
|
+
end: match.alignmentEnd
|
|
152352
|
+
});
|
|
152353
|
+
setTimeout(() => {
|
|
152354
|
+
scrollToAlignmentSelection();
|
|
152355
|
+
}, 0);
|
|
152356
|
+
buildMatchLayers(allMatches, index2);
|
|
152357
|
+
},
|
|
152358
|
+
[buildMatchLayers]
|
|
152359
|
+
);
|
|
152360
|
+
const runSearch = reactExports.useCallback(
|
|
152361
|
+
(text2) => {
|
|
152362
|
+
const query = text2.trim();
|
|
152363
|
+
if (!query) {
|
|
152364
|
+
dispatch({
|
|
152365
|
+
type: "SEARCH_COMPLETE",
|
|
152366
|
+
payload: { matches: [], currentMatchIndex: 0, searched: false }
|
|
152367
|
+
});
|
|
152368
|
+
if (setSearchMatchLayers) setSearchMatchLayers([]);
|
|
152369
|
+
return;
|
|
152370
|
+
}
|
|
152371
|
+
const allMatches = [];
|
|
152372
|
+
alignmentTracks.slice(0, 1).forEach((track, trackIndex) => {
|
|
152373
|
+
var _a2, _b2;
|
|
152374
|
+
const rawSeq = ((_a2 = track.sequenceData) == null ? void 0 : _a2.sequence) || "";
|
|
152375
|
+
const alignedSeq = ((_b2 = track.alignmentData) == null ? void 0 : _b2.sequence) || "";
|
|
152376
|
+
const gapMap = getGapMap(alignedSeq);
|
|
152377
|
+
const gapOffset = /* @__PURE__ */ __name((n2) => {
|
|
152378
|
+
var _a3, _b3;
|
|
152379
|
+
return (_b3 = (_a3 = gapMap[n2]) != null ? _a3 : gapMap[gapMap.length - 1]) != null ? _b3 : 0;
|
|
152380
|
+
}, "gapOffset");
|
|
152381
|
+
let seqMatches = [];
|
|
152382
|
+
if (dnaOrAA === "DNA" && ambiguousOrLiteral === "LITERAL" && mismatchesAllowed > 0) {
|
|
152383
|
+
const approxMatches = findApproxMatches(
|
|
152384
|
+
query.toLowerCase(),
|
|
152385
|
+
rawSeq.toLowerCase(),
|
|
152386
|
+
mismatchesAllowed,
|
|
152387
|
+
false
|
|
152388
|
+
);
|
|
152389
|
+
seqMatches = approxMatches.map((m2) => ({
|
|
152390
|
+
start: m2.index,
|
|
152391
|
+
end: m2.index + m2.match.length - 1,
|
|
152392
|
+
mismatchPositions: m2.mismatchPositions
|
|
152393
|
+
}));
|
|
152394
|
+
} else {
|
|
152395
|
+
seqMatches = findSequenceMatches(rawSeq, query, {
|
|
152396
|
+
isCircular: false,
|
|
152397
|
+
isAmbiguous: ambiguousOrLiteral === "AMBIGUOUS",
|
|
152398
|
+
isProteinSearch: dnaOrAA !== "DNA",
|
|
152399
|
+
searchReverseStrand: dnaOrAA === "DNA"
|
|
152400
|
+
});
|
|
152401
|
+
}
|
|
152402
|
+
const hitsToProcess = query.length < 2 ? seqMatches.slice(0, 1) : seqMatches;
|
|
152403
|
+
hitsToProcess.forEach(({ start: start2, end: end2, mismatchPositions }) => {
|
|
152404
|
+
const alignmentStart = start2 + gapOffset(start2);
|
|
152405
|
+
const alignmentEnd = end2 + gapOffset(end2);
|
|
152406
|
+
const mismatchAlignmentPositions = (mismatchPositions || []).map(
|
|
152407
|
+
(p2) => {
|
|
152408
|
+
const absPos = start2 + p2;
|
|
152409
|
+
return absPos + gapOffset(absPos);
|
|
152410
|
+
}
|
|
152411
|
+
);
|
|
152412
|
+
allMatches.push({
|
|
152413
|
+
trackIndex,
|
|
152414
|
+
alignmentStart,
|
|
152415
|
+
alignmentEnd,
|
|
152416
|
+
mismatchAlignmentPositions
|
|
152417
|
+
});
|
|
152418
|
+
});
|
|
152419
|
+
});
|
|
152420
|
+
const results = query.length < 2 ? allMatches.slice(0, 1) : allMatches;
|
|
152421
|
+
dispatch({
|
|
152422
|
+
type: "SEARCH_COMPLETE",
|
|
152423
|
+
payload: { matches: results, currentMatchIndex: 0, searched: true }
|
|
152424
|
+
});
|
|
152425
|
+
if (results.length) {
|
|
152426
|
+
navigateTo(results, 0);
|
|
152427
|
+
} else {
|
|
152428
|
+
if (setSearchMatchLayers) setSearchMatchLayers([]);
|
|
152429
|
+
}
|
|
152430
|
+
},
|
|
152431
|
+
[
|
|
152432
|
+
alignmentTracks,
|
|
152433
|
+
navigateTo,
|
|
152434
|
+
dnaOrAA,
|
|
152435
|
+
ambiguousOrLiteral,
|
|
152436
|
+
mismatchesAllowed,
|
|
152437
|
+
setSearchMatchLayers
|
|
152438
|
+
]
|
|
152439
|
+
);
|
|
152440
|
+
const runFeatureSearch = reactExports.useCallback(
|
|
152441
|
+
(text2) => {
|
|
152442
|
+
const query = text2.trim().toLowerCase();
|
|
152443
|
+
if (!query) {
|
|
152444
|
+
dispatch({ type: "SET_FEATURE_MATCHES", payload: [] });
|
|
152445
|
+
return;
|
|
152446
|
+
}
|
|
152447
|
+
const allMatches = [];
|
|
152448
|
+
alignmentTracks.slice(0, 1).forEach((track, trackIndex) => {
|
|
152449
|
+
const { sequenceData: sequenceData2, alignmentData } = track;
|
|
152450
|
+
const alignedSeq = (alignmentData == null ? void 0 : alignmentData.sequence) || "";
|
|
152451
|
+
const gapMap = getGapMap(alignedSeq);
|
|
152452
|
+
const gapOffset = /* @__PURE__ */ __name((n2) => {
|
|
152453
|
+
var _a2, _b2;
|
|
152454
|
+
return (_b2 = (_a2 = gapMap[n2]) != null ? _a2 : gapMap[gapMap.length - 1]) != null ? _b2 : 0;
|
|
152455
|
+
}, "gapOffset");
|
|
152456
|
+
const trackName = (alignmentData == null ? void 0 : alignmentData.name) || (sequenceData2 == null ? void 0 : sequenceData2.name) || (sequenceData2 == null ? void 0 : sequenceData2.id) || "";
|
|
152457
|
+
ANNOTATION_TYPES.forEach((type2) => {
|
|
152458
|
+
const anns = sequenceData2 == null ? void 0 : sequenceData2[type2];
|
|
152459
|
+
if (!anns) return;
|
|
152460
|
+
const annsArray = Array.isArray(anns) ? anns : Object.values(anns);
|
|
152461
|
+
annsArray.forEach((ann) => {
|
|
152462
|
+
if (!ann.name) return;
|
|
152463
|
+
if (ann.name.toLowerCase().includes(query)) {
|
|
152464
|
+
const alignmentStart = ann.start + gapOffset(ann.start);
|
|
152465
|
+
const alignmentEnd = ann.end + gapOffset(ann.end);
|
|
152466
|
+
allMatches.push({
|
|
152467
|
+
trackIndex,
|
|
152468
|
+
trackName,
|
|
152469
|
+
type: type2,
|
|
152470
|
+
annotation: ann,
|
|
152471
|
+
alignmentStart,
|
|
152472
|
+
alignmentEnd
|
|
152473
|
+
});
|
|
152474
|
+
}
|
|
152475
|
+
});
|
|
152476
|
+
});
|
|
152477
|
+
});
|
|
152478
|
+
dispatch({ type: "SET_FEATURE_MATCHES", payload: allMatches });
|
|
152479
|
+
},
|
|
152480
|
+
[alignmentTracks]
|
|
152481
|
+
);
|
|
152482
|
+
const goToPrev = reactExports.useCallback(() => {
|
|
152483
|
+
if (!matches.length) return;
|
|
152484
|
+
const newIndex = currentMatchIndex === 0 ? matches.length - 1 : currentMatchIndex - 1;
|
|
152485
|
+
dispatch({ type: "SET_CURRENT_MATCH_INDEX", payload: newIndex });
|
|
152486
|
+
navigateTo(matches, newIndex);
|
|
152487
|
+
}, [matches, currentMatchIndex, navigateTo]);
|
|
152488
|
+
const goToNext = reactExports.useCallback(() => {
|
|
152489
|
+
if (!matches.length) return;
|
|
152490
|
+
const newIndex = currentMatchIndex === matches.length - 1 ? 0 : currentMatchIndex + 1;
|
|
152491
|
+
dispatch({ type: "SET_CURRENT_MATCH_INDEX", payload: newIndex });
|
|
152492
|
+
navigateTo(matches, newIndex);
|
|
152493
|
+
}, [matches, currentMatchIndex, navigateTo]);
|
|
152494
|
+
const handleKeyDown = reactExports.useCallback(
|
|
152495
|
+
(e2) => {
|
|
152496
|
+
if (e2.key === "Escape") {
|
|
152497
|
+
setIsOpen(false);
|
|
152498
|
+
}
|
|
152499
|
+
if (e2.key === "Enter") {
|
|
152500
|
+
if (e2.shiftKey) {
|
|
152501
|
+
goToPrev();
|
|
152502
|
+
} else {
|
|
152503
|
+
goToNext();
|
|
152504
|
+
}
|
|
152505
|
+
e2.preventDefault();
|
|
152506
|
+
e2.stopPropagation();
|
|
152507
|
+
}
|
|
152508
|
+
},
|
|
152509
|
+
[goToPrev, goToNext]
|
|
152510
|
+
);
|
|
152511
|
+
reactExports.useEffect(() => {
|
|
152512
|
+
if (!searched || !searchText.trim()) return;
|
|
152513
|
+
runSearch(searchText);
|
|
152514
|
+
runFeatureSearch(searchText);
|
|
152515
|
+
}, [
|
|
152516
|
+
dnaOrAA,
|
|
152517
|
+
ambiguousOrLiteral,
|
|
152518
|
+
mismatchesAllowed,
|
|
152519
|
+
runSearch,
|
|
152520
|
+
runFeatureSearch,
|
|
152521
|
+
searched,
|
|
152522
|
+
searchText
|
|
152523
|
+
]);
|
|
152524
|
+
reactExports.useEffect(() => {
|
|
152525
|
+
if (searchText.trim().length < 1) setHighlightAll(false);
|
|
152526
|
+
}, [searchText]);
|
|
152527
|
+
const prevHighlightAll = reactExports.useRef(highlightAll);
|
|
152528
|
+
reactExports.useEffect(() => {
|
|
152529
|
+
if (prevHighlightAll.current !== highlightAll) {
|
|
152530
|
+
prevHighlightAll.current = highlightAll;
|
|
152531
|
+
if (matches.length) buildMatchLayers(matches, currentMatchIndex);
|
|
152532
|
+
}
|
|
152533
|
+
}, [highlightAll, matches, currentMatchIndex, buildMatchLayers]);
|
|
152534
|
+
const hasMatches = matches.length > 0;
|
|
152535
|
+
const handleChange = reactExports.useCallback(
|
|
152536
|
+
(e2) => {
|
|
152537
|
+
const value = e2.target.value;
|
|
152538
|
+
dispatch({ type: "SET_SEARCH_TEXT", payload: value });
|
|
152539
|
+
debouncedSearch(value, runSearch, runFeatureSearch);
|
|
152540
|
+
},
|
|
152541
|
+
[debouncedSearch, runSearch, runFeatureSearch]
|
|
152542
|
+
);
|
|
152543
|
+
const handleFeatureClick = reactExports.useCallback((featureMatch) => {
|
|
152544
|
+
updateCaretPosition({
|
|
152545
|
+
start: featureMatch.alignmentStart,
|
|
152546
|
+
end: featureMatch.alignmentEnd
|
|
152547
|
+
});
|
|
152548
|
+
setTimeout(() => {
|
|
152549
|
+
scrollToAlignmentSelection();
|
|
152550
|
+
}, 0);
|
|
152551
|
+
}, []);
|
|
152552
|
+
const matchCounter = /* @__PURE__ */ React.createElement(
|
|
152553
|
+
"span",
|
|
152554
|
+
{
|
|
152555
|
+
style: {
|
|
152556
|
+
marginRight: 3,
|
|
152557
|
+
color: "lightgrey",
|
|
152558
|
+
fontSize: "0.9em",
|
|
152559
|
+
whiteSpace: "nowrap"
|
|
152560
|
+
}
|
|
152561
|
+
},
|
|
152562
|
+
hasMatches ? currentMatchIndex + 1 : 0,
|
|
152563
|
+
"/",
|
|
152564
|
+
matches.length
|
|
152565
|
+
);
|
|
152566
|
+
const inlineNavEl = /* @__PURE__ */ React.createElement("span", { style: { display: "flex", alignItems: "center" } }, !isExpanded && /* @__PURE__ */ React.createElement(
|
|
152567
|
+
Popover,
|
|
152568
|
+
{
|
|
152569
|
+
autoFocus: false,
|
|
152570
|
+
enforceFocus: false,
|
|
152571
|
+
isOpen: isPopoverOpen,
|
|
152572
|
+
onInteraction: setIsPopoverOpen,
|
|
152573
|
+
position: Position.TOP,
|
|
152574
|
+
content: /* @__PURE__ */ React.createElement(
|
|
152575
|
+
"div",
|
|
152576
|
+
{
|
|
152577
|
+
className: "ve-find-options-popover",
|
|
152578
|
+
style: {
|
|
152579
|
+
display: "flex",
|
|
152580
|
+
flexDirection: "column",
|
|
152581
|
+
paddingLeft: 20,
|
|
152582
|
+
paddingBottom: 10,
|
|
152583
|
+
paddingTop: 10,
|
|
152584
|
+
paddingRight: 20,
|
|
152585
|
+
gap: 6
|
|
152586
|
+
}
|
|
152587
|
+
},
|
|
152588
|
+
/* @__PURE__ */ React.createElement(
|
|
152589
|
+
FindOptionsPanel,
|
|
152590
|
+
{
|
|
152591
|
+
dnaOrAA,
|
|
152592
|
+
ambiguousOrLiteral,
|
|
152593
|
+
mismatchesAllowed,
|
|
152594
|
+
searchText,
|
|
152595
|
+
matches,
|
|
152596
|
+
dispatch,
|
|
152597
|
+
highlightAll,
|
|
152598
|
+
setHighlightAll,
|
|
152599
|
+
isExpanded,
|
|
152600
|
+
onToggleExpanded: handleToggleExpanded
|
|
152601
|
+
}
|
|
152602
|
+
)
|
|
152603
|
+
),
|
|
152604
|
+
target: /* @__PURE__ */ React.createElement(Button, { minimal: true, icon: "wrench", "data-tip": "Options" })
|
|
152605
|
+
}
|
|
152606
|
+
), matchCounter, /* @__PURE__ */ React.createElement(
|
|
152607
|
+
Button,
|
|
152608
|
+
{
|
|
152609
|
+
minimal: true,
|
|
152610
|
+
small: true,
|
|
152611
|
+
icon: "caret-left",
|
|
152612
|
+
"data-tip": "Previous",
|
|
152613
|
+
disabled: !hasMatches,
|
|
152614
|
+
onClick: goToPrev
|
|
152615
|
+
}
|
|
152616
|
+
), /* @__PURE__ */ React.createElement(
|
|
152617
|
+
Button,
|
|
152618
|
+
{
|
|
152619
|
+
minimal: true,
|
|
152620
|
+
small: true,
|
|
152621
|
+
icon: "caret-right",
|
|
152622
|
+
"data-tip": "Next",
|
|
152623
|
+
disabled: !hasMatches,
|
|
152624
|
+
onClick: goToNext
|
|
152625
|
+
}
|
|
152626
|
+
), /* @__PURE__ */ React.createElement(
|
|
152627
|
+
Button,
|
|
152628
|
+
{
|
|
152629
|
+
minimal: true,
|
|
152630
|
+
small: true,
|
|
152631
|
+
"data-tip": "Close (Esc)",
|
|
152632
|
+
icon: "small-cross",
|
|
152633
|
+
onClick: /* @__PURE__ */ __name(() => setIsOpen(false), "onClick")
|
|
152634
|
+
}
|
|
152635
|
+
));
|
|
152636
|
+
const expandedNavEl = /* @__PURE__ */ React.createElement("span", { style: { display: "flex", alignItems: "center" } }, matchCounter, /* @__PURE__ */ React.createElement(
|
|
152637
|
+
Button,
|
|
152638
|
+
{
|
|
152639
|
+
minimal: true,
|
|
152640
|
+
small: true,
|
|
152641
|
+
icon: "caret-up",
|
|
152642
|
+
disabled: !hasMatches,
|
|
152643
|
+
onClick: goToPrev
|
|
152644
|
+
}
|
|
152645
|
+
), /* @__PURE__ */ React.createElement(
|
|
152646
|
+
Button,
|
|
152647
|
+
{
|
|
152648
|
+
minimal: true,
|
|
152649
|
+
small: true,
|
|
152650
|
+
icon: "caret-down",
|
|
152651
|
+
disabled: !hasMatches,
|
|
152652
|
+
onClick: goToNext
|
|
152653
|
+
}
|
|
152654
|
+
));
|
|
152655
|
+
if (!isOpen2) {
|
|
152656
|
+
return /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement(
|
|
152657
|
+
Button,
|
|
152658
|
+
{
|
|
152659
|
+
minimal: true,
|
|
152660
|
+
small: true,
|
|
152661
|
+
intent: "primary",
|
|
152662
|
+
icon: "search",
|
|
152663
|
+
rightIcon: "caret-right",
|
|
152664
|
+
"data-tip": "Search",
|
|
152665
|
+
onClick: /* @__PURE__ */ __name(() => setIsOpen(true), "onClick")
|
|
152666
|
+
}
|
|
152667
|
+
));
|
|
152668
|
+
}
|
|
152669
|
+
const annotationPopoverOpen = searched && featureMatches.length > 0;
|
|
152670
|
+
const inputEl = /* @__PURE__ */ React.createElement(
|
|
152671
|
+
InputGroup,
|
|
152672
|
+
{
|
|
152673
|
+
className: "tg-find-tool-input alignment-search-bar",
|
|
152674
|
+
leftIcon: "search",
|
|
152675
|
+
placeholder: "Search...",
|
|
152676
|
+
autoFocus: true,
|
|
152677
|
+
value: searchText,
|
|
152678
|
+
onChange: handleChange,
|
|
152679
|
+
onKeyDown: handleKeyDown,
|
|
152680
|
+
rightElement: inlineNavEl
|
|
152681
|
+
}
|
|
152682
|
+
);
|
|
152683
|
+
return /* @__PURE__ */ React.createElement("div", { style: { position: "relative" } }, !isExpanded && /* @__PURE__ */ React.createElement(
|
|
152684
|
+
Popover,
|
|
152685
|
+
{
|
|
152686
|
+
autoFocus: false,
|
|
152687
|
+
enforceFocus: false,
|
|
152688
|
+
modifiers: {
|
|
152689
|
+
arrow: false
|
|
152690
|
+
},
|
|
152691
|
+
position: Position.BOTTOM,
|
|
152692
|
+
isOpen: annotationPopoverOpen,
|
|
152693
|
+
content: /* @__PURE__ */ React.createElement(
|
|
152694
|
+
AnnotationResultsComp,
|
|
152695
|
+
{
|
|
152696
|
+
featureMatches,
|
|
152697
|
+
onClickMatch: handleFeatureClick
|
|
152698
|
+
}
|
|
152699
|
+
),
|
|
152700
|
+
target: inputEl
|
|
152701
|
+
}
|
|
152702
|
+
), isExpanded && /* @__PURE__ */ React.createElement(
|
|
152703
|
+
"div",
|
|
152704
|
+
{
|
|
152705
|
+
style: {
|
|
152706
|
+
position: "absolute",
|
|
152707
|
+
top: 0,
|
|
152708
|
+
left: 0,
|
|
152709
|
+
padding: 10,
|
|
152710
|
+
paddingBottom: 25,
|
|
152711
|
+
display: "flex",
|
|
152712
|
+
alignItems: "flex-start",
|
|
152713
|
+
gap: 10,
|
|
152714
|
+
zIndex: 5e4,
|
|
152715
|
+
background: "white",
|
|
152716
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.2)",
|
|
152717
|
+
borderRadius: 3
|
|
152718
|
+
}
|
|
152719
|
+
},
|
|
152720
|
+
/* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 6 } }, /* @__PURE__ */ React.createElement(
|
|
152721
|
+
TextArea,
|
|
152722
|
+
{
|
|
152723
|
+
autoFocus: true,
|
|
152724
|
+
placeholder: "Search sequences and annotations...",
|
|
152725
|
+
value: searchText,
|
|
152726
|
+
onChange: handleChange,
|
|
152727
|
+
onKeyDown: handleKeyDown,
|
|
152728
|
+
style: { resize: "vertical", width: 350, height: 190 }
|
|
152729
|
+
}
|
|
152730
|
+
), annotationPopoverOpen && /* @__PURE__ */ React.createElement(
|
|
152731
|
+
AnnotationResultsComp,
|
|
152732
|
+
{
|
|
152733
|
+
featureMatches,
|
|
152734
|
+
onClickMatch: handleFeatureClick
|
|
152735
|
+
}
|
|
152736
|
+
)),
|
|
152737
|
+
/* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 5 } }, expandedNavEl, /* @__PURE__ */ React.createElement(
|
|
152738
|
+
FindOptionsPanel,
|
|
152739
|
+
{
|
|
152740
|
+
dnaOrAA,
|
|
152741
|
+
ambiguousOrLiteral,
|
|
152742
|
+
mismatchesAllowed,
|
|
152743
|
+
searchText,
|
|
152744
|
+
matches,
|
|
152745
|
+
dispatch,
|
|
152746
|
+
highlightAll,
|
|
152747
|
+
setHighlightAll,
|
|
152748
|
+
isExpanded,
|
|
152749
|
+
onToggleExpanded: handleToggleExpanded
|
|
152750
|
+
}
|
|
152751
|
+
)),
|
|
152752
|
+
/* @__PURE__ */ React.createElement(
|
|
152753
|
+
Button,
|
|
152754
|
+
{
|
|
152755
|
+
minimal: true,
|
|
152756
|
+
style: { position: "absolute", bottom: 0, right: 0 },
|
|
152757
|
+
onClick: /* @__PURE__ */ __name(() => setIsOpen(false), "onClick"),
|
|
152758
|
+
icon: "cross"
|
|
152759
|
+
}
|
|
152760
|
+
)
|
|
152761
|
+
));
|
|
152762
|
+
}
|
|
152763
|
+
__name(AlignmentSearchBar, "AlignmentSearchBar");
|
|
152764
|
+
function AnnotationResultsComp({ featureMatches, onClickMatch }) {
|
|
152765
|
+
const byType = {};
|
|
152766
|
+
ANNOTATION_TYPES.forEach((type2) => {
|
|
152767
|
+
byType[type2] = [];
|
|
152768
|
+
});
|
|
152769
|
+
featureMatches.forEach((match) => {
|
|
152770
|
+
if (byType[match.type]) {
|
|
152771
|
+
byType[match.type].push(match);
|
|
152772
|
+
}
|
|
152773
|
+
});
|
|
152774
|
+
const featureColorMap = getFeatureToColorMap({ includeHidden: true });
|
|
152775
|
+
return /* @__PURE__ */ React.createElement("div", { className: "veAnnotationFindMatches" }, ANNOTATION_TYPES.map((type2) => {
|
|
152776
|
+
const anns = byType[type2];
|
|
152777
|
+
if (!anns.length) return null;
|
|
152778
|
+
const showing = anns.slice(0, 10);
|
|
152779
|
+
return /* @__PURE__ */ React.createElement("div", { key: type2 }, /* @__PURE__ */ React.createElement("div", { className: "veAnnotationFoundType" }, anns.length, " ", getSingular(type2), " match", anns.length > 1 ? "es" : null, anns.length > 10 ? ` (only showing 10)` : null, ":"), /* @__PURE__ */ React.createElement("div", null, showing.map((match, i2) => {
|
|
152780
|
+
const { annotation } = match;
|
|
152781
|
+
const annotationColor = type2 === "parts" ? "#ac68cc" : annotation.color || featureColorMap[annotation.type];
|
|
152782
|
+
return /* @__PURE__ */ React.createElement(
|
|
152783
|
+
"div",
|
|
152784
|
+
{
|
|
152785
|
+
key: i2,
|
|
152786
|
+
onClick: /* @__PURE__ */ __name(() => onClickMatch(match), "onClick"),
|
|
152787
|
+
className: "veAnnotationFoundResult"
|
|
152788
|
+
},
|
|
152789
|
+
/* @__PURE__ */ React.createElement("div", { style: { display: "flex", alignItems: "center" } }, /* @__PURE__ */ React.createElement(
|
|
152790
|
+
"div",
|
|
152791
|
+
{
|
|
152792
|
+
style: {
|
|
152793
|
+
background: annotationColor,
|
|
152794
|
+
height: 15,
|
|
152795
|
+
width: 15,
|
|
152796
|
+
marginRight: 3
|
|
152797
|
+
}
|
|
152798
|
+
}
|
|
152799
|
+
), annotation.name),
|
|
152800
|
+
/* @__PURE__ */ React.createElement("div", { className: "veAnnotationFoundResultRange" }, annotation.start + 1, "-", annotation.end + 1)
|
|
152801
|
+
);
|
|
152802
|
+
})));
|
|
152803
|
+
}));
|
|
152804
|
+
}
|
|
152805
|
+
__name(AnnotationResultsComp, "AnnotationResultsComp");
|
|
152806
|
+
function FindOptionsPanel({
|
|
152807
|
+
dnaOrAA,
|
|
152808
|
+
ambiguousOrLiteral,
|
|
152809
|
+
mismatchesAllowed,
|
|
152810
|
+
searchText,
|
|
152811
|
+
matches,
|
|
152812
|
+
dispatch,
|
|
152813
|
+
highlightAll,
|
|
152814
|
+
setHighlightAll,
|
|
152815
|
+
isExpanded,
|
|
152816
|
+
onToggleExpanded
|
|
152817
|
+
}) {
|
|
152818
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
|
|
152819
|
+
TgHTMLSelect,
|
|
152820
|
+
{
|
|
152821
|
+
options: [
|
|
152822
|
+
{ label: "DNA", value: "DNA" },
|
|
152823
|
+
{ label: "Amino Acids", value: "AA" }
|
|
152824
|
+
],
|
|
152825
|
+
value: dnaOrAA,
|
|
152826
|
+
onChange: /* @__PURE__ */ __name((e2) => dispatch({ type: "SET_DNA_OR_AA", payload: e2.target.value }), "onChange")
|
|
152827
|
+
}
|
|
152828
|
+
), /* @__PURE__ */ React.createElement("div", { style: { display: "flex" } }, /* @__PURE__ */ React.createElement(
|
|
152829
|
+
TgHTMLSelect,
|
|
152830
|
+
{
|
|
152831
|
+
options: [
|
|
152832
|
+
{ label: "Literal", value: "LITERAL" },
|
|
152833
|
+
{ label: "Ambiguous", value: "AMBIGUOUS" }
|
|
152834
|
+
],
|
|
152835
|
+
value: ambiguousOrLiteral,
|
|
152836
|
+
onChange: /* @__PURE__ */ __name((e2) => dispatch({
|
|
152837
|
+
type: "SET_AMBIGUOUS_OR_LITERAL",
|
|
152838
|
+
payload: e2.target.value
|
|
152839
|
+
}), "onChange")
|
|
152840
|
+
}
|
|
152841
|
+
), /* @__PURE__ */ React.createElement(InfoHelper, { style: { marginLeft: 10 } }, /* @__PURE__ */ React.createElement("div", null, "Ambiguous substitutions:", /* @__PURE__ */ React.createElement("div", { style: { display: "flex", fontSize: 12 } }, /* @__PURE__ */ React.createElement("div", { style: { marginRight: 20 } }, /* @__PURE__ */ React.createElement("div", { style: { fontSize: 14, marginBottom: 4, marginTop: 5 } }, "DNA:"), /* @__PURE__ */ React.createElement("div", null, "M: AC"), /* @__PURE__ */ React.createElement("div", null, "R: AG"), /* @__PURE__ */ React.createElement("div", null, "W: AT"), /* @__PURE__ */ React.createElement("div", null, "S: CG"), /* @__PURE__ */ React.createElement("div", null, "Y: CT"), /* @__PURE__ */ React.createElement("div", null, "K: GT"), /* @__PURE__ */ React.createElement("div", null, "V: ACG"), /* @__PURE__ */ React.createElement("div", null, "H: ACT"), /* @__PURE__ */ React.createElement("div", null, "D: AGT"), /* @__PURE__ */ React.createElement("div", null, "B: CGT"), /* @__PURE__ */ React.createElement("div", null, "X: GATC"), /* @__PURE__ */ React.createElement("div", null, "N: GATC"), /* @__PURE__ */ React.createElement("div", null, "*: any")), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("div", { style: { fontSize: 14, marginBottom: 4, marginTop: 5 } }, "AA:"), /* @__PURE__ */ React.createElement("div", null, "B: ND"), /* @__PURE__ */ React.createElement("div", null, "J: IL"), /* @__PURE__ */ React.createElement("div", null, "X: ACDEFGHIKLMNPQRSTVWY"), /* @__PURE__ */ React.createElement("div", null, "Z: QE"), /* @__PURE__ */ React.createElement("div", null, "*: any")))))), /* @__PURE__ */ React.createElement(
|
|
152842
|
+
"div",
|
|
152843
|
+
{
|
|
152844
|
+
style: {
|
|
152845
|
+
marginTop: "8px",
|
|
152846
|
+
display: "flex",
|
|
152847
|
+
flexDirection: "row",
|
|
152848
|
+
gap: "3px",
|
|
152849
|
+
alignItems: "center"
|
|
152850
|
+
}
|
|
152851
|
+
},
|
|
152852
|
+
/* @__PURE__ */ React.createElement("label", null, "Mismatches Allowed:"),
|
|
152853
|
+
/* @__PURE__ */ React.createElement(
|
|
152854
|
+
NumericInput,
|
|
152855
|
+
{
|
|
152856
|
+
min: 0,
|
|
152857
|
+
max: 10,
|
|
152858
|
+
className: "tg-mismatches-allowed-input",
|
|
152859
|
+
style: { width: "60px" },
|
|
152860
|
+
value: mismatchesAllowed,
|
|
152861
|
+
disabled: dnaOrAA !== "DNA" || ambiguousOrLiteral !== "LITERAL",
|
|
152862
|
+
onValueChange: /* @__PURE__ */ __name((value) => dispatch({
|
|
152863
|
+
type: "SET_MISMATCHES_ALLOWED",
|
|
152864
|
+
payload: Number.parseInt(value, 10) || 0
|
|
152865
|
+
}), "onValueChange")
|
|
152866
|
+
}
|
|
152867
|
+
),
|
|
152868
|
+
/* @__PURE__ */ React.createElement(InfoHelper, { style: { marginLeft: 10 } }, /* @__PURE__ */ React.createElement("div", null, "Number of mismatches allowed when searching DNA sequences with literal matching.", /* @__PURE__ */ React.createElement("br", null), /* @__PURE__ */ React.createElement("br", null), "Higher values may slow down search performance."))
|
|
152869
|
+
), /* @__PURE__ */ React.createElement(
|
|
152870
|
+
Switch,
|
|
152871
|
+
{
|
|
152872
|
+
checked: highlightAll,
|
|
152873
|
+
onChange: /* @__PURE__ */ __name(() => setHighlightAll((v2) => !v2), "onChange"),
|
|
152874
|
+
disabled: searchText.trim().length < 2 || matches.length > MAX_MATCHES_DISPLAYED
|
|
152875
|
+
},
|
|
152876
|
+
/* @__PURE__ */ React.createElement(
|
|
152877
|
+
Tooltip,
|
|
152878
|
+
{
|
|
152879
|
+
disabled: matches.length <= MAX_MATCHES_DISPLAYED,
|
|
152880
|
+
content: `Disabled because there are >${MAX_MATCHES_DISPLAYED} matches`
|
|
152881
|
+
},
|
|
152882
|
+
"Highlight All"
|
|
152883
|
+
)
|
|
152884
|
+
), /* @__PURE__ */ React.createElement(Switch, { checked: isExpanded, onChange: onToggleExpanded }, "Expanded"));
|
|
152885
|
+
}
|
|
152886
|
+
__name(FindOptionsPanel, "FindOptionsPanel");
|
|
151955
152887
|
const AlignmentVisibilityTool = pure(/* @__PURE__ */ __name(function AlignmentVisibilityTool2(props) {
|
|
151956
152888
|
return /* @__PURE__ */ React.createElement(
|
|
151957
152889
|
Popover,
|
|
@@ -151959,17 +152891,18 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
|
|
|
151959
152891
|
minimal: true,
|
|
151960
152892
|
position: "bottom",
|
|
151961
152893
|
content: /* @__PURE__ */ React.createElement(VisibilityOptions$2, __spreadValues({}, props)),
|
|
151962
|
-
target: /* @__PURE__ */ React.createElement(
|
|
152894
|
+
target: /* @__PURE__ */ React.createElement(
|
|
151963
152895
|
Button,
|
|
151964
152896
|
{
|
|
151965
152897
|
className: "tg-alignment-visibility-toggle",
|
|
151966
152898
|
small: true,
|
|
152899
|
+
"data-tip": "Visibility Options",
|
|
151967
152900
|
rightIcon: "caret-down",
|
|
151968
152901
|
intent: Intent.PRIMARY,
|
|
151969
152902
|
minimal: true,
|
|
151970
152903
|
icon: "eye-open"
|
|
151971
152904
|
}
|
|
151972
|
-
)
|
|
152905
|
+
)
|
|
151973
152906
|
}
|
|
151974
152907
|
);
|
|
151975
152908
|
}, "AlignmentVisibilityTool"));
|
|
@@ -165135,7 +166068,6 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
|
|
|
165135
166068
|
const PropertySidePanel = /* @__PURE__ */ __name(({ properties: properties2, setProperties, style: style2 }) => {
|
|
165136
166069
|
const sidebarRef = React.useRef(null);
|
|
165137
166070
|
const [mismatchesCount, setMismatchesCount] = React.useState(0);
|
|
165138
|
-
const [mismatchesInRange, setMismatchesInRange] = React.useState(0);
|
|
165139
166071
|
const { track, isOpen: isOpen2, selection, isPairwise } = properties2;
|
|
165140
166072
|
const getSequenceInRegion = reactExports.useCallback(() => {
|
|
165141
166073
|
var _a2, _b2;
|
|
@@ -165154,6 +166086,30 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
|
|
|
165154
166086
|
if (!Array.isArray(tr)) return [];
|
|
165155
166087
|
return isPairwise ? tr.filter((m2) => (m2 == null ? void 0 : m2.color) === "red") : tr;
|
|
165156
166088
|
}, [track, mismatchKey, isPairwise]);
|
|
166089
|
+
const mismatchSchema = reactExports.useMemo(
|
|
166090
|
+
() => ({
|
|
166091
|
+
fields: [
|
|
166092
|
+
{
|
|
166093
|
+
path: "start",
|
|
166094
|
+
type: "number",
|
|
166095
|
+
displayName: "Start",
|
|
166096
|
+
render: /* @__PURE__ */ __name((val2) => val2 + 1, "render")
|
|
166097
|
+
},
|
|
166098
|
+
{
|
|
166099
|
+
path: "end",
|
|
166100
|
+
type: "number",
|
|
166101
|
+
displayName: "End",
|
|
166102
|
+
render: /* @__PURE__ */ __name((val2) => val2 + 1, "render")
|
|
166103
|
+
}
|
|
166104
|
+
]
|
|
166105
|
+
}),
|
|
166106
|
+
[]
|
|
166107
|
+
);
|
|
166108
|
+
const mismatchEntities = reactExports.useMemo(() => {
|
|
166109
|
+
return (trackMismatches || []).map((m2, i2) => __spreadProps(__spreadValues({}, m2), {
|
|
166110
|
+
id: i2.toString()
|
|
166111
|
+
}));
|
|
166112
|
+
}, [trackMismatches]);
|
|
165157
166113
|
reactExports.useEffect(() => {
|
|
165158
166114
|
if (!isOpen2 || sidebarRef.current === null || !track) {
|
|
165159
166115
|
return;
|
|
@@ -165171,21 +166127,6 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
|
|
|
165171
166127
|
}
|
|
165172
166128
|
});
|
|
165173
166129
|
setMismatchesCount(mismatchCount);
|
|
165174
|
-
setMismatchesInRange(mismatchCount);
|
|
165175
|
-
if (selection && selection.start > -1 && selection.end > -1) {
|
|
165176
|
-
let count2 = 0;
|
|
165177
|
-
trackMismatches == null ? void 0 : trackMismatches.forEach((tm) => {
|
|
165178
|
-
if (tm === null || tm.start === null || tm.end === null) {
|
|
165179
|
-
return;
|
|
165180
|
-
}
|
|
165181
|
-
const overlapStart = Math.max(tm.start, selection.start);
|
|
165182
|
-
const overlapEnd = Math.min(tm.end, selection.end);
|
|
165183
|
-
if (overlapEnd >= overlapStart) {
|
|
165184
|
-
count2 += overlapEnd - overlapStart + 1;
|
|
165185
|
-
}
|
|
165186
|
-
});
|
|
165187
|
-
setMismatchesInRange(count2);
|
|
165188
|
-
}
|
|
165189
166130
|
}, [isOpen2, track, selection, trackMismatches]);
|
|
165190
166131
|
const aminoFreq = reactExports.useMemo(() => {
|
|
165191
166132
|
var _a2, _b2;
|
|
@@ -165221,7 +166162,7 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
|
|
|
165221
166162
|
width: "100%"
|
|
165222
166163
|
}
|
|
165223
166164
|
}
|
|
165224
|
-
), /* @__PURE__ */ React.createElement(
|
|
166165
|
+
), /* @__PURE__ */ React.createElement(HeaderItem, { title: "Track Properties" }), /* @__PURE__ */ React.createElement("div", { className: "bp3-tab-panel" }, /* @__PURE__ */ React.createElement(RowItem, { item: name2, title: "Name" }), /* @__PURE__ */ React.createElement(RowItem, { item: isProtein2 ? proteinSize : size2, title: "Length" }), /* @__PURE__ */ React.createElement(
|
|
165225
166166
|
RowItem,
|
|
165226
166167
|
{
|
|
165227
166168
|
item: molecularWeight == null ? void 0 : molecularWeight.toFixed(2),
|
|
@@ -165235,18 +166176,45 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
|
|
|
165235
166176
|
title: "Extinction Coefficient"
|
|
165236
166177
|
}
|
|
165237
166178
|
)), /* @__PURE__ */ React.createElement(
|
|
165238
|
-
RowItem,
|
|
165239
|
-
{
|
|
165240
|
-
item: `${mismatchesInRange}/${mismatchesCount}`,
|
|
165241
|
-
title: "Mismatches"
|
|
165242
|
-
}
|
|
165243
|
-
), /* @__PURE__ */ React.createElement(
|
|
165244
166179
|
RowItem,
|
|
165245
166180
|
{
|
|
165246
166181
|
item: selection && selection.start > -1 ? /* @__PURE__ */ React.createElement("span", null, selection.start + 1, " - ", selection.end + 1) : /* @__PURE__ */ React.createElement("span", null, "1 - ", isProtein2 ? proteinSize : size2),
|
|
165247
166182
|
title: "Region"
|
|
165248
166183
|
}
|
|
165249
|
-
)
|
|
166184
|
+
), /* @__PURE__ */ React.createElement(HeaderItem, { title: `Mismatches (${mismatchesCount})` }), trackMismatches && trackMismatches.length > 0 && /* @__PURE__ */ React.createElement(
|
|
166185
|
+
"div",
|
|
166186
|
+
{
|
|
166187
|
+
style: {
|
|
166188
|
+
margin: "0px 10px"
|
|
166189
|
+
}
|
|
166190
|
+
},
|
|
166191
|
+
/* @__PURE__ */ React.createElement(
|
|
166192
|
+
WrappedDT,
|
|
166193
|
+
{
|
|
166194
|
+
formName: "mismatchesTable",
|
|
166195
|
+
isSimple: true,
|
|
166196
|
+
noHeader: true,
|
|
166197
|
+
noFooter: true,
|
|
166198
|
+
withSearch: false,
|
|
166199
|
+
noPadding: true,
|
|
166200
|
+
compact: true,
|
|
166201
|
+
maxHeight: 150,
|
|
166202
|
+
entities: mismatchEntities,
|
|
166203
|
+
schema: mismatchSchema,
|
|
166204
|
+
onRowClick: /* @__PURE__ */ __name((e2, row) => {
|
|
166205
|
+
updateCaretPosition({ start: row.start, end: row.end });
|
|
166206
|
+
setTimeout(() => {
|
|
166207
|
+
scrollToAlignmentSelection();
|
|
166208
|
+
}, 0);
|
|
166209
|
+
}, "onRowClick")
|
|
166210
|
+
}
|
|
166211
|
+
)
|
|
166212
|
+
)), /* @__PURE__ */ React.createElement(
|
|
166213
|
+
HeaderItem,
|
|
166214
|
+
{
|
|
166215
|
+
title: `${isProtein2 ? "Amino Acid" : "Base Pair"} Frequencies`
|
|
166216
|
+
}
|
|
166217
|
+
), /* @__PURE__ */ React.createElement("div", { className: "sidebar-table" }, /* @__PURE__ */ React.createElement("div", { className: "sidebar-row" }, /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, isProtein2 ? "Amino Acid" : "Base"), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, "Count"), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, "Percentage")), frequencyEntries.map(([aa, data], idx) => {
|
|
165250
166218
|
return /* @__PURE__ */ React.createElement("div", { className: `sidebar-row property-amino-acid-${idx}` }, /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, aa, " ", isProtein2 ? `(${aminoAcidShortNames[aa]})` : ""), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, data.count), /* @__PURE__ */ React.createElement("div", { className: "sidebar-cell" }, data.percentage.toFixed(1), "%"));
|
|
165251
166219
|
})));
|
|
165252
166220
|
} else {
|
|
@@ -165303,11 +166271,29 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
|
|
|
165303
166271
|
);
|
|
165304
166272
|
}, "PropertySidePanel");
|
|
165305
166273
|
function RowItem({ item, title, units }) {
|
|
165306
|
-
if (
|
|
166274
|
+
if (item == null) {
|
|
166275
|
+
return null;
|
|
166276
|
+
}
|
|
165307
166277
|
const propertyClass = title.split(" ").join("-").toLowerCase();
|
|
165308
|
-
return /* @__PURE__ */ React.createElement("div", { className: `ve-flex-row property-${propertyClass}` }, /* @__PURE__ */ React.createElement("div", { className: "ve-column-left" }, title), /* @__PURE__ */ React.createElement("div", { className: "ve-column-right" }, item, " ", units != null ? units : ""));
|
|
166278
|
+
return /* @__PURE__ */ React.createElement("div", { className: `ve-flex-row property-${propertyClass}` }, /* @__PURE__ */ React.createElement("div", { style: { fontWeight: "bold" }, className: "ve-column-left" }, title), /* @__PURE__ */ React.createElement("div", { className: "ve-column-right" }, item, " ", units != null ? units : ""));
|
|
165309
166279
|
}
|
|
165310
166280
|
__name(RowItem, "RowItem");
|
|
166281
|
+
const HeaderItem = /* @__PURE__ */ __name(({ title }) => {
|
|
166282
|
+
return /* @__PURE__ */ React.createElement(
|
|
166283
|
+
"h5",
|
|
166284
|
+
{
|
|
166285
|
+
style: {
|
|
166286
|
+
margin: 0,
|
|
166287
|
+
fontSize: 15,
|
|
166288
|
+
fontWeight: "bold",
|
|
166289
|
+
textAlign: "center",
|
|
166290
|
+
padding: "5px 0",
|
|
166291
|
+
borderBottom: "1px solid #f1f1f1"
|
|
166292
|
+
}
|
|
166293
|
+
},
|
|
166294
|
+
title
|
|
166295
|
+
);
|
|
166296
|
+
}, "HeaderItem");
|
|
165311
166297
|
function calculatePairwiseIdentity(seq1, seq2, excludeGaps = true) {
|
|
165312
166298
|
if (seq1.length !== seq2.length) {
|
|
165313
166299
|
throw new Error("Sequences must be aligned (same length)");
|
|
@@ -165703,6 +166689,11 @@ Part of ${annotation.translationType} Translation from BPs ${annotation.start +
|
|
|
165703
166689
|
const [tempTrimBefore, setTempTrimBefore] = reactExports.useState({});
|
|
165704
166690
|
const [tempTrimAfter, setTempTrimAfter] = reactExports.useState({});
|
|
165705
166691
|
const [tempTrimmingCaret, setTempTrimmingCaret] = reactExports.useState({});
|
|
166692
|
+
const [searchMatchLayers, setSearchMatchLayers] = React.useState([]);
|
|
166693
|
+
const [activeFilterType, setActiveFilterType] = reactExports.useState("all");
|
|
166694
|
+
const handleFilterChange = reactExports.useCallback(({ activeFilter }) => {
|
|
166695
|
+
setActiveFilterType(activeFilter);
|
|
166696
|
+
}, []);
|
|
165706
166697
|
const bindOutsideChangeHelper = reactExports.useRef({});
|
|
165707
166698
|
const alignmentHolder = reactExports.useRef(null);
|
|
165708
166699
|
const alignmentHolderTop = reactExports.useRef(null);
|
|
@@ -166427,7 +167418,12 @@ ${seqDataToCopy}\r
|
|
|
166427
167418
|
alignmentData,
|
|
166428
167419
|
chromatogramData
|
|
166429
167420
|
}) : linearViewOptions)), {
|
|
166430
|
-
additionalSelectionLayers
|
|
167421
|
+
additionalSelectionLayers: [
|
|
167422
|
+
...i2 !== 0 ? (additionalSelectionLayers || []).filter(
|
|
167423
|
+
(layer) => activeFilterType === "all" ? layer.differenceType !== "gap" : layer.differenceType === activeFilterType
|
|
167424
|
+
) : additionalSelectionLayers || [],
|
|
167425
|
+
...searchMatchLayers || []
|
|
167426
|
+
],
|
|
166431
167427
|
dimensions: {
|
|
166432
167428
|
width: linearViewWidth
|
|
166433
167429
|
},
|
|
@@ -166955,7 +167951,7 @@ ${seqDataToCopy}\r
|
|
|
166955
167951
|
display: "flex",
|
|
166956
167952
|
minHeight: "32px",
|
|
166957
167953
|
width: "100%",
|
|
166958
|
-
flexWrap: "
|
|
167954
|
+
flexWrap: "wrap",
|
|
166959
167955
|
flexDirection: "row",
|
|
166960
167956
|
flex: "0 0 auto"
|
|
166961
167957
|
},
|
|
@@ -167076,6 +168072,22 @@ ${seqDataToCopy}\r
|
|
|
167076
168072
|
currentPairwiseAlignmentIndex
|
|
167077
168073
|
}, alignmentVisibilityToolOptions)
|
|
167078
168074
|
),
|
|
168075
|
+
/* @__PURE__ */ React.createElement(
|
|
168076
|
+
AlignmentSearchBar,
|
|
168077
|
+
{
|
|
168078
|
+
alignmentTracks,
|
|
168079
|
+
id: id2,
|
|
168080
|
+
setSearchMatchLayers
|
|
168081
|
+
}
|
|
168082
|
+
),
|
|
168083
|
+
/* @__PURE__ */ React.createElement(
|
|
168084
|
+
FindMismatches,
|
|
168085
|
+
{
|
|
168086
|
+
alignmentJson: alignmentTracks,
|
|
168087
|
+
id: id2,
|
|
168088
|
+
onFilterChange: handleFilterChange
|
|
168089
|
+
}
|
|
168090
|
+
),
|
|
167079
168091
|
additionalTopEl,
|
|
167080
168092
|
saveMessage && /* @__PURE__ */ React.createElement(
|
|
167081
168093
|
"div",
|
|
@@ -167176,6 +168188,7 @@ ${seqDataToCopy}\r
|
|
|
167176
168188
|
}
|
|
167177
168189
|
)),
|
|
167178
168190
|
alignmentTracks,
|
|
168191
|
+
activeFilterType,
|
|
167179
168192
|
dimensions: {
|
|
167180
168193
|
width: Math.max(width, 10) || 10
|
|
167181
168194
|
},
|
|
@@ -172365,108 +173378,6 @@ ${seqDataToCopy}\r
|
|
|
172365
173378
|
]
|
|
172366
173379
|
};
|
|
172367
173380
|
const DigestTool$1 = withEditorInteractions(DigestTool);
|
|
172368
|
-
const _Mismatches = class _Mismatches extends React.Component {
|
|
172369
|
-
constructor() {
|
|
172370
|
-
super(...arguments);
|
|
172371
|
-
__publicField(this, "getGapMap", /* @__PURE__ */ __name((sequence2) => {
|
|
172372
|
-
const gapMap = [0];
|
|
172373
|
-
sequence2.split("").forEach((char) => {
|
|
172374
|
-
if (char === "-") {
|
|
172375
|
-
gapMap[Math.max(0, gapMap.length - 1)] = (gapMap[Math.max(0, gapMap.length - 1)] || 0) + 1;
|
|
172376
|
-
} else {
|
|
172377
|
-
gapMap.push(gapMap[gapMap.length - 1] || 0);
|
|
172378
|
-
}
|
|
172379
|
-
});
|
|
172380
|
-
return gapMap;
|
|
172381
|
-
}, "getGapMap"));
|
|
172382
|
-
__publicField(this, "getMismatchList", /* @__PURE__ */ __name((alignmentData, mismatches) => {
|
|
172383
|
-
const mismatchList = [];
|
|
172384
|
-
let getGaps = /* @__PURE__ */ __name(() => ({
|
|
172385
|
-
gapsBefore: 0,
|
|
172386
|
-
gapsInside: 0
|
|
172387
|
-
}), "getGaps");
|
|
172388
|
-
const gapMap = this.getGapMap(alignmentData.sequence);
|
|
172389
|
-
getGaps = /* @__PURE__ */ __name((rangeOrCaretPosition) => {
|
|
172390
|
-
if (typeof rangeOrCaretPosition !== "object") {
|
|
172391
|
-
return {
|
|
172392
|
-
gapsBefore: gapMap[Math.min(rangeOrCaretPosition, gapMap.length - 1)]
|
|
172393
|
-
};
|
|
172394
|
-
}
|
|
172395
|
-
const { start: start2, end: end2 } = rangeOrCaretPosition;
|
|
172396
|
-
const toReturn = {
|
|
172397
|
-
gapsBefore: gapMap[start2],
|
|
172398
|
-
gapsInside: gapMap[Math.min(end2, gapMap.length - 1)] - gapMap[Math.min(start2, gapMap.length - 1)]
|
|
172399
|
-
};
|
|
172400
|
-
return toReturn;
|
|
172401
|
-
}, "getGaps");
|
|
172402
|
-
const gapsBeforeSequence = getGaps(0).gapsBefore;
|
|
172403
|
-
for (let mismatchI = 0; mismatchI < mismatches.length; mismatchI++) {
|
|
172404
|
-
const mismatchEnd = mismatches[mismatchI].end;
|
|
172405
|
-
const mismatchStart = mismatches[mismatchI].start;
|
|
172406
|
-
const mismatchDifference = mismatchEnd - mismatchStart;
|
|
172407
|
-
if (mismatchDifference === 0) {
|
|
172408
|
-
mismatchList.push({
|
|
172409
|
-
mismatches: mismatchStart + 1 - gapsBeforeSequence,
|
|
172410
|
-
start: mismatchStart - gapsBeforeSequence,
|
|
172411
|
-
end: mismatchStart - gapsBeforeSequence
|
|
172412
|
-
});
|
|
172413
|
-
} else {
|
|
172414
|
-
for (let innerI = 0; innerI <= mismatchDifference; innerI++) {
|
|
172415
|
-
mismatchList.push({
|
|
172416
|
-
mismatches: mismatchStart + innerI + 1 - gapsBeforeSequence,
|
|
172417
|
-
start: mismatchStart + innerI - gapsBeforeSequence,
|
|
172418
|
-
end: mismatchStart + innerI - gapsBeforeSequence
|
|
172419
|
-
});
|
|
172420
|
-
}
|
|
172421
|
-
}
|
|
172422
|
-
}
|
|
172423
|
-
return mismatchList;
|
|
172424
|
-
}, "getMismatchList"));
|
|
172425
|
-
}
|
|
172426
|
-
UNSAFE_componentWillMount() {
|
|
172427
|
-
const { alignmentData, mismatches } = this.props;
|
|
172428
|
-
const mismatchList = this.getMismatchList(alignmentData, mismatches);
|
|
172429
|
-
const schema2 = {
|
|
172430
|
-
fields: [{ path: "mismatches", type: "number" }]
|
|
172431
|
-
};
|
|
172432
|
-
this.setState({ mismatchList, schema: schema2 });
|
|
172433
|
-
}
|
|
172434
|
-
render() {
|
|
172435
|
-
const { mismatchList, schema: schema2 } = this.state;
|
|
172436
|
-
let tableOfMismatches;
|
|
172437
|
-
if (mismatchList.length === 0) {
|
|
172438
|
-
tableOfMismatches = null;
|
|
172439
|
-
} else {
|
|
172440
|
-
tableOfMismatches = /* @__PURE__ */ React.createElement(
|
|
172441
|
-
WrappedDT,
|
|
172442
|
-
{
|
|
172443
|
-
maxHeight: 168,
|
|
172444
|
-
formName: "mismatchesTable",
|
|
172445
|
-
isSimple: true,
|
|
172446
|
-
compact: true,
|
|
172447
|
-
noRouter: true,
|
|
172448
|
-
schema: schema2,
|
|
172449
|
-
entities: mismatchList
|
|
172450
|
-
}
|
|
172451
|
-
);
|
|
172452
|
-
}
|
|
172453
|
-
return /* @__PURE__ */ React.createElement("div", { style: { maxHeight: 180.8, overflowY: "scroll" } }, /* @__PURE__ */ React.createElement(
|
|
172454
|
-
"div",
|
|
172455
|
-
{
|
|
172456
|
-
style: {
|
|
172457
|
-
// margin: 10,
|
|
172458
|
-
display: "flex",
|
|
172459
|
-
flexDirection: "column",
|
|
172460
|
-
alignItems: "center"
|
|
172461
|
-
}
|
|
172462
|
-
},
|
|
172463
|
-
/* @__PURE__ */ React.createElement("div", { style: { width: 100, margin: 4 } }, tableOfMismatches)
|
|
172464
|
-
));
|
|
172465
|
-
}
|
|
172466
|
-
};
|
|
172467
|
-
__name(_Mismatches, "Mismatches");
|
|
172468
|
-
let Mismatches = _Mismatches;
|
|
172469
|
-
const Mismatches$1 = withSelectedEntities("mismatchesTable")(Mismatches);
|
|
172470
173381
|
function PCRTool(props) {
|
|
172471
173382
|
const {
|
|
172472
173383
|
sequenceData: sequenceData2,
|
|
@@ -172638,7 +173549,7 @@ ${seqDataToCopy}\r
|
|
|
172638
173549
|
comp: PropertiesDialog$1,
|
|
172639
173550
|
panelSpecificProps: ["PropertiesProps"]
|
|
172640
173551
|
},
|
|
172641
|
-
mismatches:
|
|
173552
|
+
mismatches: FindMismatches
|
|
172642
173553
|
};
|
|
172643
173554
|
const reorder = /* @__PURE__ */ __name((list2, startIndex, endIndex) => {
|
|
172644
173555
|
const result = Array.from(list2);
|
|
@@ -175438,18 +176349,6 @@ ${seqDataToCopy}\r
|
|
|
175438
176349
|
window.createVectorEditor = createVectorEditor;
|
|
175439
176350
|
window.createAlignmentView = createAlignmentView;
|
|
175440
176351
|
window.createVersionHistoryView = createVersionHistoryView;
|
|
175441
|
-
function getGapMap(sequence2) {
|
|
175442
|
-
const gapMap = [0];
|
|
175443
|
-
sequence2.split("").forEach((char) => {
|
|
175444
|
-
if (char === "-") {
|
|
175445
|
-
gapMap[Math.max(0, gapMap.length - 1)] = (gapMap[Math.max(0, gapMap.length - 1)] || 0) + 1;
|
|
175446
|
-
} else {
|
|
175447
|
-
gapMap.push(gapMap[gapMap.length - 1] || 0);
|
|
175448
|
-
}
|
|
175449
|
-
});
|
|
175450
|
-
return gapMap;
|
|
175451
|
-
}
|
|
175452
|
-
__name(getGapMap, "getGapMap");
|
|
175453
176352
|
exports2.getGaps = () => ({
|
|
175454
176353
|
gapsBefore: 0,
|
|
175455
176354
|
gapsInside: 0
|