@teselagen/ove 0.7.27 → 0.7.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. package/AASliver.js +187 -0
  2. package/AddLaddersDialog.js +82 -0
  3. package/AdditionalCutsiteInfoDialog.js +599 -0
  4. package/AlignmentView/Mismatches.d.ts +3 -3
  5. package/AlignmentVisibilityTool.js +105 -0
  6. package/AnnotationContainerHolder.js +20 -0
  7. package/AnnotationPositioner.js +27 -0
  8. package/AutoAnnotate.js +501 -0
  9. package/AutoAnnotateBpMatchingDialog.js +208 -0
  10. package/Axis.js +151 -0
  11. package/AxisNumbers.js +35 -0
  12. package/Browser.js +106 -0
  13. package/Caret.js +63 -0
  14. package/Chromatogram.js +293 -0
  15. package/CircularDnaSequence.js +73 -0
  16. package/CircularView/Labels/index.d.ts +1 -1
  17. package/CircularView/index.d.ts +0 -1
  18. package/CircularZoomMinimap.js +16 -0
  19. package/ColorPicker.js +30 -0
  20. package/CommandHotkeyHandler.js +44 -0
  21. package/CreateAnnotationsPage.d.ts +4 -4
  22. package/CreateAnnotationsPage.js +98 -0
  23. package/Cutsite.js +18 -0
  24. package/CutsiteProperties.js +176 -0
  25. package/CutsiteSelectionLayers.js +47 -0
  26. package/Cutsites.js +271 -0
  27. package/DeletionLayer.js +28 -0
  28. package/DigestTool/Ladder.d.ts +1 -1
  29. package/DropHandler.css +21 -0
  30. package/DropHandler.js +64 -0
  31. package/EditCaretPosition.js +234 -0
  32. package/EditTrackNameDialog.js +30 -0
  33. package/Feature.js +83 -0
  34. package/FeatureProperties.js +6 -0
  35. package/FillWindow.js +47 -0
  36. package/GenbankView.js +74 -0
  37. package/GeneralProperties.js +117 -0
  38. package/GenericAnnotationProperties.js +406 -0
  39. package/GlobalDialog.js +73 -0
  40. package/GlobalDialogUtils.js +110 -0
  41. package/GoToDialog.js +25 -0
  42. package/HorizontalPanelDragHandle.js +35 -0
  43. package/Keyboard.js +85 -0
  44. package/Labels.js +327 -0
  45. package/Ladder.css +20 -0
  46. package/Ladder.js +303 -0
  47. package/MeltingTemp.js +85 -0
  48. package/Menlo.ttf +0 -0
  49. package/Minimap.js +515 -0
  50. package/Mismatches.js +134 -0
  51. package/Monaco.ttf +0 -0
  52. package/MultipleSeqsDetectedOnImportDialog.js +74 -0
  53. package/Orf.js +109 -0
  54. package/OrfProperties.js +117 -0
  55. package/Orfs.js +35 -0
  56. package/PCRTool.js +179 -0
  57. package/PairwiseAlignmentView.js +68 -0
  58. package/Part.js +34 -0
  59. package/PartProperties.js +9 -0
  60. package/PassThrough.js +3 -0
  61. package/PerformantSelectionLayer.js +32 -0
  62. package/PinchHelper.js +24 -0
  63. package/PointedAnnotation.js +347 -0
  64. package/PositionAnnotationOnCircle.js +26 -0
  65. package/Primer.js +41 -0
  66. package/PrimerProperties.js +19 -0
  67. package/Reflex/index.d.ts +0 -1
  68. package/ReflexContainer.js +802 -0
  69. package/ReflexElement.js +160 -0
  70. package/ReflexEvents.js +77 -0
  71. package/ReflexSplitter.js +205 -0
  72. package/RenameSequenceDialog.js +7 -0
  73. package/RotateCircularViewSlider.js +93 -0
  74. package/RowView/index.d.ts +0 -1
  75. package/SelectDialog.js +150 -0
  76. package/SequenceName.js +15 -0
  77. package/SimpleCircularOrLinearView.js +381 -0
  78. package/SimpleOligoPreview.js +39 -0
  79. package/SingleEnzymeCutsiteInfo.js +139 -0
  80. package/ToolBar/ToolbarItem.d.ts +1 -3
  81. package/ToolbarItem.js +192 -0
  82. package/Translation.js +198 -0
  83. package/TranslationProperties.js +149 -0
  84. package/UncontrolledSliderWithPlusMinusBtns.css +5 -0
  85. package/UncontrolledSliderWithPlusMinusBtns.js +134 -0
  86. package/VeTopRightContainer.js +12 -0
  87. package/ZoomCircularViewSlider.js +62 -0
  88. package/ZoomLinearView.js +47 -0
  89. package/addAlignment.js +6 -0
  90. package/addMetaToActionCreators.js +12 -0
  91. package/addWrappedAddons.js +20 -0
  92. package/alignmentTool.js +503 -0
  93. package/alignments.js +379 -0
  94. package/annotationLabelVisibility.js +2 -0
  95. package/annotationSearchSelector.js +24 -0
  96. package/annotationTypes.js +35 -0
  97. package/annotationVisibility.js +196 -0
  98. package/annotationsToSupport.js +104 -0
  99. package/arrayToObjWithIds.js +17 -0
  100. package/arrayUtils.js +19 -0
  101. package/array_move.js +10 -0
  102. package/calculateTickMarkPositionsForGivenRange.js +47 -0
  103. package/caretPosition.js +27 -0
  104. package/cdsFeaturesSelector.js +9 -0
  105. package/charWidth.js +22 -0
  106. package/circular.js +19 -0
  107. package/circularSelector.js +4 -0
  108. package/clickAndDragUtils.js +576 -0
  109. package/coerceInitialValue.js +7 -0
  110. package/combineReducersDontIgnoreKeys.js +12 -0
  111. package/commandUtils.js +20 -0
  112. package/constants.js +2 -0
  113. package/copyOptions.js +34 -0
  114. package/createFragmentLines.js +120 -0
  115. package/createMergedDefaultStateReducer.js +30 -0
  116. package/createMetaAction.js +12 -0
  117. package/createSequenceInputPopup.js +290 -0
  118. package/createSequenceInputPopupStyle.css +87 -0
  119. package/createSimpleDialog.js +89 -0
  120. package/createYourOwnEnzyme.js +39 -0
  121. package/cutsiteLabelColorSelector.js +6 -0
  122. package/cutsiteTool.js +88 -0
  123. package/cutsitesByRangeSelector.js +5 -0
  124. package/cutsitesSelector.js +61 -0
  125. package/darkmode.css +98 -0
  126. package/defaultConfig.js +150 -0
  127. package/deletionLayers.js +36 -0
  128. package/description.js +21 -0
  129. package/digestTool.js +34 -0
  130. package/dnaToColor.js +17 -0
  131. package/downloadTool.js +39 -0
  132. package/draggableClassnames.js +5 -0
  133. package/drawAnnotations.js +440 -0
  134. package/drawDirectedPiePiece.js +142 -0
  135. package/editTool.js +49 -0
  136. package/editorSelector.js +2 -0
  137. package/editorUtils.js +205 -0
  138. package/estimateRowHeight.js +184 -0
  139. package/featureLengthsToHide.js +27 -0
  140. package/featureTool.js +34 -0
  141. package/features.js +19 -0
  142. package/featuresSelector.js +8 -0
  143. package/filteredCutsitesSelector.js +136 -0
  144. package/filteredFeaturesSelector.js +32 -0
  145. package/filteredPartsSelector.js +57 -0
  146. package/filteredPrimersSelector.js +27 -0
  147. package/filteredRestrictionEnzymesSelector.js +1 -0
  148. package/find.png +0 -0
  149. package/findTool.js +79 -0
  150. package/findToolConstants.js +1 -0
  151. package/frameTranslations.js +52 -0
  152. package/fullscreen.png +0 -0
  153. package/getAdditionalEnzymesSelector.js +46 -0
  154. package/getAngleForPositionMidpoint.js +3 -0
  155. package/getAnnotationClassnames.js +12 -0
  156. package/getAnnotationNameAndStartStopString.js +61 -0
  157. package/getBpsPerRow.js +19 -0
  158. package/getCutsiteLabelHeights.js +56 -0
  159. package/getGapMap.js +12 -0
  160. package/getGaps.js +27 -0
  161. package/getInternalLabel.js +40 -0
  162. package/getOveHotkeyDefs.js +12 -0
  163. package/getPairwiseOverviewLinearViewOptions.js +38 -0
  164. package/getRangeAnglesSpecial.js +12 -0
  165. package/getStructuredBases.js +97 -0
  166. package/getTrackFromEvent.js +25 -0
  167. package/getVisibleStartEnd.js +7 -0
  168. package/getXStartAndWidthFromNonCircularRange.js +12 -0
  169. package/getXStartAndWidthOfRangeWrtRow.js +27 -0
  170. package/getXStartAndWidthOfRowAnnotation.js +19 -0
  171. package/getYOffset.js +15 -0
  172. package/hoveredAnnotation.js +24 -0
  173. package/{html2canvas.esm--JN4fLQL.js → html2canvas.esm-DiGWN1gP.js} +187 -229
  174. package/{html2canvas.esm-B7d7VJmQ.cjs → html2canvas.esm-J1esNpMJ.cjs} +187 -229
  175. package/importTool.js +27 -0
  176. package/index.cjs.js +48165 -47142
  177. package/index.es.js +47699 -46676
  178. package/index.js +71 -0
  179. package/inlineFindTool.js +38 -0
  180. package/isElementInViewport.js +29 -0
  181. package/isEnzymeFilterAndSelector.js +1 -0
  182. package/isTargetWithinEl.js +6 -0
  183. package/labelLineIntensity.js +25 -0
  184. package/labelSize.js +23 -0
  185. package/ladderDefaults.js +25 -0
  186. package/lastSavedId.js +20 -0
  187. package/lineageLines.js +11 -0
  188. package/linear.png +0 -0
  189. package/makeStore.js +34 -0
  190. package/massageTickSpacing.js +19 -0
  191. package/materiallyAvailable.js +19 -0
  192. package/middleware.js +112 -0
  193. package/minimumOrfSize.js +24 -0
  194. package/minimumOrfSizeSelector.js +2 -0
  195. package/modalActions.js +3 -0
  196. package/moveCaret.js +58 -0
  197. package/name.js +19 -0
  198. package/normalizeAngle.js +3 -0
  199. package/normalizeAngleRange.js +9 -0
  200. package/oligoTool.js +30 -0
  201. package/onlyUpdateForKeysDeep.js +31 -0
  202. package/orfFrameToColorMap.js +10 -0
  203. package/orfTool.js +136 -0
  204. package/orfsSelector.js +15 -0
  205. package/ove.css +12107 -0
  206. package/package.json +6 -5
  207. package/panelsShown.js +294 -0
  208. package/partLengthsToHide.js +23 -0
  209. package/partOverhangs.js +6 -0
  210. package/partTagSearch.js +69 -0
  211. package/partTool.js +45 -0
  212. package/parts.js +19 -0
  213. package/partsSelector.js +8 -0
  214. package/pie.png +0 -0
  215. package/polarToSpecialCartesian.js +7 -0
  216. package/positionCutsites.js +6 -0
  217. package/prepareRowData.js +64 -0
  218. package/primerBases.js +221 -0
  219. package/primerLengthsToHide.js +27 -0
  220. package/primers.js +19 -0
  221. package/primersSelector.js +8 -0
  222. package/print.png +0 -0
  223. package/printTool.js +31 -0
  224. package/propertiesTool.js +40 -0
  225. package/proteinUtils.js +3 -0
  226. package/pureNoFunc.js +18 -0
  227. package/readOnly.js +25 -0
  228. package/redoTool.js +30 -0
  229. package/reflex-styles.css +128 -0
  230. package/reflex-styles.css.map +9 -0
  231. package/relaxLabelAngles.js +157 -0
  232. package/relaxLabels_DEPRECATED.js +105 -0
  233. package/replacementLayers.js +36 -0
  234. package/restrictionEnzymes.js +52 -0
  235. package/restrictionEnzymesSelector.js +34 -0
  236. package/rowviewContants.js +3 -0
  237. package/ruler.css +89 -0
  238. package/save.png +0 -0
  239. package/saveTool.js +44 -0
  240. package/searchLayersSelector.js +71 -0
  241. package/selectedAnnotations.js +89 -0
  242. package/selectedAnnotationsSelector.js +1 -0
  243. package/selectedCutsitesSelector.js +21 -0
  244. package/selectedPartTags.js +21 -0
  245. package/selectionLayer.js +25 -0
  246. package/selectors/annotationSearchSelector.d.ts +1 -1
  247. package/sequence.js +12 -0
  248. package/sequenceDataHistory.js +43 -0
  249. package/sequenceDataSelector.js +2 -0
  250. package/sequenceLengthSelector.js +5 -0
  251. package/sequenceSelector.js +4 -0
  252. package/sharedActionCreators.js +0 -0
  253. package/shouldFlipText.js +4 -0
  254. package/shouldRerender.js +27 -0
  255. package/showFileDialog.js +25 -0
  256. package/showGCContent.js +23 -0
  257. package/show_cut_sites.png +0 -0
  258. package/show_features.png +0 -0
  259. package/show_orfs.png +0 -0
  260. package/show_primers.png +0 -0
  261. package/simpleDialog.css +13 -0
  262. package/specialCutsiteFilterOptions.js +22 -0
  263. package/src/Editor/DropHandler.js +2 -1
  264. package/src/Editor/index.js +0 -2
  265. package/src/RowItem/StackedAnnotations/getStructuredBases.js +20 -6
  266. package/src/ToolBar/cutsiteTool.js +1 -1
  267. package/src/helperComponents/PropertiesDialog/TranslationProperties.js +2 -1
  268. package/style.css +3 -12100
  269. package/tagsToBoldSelector.js +2 -0
  270. package/toggle_views.svg +1 -0
  271. package/toolBar.js +23 -0
  272. package/translationSearchMatchesSelector.js +14 -0
  273. package/translations.js +20 -0
  274. package/translationsRawSelector.js +8 -0
  275. package/translationsSelector.js +137 -0
  276. package/typeField.js +24 -0
  277. package/undoTool.js +30 -0
  278. package/updateEditor.d.ts +1 -3
  279. package/updateEditor.js +200 -0
  280. package/updateLabelsForInViewFeatures.js +55 -0
  281. package/updateLabelsForInViewFeaturesCircView.js +41 -0
  282. package/updateTrackHelper.js +58 -0
  283. package/uppercaseSequenceMapFont.js +25 -0
  284. package/upsertDeleteActionGenerator.js +31 -0
  285. package/useAAColorType.js +8 -0
  286. package/useAdditionalOrfStartCodons.js +24 -0
  287. package/useAnnotationLimits.js +42 -0
  288. package/useChromatogramPrefs.js +31 -0
  289. package/useFormValue.js +7 -0
  290. package/useLadders.js +6 -0
  291. package/useMeltingTemp.js +7 -0
  292. package/useTmType.js +10 -0
  293. package/userDefinedHandlersAndOpts.js +61 -0
  294. package/utils/getAnnotationNameAndStartStopString.d.ts +1 -5
  295. package/utils/selectionLayer.d.ts +2 -2
  296. package/utils.js +37 -0
  297. package/versionHistory.js +26 -0
  298. package/versionHistoryTool.js +21 -0
  299. package/viewSubmenu.js +479 -0
  300. package/visibilityTool.js +39 -0
  301. package/withEditorInteractions/getBpsPerRow.d.ts +1 -3
  302. package/withHover.js +113 -0
  303. package/withRestrictionEnzymes.js +15 -0
  304. package/index.umd.js +0 -188322
