@teselagen/ove 0.8.2 → 0.8.4
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/LabileSitesLayer.d.ts +13 -0
- package/AlignmentView/PairwiseAlignmentView.d.ts +1 -9
- package/BarPlot/index.d.ts +33 -0
- package/LinearView/SequenceName.d.ts +2 -1
- package/PropertySidePanel/calculateAminoAcidFrequency.d.ts +46 -0
- package/PropertySidePanel/index.d.ts +6 -0
- package/RowItem/Caret/index.d.ts +2 -1
- package/StatusBar/index.d.ts +2 -1
- package/aaprops.svg +2287 -0
- package/constants/dnaToColor.d.ts +122 -4
- package/index.cjs.js +4214 -7859
- package/index.es.js +2166 -5811
- package/index.umd.js +3745 -7390
- package/ove.css +100 -19
- package/package.json +2 -2
- package/src/AlignmentView/AlignmentVisibilityTool.js +141 -37
- package/src/AlignmentView/LabileSitesLayer.js +33 -0
- package/src/AlignmentView/Minimap.js +5 -3
- package/src/AlignmentView/PairwiseAlignmentView.js +55 -61
- package/src/AlignmentView/index.js +476 -257
- package/src/AlignmentView/style.css +27 -0
- package/src/BarPlot/index.js +156 -0
- package/src/CircularView/Caret.js +8 -2
- package/src/CircularView/SelectionLayer.js +4 -2
- package/src/CircularView/index.js +5 -1
- package/src/Editor/darkmode.css +10 -0
- package/src/Editor/index.js +3 -0
- package/src/Editor/userDefinedHandlersAndOpts.js +2 -1
- package/src/FindBar/index.js +2 -3
- package/src/LinearView/SequenceName.js +8 -2
- package/src/LinearView/index.js +21 -0
- package/src/PropertySidePanel/calculateAminoAcidFrequency.js +77 -0
- package/src/PropertySidePanel/index.js +236 -0
- package/src/PropertySidePanel/style.css +39 -0
- package/src/RowItem/Caret/index.js +8 -2
- package/src/RowItem/Labels.js +1 -1
- package/src/RowItem/SelectionLayer/index.js +5 -1
- package/src/RowItem/Sequence.js +99 -5
- package/src/RowItem/Translations/Translation.js +3 -2
- package/src/RowItem/Translations/index.js +2 -0
- package/src/RowItem/index.js +74 -8
- package/src/RowItem/style.css +3 -4
- package/src/StatusBar/index.js +11 -4
- package/src/constants/dnaToColor.js +151 -0
- package/src/helperComponents/PinchHelper/PinchHelper.js +5 -1
- package/src/helperComponents/SelectDialog.js +5 -2
- package/src/style.css +2 -2
- package/src/utils/editorUtils.js +5 -3
- package/src/utils/getAlignedAminoAcidSequenceProps.js +379 -0
- package/src/withEditorInteractions/createSequenceInputPopup.js +19 -5
- package/src/withEditorInteractions/index.js +9 -3
- package/utils/editorUtils.d.ts +2 -1
- package/utils/getAlignedAminoAcidSequenceProps.d.ts +49 -0
|
@@ -72,6 +72,9 @@ import { isTargetWithinEl } from "./isTargetWithinEl";
|
|
|
72
72
|
import { EditTrackNameDialog } from "./EditTrackNameDialog";
|
|
73
73
|
import { coerceInitialValue } from "./coerceInitialValue";
|
|
74
74
|
import { tabHeight } from "../constants";
|
|
75
|
+
import LabileSitesLayer from "./LabileSitesLayer";
|
|
76
|
+
import PropertySidePanel from "../PropertySidePanel";
|
|
77
|
+
import { getAlignedAminoAcidSequenceProps } from "../utils/getAlignedAminoAcidSequenceProps";
|
|
75
78
|
|
|
76
79
|
let charWidthInLinearViewDefault = 12;
|
|
77
80
|
try {
|
|
@@ -173,6 +176,13 @@ export const AlignmentView = props => {
|
|
|
173
176
|
})
|
|
174
177
|
);
|
|
175
178
|
|
|
179
|
+
const [propertySidePanel, setPropertySidePanel] = useState({
|
|
180
|
+
isOpen: false,
|
|
181
|
+
selection: null,
|
|
182
|
+
track: null,
|
|
183
|
+
isPairwise: false
|
|
184
|
+
});
|
|
185
|
+
|
|
176
186
|
const getAllAlignmentsFastaText = useCallback(() => {
|
|
177
187
|
const selectionLayer =
|
|
178
188
|
store.getState().VectorEditor.__allEditorsOptions.alignments[id]
|
|
@@ -245,6 +255,67 @@ export const AlignmentView = props => {
|
|
|
245
255
|
};
|
|
246
256
|
}, []);
|
|
247
257
|
|
|
258
|
+
const {
|
|
259
|
+
alignmentAnnotationVisibility,
|
|
260
|
+
togglableAlignmentAnnotationSettings
|
|
261
|
+
} = alignmentVisibilityToolOptions;
|
|
262
|
+
|
|
263
|
+
useEffect(() => {
|
|
264
|
+
const dnaAnnotations = [
|
|
265
|
+
"chromatogram",
|
|
266
|
+
"reverseSequence",
|
|
267
|
+
"cdsFeatureTranslations",
|
|
268
|
+
"dnaColors",
|
|
269
|
+
"translations",
|
|
270
|
+
"compactNames"
|
|
271
|
+
];
|
|
272
|
+
|
|
273
|
+
const aminoAcidAnnotations = [
|
|
274
|
+
"physicalProperties",
|
|
275
|
+
"serineThreonine",
|
|
276
|
+
"labileSites",
|
|
277
|
+
"colorScheme",
|
|
278
|
+
"plot",
|
|
279
|
+
"conservation",
|
|
280
|
+
"properties",
|
|
281
|
+
"hydrophobicity",
|
|
282
|
+
"polar",
|
|
283
|
+
"negative",
|
|
284
|
+
"positive",
|
|
285
|
+
"charged",
|
|
286
|
+
"aliphatic",
|
|
287
|
+
"aromatic",
|
|
288
|
+
"compactNames"
|
|
289
|
+
];
|
|
290
|
+
|
|
291
|
+
const noNeededAnnotationsForPairwise = ["plot", "labileSites"];
|
|
292
|
+
|
|
293
|
+
if (alignmentTracks[0].sequenceData.isProtein) {
|
|
294
|
+
dnaAnnotations.forEach(key => {
|
|
295
|
+
delete alignmentAnnotationVisibility[key];
|
|
296
|
+
delete togglableAlignmentAnnotationSettings[key];
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
aminoAcidAnnotations.forEach(key => {
|
|
300
|
+
alignmentAnnotationVisibility[key] = false;
|
|
301
|
+
togglableAlignmentAnnotationSettings[key] = false;
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
if (isPairwise) {
|
|
305
|
+
noNeededAnnotationsForPairwise.forEach(key => {
|
|
306
|
+
delete alignmentAnnotationVisibility[key];
|
|
307
|
+
delete togglableAlignmentAnnotationSettings[key];
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
} else {
|
|
311
|
+
aminoAcidAnnotations.forEach(key => {
|
|
312
|
+
delete alignmentAnnotationVisibility[key];
|
|
313
|
+
delete togglableAlignmentAnnotationSettings[key];
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
317
|
+
}, [alignmentTracks, isPairwise]);
|
|
318
|
+
|
|
248
319
|
const maxLength = useMemo(() => {
|
|
249
320
|
const { sequenceData = { sequence: "" }, alignmentData } =
|
|
250
321
|
alignmentTracks[0];
|
|
@@ -393,6 +464,13 @@ export const AlignmentView = props => {
|
|
|
393
464
|
)
|
|
394
465
|
};
|
|
395
466
|
callback(callbackVals);
|
|
467
|
+
|
|
468
|
+
setPropertySidePanel(prev => {
|
|
469
|
+
return {
|
|
470
|
+
...prev,
|
|
471
|
+
selection: easyStore.current.selectionLayer
|
|
472
|
+
};
|
|
473
|
+
});
|
|
396
474
|
},
|
|
397
475
|
[
|
|
398
476
|
caretPositionUpdate,
|
|
@@ -606,7 +684,12 @@ export const AlignmentView = props => {
|
|
|
606
684
|
});
|
|
607
685
|
};
|
|
608
686
|
|
|
609
|
-
const
|
|
687
|
+
const aminoAcidAlignmentProperties = useMemo(() => {
|
|
688
|
+
if (isPairwise || !alignmentTracks[0].sequenceData.isProtein) return;
|
|
689
|
+
return getAlignedAminoAcidSequenceProps(alignmentTracks);
|
|
690
|
+
}, [alignmentTracks, isPairwise]);
|
|
691
|
+
|
|
692
|
+
const renderItem = (_i, _key, isTemplate, cloneProps) => {
|
|
610
693
|
const isDragDisabled = !allowTrackRearrange || isPairwise;
|
|
611
694
|
let i;
|
|
612
695
|
if (isTemplate) {
|
|
@@ -653,12 +736,36 @@ export const AlignmentView = props => {
|
|
|
653
736
|
className: "tg-trimmed-region",
|
|
654
737
|
color: "gray"
|
|
655
738
|
}));
|
|
739
|
+
|
|
740
|
+
const trackIdentifier = track?.sequenceData.id ? "id" : "hash";
|
|
741
|
+
const selectedTrack = propertySidePanel?.track;
|
|
742
|
+
const isTrackSelected =
|
|
743
|
+
selectedTrack?.sequenceData[trackIdentifier] ===
|
|
744
|
+
track?.sequenceData[trackIdentifier];
|
|
745
|
+
|
|
746
|
+
let aaIdentity;
|
|
747
|
+
let aaIdenticalPosition;
|
|
748
|
+
if (sequenceData.isProtein && !isPairwise) {
|
|
749
|
+
aaIdentity = aminoAcidAlignmentProperties?.matrix?.[0]?.[i]?.toFixed(1);
|
|
750
|
+
aaIdenticalPosition =
|
|
751
|
+
aminoAcidAlignmentProperties?.identicalPositions?.[i - 1]
|
|
752
|
+
?.identicalPositions;
|
|
753
|
+
|
|
754
|
+
if (sequenceData.name === "Consensus") {
|
|
755
|
+
sequenceData.aminoAcidProperties =
|
|
756
|
+
isPairwise || !sequenceData.isProtein
|
|
757
|
+
? null
|
|
758
|
+
: aminoAcidAlignmentProperties;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
|
|
656
762
|
const innerRenderItem = (provided = {}, snapshot) => (
|
|
657
763
|
<div
|
|
658
764
|
ref={provided?.innerRef}
|
|
659
765
|
{...provided?.draggableProps}
|
|
660
766
|
className={classNames("alignmentViewTrackContainer", {
|
|
661
|
-
isDragDisabled
|
|
767
|
+
isDragDisabled,
|
|
768
|
+
isTrackSelected
|
|
662
769
|
})}
|
|
663
770
|
data-alignment-track-index={i}
|
|
664
771
|
style={{
|
|
@@ -670,6 +777,16 @@ export const AlignmentView = props => {
|
|
|
670
777
|
...(snapshot?.isDragging && { left: unset })
|
|
671
778
|
}}
|
|
672
779
|
key={i}
|
|
780
|
+
onClick={() => {
|
|
781
|
+
setPropertySidePanel(prev => {
|
|
782
|
+
return {
|
|
783
|
+
...prev,
|
|
784
|
+
selection: easyStore.current.selectionLayer,
|
|
785
|
+
track,
|
|
786
|
+
isPairwise
|
|
787
|
+
};
|
|
788
|
+
});
|
|
789
|
+
}}
|
|
673
790
|
>
|
|
674
791
|
<div
|
|
675
792
|
className="alignmentTrackName"
|
|
@@ -792,7 +909,21 @@ export const AlignmentView = props => {
|
|
|
792
909
|
TRIMMED
|
|
793
910
|
</span>
|
|
794
911
|
)}
|
|
795
|
-
{sequenceData.
|
|
912
|
+
{sequenceData.isProtein ? (
|
|
913
|
+
<>
|
|
914
|
+
<span>{sequenceData.proteinSequence.length} AAs</span>
|
|
915
|
+
{!compactNames && i > 0 && !isPairwise && (
|
|
916
|
+
<>
|
|
917
|
+
<br />
|
|
918
|
+
<span>Identical Positions: {aaIdenticalPosition}</span>
|
|
919
|
+
<br />
|
|
920
|
+
<span>Identity: {aaIdentity}%</span>
|
|
921
|
+
</>
|
|
922
|
+
)}
|
|
923
|
+
</>
|
|
924
|
+
) : (
|
|
925
|
+
<span>{sequenceData.sequence.length} bps</span>
|
|
926
|
+
)}
|
|
796
927
|
</div>
|
|
797
928
|
</div>
|
|
798
929
|
<HorizontalPanelDragHandle
|
|
@@ -801,7 +932,6 @@ export const AlignmentView = props => {
|
|
|
801
932
|
}}
|
|
802
933
|
/>
|
|
803
934
|
</div>
|
|
804
|
-
|
|
805
935
|
{handleSelectTrack && !isTemplate && (
|
|
806
936
|
<div
|
|
807
937
|
onClick={() => {
|
|
@@ -1111,7 +1241,16 @@ export const AlignmentView = props => {
|
|
|
1111
1241
|
return "corrupted data!";
|
|
1112
1242
|
}
|
|
1113
1243
|
|
|
1114
|
-
const getTrackVis = (
|
|
1244
|
+
const getTrackVis = (
|
|
1245
|
+
alignmentTracks,
|
|
1246
|
+
isTemplate,
|
|
1247
|
+
allTracks,
|
|
1248
|
+
aminoAcidAlignmentProperties,
|
|
1249
|
+
labileSites
|
|
1250
|
+
) => {
|
|
1251
|
+
const labilePositions =
|
|
1252
|
+
aminoAcidAlignmentProperties?.labileSites.sites.map(ls => ls.position) ||
|
|
1253
|
+
[];
|
|
1115
1254
|
const rowData = {};
|
|
1116
1255
|
const innerTrackVis = (drop_provided, drop_snapshot) => {
|
|
1117
1256
|
return (
|
|
@@ -1324,6 +1463,13 @@ export const AlignmentView = props => {
|
|
|
1324
1463
|
row={{ start: 0, end: maxLength - 1 }}
|
|
1325
1464
|
easyStore={easyStore.current}
|
|
1326
1465
|
/>
|
|
1466
|
+
{labileSites && labilePositions.length > 0 && (
|
|
1467
|
+
<LabileSitesLayer
|
|
1468
|
+
leftMargin={nameDivWidth}
|
|
1469
|
+
charWidth={charWidth}
|
|
1470
|
+
positionsToMark={labilePositions}
|
|
1471
|
+
/>
|
|
1472
|
+
)}
|
|
1327
1473
|
{isTemplate ? (
|
|
1328
1474
|
renderItem(0, 0, isTemplate)
|
|
1329
1475
|
) : (
|
|
@@ -1409,279 +1555,338 @@ export const AlignmentView = props => {
|
|
|
1409
1555
|
updateLabelsForInViewFeatures();
|
|
1410
1556
|
}
|
|
1411
1557
|
};
|
|
1558
|
+
|
|
1559
|
+
const { labileSites } =
|
|
1560
|
+
alignmentVisibilityToolOptions.alignmentAnnotationVisibility;
|
|
1561
|
+
|
|
1412
1562
|
return (
|
|
1413
1563
|
<PinchHelper {...pinchHandler}>
|
|
1414
|
-
<
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1564
|
+
<div
|
|
1565
|
+
style={{
|
|
1566
|
+
display: "flex",
|
|
1567
|
+
flexDirection: "row"
|
|
1568
|
+
}}
|
|
1569
|
+
>
|
|
1570
|
+
<ResizeSensor onResize={handleResize}>
|
|
1571
|
+
<div
|
|
1572
|
+
style={{
|
|
1573
|
+
height: height || (isPairwise ? "auto" : viewportHeight * 0.88),
|
|
1574
|
+
width: "100%",
|
|
1575
|
+
display: "flex",
|
|
1576
|
+
flexDirection: "column",
|
|
1577
|
+
justifyContent: "space-between",
|
|
1578
|
+
position: "relative",
|
|
1579
|
+
overflowY: "auto",
|
|
1580
|
+
...style
|
|
1581
|
+
// borderTop: "1px solid black"
|
|
1582
|
+
}}
|
|
1583
|
+
className="alignmentView"
|
|
1431
1584
|
>
|
|
1432
|
-
<
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
flexDirection: "column",
|
|
1436
|
-
position: "relative",
|
|
1437
|
-
overflowY: "auto"
|
|
1438
|
-
}}
|
|
1439
|
-
className="alignmentView-top-container"
|
|
1585
|
+
<DragDropContext
|
|
1586
|
+
onDragStart={onTrackDragStart}
|
|
1587
|
+
onDragEnd={onTrackDragEnd}
|
|
1440
1588
|
>
|
|
1441
1589
|
<div
|
|
1442
1590
|
style={{
|
|
1443
|
-
paddingTop: "3px",
|
|
1444
|
-
paddingBottom: "5px",
|
|
1445
|
-
borderBottom: "1px solid",
|
|
1446
1591
|
display: "flex",
|
|
1447
|
-
|
|
1592
|
+
flexDirection: "column",
|
|
1593
|
+
position: "relative",
|
|
1448
1594
|
width: "100%",
|
|
1449
|
-
|
|
1450
|
-
flexDirection: "row",
|
|
1451
|
-
flex: "0 0 auto"
|
|
1595
|
+
overflowY: "auto"
|
|
1452
1596
|
}}
|
|
1453
|
-
className="
|
|
1597
|
+
className="alignmentView-top-container"
|
|
1454
1598
|
>
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1599
|
+
<div
|
|
1600
|
+
style={{
|
|
1601
|
+
paddingTop: "3px",
|
|
1602
|
+
paddingBottom: "5px",
|
|
1603
|
+
borderBottom: "1px solid",
|
|
1604
|
+
display: "flex",
|
|
1605
|
+
minHeight: "32px",
|
|
1606
|
+
width: "100%",
|
|
1607
|
+
flexWrap: "nowrap",
|
|
1608
|
+
flexDirection: "row",
|
|
1609
|
+
flex: "0 0 auto"
|
|
1610
|
+
}}
|
|
1611
|
+
className="ve-alignment-top-bar"
|
|
1612
|
+
>
|
|
1613
|
+
{additionalTopLeftEl}
|
|
1614
|
+
{handleBackButtonClicked && (
|
|
1615
|
+
<Tooltip content="Back to Pairwise Alignment Overview">
|
|
1616
|
+
<Button
|
|
1617
|
+
icon="arrow-left"
|
|
1618
|
+
onClick={() => {
|
|
1619
|
+
handleBackButtonClicked();
|
|
1620
|
+
caretPositionUpdate(-1);
|
|
1621
|
+
}}
|
|
1622
|
+
small
|
|
1623
|
+
intent={Intent.PRIMARY}
|
|
1624
|
+
minimal
|
|
1625
|
+
style={{ marginRight: 10 }}
|
|
1626
|
+
className="alignmentViewBackButton"
|
|
1627
|
+
/>
|
|
1628
|
+
</Tooltip>
|
|
1629
|
+
)}
|
|
1630
|
+
|
|
1631
|
+
<div style={{ display: "flex" }}>
|
|
1632
|
+
<EditableText
|
|
1633
|
+
disabled={!handleAlignmentRename}
|
|
1634
|
+
onChange={v => {
|
|
1635
|
+
setAlignmentName(v);
|
|
1463
1636
|
}}
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1637
|
+
maxLength={399} //stop the name from being tooo long
|
|
1638
|
+
value={alignmentName}
|
|
1639
|
+
onConfirm={async v => {
|
|
1640
|
+
if (!v) {
|
|
1641
|
+
setAlignmentName(_alignmentName);
|
|
1642
|
+
return;
|
|
1643
|
+
}
|
|
1644
|
+
if (v === _alignmentName) {
|
|
1645
|
+
return; //already saved this name
|
|
1646
|
+
}
|
|
1647
|
+
setSaveMessage("Alignment Renaming..");
|
|
1648
|
+
setSaveMessageLoading(true);
|
|
1649
|
+
await handleAlignmentRename(v, props);
|
|
1650
|
+
setSaveMessage("Rename Successful");
|
|
1651
|
+
setSaveMessageLoading(false);
|
|
1652
|
+
setTimeout(() => {
|
|
1653
|
+
setSaveMessage(undefined);
|
|
1654
|
+
setSaveMessageLoading(false);
|
|
1655
|
+
}, 5000);
|
|
1656
|
+
}}
|
|
1657
|
+
selectAllOnFocus={true}
|
|
1658
|
+
className="veAlignmentName"
|
|
1469
1659
|
/>
|
|
1470
|
-
|
|
1471
|
-
|
|
1660
|
+
|
|
1661
|
+
<div
|
|
1662
|
+
className="veAlignmentType"
|
|
1663
|
+
style={{
|
|
1664
|
+
paddingTop: "3px",
|
|
1665
|
+
fontSize: "14px",
|
|
1666
|
+
color: "grey",
|
|
1667
|
+
maxWidth: "300px",
|
|
1668
|
+
overflow: "hidden",
|
|
1669
|
+
textOverflow: "ellipsis",
|
|
1670
|
+
whiteSpace: "nowrap"
|
|
1671
|
+
}}
|
|
1672
|
+
data-title={alignmentType || "Unknown Alignment Type"}
|
|
1673
|
+
>
|
|
1674
|
+
{alignmentType || "Unknown Alignment Type"}
|
|
1675
|
+
</div>
|
|
1676
|
+
</div>
|
|
1472
1677
|
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
return;
|
|
1678
|
+
{unmappedSeqs && (
|
|
1679
|
+
<InfoHelper
|
|
1680
|
+
size={20}
|
|
1681
|
+
content={
|
|
1682
|
+
<div>
|
|
1683
|
+
This alignment had sequences that did not map to the
|
|
1684
|
+
template sequence:
|
|
1685
|
+
{unmappedSeqs.map(({ sequenceData }, i) => (
|
|
1686
|
+
<div key={i}>{sequenceData.name}</div>
|
|
1687
|
+
))}
|
|
1688
|
+
</div>
|
|
1485
1689
|
}
|
|
1486
|
-
|
|
1487
|
-
|
|
1690
|
+
intent="warning"
|
|
1691
|
+
icon="warning-sign"
|
|
1692
|
+
/>
|
|
1693
|
+
)}
|
|
1694
|
+
{!isInPairwiseOverviewView && (
|
|
1695
|
+
<UncontrolledSliderWithPlusMinusBtns
|
|
1696
|
+
noWraparound
|
|
1697
|
+
bindOutsideChangeHelper={bindOutsideChangeHelper.current}
|
|
1698
|
+
onClick={() => {
|
|
1699
|
+
setTimeout(scrollToCaret, 0);
|
|
1700
|
+
}}
|
|
1701
|
+
minCharWidth={getMinCharWidth()}
|
|
1702
|
+
onChange={async zoomLvl => {
|
|
1703
|
+
isZooming.current = true;
|
|
1704
|
+
setTimeout(() => {
|
|
1705
|
+
isZooming.current = false;
|
|
1706
|
+
}, 10);
|
|
1707
|
+
// zoomLvl is in the range of 0 to 10
|
|
1708
|
+
const minCharWidth = getMinCharWidth();
|
|
1709
|
+
const scaleFactor = Math.pow(12 / minCharWidth, 1 / 10);
|
|
1710
|
+
const newCharWidth =
|
|
1711
|
+
minCharWidth * Math.pow(scaleFactor, zoomLvl);
|
|
1712
|
+
await setCharWidthInLinearView({
|
|
1713
|
+
charWidthInLinearView: newCharWidth
|
|
1714
|
+
});
|
|
1715
|
+
await scrollToCaret();
|
|
1716
|
+
await updateLabelsForInViewFeatures({
|
|
1717
|
+
rectElement: ".alignmentHolder"
|
|
1718
|
+
});
|
|
1719
|
+
}}
|
|
1720
|
+
coerceInitialValue={coerceInitialValue}
|
|
1721
|
+
title="Adjust Zoom Level"
|
|
1722
|
+
style={{ paddingTop: "4px", width: 100 }}
|
|
1723
|
+
className="veZoomAlignmentSlider ove-slider"
|
|
1724
|
+
labelRenderer={false}
|
|
1725
|
+
initialValue={charWidth}
|
|
1726
|
+
stepSize={0.05} //was 0.01
|
|
1727
|
+
max={10}
|
|
1728
|
+
min={0}
|
|
1729
|
+
clickStepSize={0.5}
|
|
1730
|
+
/>
|
|
1731
|
+
)}
|
|
1732
|
+
{!noVisibilityOptions && !isInPairwiseOverviewView && (
|
|
1733
|
+
<AlignmentVisibilityTool
|
|
1734
|
+
currentPairwiseAlignmentIndex={
|
|
1735
|
+
currentPairwiseAlignmentIndex
|
|
1488
1736
|
}
|
|
1489
|
-
|
|
1490
|
-
setSaveMessageLoading(true);
|
|
1491
|
-
await handleAlignmentRename(v, props);
|
|
1492
|
-
setSaveMessage("Rename Successful");
|
|
1493
|
-
setSaveMessageLoading(false);
|
|
1494
|
-
setTimeout(() => {
|
|
1495
|
-
setSaveMessage(undefined);
|
|
1496
|
-
setSaveMessageLoading(false);
|
|
1497
|
-
}, 5000);
|
|
1498
|
-
}}
|
|
1499
|
-
selectAllOnFocus={true}
|
|
1500
|
-
className="veAlignmentName"
|
|
1501
|
-
/>
|
|
1502
|
-
|
|
1503
|
-
<div
|
|
1504
|
-
className="veAlignmentType"
|
|
1505
|
-
style={{
|
|
1506
|
-
paddingTop: "3px",
|
|
1507
|
-
fontSize: "14px",
|
|
1508
|
-
color: "grey",
|
|
1509
|
-
maxWidth: "300px",
|
|
1510
|
-
overflow: "hidden",
|
|
1511
|
-
textOverflow: "ellipsis",
|
|
1512
|
-
whiteSpace: "nowrap"
|
|
1513
|
-
}}
|
|
1514
|
-
data-title={alignmentType || "Unknown Alignment Type"}
|
|
1515
|
-
>
|
|
1516
|
-
{alignmentType || "Unknown Alignment Type"}
|
|
1517
|
-
</div>
|
|
1518
|
-
</div>
|
|
1519
|
-
|
|
1520
|
-
{unmappedSeqs && (
|
|
1521
|
-
<InfoHelper
|
|
1522
|
-
size={20}
|
|
1523
|
-
content={
|
|
1524
|
-
<div>
|
|
1525
|
-
This alignment had sequences that did not map to the
|
|
1526
|
-
template sequence:
|
|
1527
|
-
{unmappedSeqs.map(({ sequenceData }, i) => (
|
|
1528
|
-
<div key={i}>{sequenceData.name}</div>
|
|
1529
|
-
))}
|
|
1530
|
-
</div>
|
|
1531
|
-
}
|
|
1532
|
-
intent="warning"
|
|
1533
|
-
icon="warning-sign"
|
|
1534
|
-
/>
|
|
1535
|
-
)}
|
|
1536
|
-
{!isInPairwiseOverviewView && (
|
|
1537
|
-
<UncontrolledSliderWithPlusMinusBtns
|
|
1538
|
-
noWraparound
|
|
1539
|
-
bindOutsideChangeHelper={bindOutsideChangeHelper.current}
|
|
1540
|
-
onClick={() => {
|
|
1541
|
-
setTimeout(scrollToCaret, 0);
|
|
1542
|
-
}}
|
|
1543
|
-
minCharWidth={getMinCharWidth()}
|
|
1544
|
-
onChange={async zoomLvl => {
|
|
1545
|
-
isZooming.current = true;
|
|
1546
|
-
setTimeout(() => {
|
|
1547
|
-
isZooming.current = false;
|
|
1548
|
-
}, 10);
|
|
1549
|
-
// zoomLvl is in the range of 0 to 10
|
|
1550
|
-
const minCharWidth = getMinCharWidth();
|
|
1551
|
-
const scaleFactor = Math.pow(12 / minCharWidth, 1 / 10);
|
|
1552
|
-
const newCharWidth =
|
|
1553
|
-
minCharWidth * Math.pow(scaleFactor, zoomLvl);
|
|
1554
|
-
await setCharWidthInLinearView({
|
|
1555
|
-
charWidthInLinearView: newCharWidth
|
|
1556
|
-
});
|
|
1557
|
-
await scrollToCaret();
|
|
1558
|
-
await updateLabelsForInViewFeatures({
|
|
1559
|
-
rectElement: ".alignmentHolder"
|
|
1560
|
-
});
|
|
1561
|
-
}}
|
|
1562
|
-
coerceInitialValue={coerceInitialValue}
|
|
1563
|
-
title="Adjust Zoom Level"
|
|
1564
|
-
style={{ paddingTop: "4px", width: 100 }}
|
|
1565
|
-
className="veZoomAlignmentSlider ove-slider"
|
|
1566
|
-
labelRenderer={false}
|
|
1567
|
-
initialValue={charWidth}
|
|
1568
|
-
stepSize={0.05} //was 0.01
|
|
1569
|
-
max={10}
|
|
1570
|
-
min={0}
|
|
1571
|
-
clickStepSize={0.5}
|
|
1572
|
-
/>
|
|
1573
|
-
)}
|
|
1574
|
-
{!noVisibilityOptions && !isInPairwiseOverviewView && (
|
|
1575
|
-
<AlignmentVisibilityTool
|
|
1576
|
-
currentPairwiseAlignmentIndex={
|
|
1577
|
-
currentPairwiseAlignmentIndex
|
|
1578
|
-
}
|
|
1579
|
-
{...alignmentVisibilityToolOptions}
|
|
1580
|
-
/>
|
|
1581
|
-
)}
|
|
1582
|
-
{additionalTopEl}
|
|
1583
|
-
{saveMessage && (
|
|
1584
|
-
<div
|
|
1585
|
-
className="ove-menu-toast"
|
|
1586
|
-
style={{
|
|
1587
|
-
display: "flex",
|
|
1588
|
-
alignItems: "center",
|
|
1589
|
-
marginLeft: "auto",
|
|
1590
|
-
marginRight: 10
|
|
1591
|
-
}}
|
|
1592
|
-
>
|
|
1593
|
-
{saveMessageLoading ? (
|
|
1594
|
-
<div>
|
|
1595
|
-
<Spinner size={15}></Spinner>
|
|
1596
|
-
</div>
|
|
1597
|
-
) : (
|
|
1598
|
-
<Icon icon="tick-circle" intent="success"></Icon>
|
|
1599
|
-
)}{" "}
|
|
1600
|
-
|
|
1601
|
-
{saveMessage}
|
|
1602
|
-
</div>
|
|
1603
|
-
)}
|
|
1604
|
-
</div>
|
|
1605
|
-
{hasTemplate ? (
|
|
1606
|
-
<>
|
|
1607
|
-
<div className="alignmentTrackFixedToTop">
|
|
1608
|
-
{getTrackVis([firstTrack], true, alignmentTracks)}
|
|
1609
|
-
</div>
|
|
1610
|
-
{getTrackVis(otherTracks, false, alignmentTracks)}
|
|
1611
|
-
</>
|
|
1612
|
-
) : (
|
|
1613
|
-
getTrackVis(alignmentTracks, false, alignmentTracks)
|
|
1614
|
-
)}
|
|
1615
|
-
</div>
|
|
1616
|
-
</DragDropContext>
|
|
1617
|
-
{!isInPairwiseOverviewView && (
|
|
1618
|
-
<div
|
|
1619
|
-
className="alignmentViewBottomBar"
|
|
1620
|
-
style={{
|
|
1621
|
-
// flexGrow: 1,
|
|
1622
|
-
// minHeight: "-webkit-min-content", //https://stackoverflow.com/questions/28029736/how-to-prevent-a-flex-item-from-shrinking-smaller-than-its-content
|
|
1623
|
-
maxHeight: 210,
|
|
1624
|
-
marginTop: 4,
|
|
1625
|
-
paddingTop: 4,
|
|
1626
|
-
borderTop: "1px solid lightgrey",
|
|
1627
|
-
display: "flex"
|
|
1628
|
-
}}
|
|
1629
|
-
>
|
|
1630
|
-
<Minimap
|
|
1631
|
-
selectionLayerComp={
|
|
1632
|
-
<>
|
|
1633
|
-
<PerformantSelectionLayer
|
|
1634
|
-
is
|
|
1635
|
-
hideCarets
|
|
1636
|
-
className="veAlignmentSelectionLayer veMinimapSelectionLayer"
|
|
1637
|
-
easyStore={easyStore.current}
|
|
1638
|
-
sequenceLength={maxLength}
|
|
1639
|
-
charWidth={getMinCharWidth(true)}
|
|
1640
|
-
row={{ start: 0, end: maxLength - 1 }}
|
|
1737
|
+
{...alignmentVisibilityToolOptions}
|
|
1641
1738
|
/>
|
|
1642
|
-
|
|
1739
|
+
)}
|
|
1740
|
+
{additionalTopEl}
|
|
1741
|
+
{saveMessage && (
|
|
1742
|
+
<div
|
|
1743
|
+
className="ove-menu-toast"
|
|
1643
1744
|
style={{
|
|
1644
|
-
|
|
1745
|
+
display: "flex",
|
|
1746
|
+
alignItems: "center",
|
|
1747
|
+
marginLeft: "auto",
|
|
1748
|
+
marginRight: 10
|
|
1645
1749
|
}}
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1750
|
+
>
|
|
1751
|
+
{saveMessageLoading ? (
|
|
1752
|
+
<div>
|
|
1753
|
+
<Spinner size={15}></Spinner>
|
|
1754
|
+
</div>
|
|
1755
|
+
) : (
|
|
1756
|
+
<Icon icon="tick-circle" intent="success"></Icon>
|
|
1757
|
+
)}{" "}
|
|
1758
|
+
|
|
1759
|
+
{saveMessage}
|
|
1760
|
+
</div>
|
|
1761
|
+
)}
|
|
1762
|
+
{!propertySidePanel.isOpen && (
|
|
1763
|
+
<Button
|
|
1764
|
+
small
|
|
1765
|
+
minimal
|
|
1766
|
+
className={"showTrackPropertiesBtn"}
|
|
1767
|
+
icon={"menu-closed"}
|
|
1768
|
+
intent="primary"
|
|
1769
|
+
style={{ marginLeft: "auto" }}
|
|
1770
|
+
onClick={() => {
|
|
1771
|
+
setPropertySidePanel(prev => {
|
|
1772
|
+
return {
|
|
1773
|
+
...prev,
|
|
1774
|
+
isOpen: true
|
|
1775
|
+
};
|
|
1776
|
+
});
|
|
1777
|
+
}}
|
|
1778
|
+
data-tip={"Show Track Properties"}
|
|
1779
|
+
></Button>
|
|
1780
|
+
)}
|
|
1781
|
+
</div>
|
|
1782
|
+
{hasTemplate ? (
|
|
1783
|
+
<>
|
|
1784
|
+
<div className="alignmentTrackFixedToTop">
|
|
1785
|
+
{getTrackVis(
|
|
1786
|
+
[firstTrack],
|
|
1787
|
+
true,
|
|
1788
|
+
alignmentTracks,
|
|
1789
|
+
aminoAcidAlignmentProperties,
|
|
1790
|
+
labileSites
|
|
1791
|
+
)}
|
|
1792
|
+
</div>
|
|
1793
|
+
{getTrackVis(
|
|
1794
|
+
otherTracks,
|
|
1795
|
+
false,
|
|
1796
|
+
alignmentTracks,
|
|
1797
|
+
aminoAcidAlignmentProperties,
|
|
1798
|
+
labileSites
|
|
1799
|
+
)}
|
|
1652
1800
|
</>
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1801
|
+
) : (
|
|
1802
|
+
getTrackVis(
|
|
1803
|
+
alignmentTracks,
|
|
1804
|
+
false,
|
|
1805
|
+
alignmentTracks,
|
|
1806
|
+
aminoAcidAlignmentProperties,
|
|
1807
|
+
labileSites
|
|
1808
|
+
)
|
|
1809
|
+
)}
|
|
1810
|
+
</div>
|
|
1811
|
+
</DragDropContext>
|
|
1812
|
+
{!isInPairwiseOverviewView && (
|
|
1813
|
+
<div
|
|
1814
|
+
className="alignmentViewBottomBar"
|
|
1815
|
+
style={{
|
|
1816
|
+
// flexGrow: 1,
|
|
1817
|
+
// minHeight: "-webkit-min-content", //https://stackoverflow.com/questions/28029736/how-to-prevent-a-flex-item-from-shrinking-smaller-than-its-content
|
|
1818
|
+
maxHeight: 210,
|
|
1819
|
+
marginTop: 4,
|
|
1820
|
+
paddingTop: 4,
|
|
1821
|
+
borderTop: "1px solid lightgrey",
|
|
1822
|
+
display: "flex"
|
|
1657
1823
|
}}
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1824
|
+
>
|
|
1825
|
+
<Minimap
|
|
1826
|
+
selectionLayerComp={
|
|
1827
|
+
<>
|
|
1828
|
+
<PerformantSelectionLayer
|
|
1829
|
+
is
|
|
1830
|
+
hideCarets
|
|
1831
|
+
className="veAlignmentSelectionLayer veMinimapSelectionLayer"
|
|
1832
|
+
easyStore={easyStore.current}
|
|
1833
|
+
sequenceLength={maxLength}
|
|
1834
|
+
charWidth={getMinCharWidth(true)}
|
|
1835
|
+
row={{ start: 0, end: maxLength - 1 }}
|
|
1836
|
+
/>
|
|
1837
|
+
<PerformantCaret
|
|
1838
|
+
style={{
|
|
1839
|
+
opacity: 0.2
|
|
1840
|
+
}}
|
|
1841
|
+
className="veAlignmentSelectionLayer veMinimapSelectionLayer"
|
|
1842
|
+
sequenceLength={maxLength}
|
|
1843
|
+
charWidth={getMinCharWidth(true)}
|
|
1844
|
+
row={{ start: 0, end: maxLength - 1 }}
|
|
1845
|
+
easyStore={easyStore.current}
|
|
1846
|
+
/>
|
|
1847
|
+
</>
|
|
1848
|
+
}
|
|
1849
|
+
alignmentTracks={alignmentTracks}
|
|
1850
|
+
dimensions={{
|
|
1851
|
+
width: Math.max(width, 10) || 10
|
|
1852
|
+
}}
|
|
1853
|
+
nameDivOffsetPercent={0}
|
|
1854
|
+
scrollYToTrack={scrollYToTrack}
|
|
1855
|
+
onSizeAdjust={onMinimapSizeAdjust}
|
|
1856
|
+
minSliderSize={minSliderSize}
|
|
1857
|
+
laneHeight={
|
|
1858
|
+
minimapLaneHeight || (alignmentTracks.length > 5 ? 10 : 17)
|
|
1859
|
+
}
|
|
1860
|
+
laneSpacing={
|
|
1861
|
+
minimapLaneSpacing || (alignmentTracks.length > 5 ? 2 : 1)
|
|
1862
|
+
}
|
|
1863
|
+
easyStore={easyStore.current}
|
|
1864
|
+
numBpsShownInLinearView={getNumBpsShownInLinearView()}
|
|
1865
|
+
scrollAlignmentView={false}
|
|
1866
|
+
onMinimapScrollX={scrollAlignmentToPercent}
|
|
1867
|
+
/>
|
|
1868
|
+
</div>
|
|
1869
|
+
)}
|
|
1870
|
+
<GlobalDialog
|
|
1871
|
+
// {...pickedUserDefinedHandlersAndOpts}
|
|
1872
|
+
// dialogOverrides={pick(this.props, [
|
|
1873
|
+
// "AddOrEditFeatureDialogOverride",
|
|
1874
|
+
// "AddOrEditPartDialogOverride",
|
|
1875
|
+
// "AddOrEditPrimerDialogOverride"
|
|
1876
|
+
// ])}
|
|
1877
|
+
/>
|
|
1878
|
+
</div>
|
|
1879
|
+
</ResizeSensor>
|
|
1880
|
+
{propertySidePanel.isOpen && (
|
|
1881
|
+
<PropertySidePanel
|
|
1882
|
+
properties={propertySidePanel}
|
|
1883
|
+
setProperties={setPropertySidePanel}
|
|
1884
|
+
style={{
|
|
1885
|
+
height: viewportHeight * 0.88
|
|
1886
|
+
}}
|
|
1682
1887
|
/>
|
|
1683
|
-
|
|
1684
|
-
</
|
|
1888
|
+
)}
|
|
1889
|
+
</div>
|
|
1685
1890
|
</PinchHelper>
|
|
1686
1891
|
);
|
|
1687
1892
|
};
|
|
@@ -1737,6 +1942,20 @@ export default compose(
|
|
|
1737
1942
|
"cdsFeatureTranslations",
|
|
1738
1943
|
"chromatogram",
|
|
1739
1944
|
"dnaColors",
|
|
1945
|
+
"physicalProperties",
|
|
1946
|
+
"serineThreonine",
|
|
1947
|
+
"labileSites",
|
|
1948
|
+
"colorScheme",
|
|
1949
|
+
"plot",
|
|
1950
|
+
"conservation",
|
|
1951
|
+
"properties",
|
|
1952
|
+
"hydrophobicity",
|
|
1953
|
+
"polar",
|
|
1954
|
+
"negative",
|
|
1955
|
+
"positive",
|
|
1956
|
+
"charged",
|
|
1957
|
+
"aliphatic",
|
|
1958
|
+
"aromatic",
|
|
1740
1959
|
"compactNames"
|
|
1741
1960
|
];
|
|
1742
1961
|
const togglableAlignmentAnnotationSettings = {};
|