@teselagen/ove 0.0.13 → 0.0.15

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 (362) hide show
  1. package/index.umd.js +164751 -135808
  2. package/package.json +78 -2
  3. package/src/AlignmentTool/index.js +16 -0
  4. package/src/AlignmentView/AlignmentVisibilityTool.js +105 -0
  5. package/src/AlignmentView/EditTrackNameDialog.js +34 -0
  6. package/src/AlignmentView/HorizontalPanelDragHandle.js +35 -0
  7. package/src/AlignmentView/Minimap.js +520 -0
  8. package/src/AlignmentView/Mismatches.js +134 -0
  9. package/src/AlignmentView/PairwiseAlignmentView.js +68 -0
  10. package/src/AlignmentView/PerformantSelectionLayer.js +32 -0
  11. package/src/AlignmentView/coerceInitialValue.js +7 -0
  12. package/src/AlignmentView/getGapMap.js +12 -0
  13. package/src/AlignmentView/getGaps.js +27 -0
  14. package/src/AlignmentView/getPairwiseOverviewLinearViewOptions.js +38 -0
  15. package/src/AlignmentView/getTrackFromEvent.js +25 -0
  16. package/src/AlignmentView/index.js +2058 -0
  17. package/src/AlignmentView/isTargetWithinEl.js +6 -0
  18. package/src/AlignmentView/style.css +100 -0
  19. package/src/AlignmentView/updateTrackHelper.js +58 -0
  20. package/src/AutoAnnotate.js +500 -0
  21. package/src/AutoAnnotateBpMatchingDialog.js +208 -0
  22. package/src/CircularView/Axis.js +40 -0
  23. package/src/CircularView/AxisNumbers.js +35 -0
  24. package/src/CircularView/Caret.js +63 -0
  25. package/src/CircularView/CircularDnaSequence.js +73 -0
  26. package/src/CircularView/CircularZoomMinimap.js +16 -0
  27. package/src/CircularView/Cutsite.js +18 -0
  28. package/src/CircularView/Cutsites.js +113 -0
  29. package/src/CircularView/DeletionLayer.js +28 -0
  30. package/src/CircularView/Feature.js +83 -0
  31. package/src/CircularView/Labels/index.js +536 -0
  32. package/src/CircularView/Labels/relaxLabelAngles.js +157 -0
  33. package/src/CircularView/Labels/relaxLabels_DEPRECATED.js +105 -0
  34. package/src/CircularView/Labels/style.css +55 -0
  35. package/src/CircularView/Orf.js +25 -0
  36. package/src/CircularView/Part.js +34 -0
  37. package/src/CircularView/PositionAnnotationOnCircle.js +26 -0
  38. package/src/CircularView/Primer.js +41 -0
  39. package/src/CircularView/RotateCircularViewSlider.js +82 -0
  40. package/src/CircularView/SelectionLayer.js +132 -0
  41. package/src/CircularView/VeTopRightContainer.js +12 -0
  42. package/src/CircularView/ZoomCircularViewSlider.js +62 -0
  43. package/src/CircularView/drawAnnotations.js +433 -0
  44. package/src/CircularView/drawDirectedPiePiece.js +142 -0
  45. package/src/CircularView/getAngleForPositionMidpoint.js +3 -0
  46. package/src/CircularView/getInternalLabel.js +40 -0
  47. package/src/CircularView/getRangeAnglesSpecial.js +12 -0
  48. package/src/CircularView/getYOffset.js +15 -0
  49. package/src/CircularView/index.d.ts +20 -0
  50. package/src/CircularView/index.js +930 -0
  51. package/src/CircularView/normalizeAngle.js +3 -0
  52. package/src/CircularView/normalizeAngleRange.js +9 -0
  53. package/src/CircularView/positionCutsites.js +6 -0
  54. package/src/CircularView/shouldFlipText.js +4 -0
  55. package/src/CircularView/style.css +47 -0
  56. package/src/CircularView/utils/polarToSpecialCartesian.js +7 -0
  57. package/src/CreateAnnotationsPage.js +96 -0
  58. package/src/CreateCustomEnzyme/index.js +337 -0
  59. package/src/CreateCustomEnzyme/style.css +100 -0
  60. package/src/CutsiteFilter/AdditionalCutsiteInfoDialog.js +599 -0
  61. package/src/CutsiteFilter/index.js +408 -0
  62. package/src/CutsiteFilter/style.css +23 -0
  63. package/src/CutsiteFilter/withRestrictionEnzymes.js +15 -0
  64. package/src/DigestTool/AddLaddersDialog.js +82 -0
  65. package/src/DigestTool/DigestTool.js +223 -0
  66. package/src/DigestTool/Ladder.css +20 -0
  67. package/src/DigestTool/Ladder.js +303 -0
  68. package/src/DigestTool/createFragmentLines.js +120 -0
  69. package/src/DigestTool/ladderDefaults.js +26 -0
  70. package/src/DigestTool/ruler.css +89 -0
  71. package/src/Editor/CommandHotkeyHandler.js +44 -0
  72. package/src/Editor/DropHandler.css +21 -0
  73. package/src/Editor/DropHandler.js +64 -0
  74. package/src/Editor/FillWindow.js +46 -0
  75. package/src/Editor/darkmode.css +98 -0
  76. package/src/Editor/index.js +1005 -0
  77. package/src/Editor/style.css +235 -0
  78. package/src/Editor/userDefinedHandlersAndOpts.js +56 -0
  79. package/src/EnzymeViewer/index.js +81 -0
  80. package/src/EnzymeViewer/style.css +6 -0
  81. package/src/FindBar/index.js +411 -0
  82. package/src/FindBar/style.css +46 -0
  83. package/src/GlobalDialog.js +66 -0
  84. package/src/GlobalDialogUtils.js +85 -0
  85. package/src/LinearView/SequenceName.js +15 -0
  86. package/src/LinearView/ZoomLinearView.js +47 -0
  87. package/src/LinearView/index.js +374 -0
  88. package/src/LinearView/style.css +12 -0
  89. package/src/ManageEnzymes/index.js +326 -0
  90. package/src/ManageEnzymes/style.css +100 -0
  91. package/src/MenuBar/defaultConfig.js +149 -0
  92. package/src/MenuBar/index.js +98 -0
  93. package/src/MenuBar/viewSubmenu.js +479 -0
  94. package/src/PCRTool/PCRTool.js +173 -0
  95. package/src/Reflex/Browser.js +107 -0
  96. package/src/Reflex/ReflexContainer.js +802 -0
  97. package/src/Reflex/ReflexElement.js +160 -0
  98. package/src/Reflex/ReflexEvents.js +77 -0
  99. package/src/Reflex/ReflexSplitter.js +205 -0
  100. package/src/Reflex/index.js +5 -0
  101. package/src/Reflex/reflex-styles.css +128 -0
  102. package/src/Reflex/reflex-styles.css.map +9 -0
  103. package/src/RowItem/AnnotationContainerHolder.js +20 -0
  104. package/src/RowItem/AnnotationPositioner.js +27 -0
  105. package/src/RowItem/Axis.js +149 -0
  106. package/src/RowItem/Caret/index.js +64 -0
  107. package/src/RowItem/Caret/style.css +8 -0
  108. package/src/RowItem/Chromatograms/Chromatogram.js +289 -0
  109. package/src/RowItem/CutsiteSelectionLayers.js +47 -0
  110. package/src/RowItem/Cutsites.js +271 -0
  111. package/src/RowItem/DeletionLayers/index.js +113 -0
  112. package/src/RowItem/DeletionLayers/style.css +5 -0
  113. package/src/RowItem/Labels.js +327 -0
  114. package/src/RowItem/Orf.js +109 -0
  115. package/src/RowItem/Orfs.js +35 -0
  116. package/src/RowItem/ReplacementLayers/style.css +5 -0
  117. package/src/RowItem/SelectionLayer/index.js +184 -0
  118. package/src/RowItem/SelectionLayer/style.css +21 -0
  119. package/src/RowItem/Sequence.js +269 -0
  120. package/src/RowItem/StackedAnnotations/PointedAnnotation.js +347 -0
  121. package/src/RowItem/StackedAnnotations/getStructuredBases.js +97 -0
  122. package/src/RowItem/StackedAnnotations/index.js +182 -0
  123. package/src/RowItem/StackedAnnotations/primerBases.js +218 -0
  124. package/src/RowItem/StackedAnnotations/style.css +14 -0
  125. package/src/RowItem/Translations/AASliver.js +190 -0
  126. package/src/RowItem/Translations/Translation.js +162 -0
  127. package/src/RowItem/Translations/index.js +54 -0
  128. package/src/RowItem/Translations/style.css +3 -0
  129. package/src/RowItem/constants.js +3 -0
  130. package/src/RowItem/getCutsiteLabelHeights.js +56 -0
  131. package/src/RowItem/getXStartAndWidthFromNonCircularRange.js +12 -0
  132. package/src/RowItem/getXStartAndWidthOfRangeWrtRow.js +27 -0
  133. package/src/RowItem/getXStartAndWidthOfRowAnnotation.js +19 -0
  134. package/src/RowItem/index.js +647 -0
  135. package/src/RowItem/partOverhangs.js +6 -0
  136. package/src/RowItem/style.css +103 -0
  137. package/src/RowItem/utils.js +32 -0
  138. package/src/RowView/estimateRowHeight.js +184 -0
  139. package/src/RowView/index.d.ts +10 -0
  140. package/src/RowView/index.js +554 -0
  141. package/src/RowView/style.css +12 -0
  142. package/src/SimpleCircularOrLinearView.js +379 -0
  143. package/src/SimpleOligoPreview.js +39 -0
  144. package/src/StatusBar/MeltingTemp.js +81 -0
  145. package/src/StatusBar/index.js +275 -0
  146. package/src/StatusBar/style.css +38 -0
  147. package/src/ToolBar/ToolbarItem.js +194 -0
  148. package/src/ToolBar/alignmentTool.js +503 -0
  149. package/src/ToolBar/array_move.js +10 -0
  150. package/src/ToolBar/cutsiteTool.js +88 -0
  151. package/src/ToolBar/downloadTool.js +38 -0
  152. package/src/ToolBar/editTool.js +26 -0
  153. package/src/ToolBar/featureTool.js +34 -0
  154. package/src/ToolBar/findTool.js +2 -0
  155. package/src/ToolBar/importTool.js +27 -0
  156. package/src/ToolBar/index.js +231 -0
  157. package/src/ToolBar/inlineFindTool.js +38 -0
  158. package/src/ToolBar/oligoTool.js +30 -0
  159. package/src/ToolBar/orfTool.js +141 -0
  160. package/src/ToolBar/partTool.js +47 -0
  161. package/src/ToolBar/printTool.js +31 -0
  162. package/src/ToolBar/redoTool.js +30 -0
  163. package/src/ToolBar/saveTool.js +48 -0
  164. package/src/ToolBar/style.css +138 -0
  165. package/src/ToolBar/undoTool.js +30 -0
  166. package/src/ToolBar/veToolbarIcons/find.png +0 -0
  167. package/src/ToolBar/veToolbarIcons/fullscreen.png +0 -0
  168. package/src/ToolBar/veToolbarIcons/linear.png +0 -0
  169. package/src/ToolBar/veToolbarIcons/pie.png +0 -0
  170. package/src/ToolBar/veToolbarIcons/print.png +0 -0
  171. package/src/ToolBar/veToolbarIcons/save.png +0 -0
  172. package/src/ToolBar/veToolbarIcons/show_cut_sites.png +0 -0
  173. package/src/ToolBar/veToolbarIcons/show_features.png +0 -0
  174. package/src/ToolBar/veToolbarIcons/show_orfs.png +0 -0
  175. package/src/ToolBar/veToolbarIcons/show_primers.png +0 -0
  176. package/src/ToolBar/veToolbarIcons/toggle_views.svg +1 -0
  177. package/src/ToolBar/versionHistoryTool.js +20 -0
  178. package/src/ToolBar/visibilityTool.js +39 -0
  179. package/src/VersionHistoryView/index.js +215 -0
  180. package/src/addAlignment.js +6 -0
  181. package/src/commands/getOveHotkeyDefs.js +12 -0
  182. package/src/commands/index.js +1585 -0
  183. package/src/constants/constants.js +2 -0
  184. package/src/constants/dnaToColor.js +17 -0
  185. package/src/constants/draggableClassnames.js +5 -0
  186. package/src/constants/findToolConstants.js +1 -0
  187. package/src/constants/orfFrameToColorMap.js +10 -0
  188. package/src/constants/rowviewContants.js +3 -0
  189. package/src/constants/specialCutsiteFilterOptions.js +22 -0
  190. package/src/constants.js +1 -0
  191. package/src/createVectorEditor/index.js +138 -0
  192. package/src/createVectorEditor/makeStore.js +34 -0
  193. package/src/fileUtils.js +103 -0
  194. package/src/helperComponents/AddOrEditAnnotationDialog/index.js +711 -0
  195. package/src/helperComponents/AddOrEditAnnotationDialog/style.css +11 -0
  196. package/src/helperComponents/AddOrEditFeatureDialog/index.js +58 -0
  197. package/src/helperComponents/AddOrEditPartDialog/index.js +101 -0
  198. package/src/helperComponents/AddOrEditPrimerDialog/EditCaretPosition.js +234 -0
  199. package/src/helperComponents/AddOrEditPrimerDialog/index.js +329 -0
  200. package/src/helperComponents/AddOrEditPrimerDialog/style.css +41 -0
  201. package/src/helperComponents/EnzymesDialog/index.js +904 -0
  202. package/src/helperComponents/EnzymesDialog/style.css +21 -0
  203. package/src/helperComponents/GoToDialog.js +21 -0
  204. package/src/helperComponents/MergeFeaturesDialog/index.js +253 -0
  205. package/src/helperComponents/MergeFeaturesDialog/style.css +3 -0
  206. package/src/helperComponents/MultipleSeqsDetectedOnImportDialog.js +74 -0
  207. package/src/helperComponents/PinchHelper/PinchHelper.js +24 -0
  208. package/src/helperComponents/PrintDialog/index.js +396 -0
  209. package/src/helperComponents/PrintDialog/style.css +4 -0
  210. package/src/helperComponents/PropertiesDialog/ColorPicker.js +30 -0
  211. package/src/helperComponents/PropertiesDialog/CutsiteProperties.js +185 -0
  212. package/src/helperComponents/PropertiesDialog/FeatureProperties.js +6 -0
  213. package/src/helperComponents/PropertiesDialog/GenbankView.js +74 -0
  214. package/src/helperComponents/PropertiesDialog/GeneralProperties.js +140 -0
  215. package/src/helperComponents/PropertiesDialog/GenericAnnotationProperties.js +406 -0
  216. package/src/helperComponents/PropertiesDialog/OrfProperties.js +117 -0
  217. package/src/helperComponents/PropertiesDialog/PartProperties.js +9 -0
  218. package/src/helperComponents/PropertiesDialog/PrimerProperties.js +19 -0
  219. package/src/helperComponents/PropertiesDialog/SingleEnzymeCutsiteInfo.js +131 -0
  220. package/src/helperComponents/PropertiesDialog/TranslationProperties.js +149 -0
  221. package/src/helperComponents/PropertiesDialog/index.js +166 -0
  222. package/src/helperComponents/PropertiesDialog/style.css +68 -0
  223. package/src/helperComponents/PropertiesDialog/typeField.js +24 -0
  224. package/src/helperComponents/PropertiesDialog/utils.js +37 -0
  225. package/src/helperComponents/RemoveDuplicates/index.js +194 -0
  226. package/src/helperComponents/RenameSequenceDialog.js +7 -0
  227. package/src/helperComponents/SelectDialog.js +150 -0
  228. package/src/helperComponents/UncontrolledSliderWithPlusMinusBtns.css +5 -0
  229. package/src/helperComponents/UncontrolledSliderWithPlusMinusBtns.js +134 -0
  230. package/src/helperComponents/VeWarning/index.js +22 -0
  231. package/src/helperComponents/VeWarning/style.css +10 -0
  232. package/src/helperComponents/createSimpleDialog.js +89 -0
  233. package/src/helperComponents/partTagSearch.js +72 -0
  234. package/src/helperComponents/simpleDialog.css +13 -0
  235. package/src/helperComponents/withHover.js +90 -0
  236. package/src/index.js +60 -0
  237. package/src/redux/alignments.js +373 -0
  238. package/src/redux/annotationLabelVisibility.js +53 -0
  239. package/src/redux/annotationVisibility.js +196 -0
  240. package/src/redux/annotationsToSupport.js +104 -0
  241. package/src/redux/caretPosition.js +27 -0
  242. package/src/redux/charWidth.js +22 -0
  243. package/src/redux/copyOptions.js +34 -0
  244. package/src/redux/createYourOwnEnzyme.js +39 -0
  245. package/src/redux/deletionLayers.js +36 -0
  246. package/src/redux/digestTool.js +34 -0
  247. package/src/redux/featureLengthsToHide.js +27 -0
  248. package/src/redux/findTool.js +79 -0
  249. package/src/redux/frameTranslations.js +52 -0
  250. package/src/redux/hoveredAnnotation.js +24 -0
  251. package/src/redux/index.js +196 -0
  252. package/src/redux/labelLineIntensity.js +25 -0
  253. package/src/redux/labelSize.js +23 -0
  254. package/src/redux/lastSavedId.js +20 -0
  255. package/src/redux/middleware.js +112 -0
  256. package/src/redux/minimumOrfSize.js +24 -0
  257. package/src/redux/modalActions.js +3 -0
  258. package/src/redux/panelsShown.js +273 -0
  259. package/src/redux/partLengthsToHide.js +23 -0
  260. package/src/redux/primerLengthsToHide.js +27 -0
  261. package/src/redux/propertiesTool.js +40 -0
  262. package/src/redux/readOnly.js +28 -0
  263. package/src/redux/replacementLayers.js +36 -0
  264. package/src/redux/restrictionEnzymes.js +52 -0
  265. package/src/redux/selectedAnnotations.js +89 -0
  266. package/src/redux/selectedPartTags.js +21 -0
  267. package/src/redux/selectionLayer.js +46 -0
  268. package/src/redux/sequenceData/circular.js +19 -0
  269. package/src/redux/sequenceData/description.js +21 -0
  270. package/src/redux/sequenceData/features.js +19 -0
  271. package/src/redux/sequenceData/index.js +81 -0
  272. package/src/redux/sequenceData/lineageLines.js +11 -0
  273. package/src/redux/sequenceData/materiallyAvailable.js +19 -0
  274. package/src/redux/sequenceData/name.js +19 -0
  275. package/src/redux/sequenceData/parts.js +19 -0
  276. package/src/redux/sequenceData/primers.js +19 -0
  277. package/src/redux/sequenceData/sequence.js +12 -0
  278. package/src/redux/sequenceData/sharedActionCreators.js +0 -0
  279. package/src/redux/sequenceData/translations.js +20 -0
  280. package/src/redux/sequenceData/upsertDeleteActionGenerator.js +31 -0
  281. package/src/redux/sequenceDataHistory.js +43 -0
  282. package/src/redux/showGCContent.js +23 -0
  283. package/src/redux/toolBar.js +25 -0
  284. package/src/redux/uppercaseSequenceMapFont.js +25 -0
  285. package/src/redux/useAdditionalOrfStartCodons.js +24 -0
  286. package/src/redux/utils/addDashesForMatchStartAndEndForTracks/index.js +71 -0
  287. package/src/redux/utils/addMetaToActionCreators.js +12 -0
  288. package/src/redux/utils/createMergedDefaultStateReducer.js +30 -0
  289. package/src/redux/utils/createMetaAction.js +12 -0
  290. package/src/redux/versionHistory.js +27 -0
  291. package/src/selectors/annotationLabelVisibility.js +2 -0
  292. package/src/selectors/annotationSearchSelector.js +24 -0
  293. package/src/selectors/cdsFeaturesSelector.js +9 -0
  294. package/src/selectors/circularSelector.js +4 -0
  295. package/src/selectors/cutsiteLabelColorSelector.js +6 -0
  296. package/src/selectors/cutsitesByRangeSelector.js +5 -0
  297. package/src/selectors/cutsitesSelector.js +61 -0
  298. package/src/selectors/editorSelector.js +2 -0
  299. package/src/selectors/featuresSelector.js +8 -0
  300. package/src/selectors/filteredCutsitesSelector.js +137 -0
  301. package/src/selectors/filteredFeaturesSelector.js +32 -0
  302. package/src/selectors/filteredPartsSelector.js +57 -0
  303. package/src/selectors/filteredPrimersSelector.js +27 -0
  304. package/src/selectors/filteredRestrictionEnzymesSelector.js +1 -0
  305. package/src/selectors/getAdditionalEnzymesSelector.js +46 -0
  306. package/src/selectors/index.js +41 -0
  307. package/src/selectors/isEnzymeFilterAndSelector.js +1 -0
  308. package/src/selectors/minimumOrfSizeSelector.js +2 -0
  309. package/src/selectors/orfsSelector.js +15 -0
  310. package/src/selectors/partsSelector.js +8 -0
  311. package/src/selectors/primersSelector.js +8 -0
  312. package/src/selectors/restrictionEnzymesSelector.js +34 -0
  313. package/src/selectors/searchLayersSelector.js +71 -0
  314. package/src/selectors/selectedAnnotationsSelector.js +1 -0
  315. package/src/selectors/selectedCutsitesSelector.js +21 -0
  316. package/src/selectors/sequenceDataSelector.js +2 -0
  317. package/src/selectors/sequenceLengthSelector.js +5 -0
  318. package/src/selectors/sequenceSelector.js +4 -0
  319. package/src/selectors/tagsToBoldSelector.js +2 -0
  320. package/src/selectors/translationSearchMatchesSelector.js +14 -0
  321. package/src/selectors/translationsRawSelector.js +8 -0
  322. package/src/selectors/translationsSelector.js +137 -0
  323. package/src/style.css +82 -0
  324. package/src/updateEditor.js +198 -0
  325. package/src/utils/PassThrough.js +3 -0
  326. package/src/utils/addWrappedAddons.js +20 -0
  327. package/src/utils/annotationTypes.js +37 -0
  328. package/src/utils/arrayUtils.js +19 -0
  329. package/src/utils/calculateTickMarkPositionsForGivenRange.js +47 -0
  330. package/src/utils/cleanSequenceData_DEPRECATED/arrayToObjWithIds.js +17 -0
  331. package/src/utils/combineReducersDontIgnoreKeys.js +12 -0
  332. package/src/utils/commandUtils.js +18 -0
  333. package/src/utils/editorUtils.js +223 -0
  334. package/src/utils/getAnnotationClassnames.js +12 -0
  335. package/src/utils/getAnnotationNameAndStartStopString.js +61 -0
  336. package/src/utils/getVisibleStartEnd.js +7 -0
  337. package/src/utils/massageTickSpacing.js +19 -0
  338. package/src/utils/onlyUpdateForKeysDeep.js +31 -0
  339. package/src/utils/prepareRowData.js +64 -0
  340. package/src/utils/proteinUtils.js +3 -0
  341. package/src/utils/pureNoFunc.js +18 -0
  342. package/src/utils/selectionLayer.js +25 -0
  343. package/src/utils/shouldRerender.js +27 -0
  344. package/src/utils/showFileDialog.js +26 -0
  345. package/src/utils/updateLabelsForInViewFeatures.js +55 -0
  346. package/src/utils/updateLabelsForInViewFeaturesCircView.js +41 -0
  347. package/src/utils/useAAColorType.js +8 -0
  348. package/src/utils/useAnnotationLimits.js +42 -0
  349. package/src/utils/useChromatogramPrefs.js +31 -0
  350. package/src/utils/useLadders.js +6 -0
  351. package/src/utils/useMeltingTemp.js +7 -0
  352. package/src/utils/useTmType.js +10 -0
  353. package/src/withEditorInteractions/Keyboard.js +86 -0
  354. package/src/withEditorInteractions/clickAndDragUtils.js +576 -0
  355. package/src/withEditorInteractions/createSequenceInputPopup.js +296 -0
  356. package/src/withEditorInteractions/createSequenceInputPopupStyle.css +85 -0
  357. package/src/withEditorInteractions/getBpsPerRow.js +19 -0
  358. package/src/withEditorInteractions/index.js +1252 -0
  359. package/src/withEditorInteractions/isElementInViewport.js +29 -0
  360. package/src/withEditorInteractions/moveCaret.js +58 -0
  361. package/src/withEditorProps/index.js +1010 -0
  362. package/index.mjs +0 -193201