package/Minimap.js ADDED
@@ -0,0 +1,515 @@
1
+ import React from "react";
2
+ import Draggable from "react-draggable";
3
+ import ReactList from "@teselagen/react-list";
4
+ import Axis from "../RowItem/Axis";
5
+ import getXStartAndWidthFromNonCircularRange from "../RowItem/getXStartAndWidthFromNonCircularRange";
6
+ import { view } from "@risingstack/react-easy-state";
7
+ import { flatMap, some, toNumber } from "lodash-es";
8
+ import {
9
+ getOverlapOfNonCircularRanges,
10
+ invertRange,
11
+ isPositionWithinRange,
12
+ splitRangeIntoTwoPartsIfItIsCircular
13
+ } from "@teselagen/range-utils";
14
+ import { massageTickSpacing } from "../utils/massageTickSpacing";
15
+ import { getClientX, getClientY } from "../utils/editorUtils";
16
+ export default class Minimap extends React.Component {
17
+ shouldComponentUpdate(newProps) {
18
+ const { props } = this;
19
+ if (
20
+ [
21
+ "alignmentTracks",
22
+ "numBpsShownInLinearView",
23
+ "scrollAlignmentView",
24
+ "laneHeight",
25
+ "laneSpacing"
26
+ ].some(key => props[key] !== newProps[key])
27
+ )
28
+ return true;
29
+ return false;
30
+ }
31
+ handleMinimapClick = e => {
32
+ if (
33
+ this.isDragging ||
34
+ (e.target && e.target.classList.contains("minimapCaret"))
35
+ ) {
36
+ e.stopPropagation();
37
+ return;
38
+ }
39
+ const {
40
+ onMinimapScrollX,
41
+ dimensions: { width = 200 }
42
+ } = this.props;
43
+ const scrollHandleWidth = this.getScrollHandleWidth();
44
+ const percent =
45
+ (this.getXPositionOfClickInMinimap(e) - scrollHandleWidth / 2) /
46
+ (width - scrollHandleWidth);
47
+ onMinimapScrollX(percent);
48
+ this.scrollMinimapVertical({ e, force: true });
49
+ };
50
+ getSeqLen = () => {
51
+ const { alignmentTracks = [] } = this.props;
52
+ const [template] = alignmentTracks;
53
+ const seqLength = template.alignmentData.sequence.length;
54
+ return seqLength;
55
+ };
56
+ /**
57
+ * @returns current nucleotide char
58
+ * width, nucelotide char width scales with zooming
59
+ */
60
+ getCharWidth = () => {
61
+ const {
62
+ dimensions: { width = 200 }
63
+ } = this.props;
64
+ const seqLength = this.getSeqLen();
65
+ const charWidth = Math.min(16, width / seqLength);
66
+ return charWidth || 12;
67
+ };
68
+ /**
69
+ * @returns the width of the highlighted region of the minimap
70
+ */
71
+ getScrollHandleWidth = () => {
72
+ const { numBpsShownInLinearView, dimensions } = this.props;
73
+ const charWidth = this.getCharWidth();
74
+ const { width } = getXStartAndWidthFromNonCircularRange(
75
+ { start: 0, end: Math.max(numBpsShownInLinearView - 1, 0) },
76
+ charWidth
77
+ );
78
+ return Math.min(width, dimensions.width);
79
+ };
80
+ getXPositionOfClickInMinimap = e => {
81
+ const leftStart = this.minimap.getBoundingClientRect().left;
82
+ return Math.max(getClientX(e) - leftStart, 0);
83
+ };
84
+ getYPositionOfClickInMinimap = e => {
85
+ const topStart = this.minimap.getBoundingClientRect().top;
86
+ return Math.max(getClientY(e) + this.minimapTracks.scrollTop - topStart, 0);
87
+ };
88
+
89
+ scrollMinimapVertical = ({ e, force, initialDragYOffsetFromCenter }) => {
90
+ const clientY = getClientY(e) - (initialDragYOffsetFromCenter || 0);
91
+ try {
92
+ if (
93
+ !force &&
94
+ isPositionWithinRange(clientY, {
95
+ start: this.lastYPosition - 5,
96
+ end: this.lastYPosition + 5
97
+ })
98
+ ) {
99
+ // this.lastYPosition = clientY
100
+ return;
101
+ }
102
+ const lanes = document.querySelectorAll(".minimapLane");
103
+ some(lanes, lane => {
104
+ const rect = lane.getBoundingClientRect();
105
+ if (rect.top > clientY && rect.top - rect.height < clientY) {
106
+ const laneI = toNumber(lane.getAttribute("data-lane-index"));
107
+ let scrollToLane = laneI - 3;
108
+ if (laneI === lanes.length - 1) {
109
+ scrollToLane = laneI - 1;
110
+ } else if (laneI === lanes.length - 2) {
111
+ scrollToLane = laneI - 2;
112
+ }
113
+ this.props.scrollYToTrack(Math.max(scrollToLane, 0));
114
+ return true;
115
+ }
116
+ return false;
117
+ });
118
+ this.lastYPosition = clientY;
119
+ } catch (error) {
120
+ console.error(`error in scrollMinimapVertical:`, error);
121
+ }
122
+ };
123
+ handleDragStop = () => {
124
+ // this.hasSetDirection = false;
125
+ setTimeout(() => {
126
+ this.isDragging = false;
127
+ }, 150);
128
+ };
129
+ /**
130
+ * Handler for beginning to drag across the minimap
131
+ * Sets this.initialDragXOffsetFromCenter and Y for dragging
132
+ * @param {*} e - event
133
+ */
134
+ handleDragStart = e => {
135
+ const eventX = e.pageX;
136
+ const handleEl = window.document.querySelector(".verticalScrollDisplay");
137
+ if (!handleEl) return;
138
+ const { x, width } = handleEl.getBoundingClientRect();
139
+ const yellowScrollHandleXCenter = x + width / 2;
140
+ this.initialDragXOffsetFromCenter = eventX - yellowScrollHandleXCenter;
141
+ const eventY = e.pageY;
142
+
143
+ if (!handleEl) return;
144
+ const { y, height } = handleEl.getBoundingClientRect();
145
+ const yellowScrollHandleYCenter = y + height / 2;
146
+ this.initialDragYOffsetFromCenter = eventY - yellowScrollHandleYCenter;
147
+ };
148
+ /**
149
+ * Moves the highlighted region as we drag
150
+ * @param {*} e - event
151
+ */
152
+ handleDrag = e => {
153
+ const {
154
+ onMinimapScrollX,
155
+ dimensions: { width = 200 }
156
+ } = this.props;
157
+ this.isDragging = true; //needed to block erroneous click events from being triggered!
158
+
159
+ const scrollHandleWidth = this.getScrollHandleWidth();
160
+ const percent =
161
+ (this.getXPositionOfClickInMinimap(e) -
162
+ (this.initialDragXOffsetFromCenter || 0) -
163
+ scrollHandleWidth / 2) /
164
+ (width - scrollHandleWidth);
165
+ onMinimapScrollX(percent);
166
+ this.scrollMinimapVertical({
167
+ e,
168
+ initialDragYOffsetFromCenter: this.initialDragYOffsetFromCenter
169
+ });
170
+ };
171
+ /**
172
+ * @returns this.props.laneheight
173
+ */
174
+ itemSizeGetter = () => {
175
+ return this.props.laneHeight;
176
+ };
177
+ /**
178
+ * Renders a lane (one by one for each call)
179
+ * @param {*} i - lane info
180
+ */
181
+ renderItem = i => {
182
+ const {
183
+ alignmentTracks = [],
184
+ dimensions: { width = 200 },
185
+ laneHeight,
186
+ laneSpacing = 1
187
+ } = this.props;
188
+ const charWidth = this.getCharWidth();
189
+
190
+ const {
191
+ matchHighlightRanges: _matchHighlightRanges,
192
+ alignmentData: { trimmedRange } = {}
193
+ } = alignmentTracks[i];
194
+ const matchHighlightRanges = !trimmedRange
195
+ ? _matchHighlightRanges
196
+ : flatMap(_matchHighlightRanges, r => {
197
+ const overlap = getOverlapOfNonCircularRanges(r, trimmedRange);
198
+ if (!overlap) return [];
199
+ return { ...r, ...overlap };
200
+ });
201
+
202
+ //need to get the chunks that can be rendered
203
+ let redPath = ""; //draw these as just 1 path instead of a bunch of rectangles to improve browser performance
204
+ let bluePath = "";
205
+ // draw one grey rectangle then draw red/mismatching regions on top of it
206
+ const height = laneHeight - laneSpacing;
207
+ const y = 0;
208
+ const firstRange = getXStartAndWidthFromNonCircularRange(
209
+ matchHighlightRanges[0],
210
+ charWidth
211
+ );
212
+ const lastRange = getXStartAndWidthFromNonCircularRange(
213
+ matchHighlightRanges[matchHighlightRanges.length - 1],
214
+ charWidth
215
+ );
216
+ bluePath += `M${firstRange.xStart},${y} L${
217
+ lastRange.xStart + lastRange.width
218
+ },${y} L${lastRange.xStart + lastRange.width},${y + height} L${
219
+ firstRange.xStart
220
+ },${y + height}`;
221
+ matchHighlightRanges.forEach(range => {
222
+ const { xStart, width } = getXStartAndWidthFromNonCircularRange(
223
+ range,
224
+ charWidth
225
+ );
226
+ const toAdd = `M${xStart},${y} L${xStart + width},${y} L${
227
+ xStart + width
228
+ },${y + height} L${xStart},${y + height}`;
229
+ if (!range.isMatch) {
230
+ redPath += toAdd;
231
+ }
232
+ });
233
+ return (
234
+ <div
235
+ key={i + "-lane"}
236
+ className="minimapLane"
237
+ data-lane-index={i}
238
+ style={{ height: laneHeight, maxHeight: laneHeight }}
239
+ >
240
+ <svg
241
+ height={laneHeight}
242
+ width={width}
243
+ shapeRendering="geometricPrecision"
244
+ >
245
+ <path className="miniBluePath" d={bluePath} fill="#9abeff" />
246
+ <path className="miniRedPath" d={redPath} fill="red" />
247
+ </svg>
248
+ </div>
249
+ );
250
+ };
251
+ /**
252
+ * @returns minimap compoent
253
+ */
254
+ render() {
255
+ const {
256
+ alignmentTracks = [],
257
+ dimensions: { width = 200 },
258
+ laneHeight,
259
+ onSizeAdjust,
260
+ minSliderSize,
261
+ onMinimapScrollX,
262
+ easyStore,
263
+ selectionLayerComp
264
+ } = this.props;
265
+
266
+ const [template /* ...nonTemplates */] = alignmentTracks;
267
+ const seqLength = template.alignmentData.sequence.length;
268
+ const charWidth = this.getCharWidth();
269
+ const scrollHandleWidth = this.getScrollHandleWidth();
270
+ const minimapTracksPartialHeight = laneHeight * alignmentTracks.length;
271
+
272
+ return (
273
+ <div
274
+ ref={ref => (this.minimap = ref)}
275
+ className="alignmentMinimap"
276
+ style={{
277
+ position: "relative",
278
+ width,
279
+ display: "flex",
280
+ flexDirection: "column",
281
+ overflowX: "visible"
282
+ }}
283
+ onClick={this.handleMinimapClick}
284
+ >
285
+ {selectionLayerComp}
286
+ <div
287
+ ref={ref => {
288
+ if (ref) {
289
+ this.minimapTracks = ref;
290
+ }
291
+ }}
292
+ style={{
293
+ overflowY: minimapTracksPartialHeight > 190 ? "auto" : "hidden",
294
+ overflowX: "hidden",
295
+ position: "relative"
296
+ }}
297
+ className="alignmentMinimapTracks"
298
+ >
299
+ <YellowScrollHandle
300
+ width={width}
301
+ handleDragStart={this.handleDragStart}
302
+ handleDrag={this.handleDrag}
303
+ handleDragStop={this.handleDragStop}
304
+ onMinimapScrollX={onMinimapScrollX}
305
+ minSliderSize={minSliderSize}
306
+ onSizeAdjust={onSizeAdjust}
307
+ easyStore={easyStore} //we use react-easy-state here to prevent costly setStates from being called
308
+ scrollHandleWidth={scrollHandleWidth}
309
+ alignmentTracks={alignmentTracks}
310
+ laneHeight={laneHeight}
311
+ minimapTracksPartialHeight={minimapTracksPartialHeight}
312
+ />
313
+
314
+ <ReactList
315
+ itemsRenderer={(items, ref) => (
316
+ <div
317
+ style={{
318
+ marginTop: -3
319
+ }}
320
+ ref={ref}
321
+ >
322
+ {items}
323
+ </div>
324
+ )}
325
+ type="uniform"
326
+ itemSizeGetter={this.itemSizeGetter}
327
+ itemRenderer={this.renderItem}
328
+ length={alignmentTracks.length}
329
+ />
330
+ </div>
331
+
332
+ <Axis
333
+ {...{
334
+ row: { start: 0, end: seqLength - 1 },
335
+ tickSpacing: massageTickSpacing(Math.floor(seqLength / 10)),
336
+ bpsPerRow: seqLength,
337
+ charWidth,
338
+ annotationHeight: 15,
339
+ sequenceLength: seqLength,
340
+ style: {
341
+ height: 17,
342
+ width: "100%"
343
+ }
344
+ }}
345
+ />
346
+ </div>
347
+ );
348
+ }
349
+ }
350
+ /**
351
+ * Yellow Scroll handle
352
+ * Responsible for designating the current viewing area
353
+ * Also supports zoom/resizing using handles
354
+ */
355
+ const YellowScrollHandle = view(
356
+ class YellowScrollHandleInner extends React.Component {
357
+ render() {
358
+ const {
359
+ scrollHandleWidth,
360
+ width,
361
+ easyStore,
362
+ handleDrag,
363
+ handleDragStop,
364
+ minSliderSize,
365
+ laneHeight,
366
+ onSizeAdjust,
367
+ handleDragStart,
368
+ minimapTracksPartialHeight
369
+ } = this.props;
370
+ const { verticalVisibleRange, percentScrolled } = easyStore;
371
+ const xScroll = percentScrolled * (width - scrollHandleWidth);
372
+ return (
373
+ <Draggable
374
+ bounds="parent"
375
+ zIndex={105}
376
+ handle=".handle"
377
+ position={{ x: xScroll, y: 0 }}
378
+ axis="x"
379
+ // onStart={this.onStart}
380
+ onStop={handleDragStop}
381
+ onDrag={handleDrag}
382
+ onStart={handleDragStart}
383
+ >
384
+ <div
385
+ style={{
386
+ height: minimapTracksPartialHeight || 0,
387
+ // height: "100%",
388
+ border: "none",
389
+ top: "0px",
390
+ position: "absolute",
391
+ zIndex: "10"
392
+ }}
393
+ >
394
+ {/* left hand side drag handle */}
395
+ <Draggable
396
+ bounds={{
397
+ left: -xScroll,
398
+ right: scrollHandleWidth - minSliderSize
399
+ }}
400
+ zIndex={105}
401
+ position={{ x: 0, y: 0 }}
402
+ axis="x"
403
+ onStart={(e, { x }) => {
404
+ this.x = x;
405
+ }}
406
+ onStop={(e, { x }) => {
407
+ const deltaX = x - this.x;
408
+
409
+ const newSliderSize = scrollHandleWidth - deltaX;
410
+ //user is resizing to the left so we need to update the scroll percentage so the slider does not jump
411
+ const newScrollPercent = Math.min(
412
+ 1,
413
+ (xScroll + deltaX) / (width - newSliderSize)
414
+ );
415
+ onSizeAdjust(newSliderSize, newScrollPercent);
416
+ }}
417
+ >
418
+ {/* caret component */}
419
+ <div
420
+ style={{
421
+ height: minimapTracksPartialHeight || 0,
422
+ // height: "100%",
423
+ border: "none",
424
+ cursor: "ew-resize",
425
+ opacity: "1",
426
+ top: "0px",
427
+ position: "absolute",
428
+ zIndex: "10",
429
+ width: 2,
430
+ background: "black"
431
+ }}
432
+ className="minimapCaret"
433
+ />
434
+ </Draggable>
435
+ {/* the actual handle component */}
436
+ <div
437
+ className="handle alignmentMinimapScrollHandle"
438
+ dataname="scrollGroup"
439
+ style={{
440
+ height: minimapTracksPartialHeight || 0,
441
+ border: "none",
442
+ cursor: "move",
443
+
444
+ zIndex: "10",
445
+ width: scrollHandleWidth,
446
+ background: "transparent"
447
+ }}
448
+ >
449
+ {/* this is the vertical scroll position display element */}
450
+ <div
451
+ className="verticalScrollDisplay"
452
+ style={{
453
+ height:
454
+ (verticalVisibleRange.end -
455
+ verticalVisibleRange.start +
456
+ 1) *
457
+ laneHeight,
458
+ zIndex: "-10",
459
+ background: "#fbfb2873",
460
+ borderTop: "2px solid yellow",
461
+ borderBottom: "2px solid yellow",
462
+ position: "relative",
463
+ top: verticalVisibleRange.start * laneHeight
464
+ }}
465
+ />
466
+ </div>
467
+ {/* right hand side drag handle */}
468
+ <Draggable
469
+ bounds={{
470
+ right: minSliderSize + width - xScroll,
471
+ left: minSliderSize
472
+ }}
473
+ zIndex={105}
474
+ position={{ x: scrollHandleWidth, y: 0 }}
475
+ axis="x"
476
+ onStart={(e, { x }) => {
477
+ this.x = x;
478
+ }}
479
+ onStop={(e, { x }) => {
480
+ const deltaX = this.x - x;
481
+ const newSliderSize = scrollHandleWidth - deltaX;
482
+ //user is resizing to the right so we need to update the scroll percentage so the slider does not jump
483
+ const newScrollPercent = xScroll / (width - newSliderSize);
484
+ onSizeAdjust(newSliderSize, newScrollPercent);
485
+ }}
486
+ >
487
+ <div
488
+ style={{
489
+ height: minimapTracksPartialHeight || 0,
490
+ // height: "100%",
491
+ border: "none",
492
+ cursor: "ew-resize",
493
+ opacity: "1",
494
+ top: "0px",
495
+ // right: 0,
496
+ position: "absolute",
497
+ zIndex: "10",
498
+ width: 2,
499
+ background: "black"
500
+ }}
501
+ className="minimapCaret"
502
+ />
503
+ </Draggable>
504
+ </div>
505
+ </Draggable>
506
+ );
507
+ }
508
+ }
509
+ );
510
+
511
+ export function getTrimmedRangesToDisplay({ trimmedRange, seqLen }) {
512
+ if (!trimmedRange) return [];
513
+ const inverted = invertRange(trimmedRange, seqLen);
514
+ return splitRangeIntoTwoPartsIfItIsCircular(inverted, seqLen);
515
+ }
package/Mismatches.js ADDED
@@ -0,0 +1,134 @@
1
+ import React from "react";
2
+ import { DataTable, withSelectedEntities } from "@teselagen/ui";
3
+
4
+ class Mismatches extends React.Component {
5
+ UNSAFE_componentWillMount() {
6
+ const { alignmentData, mismatches } = this.props;
7
+ // const { alignmentId, alignments } = this.props;
8
+ const mismatchList = this.getMismatchList(alignmentData, mismatches);
9
+ // const mismatchListAll = this.getMismatchList(alignmentId, alignments);
10
+ const schema = {
11
+ fields: [{ path: "mismatches", type: "number" }]
12
+ };
13
+ this.setState({ mismatchList, schema });
14
+ }
15
+
16
+ getGapMap = sequence => {
17
+ const gapMap = [0]; //a map of position to how many gaps come before that position [0,0,0,5,5,5,5,17,17,17, ]
18
+ sequence.split("").forEach(char => {
19
+ if (char === "-") {
20
+ gapMap[Math.max(0, gapMap.length - 1)] =
21
+ (gapMap[Math.max(0, gapMap.length - 1)] || 0) + 1;
22
+ } else {
23
+ gapMap.push(gapMap[gapMap.length - 1] || 0);
24
+ }
25
+ });
26
+ return gapMap;
27
+ };
28
+
29
+ getMismatchList = (alignmentData, mismatches) => {
30
+ // getMismatchList = (alignmentId, alignments) => {
31
+ // let mismatchListAll = [];
32
+ // skip first sequence/ref seq, since there will be no mismatches
33
+ // for (let trackI = 1; trackI < alignments[alignmentId].alignmentTracks.length; trackI++) {
34
+ const mismatchList = [];
35
+ // const trackName = alignmentData.name;
36
+ // const editedTrackName = trackName.slice(trackName.indexOf("_") + 1);
37
+
38
+ let getGaps = () => ({
39
+ gapsBefore: 0,
40
+ gapsInside: 0
41
+ });
42
+ const gapMap = this.getGapMap(alignmentData.sequence);
43
+ getGaps = rangeOrCaretPosition => {
44
+ if (typeof rangeOrCaretPosition !== "object") {
45
+ return {
46
+ gapsBefore: gapMap[Math.min(rangeOrCaretPosition, gapMap.length - 1)]
47
+ };
48
+ }
49
+ const { start, end } = rangeOrCaretPosition;
50
+ const toReturn = {
51
+ gapsBefore: gapMap[start],
52
+ gapsInside:
53
+ gapMap[Math.min(end, gapMap.length - 1)] -
54
+ gapMap[Math.min(start, gapMap.length - 1)]
55
+ };
56
+ return toReturn;
57
+ };
58
+
59
+ const gapsBeforeSequence = getGaps(0).gapsBefore;
60
+ for (let mismatchI = 0; mismatchI < mismatches.length; mismatchI++) {
61
+ const mismatchEnd = mismatches[mismatchI].end;
62
+ const mismatchStart = mismatches[mismatchI].start;
63
+ const mismatchDifference = mismatchEnd - mismatchStart;
64
+ // display 'position' as 1-based but store 'start' & 'end' as 0-based
65
+ if (mismatchDifference === 0) {
66
+ mismatchList.push({
67
+ mismatches: mismatchStart + 1 - gapsBeforeSequence,
68
+ start: mismatchStart - gapsBeforeSequence,
69
+ end: mismatchStart - gapsBeforeSequence
70
+ });
71
+ } else {
72
+ for (let innerI = 0; innerI <= mismatchDifference; innerI++) {
73
+ mismatchList.push({
74
+ mismatches: mismatchStart + innerI + 1 - gapsBeforeSequence,
75
+ start: mismatchStart + innerI - gapsBeforeSequence,
76
+ end: mismatchStart + innerI - gapsBeforeSequence
77
+ });
78
+ }
79
+ }
80
+ }
81
+ return mismatchList;
82
+ };
83
+
84
+ render() {
85
+ const { mismatchList, schema } = this.state;
86
+ let tableOfMismatches;
87
+ if (mismatchList.length === 0) {
88
+ tableOfMismatches = null;
89
+ } else {
90
+ tableOfMismatches = (
91
+ <DataTable
92
+ maxHeight={168}
93
+ formName={"mismatchesTable"}
94
+ isSimple
95
+ compact
96
+ noRouter
97
+ // onRowSelect={this.handleMismatchClick}
98
+ schema={schema}
99
+ entities={mismatchList}
100
+ />
101
+ );
102
+ }
103
+
104
+ return (
105
+ <div style={{ maxHeight: 180.8, overflowY: "scroll" }}>
106
+ {/* <div style={{ fontSize: 15, textAlign: "center" }}><b>Positions of Mismatches</b></div> */}
107
+ <div
108
+ style={{
109
+ // margin: 10,
110
+ display: "flex",
111
+ flexDirection: "column",
112
+ alignItems: "center"
113
+ }}
114
+ >
115
+ <div style={{ width: 100, margin: 4 }}>
116
+ {/* <div style={{
117
+ paddingBottom: 10,
118
+ textOverflow: "ellipsis",
119
+ overflowY: "auto",
120
+ whiteSpace: "nowrap",
121
+ fontSize: 13,
122
+ textAlign: "center"
123
+ }}>
124
+ <b>{mismatchList[0].name}</b>
125
+ </div> */}
126
+ {tableOfMismatches}
127
+ </div>
128
+ </div>
129
+ </div>
130
+ );
131
+ }
132
+ }
133
+
134
+ export default withSelectedEntities("mismatchesTable")(Mismatches);
package/Monaco.ttf ADDED
Binary file