@@ -0,0 +1,223 @@
1
+ // import uniqid from "shortid";
2
+ // import Ladder from "./Ladder";
3
+ import { compose, withProps } from "recompose";
4
+ // import selectionLayer from "../redux/selectionLayer";
5
+ import React from "react";
6
+ import { DataTable } from "@teselagen/ui";
7
+ import { getCutsiteType, getVirtualDigest } from "@teselagen/sequence-utils";
8
+ import CutsiteFilter from "../CutsiteFilter";
9
+ import Ladder from "./Ladder";
10
+ // import getCutsiteType from "./getCutsiteType";
11
+ import {
12
+ Tabs,
13
+ Tab,
14
+ Button,
15
+ InputGroup,
16
+ Intent,
17
+ Checkbox
18
+ } from "@blueprintjs/core";
19
+ import withEditorInteractions from "../withEditorInteractions";
20
+ import { userDefinedHandlersAndOpts } from "../Editor/userDefinedHandlersAndOpts";
21
+ import { noop, pick } from "lodash";
22
+
23
+ const MAX_DIGEST_CUTSITES = 50;
24
+ const MAX_PARTIAL_DIGEST_CUTSITES = 10;
25
+ export class DigestTool extends React.Component {
26
+ state = { selectedTab: "virtualDigest" };
27
+ render() {
28
+ const {
29
+ editorName,
30
+ // height = 100,
31
+ dimensions = {},
32
+ lanes,
33
+ digestTool: { selectedFragment, computePartialDigest },
34
+ onDigestSave,
35
+ computePartialDigestDisabled,
36
+ computeDigestDisabled,
37
+ updateComputePartialDigest
38
+ } = this.props;
39
+ const { selectedTab } = this.state;
40
+ return (
41
+ <div
42
+ style={{
43
+ height:
44
+ typeof dimensions.height === "string" ? 100 : dimensions.height,
45
+ overflowY: "auto",
46
+ padding: 10
47
+ }}
48
+ >
49
+ {onDigestSave && (
50
+ <div style={{ display: "flex", marginBottom: 10 }}>
51
+ <InputGroup placeholder="My Digest" />
52
+ <Button
53
+ intent={Intent.PRIMARY}
54
+ onClick={() => {
55
+ onDigestSave({});
56
+ }}
57
+ style={{ marginLeft: 5 }}
58
+ >
59
+ {" "}
60
+ Save
61
+ </Button>
62
+ </div>
63
+ )}
64
+ <div style={{ display: "flex", justifyContent: "space-between" }}>
65
+ <Checkbox
66
+ onChange={() => {
67
+ updateComputePartialDigest(!computePartialDigest);
68
+ }}
69
+ checked={computePartialDigest}
70
+ label={
71
+ <span>
72
+ Show Partial Digests{" "}
73
+ {computePartialDigestDisabled ? (
74
+ <span style={{ fontSize: 10 }}>
75
+ {" "}
76
+ -- Disabled (only supports {MAX_PARTIAL_DIGEST_CUTSITES} or
77
+ fewer cut sites){" "}
78
+ </span>
79
+ ) : null}
80
+ </span>
81
+ }
82
+ disabled={computePartialDigestDisabled}
83
+ ></Checkbox>
84
+ <a
85
+ target="_blank"
86
+ rel="noopener noreferrer"
87
+ href="http://docs.teselagen.com/en/articles/5489322-restriction-digest-in-the-vector-editor"
88
+ >
89
+ Read the docs
90
+ </a>
91
+ </div>
92
+ Choose your enzymes:
93
+ <CutsiteFilter
94
+ {...pick(this.props, userDefinedHandlersAndOpts)}
95
+ editorName={editorName}
96
+ />
97
+ <br />
98
+ {computeDigestDisabled && (
99
+ <div
100
+ style={{
101
+ color: "red",
102
+ marginBottom: "6px",
103
+ fontSize: "15px"
104
+ }}
105
+ >
106
+ {`>${MAX_DIGEST_CUTSITES} cut sites detected. Filter out additional
107
+ restriction enzymes to visualize digest results`}
108
+ </div>
109
+ )}
110
+ <Tabs
111
+ selectedTabId={selectedTab}
112
+ onChange={(id) => {
113
+ this.setState({ selectedTab: id });
114
+ }}
115
+ >
116
+ <Tab
117
+ title="Virtual Digest"
118
+ id="virtualDigest"
119
+ panel={<Ladder {...this.props} editorName={editorName} />}
120
+ />
121
+ <Tab
122
+ title="Digest Info"
123
+ id="table"
124
+ panel={
125
+ <DataTable
126
+ noRouter
127
+ isSimple
128
+ maxHeight={400}
129
+ // noFooter
130
+ withSearch={false}
131
+ onSingleRowSelect={({ onFragmentSelect }) => {
132
+ onFragmentSelect();
133
+ }}
134
+ reduxFormSelectedEntityIdMap={{
135
+ input: {
136
+ value: {
137
+ [selectedFragment]: true
138
+ },
139
+ onChange: noop
140
+ }
141
+ }}
142
+ formName="digestInfoTable"
143
+ entities={lanes[0].map(
144
+ ({ id, cut1, cut2, start, end, size, ...rest }) => {
145
+ return {
146
+ ...rest,
147
+ id,
148
+ start,
149
+ end,
150
+ length: size,
151
+ leftCutter: cut1.restrictionEnzyme.name,
152
+ rightCutter: cut2.restrictionEnzyme.name,
153
+ leftOverhang: getCutsiteType(cut1.restrictionEnzyme),
154
+ rightOverhang: getCutsiteType(cut2.restrictionEnzyme)
155
+ };
156
+ }
157
+ )}
158
+ schema={schema}
159
+ />
160
+ }
161
+ />
162
+ </Tabs>
163
+ <br />
164
+ </div>
165
+ );
166
+ }
167
+ }
168
+ const schema = {
169
+ fields: [
170
+ { width: 60, path: "start", displayName: "Start", type: "string" },
171
+ { width: 60, path: "end", displayName: "End", type: "string" },
172
+ { width: 70, path: "length", displayName: "Length", type: "string" },
173
+ { path: "leftCutter", displayName: "Left Cutter", type: "string" },
174
+ { path: "leftOverhang", displayName: "Left Overhang", type: "string" },
175
+ { path: "rightCutter", displayName: "Right Cutter", type: "string" },
176
+ { path: "rightOverhang", displayName: "Right Overhang", type: "string" }
177
+ ]
178
+ };
179
+
180
+ export default compose(
181
+ withEditorInteractions,
182
+ withProps((props) => {
183
+ const {
184
+ sequenceData,
185
+ sequenceLength,
186
+ selectionLayerUpdate,
187
+ updateSelectedFragment,
188
+ digestTool: { computePartialDigest }
189
+ } = props;
190
+ const isCircular = sequenceData.circular;
191
+ const cutsites = sequenceData.cutsites;
192
+ const computePartialDigestDisabled =
193
+ cutsites.length > MAX_PARTIAL_DIGEST_CUTSITES;
194
+ const computeDigestDisabled = cutsites.length > MAX_DIGEST_CUTSITES;
195
+
196
+ const { fragments, overlappingEnzymes } = getVirtualDigest({
197
+ cutsites,
198
+ sequenceLength,
199
+ isCircular,
200
+ computePartialDigest,
201
+ computePartialDigestDisabled,
202
+ computeDigestDisabled
203
+ });
204
+ return {
205
+ computePartialDigestDisabled,
206
+ computeDigestDisabled,
207
+ lanes: [
208
+ fragments.map((f) => ({
209
+ ...f,
210
+ onFragmentSelect: () => {
211
+ selectionLayerUpdate({
212
+ start: f.start,
213
+ end: f.end,
214
+ name: f.name
215
+ });
216
+ updateSelectedFragment(f.Intentid);
217
+ }
218
+ }))
219
+ ],
220
+ overlappingEnzymes
221
+ };
222
+ })
223
+ )(DigestTool);
@@ -0,0 +1,20 @@
1
+ .ve-digest-column {
2
+ position: relative;
3
+ width: 90px;
4
+ }
5
+ .ve-digest-header {
6
+ height: 40px;
7
+ padding-left: 10px;
8
+ padding-top: 10px;
9
+ }
10
+ .ve-digest-container {
11
+ display: flex;
12
+ width: fit-content;
13
+ }
14
+ .ve-digest-fragment-tooltip {
15
+ height: 100%;
16
+ width: 100%;
17
+ }
18
+ .tg-ladder-selector .tg-select-value .bp3-button {
19
+ display: none;
20
+ }
@@ -0,0 +1,303 @@
1
+ /* eslint-disable react/jsx-no-bind */
2
+ import React, { useState } from "react";
3
+ import { showConfirmationDialog, TgSelect } from "@teselagen/ui";
4
+ import html2canvas from "html2canvas";
5
+
6
+ import "./Ladder.css";
7
+ import { Button, Tooltip } from "@blueprintjs/core";
8
+ import { showDialog } from "../GlobalDialogUtils";
9
+ import { AddLaddersDialog } from "./AddLaddersDialog";
10
+ import { ladderDefaults } from "./ladderDefaults";
11
+ import useLadders from "../utils/useLadders";
12
+ import { map } from "lodash";
13
+ import { filter } from "lodash";
14
+
15
+ export default function Ladder({
16
+ // gelDigestEnzymes = [],
17
+ boxHeight = 550,
18
+ lanes = [],
19
+ digestLaneRightClicked,
20
+ selectedFragment,
21
+ ladders = ladderDefaults
22
+ }) {
23
+ const [additionalLadders, setLadders] = useLadders();
24
+ const laddersToUse = [
25
+ ...ladders,
26
+ ...map(additionalLadders, (l, i) => ({
27
+ ...l,
28
+ label: (
29
+ <div
30
+ key={i}
31
+ style={{
32
+ display: "flex",
33
+ alignItems: "center",
34
+ justifyContent: "space-between",
35
+ width: "100%"
36
+ }}
37
+ >
38
+ {l.label}{" "}
39
+ <Button
40
+ onClick={async (e) => {
41
+ e.preventDefault();
42
+ e.stopPropagation();
43
+ const confirm = await showConfirmationDialog({
44
+ text: "Are you sure you want to delete this custom ladder? You cannot undo this action",
45
+ intent: "danger",
46
+ confirmButtonText: "Delete",
47
+ cancelButtonText: "Cancel",
48
+ canEscapeKeyCancel: true
49
+ });
50
+ if (!confirm) {
51
+ return;
52
+ }
53
+ setSelectedLadder(ladders[0].value);
54
+ setLadders(
55
+ filter(additionalLadders, (lad) => lad.value !== l.value)
56
+ );
57
+ }}
58
+ intent="danger"
59
+ small
60
+ minimal
61
+ icon="trash"
62
+ ></Button>
63
+ </div>
64
+ )
65
+ }))
66
+ ];
67
+ const [highlightedFragment, setHighlightedFragment] = useState();
68
+ const [selectedLadder, setSelectedLadder] = useState(ladders[0].value);
69
+ let ladderInfo;
70
+ laddersToUse.forEach((ladder) => {
71
+ if (ladder.value === selectedLadder)
72
+ ladderInfo = {
73
+ ...ladder,
74
+ markings: ladder.markings.sort((a, b) => {
75
+ return b - a;
76
+ })
77
+ };
78
+ });
79
+ if (!ladderInfo) {
80
+ return console.error("Uh oh there needs to be ladder info here!");
81
+ }
82
+ const sharedStyle = { color: "white", background: "black" }; //use a shared style to get the copy image to look nice
83
+ const upperBoundary = ladderInfo.markings[0];
84
+ return (
85
+ <div>
86
+ Ladder:
87
+ <div style={{ display: "flex" }}>
88
+ <TgSelect
89
+ className="tg-ladder-selector"
90
+ value={selectedLadder}
91
+ onChange={(val) => setSelectedLadder(val.value)}
92
+ options={laddersToUse}
93
+ />
94
+ <Button
95
+ onClick={() => {
96
+ showDialog({
97
+ ModalComponent: AddLaddersDialog,
98
+ props: {
99
+ setSelectedLadder
100
+ }
101
+ });
102
+ }}
103
+ style={{ minWidth: 150 }}
104
+ minimal
105
+ small
106
+ icon="plus"
107
+ intent="primary"
108
+ >
109
+ Add Ladder
110
+ </Button>
111
+ </div>
112
+ <br />
113
+ <div
114
+ className="ve-digest-outer-container"
115
+ style={{
116
+ position: "relative",
117
+ width: "fit-content",
118
+ ...sharedStyle
119
+ }}
120
+ >
121
+ {navigator.clipboard && window.isSecureContext && (
122
+ <Button
123
+ icon="duplicate"
124
+ minimal
125
+ style={{ position: "absolute", top: 5, right: 5, color: "white" }}
126
+ onClick={() => {
127
+ try {
128
+ html2canvas(
129
+ document.querySelector(".ve-digest-container")
130
+ ).then((canvas) => {
131
+ canvas.toBlob((blob) =>
132
+ navigator.clipboard.write([
133
+ new window.ClipboardItem({ "image/png": blob })
134
+ ])
135
+ );
136
+ window.toastr.success("Image copied to clipboard!");
137
+ });
138
+ } catch (e) {
139
+ window.toastr.error(
140
+ "Error copying the image, try just taking a screenshot instead ;)"
141
+ );
142
+ }
143
+ }}
144
+ ></Button>
145
+ )}
146
+ <div style={{ padding: 3, paddingLeft: 7, width: 290 }}>
147
+ Highlighted Fragment:{" "}
148
+ {highlightedFragment ? highlightedFragment.size : "--"}{" "}
149
+ </div>
150
+ <div
151
+ style={{ height: boxHeight, ...sharedStyle }}
152
+ className="ve-digest-container"
153
+ >
154
+ <div
155
+ style={{ width: 100 }}
156
+ className="ve-digest-column ve-digest-ladder"
157
+ >
158
+ <div className="ve-digest-header"> </div>
159
+ {ladderInfo.markings.map((val, index) => {
160
+ return (
161
+ <div
162
+ key={index}
163
+ style={{
164
+ fontSize: 12,
165
+ position: "absolute",
166
+ width: "100%",
167
+ display: "flex",
168
+ alignItems: "center",
169
+ color: "white",
170
+ bottom: calculateOffset(boxHeight, val, upperBoundary) - 3 //subtract 3 to get the labels to align better
171
+ }}
172
+ >
173
+ <span
174
+ style={{
175
+ color: "white",
176
+ paddingLeft: 6,
177
+ paddingRight: 4
178
+ }}
179
+ >
180
+ {val}{" "}
181
+ </span>
182
+ <span style={{ color: "white", paddingRight: 4 }}> bp </span>
183
+ </div>
184
+ );
185
+ })}
186
+ </div>
187
+ <div className="ve-digest-column ve-digest-ladder">
188
+ <div className="ve-digest-header">Ladder </div>
189
+ {ladderInfo.markings.map((val, index) => {
190
+ return (
191
+ <div
192
+ key={index}
193
+ style={{
194
+ fontSize: 12,
195
+ position: "absolute",
196
+ width: "100%",
197
+ display: "flex",
198
+ alignItems: "center",
199
+ color: "white",
200
+ height: "2px",
201
+ background: "white",
202
+ bottom: calculateOffset(boxHeight, val, upperBoundary)
203
+ }}
204
+ />
205
+ );
206
+ })}
207
+ </div>
208
+ {lanes.map((fragments, index) => {
209
+ return (
210
+ <Lane
211
+ key={index}
212
+ {...{
213
+ onMouseOver: (fragment) => setHighlightedFragment(fragment),
214
+ onMouseOut: () => setHighlightedFragment(undefined),
215
+ digestLaneRightClicked,
216
+ laneNumber: index + 1,
217
+ fragments,
218
+ highlightedFragment,
219
+ selectedFragment,
220
+ boxHeight,
221
+ upperBoundary
222
+ }}
223
+ />
224
+ );
225
+ })}
226
+ </div>
227
+ </div>
228
+ </div>
229
+ );
230
+ }
231
+
232
+ function Lane({
233
+ laneNumber,
234
+ onMouseOver,
235
+ onMouseOut,
236
+ digestLaneRightClicked,
237
+ fragments,
238
+ highlightedFragment,
239
+ selectedFragment,
240
+ boxHeight,
241
+ upperBoundary
242
+ }) {
243
+ return (
244
+ <div
245
+ style={{ marginLeft: 20, marginRight: 20 }}
246
+ className="ve-digest-column ve-digest-lane"
247
+ >
248
+ <div className="ve-digest-header">Lane {laneNumber} </div>
249
+ {fragments.map((fragment, index) => {
250
+ const { size, id, name } = fragment;
251
+ const isHighlighted =
252
+ (highlightedFragment && id === highlightedFragment.id) ||
253
+ (selectedFragment && id === highlightedFragment.id);
254
+ return (
255
+ <div
256
+ key={index}
257
+ onMouseOver={() => {
258
+ onMouseOver(fragment);
259
+ }}
260
+ onMouseOut={() => {
261
+ onMouseOut(fragment);
262
+ }}
263
+ onClick={() => {
264
+ fragment.onFragmentSelect();
265
+ }}
266
+ onContextMenu={(e) => {
267
+ fragment.onFragmentSelect();
268
+ digestLaneRightClicked(e);
269
+ }}
270
+ data-test={name}
271
+ style={{
272
+ fontSize: 12,
273
+ position: "absolute",
274
+ display: "flex",
275
+ alignItems: "center",
276
+ color: isHighlighted ? "#fdffdd" : "white",
277
+ width: "90%",
278
+ height: isHighlighted ? "3px" : "2px",
279
+ background: "white",
280
+ bottom: calculateOffset(boxHeight, size, upperBoundary)
281
+ }}
282
+ >
283
+ <Tooltip
284
+ className="ve-digest-fragment-tooltip"
285
+ content={<div>{name}</div>}
286
+ >
287
+ <div
288
+ style={{
289
+ width: "100%",
290
+ height: isHighlighted ? "3px" : "2px"
291
+ }}
292
+ />
293
+ </Tooltip>
294
+ </div>
295
+ );
296
+ })}
297
+ </div>
298
+ );
299
+ }
300
+
301
+ function calculateOffset(boxHeight, size, upperBoundary) {
302
+ return (boxHeight * Math.log(size)) / Math.log(upperBoundary) - 55;
303
+ }
@@ -0,0 +1,120 @@
1
+ // let {getCutsitesFromSequence} = require('@teselagen/sequence-utils');
2
+ // let {assign} = require('lodash');
3
+
4
+ // module.exports = function createFragmentsLines({input: {geneRuler, enzymes}, state, output}) {
5
+ // if (geneRuler === "geneRuler1kb") {
6
+ // geneRuler = [20000, 10000, 7000, 5000, 4000, 3000, 2000, 1500, 1000, 700, 500, 400, 300, 200, 75];
7
+ // } else {
8
+ // geneRuler = [3000, 2000, 1500, 1200, 1000, 900, 800, 700, 600, 500, 400, 300, 200, 100];
9
+ // }
10
+
11
+ // let cutsites = state.get('digestCutsites');
12
+ // if (cutsites.length === 0) {
13
+ // state.set('fragmentsNum', 0);
14
+ // state.set('fragments', []);
15
+ // return;
16
+ // }
17
+
18
+ // let sequenceLength = state.get(['sequenceData', 'sequence']).length;
19
+ // let circular = state.get(['sequenceData', 'circular']);
20
+
21
+ // function sortNumber(a,b) {
22
+ // if (a.position) {
23
+ // return a.position - b.position;
24
+ // }
25
+ // if (a.segmentLength) {
26
+ // return a.segmentLength - b.segmentLength;
27
+ // }
28
+ // }
29
+
30
+ // let cutsitesData = [];
31
+ // let position;
32
+ // let cutsite;
33
+ // for (let i = 0; i < cutsites.length; i++) {
34
+ // cutsite = Object.assign({}, cutsites[i]);
35
+ // position = Math.floor((cutsite.end + cutsite.start)/2);
36
+ // cutsite.position = position;
37
+ // cutsitesData.push(cutsite);
38
+ // }
39
+
40
+ // // circular or linear
41
+ // cutsitesData = cutsitesData.sort(sortNumber);
42
+ // if (circular) {
43
+ // var lines = [ // if circular, fragment wraps around origin
44
+ // {
45
+ // segmentLength: sequenceLength - cutsitesData[cutsitesData.length-1].start + cutsitesData[0].end,
46
+ // enzyme1: cutsitesData[cutsitesData.length-1].start + '('+cutsitesData[cutsitesData.length-1].name+')',
47
+ // enzyme2: cutsitesData[0].end + '('+cutsitesData[0].name+')'
48
+ // }
49
+ // ];
50
+ // } else {
51
+ // var lines = [ // if not ciruclar, need to split into two seperate fragments
52
+ // {
53
+ // segmentLength: sequenceLength - cutsitesData[cutsitesData.length-1].start,
54
+ // enzyme1: cutsitesData[cutsitesData.length-1].start + '('+cutsitesData[cutsitesData.length-1].name+')',
55
+ // enzyme2: sequenceLength
56
+ // },
57
+ // {
58
+ // segmentLength: cutsitesData[0].end,
59
+ // enzyme1: 0,
60
+ // enzyme2: cutsitesData[0].end + '('+cutsitesData[0].name+')'
61
+ // }
62
+ // ];
63
+ // }
64
+
65
+ // // get fragments
66
+ // for (let i=0; i<cutsitesData.length-1; i++) {
67
+ // lines.push({
68
+ // segmentLength: Math.abs(cutsitesData[i+1].end - cutsitesData[i].start),
69
+ // enzyme1: cutsitesData[i].start + ' ('+cutsitesData[i].name+')',
70
+ // enzyme2: cutsitesData[i+1].end + ' ('+cutsitesData[i+1].name+')'
71
+ // });
72
+ // }
73
+
74
+ // lines = lines.sort(sortNumber).reverse();
75
+
76
+ // let fragmentsNum = 0; // counter for number of fragments
77
+ // let lineWidth = 1;
78
+ // let boxHeight = 275;
79
+ // let upperBoundary = lines[0].segmentLength > geneRuler[0] ? lines[0].segmentLength : geneRuler[0];
80
+ // let fragments = [];
81
+
82
+ // // position fragments on the ladder
83
+ // for (let iLeft = 0, iRight = 0; ; ) {
84
+ // if (iLeft == geneRuler.length && iRight === lines.length) {
85
+ // break;
86
+
87
+ // } else if (iRight == lines.length || geneRuler[iLeft] >= lines[iRight].segmentLength) {
88
+ // fragments.push({
89
+ // align: "left",
90
+ // bottom: (boxHeight * Math.log(geneRuler[iLeft]) / Math.log(upperBoundary)) - 25,
91
+ // left: 15,
92
+ // width: '25%',
93
+ // borderWidth: 1,
94
+ // position: geneRuler[iLeft],
95
+ // tooltip: geneRuler[iLeft]
96
+ // });
97
+ // iLeft++;
98
+
99
+ // } else if (iLeft == geneRuler.length || geneRuler[iLeft] < lines[iRight].segmentLength) {
100
+ // fragments.push({
101
+ // align: "right",
102
+ // bottom: (boxHeight * Math.log(lines[iRight].segmentLength) / Math.log(upperBoundary)) - 25,
103
+ // left: 75,
104
+ // width: '75%',
105
+ // borderWidth: lineWidth,
106
+ // position: lines[iRight].segmentLength,
107
+ // tooltip: lines[iRight].segmentLength + ' : ' + lines[iRight].enzyme1 + ' .. ' + lines[iRight].enzyme2
108
+ // });
109
+ // fragmentsNum++;
110
+ // iRight++;
111
+
112
+ // } else {
113
+ // console.warn("error getting digest fragments");
114
+ // break;
115
+ // }
116
+ // }
117
+
118
+ // state.set('fragmentsNum', fragmentsNum);
119
+ // state.set('fragments', fragments);
120
+ // };
@@ -0,0 +1,26 @@
1
+ export const ladderDefaults = [
2
+ {
3
+ value: "geneRuler1KB",
4
+ label: "GeneRuler 1kb + DNA 75-20,000 bp",
5
+ markings: [
6
+ 20000, 10000, 7000, 5000, 4000, 3000, 2000, 1500, 1000, 700, 500, 400,
7
+ 300, 200, 75
8
+ ]
9
+ },
10
+ {
11
+ value: "geneRuler100BP",
12
+ label: "GeneRuler 100bp + DNA 100-3000 bp",
13
+ markings: [
14
+ 3000, 2000, 1500, 1200, 1000, 900, 800, 700, 600, 500, 400, 300, 200,
15
+ 100
16
+ ]
17
+ },
18
+ {
19
+ value: "invitrogen1KbPlus",
20
+ label: "Invitrogen 1kb + DNA 100-15,000 bp",
21
+ markings: [
22
+ 15000, 10000, 8000, 7000, 6000, 5000, 4000, 3000, 2000, 1500, 1000, 850,
23
+ 650, 500, 400, 300, 200, 100
24
+ ]
25
+ }
26
+ ];