react-msaview 4.4.4 → 4.4.6

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 (192) hide show
  1. package/bundle/index.js +111 -111
  2. package/bundle/index.js.LICENSE.txt +24 -6
  3. package/bundle/index.js.map +1 -1
  4. package/dist/components/dialogs/InterProScanDialog.js +1 -1
  5. package/dist/components/dialogs/InterProScanDialog.js.map +1 -1
  6. package/dist/components/dialogs/SettingsDialog.js +1 -1
  7. package/dist/components/dialogs/SettingsDialog.js.map +1 -1
  8. package/dist/components/msa/MSACanvasBlock.js +8 -1
  9. package/dist/components/msa/MSACanvasBlock.js.map +1 -1
  10. package/dist/components/msa/renderMSABlock.js +22 -4
  11. package/dist/components/msa/renderMSABlock.js.map +1 -1
  12. package/dist/components/msa/renderMSAMouseover.js +21 -1
  13. package/dist/components/msa/renderMSAMouseover.js.map +1 -1
  14. package/dist/components/tree/TreeCanvas.js +61 -2
  15. package/dist/components/tree/TreeCanvas.js.map +1 -1
  16. package/dist/components/tree/TreeCanvasBlock.js +56 -5
  17. package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
  18. package/dist/components/tree/TreeNodeMenu.js +6 -2
  19. package/dist/components/tree/TreeNodeMenu.js.map +1 -1
  20. package/dist/components/tree/renderTreeCanvas.d.ts +14 -4
  21. package/dist/components/tree/renderTreeCanvas.js +3 -0
  22. package/dist/components/tree/renderTreeCanvas.js.map +1 -1
  23. package/dist/components/util.js +1 -1
  24. package/dist/components/util.js.map +1 -1
  25. package/dist/layout.d.ts +4 -1
  26. package/dist/layout.js +30 -8
  27. package/dist/layout.js.map +1 -1
  28. package/dist/model/treeModel.js +2 -2
  29. package/dist/model/treeModel.js.map +1 -1
  30. package/dist/model.d.ts +14 -79
  31. package/dist/model.js +94 -4
  32. package/dist/model.js.map +1 -1
  33. package/dist/rowCoordinateCalculations.js +1 -5
  34. package/dist/rowCoordinateCalculations.js.map +1 -1
  35. package/dist/rowCoordinateCalculations.test.js +14 -2
  36. package/dist/rowCoordinateCalculations.test.js.map +1 -1
  37. package/dist/seqCoordToRowSpecificGlobalCoord.js +9 -5
  38. package/dist/seqCoordToRowSpecificGlobalCoord.js.map +1 -1
  39. package/dist/seqCoordToRowSpecificGlobalCoord.test.js +6 -6
  40. package/dist/version.d.ts +1 -1
  41. package/dist/version.js +1 -1
  42. package/package.json +3 -2
  43. package/src/components/dialogs/InterProScanDialog.tsx +1 -1
  44. package/src/components/dialogs/SettingsDialog.tsx +1 -1
  45. package/src/components/msa/MSACanvasBlock.tsx +8 -1
  46. package/src/components/msa/renderMSABlock.ts +32 -2
  47. package/src/components/msa/renderMSAMouseover.ts +26 -0
  48. package/src/components/tree/TreeCanvas.tsx +76 -1
  49. package/src/components/tree/TreeCanvasBlock.tsx +69 -5
  50. package/src/components/tree/TreeNodeMenu.tsx +12 -1
  51. package/src/components/tree/renderTreeCanvas.ts +20 -4
  52. package/src/components/util.ts +1 -1
  53. package/src/layout.ts +48 -8
  54. package/src/model/treeModel.ts +2 -2
  55. package/src/model.ts +108 -5
  56. package/src/rowCoordinateCalculations.test.ts +15 -2
  57. package/src/rowCoordinateCalculations.ts +1 -5
  58. package/src/seqCoordToRowSpecificGlobalCoord.test.ts +6 -6
  59. package/src/seqCoordToRowSpecificGlobalCoord.ts +9 -4
  60. package/src/version.ts +1 -1
  61. package/dist/DataModel.d.ts +0 -34
  62. package/dist/DataModel.js +0 -46
  63. package/dist/DataModel.js.map +0 -1
  64. package/dist/DialogQueue.d.ts +0 -25
  65. package/dist/DialogQueue.js +0 -44
  66. package/dist/DialogQueue.js.map +0 -1
  67. package/dist/SelectedStructuresMixin.d.ts +0 -46
  68. package/dist/SelectedStructuresMixin.js +0 -52
  69. package/dist/SelectedStructuresMixin.js.map +0 -1
  70. package/dist/StructureModel.d.ts +0 -9
  71. package/dist/StructureModel.js +0 -11
  72. package/dist/StructureModel.js.map +0 -1
  73. package/dist/UniprotTrack.d.ts +0 -27
  74. package/dist/UniprotTrack.js +0 -53
  75. package/dist/UniprotTrack.js.map +0 -1
  76. package/dist/components/BoxTrack.d.ts +0 -7
  77. package/dist/components/BoxTrack.js +0 -15
  78. package/dist/components/BoxTrack.js.map +0 -1
  79. package/dist/components/BoxTrackBlock.d.ts +0 -8
  80. package/dist/components/BoxTrackBlock.js +0 -136
  81. package/dist/components/BoxTrackBlock.js.map +0 -1
  82. package/dist/components/ExportSVGDialog.d.ts +0 -6
  83. package/dist/components/ExportSVGDialog.js +0 -39
  84. package/dist/components/ExportSVGDialog.js.map +0 -1
  85. package/dist/components/Header.d.ts +0 -6
  86. package/dist/components/Header.js +0 -62
  87. package/dist/components/Header.js.map +0 -1
  88. package/dist/components/HeaderInfoArea.d.ts +0 -6
  89. package/dist/components/HeaderInfoArea.js +0 -12
  90. package/dist/components/HeaderInfoArea.js.map +0 -1
  91. package/dist/components/ImportForm/ImportFormExamples.d.ts +0 -6
  92. package/dist/components/ImportForm/ImportFormExamples.js +0 -50
  93. package/dist/components/ImportForm/ImportFormExamples.js.map +0 -1
  94. package/dist/components/ImportForm/data/seq2.d.ts +0 -3
  95. package/dist/components/ImportForm/data/seq2.js +0 -33
  96. package/dist/components/ImportForm/data/seq2.js.map +0 -1
  97. package/dist/components/ImportForm/index.d.ts +0 -6
  98. package/dist/components/ImportForm/index.js +0 -31
  99. package/dist/components/ImportForm/index.js.map +0 -1
  100. package/dist/components/ImportForm/util.d.ts +0 -3
  101. package/dist/components/ImportForm/util.js +0 -16
  102. package/dist/components/ImportForm/util.js.map +0 -1
  103. package/dist/components/MSACanvas.d.ts +0 -6
  104. package/dist/components/MSACanvas.js +0 -141
  105. package/dist/components/MSACanvas.js.map +0 -1
  106. package/dist/components/MSAPanel/Loading.d.ts +0 -2
  107. package/dist/components/MSAPanel/Loading.js +0 -12
  108. package/dist/components/MSAPanel/Loading.js.map +0 -1
  109. package/dist/components/MSAPanel/MSABlock.d.ts +0 -8
  110. package/dist/components/MSAPanel/MSABlock.js +0 -62
  111. package/dist/components/MSAPanel/MSABlock.js.map +0 -1
  112. package/dist/components/MSAPanel/MSACanvas.d.ts +0 -7
  113. package/dist/components/MSAPanel/MSACanvas.js +0 -69
  114. package/dist/components/MSAPanel/MSACanvas.js.map +0 -1
  115. package/dist/components/MSAPanel/MSAMouseoverCanvas.d.ts +0 -6
  116. package/dist/components/MSAPanel/MSAMouseoverCanvas.js +0 -27
  117. package/dist/components/MSAPanel/MSAMouseoverCanvas.js.map +0 -1
  118. package/dist/components/MSAPanel/index.d.ts +0 -5
  119. package/dist/components/MSAPanel/index.js +0 -9
  120. package/dist/components/MSAPanel/index.js.map +0 -1
  121. package/dist/components/MSAPanel/renderMSABlock.d.ts +0 -9
  122. package/dist/components/MSAPanel/renderMSABlock.js +0 -89
  123. package/dist/components/MSAPanel/renderMSABlock.js.map +0 -1
  124. package/dist/components/MSAPanel/renderMSABlock_BACKUP_139826.d.ts +0 -9
  125. package/dist/components/MSAPanel/renderMSABlock_BACKUP_139826.js +0 -89
  126. package/dist/components/MSAPanel/renderMSABlock_BACKUP_139826.js.map +0 -1
  127. package/dist/components/MSAPanel/renderMSABlock_BASE_139826.d.ts +0 -13
  128. package/dist/components/MSAPanel/renderMSABlock_BASE_139826.js +0 -82
  129. package/dist/components/MSAPanel/renderMSABlock_BASE_139826.js.map +0 -1
  130. package/dist/components/MSAPanel/renderMSABlock_LOCAL_139826.d.ts +0 -9
  131. package/dist/components/MSAPanel/renderMSABlock_LOCAL_139826.js +0 -89
  132. package/dist/components/MSAPanel/renderMSABlock_LOCAL_139826.js.map +0 -1
  133. package/dist/components/MSAPanel/renderMSABlock_REMOTE_139826.d.ts +0 -0
  134. package/dist/components/MSAPanel/renderMSABlock_REMOTE_139826.js +0 -2
  135. package/dist/components/MSAPanel/renderMSABlock_REMOTE_139826.js.map +0 -1
  136. package/dist/components/MSAPanel/renderMSAMouseover.d.ts +0 -5
  137. package/dist/components/MSAPanel/renderMSAMouseover.js +0 -30
  138. package/dist/components/MSAPanel/renderMSAMouseover.js.map +0 -1
  139. package/dist/components/Minimap.d.ts +0 -6
  140. package/dist/components/Minimap.js +0 -72
  141. package/dist/components/Minimap.js.map +0 -1
  142. package/dist/components/MinimapSVG.d.ts +0 -6
  143. package/dist/components/MinimapSVG.js +0 -25
  144. package/dist/components/MinimapSVG.js.map +0 -1
  145. package/dist/components/MultiAlignmentSelector.d.ts +0 -6
  146. package/dist/components/MultiAlignmentSelector.js +0 -13
  147. package/dist/components/MultiAlignmentSelector.js.map +0 -1
  148. package/dist/components/TreePanel/TreeBranchMenu.d.ts +0 -14
  149. package/dist/components/TreePanel/TreeBranchMenu.js +0 -26
  150. package/dist/components/TreePanel/TreeBranchMenu.js.map +0 -1
  151. package/dist/components/TreePanel/TreeCanvas.d.ts +0 -6
  152. package/dist/components/TreePanel/TreeCanvas.js +0 -100
  153. package/dist/components/TreePanel/TreeCanvas.js.map +0 -1
  154. package/dist/components/TreePanel/TreeCanvasBlock.d.ts +0 -7
  155. package/dist/components/TreePanel/TreeCanvasBlock.js +0 -118
  156. package/dist/components/TreePanel/TreeCanvasBlock.js.map +0 -1
  157. package/dist/components/TreePanel/TreeNodeMenu.d.ts +0 -13
  158. package/dist/components/TreePanel/TreeNodeMenu.js +0 -74
  159. package/dist/components/TreePanel/TreeNodeMenu.js.map +0 -1
  160. package/dist/components/TreePanel/TreeRuler.d.ts +0 -6
  161. package/dist/components/TreePanel/TreeRuler.js +0 -8
  162. package/dist/components/TreePanel/TreeRuler.js.map +0 -1
  163. package/dist/components/TreePanel/dialogs/TreeNodeInfoDialog.d.ts +0 -9
  164. package/dist/components/TreePanel/dialogs/TreeNodeInfoDialog.js +0 -16
  165. package/dist/components/TreePanel/dialogs/TreeNodeInfoDialog.js.map +0 -1
  166. package/dist/components/TreePanel/index.d.ts +0 -6
  167. package/dist/components/TreePanel/index.js +0 -10
  168. package/dist/components/TreePanel/index.js.map +0 -1
  169. package/dist/components/TreePanel/renderTreeCanvas.d.ts +0 -46
  170. package/dist/components/TreePanel/renderTreeCanvas.js +0 -180
  171. package/dist/components/TreePanel/renderTreeCanvas.js.map +0 -1
  172. package/dist/components/VerticalGuide.d.ts +0 -7
  173. package/dist/components/VerticalGuide.js +0 -30
  174. package/dist/components/VerticalGuide.js.map +0 -1
  175. package/dist/components/ZoomControls.d.ts +0 -6
  176. package/dist/components/ZoomControls.js +0 -59
  177. package/dist/components/ZoomControls.js.map +0 -1
  178. package/dist/components/msa/MSACanvas_BACKUP_139826.d.ts +0 -7
  179. package/dist/components/msa/MSACanvas_BACKUP_139826.js +0 -68
  180. package/dist/components/msa/MSACanvas_BACKUP_139826.js.map +0 -1
  181. package/dist/components/msa/MSACanvas_BASE_139826.d.ts +0 -6
  182. package/dist/components/msa/MSACanvas_BASE_139826.js +0 -107
  183. package/dist/components/msa/MSACanvas_BASE_139826.js.map +0 -1
  184. package/dist/components/msa/MSACanvas_LOCAL_139826.d.ts +0 -7
  185. package/dist/components/msa/MSACanvas_LOCAL_139826.js +0 -69
  186. package/dist/components/msa/MSACanvas_LOCAL_139826.js.map +0 -1
  187. package/dist/components/msa/MSACanvas_REMOTE_139826.d.ts +0 -6
  188. package/dist/components/msa/MSACanvas_REMOTE_139826.js +0 -106
  189. package/dist/components/msa/MSACanvas_REMOTE_139826.js.map +0 -1
  190. package/dist/sansserif.d.ts +0 -3
  191. package/dist/sansserif.js +0 -1583
  192. package/dist/sansserif.js.map +0 -1
package/src/layout.ts CHANGED
@@ -1,4 +1,4 @@
1
- import RBush from 'rbush'
1
+ import Flatbush from 'flatbush'
2
2
 
3
3
  export default class Layout {
4
4
  public rectangles: Map<
@@ -13,11 +13,13 @@ export default class Layout {
13
13
  }
14
14
  >
15
15
 
16
- public maxHeightReached: boolean
16
+ public maxHeightReached = false
17
17
 
18
18
  private maxHeight: number
19
19
 
20
- private rbush: RBush<{ id: string }>
20
+ private flatbush: Flatbush | null = null
21
+
22
+ private indexToId: string[] = []
21
23
 
22
24
  private pTotalHeight: number
23
25
 
@@ -26,13 +28,51 @@ export default class Layout {
26
28
  }: {
27
29
  maxHeight?: number
28
30
  } = {}) {
29
- this.maxHeightReached = false
30
- this.rbush = new RBush()
31
31
  this.rectangles = new Map()
32
32
  this.maxHeight = Math.ceil(maxHeight)
33
33
  this.pTotalHeight = 0 // total height, in units of bitmap squares (px/pitchY)
34
34
  }
35
35
 
36
+ private rebuildIndex() {
37
+ // Rebuild the spatial index with current rectangles
38
+ const rects = Array.from(this.rectangles.values())
39
+ if (rects.length === 0) {
40
+ this.flatbush = null
41
+ this.indexToId = []
42
+ return
43
+ }
44
+
45
+ this.flatbush = new Flatbush(rects.length)
46
+ this.indexToId = []
47
+
48
+ for (const rect of rects) {
49
+ this.flatbush.add(rect.minX, rect.minY, rect.maxX, rect.maxY)
50
+ this.indexToId.push(rect.id)
51
+ }
52
+
53
+ this.flatbush.finish()
54
+ }
55
+
56
+ private collides(box: {
57
+ minX: number
58
+ minY: number
59
+ maxX: number
60
+ maxY: number
61
+ }): boolean {
62
+ if (!this.flatbush) {
63
+ return false
64
+ }
65
+
66
+ const results = this.flatbush.search(
67
+ box.minX,
68
+ box.minY,
69
+ box.maxX,
70
+ box.maxY,
71
+ )
72
+
73
+ return results.length > 0
74
+ }
75
+
36
76
  /**
37
77
  * @returns top position for the rect, or Null if laying
38
78
  * out the rect would exceed maxHeighe
@@ -44,7 +84,7 @@ export default class Layout {
44
84
  height: number,
45
85
  data: unknown,
46
86
  ): number | null {
47
- // add to rbush
87
+ // add to flatbush
48
88
  const existingRecord = this.rectangles.get(id)
49
89
  if (existingRecord) {
50
90
  return existingRecord.minY
@@ -52,7 +92,7 @@ export default class Layout {
52
92
 
53
93
  let currHeight = 0
54
94
  while (
55
- this.rbush.collides({
95
+ this.collides({
56
96
  minX: left,
57
97
  minY: currHeight,
58
98
  maxX: right,
@@ -71,8 +111,8 @@ export default class Layout {
71
111
  id,
72
112
  data,
73
113
  }
74
- this.rbush.insert(record)
75
114
  this.rectangles.set(id, record)
115
+ this.rebuildIndex()
76
116
  this.pTotalHeight = Math.max(this.pTotalHeight, currHeight)
77
117
  return currHeight
78
118
  }
@@ -70,14 +70,14 @@ export function TreeModelF() {
70
70
  * set tree area width (px)
71
71
  */
72
72
  setTreeAreaWidth(n: number) {
73
- self.treeAreaWidth = n
73
+ self.treeAreaWidth = Math.round(n)
74
74
  },
75
75
  /**
76
76
  * #action
77
77
  * set tree width (px)
78
78
  */
79
79
  setTreeWidth(n: number) {
80
- self.treeWidth = n
80
+ self.treeWidth = Math.round(n)
81
81
  },
82
82
 
83
83
  /**
package/src/model.ts CHANGED
@@ -289,6 +289,14 @@ function stateModelFactory() {
289
289
  */
290
290
  mouseClickCol: undefined as number | undefined,
291
291
 
292
+ /**
293
+ * #volatile
294
+ * the currently hovered tree node ID and its descendant leaf names
295
+ */
296
+ hoveredTreeNode: undefined as
297
+ | { nodeId: string; descendantNames: string[] }
298
+ | undefined,
299
+
292
300
  /**
293
301
  * #volatile
294
302
  * a dummy variable that is incremented when ref changes so autorun for
@@ -327,7 +335,7 @@ function stateModelFactory() {
327
335
  /**
328
336
  * #action
329
337
  */
330
- drawRelativeTo(id: string) {
338
+ drawRelativeTo(id: string | undefined) {
331
339
  self.relativeTo = id
332
340
  },
333
341
  /**
@@ -396,6 +404,31 @@ function stateModelFactory() {
396
404
  self.mouseCol = col
397
405
  self.mouseRow = row
398
406
  },
407
+
408
+ /**
409
+ * #action
410
+ * set hovered tree node and its descendants
411
+ */
412
+ setHoveredTreeNode(nodeId?: string) {
413
+ if (!nodeId) {
414
+ self.hoveredTreeNode = undefined
415
+ return
416
+ }
417
+
418
+ // Find the node in the hierarchy
419
+ const node = (self as any).hierarchy.find(
420
+ (n: any) => n.data.id === nodeId,
421
+ )
422
+ if (!node) {
423
+ self.hoveredTreeNode = undefined
424
+ return
425
+ }
426
+
427
+ // Get all descendant leaf names
428
+ const descendantNames = node.leaves().map((leaf: any) => leaf.data.name)
429
+
430
+ self.hoveredTreeNode = { nodeId, descendantNames }
431
+ },
399
432
  /**
400
433
  * #action
401
434
  */
@@ -673,6 +706,7 @@ function stateModelFactory() {
673
706
  // todo: investigate whether needed, typescript says children always true
674
707
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
675
708
  .sum(d => (d.children ? 0 : 1))
709
+ // eslint-disable-next-line unicorn/no-array-sort
676
710
  .sort((a, b) => ascending(a.data.length || 1, b.data.length || 1))
677
711
 
678
712
  if (self.showOnly) {
@@ -911,7 +945,7 @@ function stateModelFactory() {
911
945
  * #getter
912
946
  */
913
947
  get maxScrollX() {
914
- return -self.totalWidth + (self.msaAreaWidth - 100)
948
+ return Math.min(-self.totalWidth + (self.msaAreaWidth - 100), 0)
915
949
  },
916
950
  /**
917
951
  * #getter
@@ -1009,7 +1043,7 @@ function stateModelFactory() {
1009
1043
  * #action
1010
1044
  */
1011
1045
  doScrollX(deltaX: number) {
1012
- self.scrollX = clamp(self.scrollX + deltaX, self.maxScrollX, 0)
1046
+ this.setScrollX(self.scrollX + deltaX)
1013
1047
  },
1014
1048
 
1015
1049
  /**
@@ -1243,7 +1277,7 @@ function stateModelFactory() {
1243
1277
  }
1244
1278
  }
1245
1279
  }
1246
- return ret.sort((a, b) => len(b) - len(a))
1280
+ return ret.toSorted((a, b) => len(b) - len(a))
1247
1281
  },
1248
1282
  /**
1249
1283
  * #getter
@@ -1525,6 +1559,75 @@ function stateModelFactory() {
1525
1559
  ...rest
1526
1560
  } = snap
1527
1561
 
1562
+ // Default values to filter out
1563
+ const defaults = {
1564
+ // Main model defaults
1565
+ showDomains: false,
1566
+ hideGaps: true,
1567
+ allowedGappyness: 100,
1568
+ contrastLettering: true,
1569
+ subFeatureRows: false,
1570
+ drawMsaLetters: true,
1571
+ height: 550,
1572
+ rowHeight: defaultRowHeight,
1573
+ scrollY: 0,
1574
+ scrollX: 0,
1575
+ colWidth: defaultColWidth,
1576
+ currentAlignment: 0,
1577
+ // MSA model defaults
1578
+ bgColor: true,
1579
+ colorSchemeName: 'maeditor',
1580
+ // Tree model defaults
1581
+ drawLabels: true,
1582
+ labelsAlignRight: false,
1583
+ treeAreaWidth: 400,
1584
+ treeWidth: 300,
1585
+ treeWidthMatchesArea: true,
1586
+ showBranchLen: true,
1587
+ drawTree: true,
1588
+ drawNodeBubbles: true,
1589
+ }
1590
+
1591
+ // Properties that should always be included even if they match defaults
1592
+ const alwaysInclude = new Set(['id', 'type', 'relativeTo'])
1593
+
1594
+ // Filter out properties that match default values
1595
+ function filterDefaults(obj: Record<string, any>): Record<string, any> {
1596
+ const filtered: Record<string, any> = {}
1597
+ for (const [key, value] of Object.entries(obj)) {
1598
+ // Always include essential properties
1599
+ if (alwaysInclude.has(key)) {
1600
+ filtered[key] = value
1601
+ continue
1602
+ }
1603
+
1604
+ // Skip if value matches default
1605
+ if (defaults[key as keyof typeof defaults] === value) {
1606
+ continue
1607
+ }
1608
+
1609
+ // Handle nested objects
1610
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
1611
+ const filteredNested = filterDefaults(value)
1612
+ // Only include nested object if it has non-default properties
1613
+ if (Object.keys(filteredNested).length > 0) {
1614
+ filtered[key] = filteredNested
1615
+ }
1616
+ } else if (Array.isArray(value)) {
1617
+ // Only include arrays that aren't empty
1618
+ if (value.length > 0) {
1619
+ filtered[key] = value
1620
+ }
1621
+ } else {
1622
+ // Include non-default primitives
1623
+ filtered[key] = value
1624
+ }
1625
+ }
1626
+ return filtered
1627
+ }
1628
+
1629
+ const filteredRest = filterDefaults(rest)
1630
+
1528
1631
  // remove the MSA/tree data from the tree if the filehandle available in
1529
1632
  // which case it can be reloaded on refresh
1530
1633
  return {
@@ -1533,7 +1636,7 @@ function stateModelFactory() {
1533
1636
  ...(result.msaFilehandle ? {} : { msa }),
1534
1637
  ...(result.treeMetadataFilehandle ? {} : { treeMetadata }),
1535
1638
  },
1536
- ...rest,
1639
+ ...filteredRest,
1537
1640
  }
1538
1641
  })
1539
1642
  }
@@ -90,11 +90,24 @@ test('with gaps in sequence', () => {
90
90
  expect(globalCoordToRowSpecificCoord(sequence, 0)).toBe(0)
91
91
  expect(globalCoordToRowSpecificCoord(sequence, 1)).toBe(1)
92
92
  expect(globalCoordToRowSpecificCoord(sequence, 2)).toBe(2)
93
- // Position 3 in global coordinates is after the gap
93
+ // Position 2 is a gap, so count before it is 2
94
94
  expect(globalCoordToRowSpecificCoord(sequence, 3)).toBe(2)
95
95
  expect(globalCoordToRowSpecificCoord(sequence, 4)).toBe(3)
96
96
  expect(globalCoordToRowSpecificCoord(sequence, 5)).toBe(4)
97
- // Position 6 in global coordinates is after the gap
97
+ // Position 5 is a gap, so count before it is 4
98
+ expect(globalCoordToRowSpecificCoord(sequence, 6)).toBe(4)
99
+ })
100
+
101
+ test('with mixed gap characters (- and .)', () => {
102
+ const sequence = 'AC.GT-A'
103
+ expect(globalCoordToRowSpecificCoord(sequence, 0)).toBe(0)
104
+ expect(globalCoordToRowSpecificCoord(sequence, 1)).toBe(1)
105
+ // Position 2 is a gap (.), so count before it is 2
106
+ expect(globalCoordToRowSpecificCoord(sequence, 2)).toBe(2)
107
+ expect(globalCoordToRowSpecificCoord(sequence, 3)).toBe(2)
108
+ expect(globalCoordToRowSpecificCoord(sequence, 4)).toBe(3)
109
+ // Position 5 is a gap (-), so count before it is 4
110
+ expect(globalCoordToRowSpecificCoord(sequence, 5)).toBe(4)
98
111
  expect(globalCoordToRowSpecificCoord(sequence, 6)).toBe(4)
99
112
  })
100
113
 
@@ -38,13 +38,9 @@ export function globalCoordToRowSpecificCoord(seq: string, position: number) {
38
38
  // Iterate until we reach the target position or end of sequence
39
39
  while (currentPosition < position && currentPosition < sequenceLength) {
40
40
  // If current character is not a gap, increment the non-gap counter
41
- if (seq[currentPosition] !== '-') {
41
+ if (!isBlank(seq[currentPosition])) {
42
42
  nonGapCount++
43
43
  }
44
- // If we've reached the target position in non-gap coordinates, break
45
- else if (nonGapCount >= position) {
46
- break
47
- }
48
44
  currentPosition++
49
45
  }
50
46
 
@@ -19,13 +19,13 @@ describe('seqCoordToRowSpecificGlobalCoord', () => {
19
19
  expect(seqCoordToRowSpecificGlobalCoord({ row, position: 0 })).toBe(0)
20
20
 
21
21
  // Position 1 (T after first gap) -> Global index 2
22
- expect(seqCoordToRowSpecificGlobalCoord({ row, position: 1 })).toBe(1)
22
+ expect(seqCoordToRowSpecificGlobalCoord({ row, position: 1 })).toBe(2)
23
23
 
24
24
  // Position 3 (C after second gap) -> Global index 5
25
- expect(seqCoordToRowSpecificGlobalCoord({ row, position: 3 })).toBe(4)
25
+ expect(seqCoordToRowSpecificGlobalCoord({ row, position: 3 })).toBe(5)
26
26
 
27
27
  // Position 5 (T after third gap) -> Global index 8
28
- expect(seqCoordToRowSpecificGlobalCoord({ row, position: 5 })).toBe(7)
28
+ expect(seqCoordToRowSpecificGlobalCoord({ row, position: 5 })).toBe(8)
29
29
 
30
30
  // Position 8 (end of sequence) -> Global index 11
31
31
  expect(seqCoordToRowSpecificGlobalCoord({ row, position: 8 })).toBe(11)
@@ -46,8 +46,8 @@ describe('seqCoordToRowSpecificGlobalCoord', () => {
46
46
  // Sequence positions: A(0) G(1) C(2)
47
47
 
48
48
  expect(seqCoordToRowSpecificGlobalCoord({ row, position: 0 })).toBe(0)
49
- expect(seqCoordToRowSpecificGlobalCoord({ row, position: 1 })).toBe(1)
50
- expect(seqCoordToRowSpecificGlobalCoord({ row, position: 2 })).toBe(4)
51
- expect(seqCoordToRowSpecificGlobalCoord({ row, position: 3 })).toBe(6)
49
+ expect(seqCoordToRowSpecificGlobalCoord({ row, position: 1 })).toBe(3)
50
+ expect(seqCoordToRowSpecificGlobalCoord({ row, position: 2 })).toBe(5)
51
+ expect(seqCoordToRowSpecificGlobalCoord({ row, position: 3 })).toBe(7)
52
52
  })
53
53
  })
@@ -9,12 +9,17 @@ export function seqCoordToRowSpecificGlobalCoord({
9
9
  }) {
10
10
  let k = 0
11
11
  let i = 0
12
- for (; k < position; i++) {
12
+ // Find the position-th non-gap character
13
+ while (i < row.length) {
13
14
  if (!isBlank(row[i])) {
15
+ if (k === position) {
16
+ return i
17
+ }
14
18
  k++
15
- } else if (k >= position) {
16
- break
17
19
  }
20
+ i++
18
21
  }
19
- return i
22
+ // If position is 0 and we didn't find any non-gap character, return 0
23
+ // Otherwise return i (which is row.length at this point)
24
+ return position === 0 ? 0 : i
20
25
  }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '4.4.4'
1
+ export const version = '4.4.6'
@@ -1,34 +0,0 @@
1
- /**
2
- * #stateModel DataModel
3
- * the data stored for the model. this is sometimes temporary in the case that
4
- * e.g. msaFilehandle is available on the parent model, because then the msa
5
- * data will not be persisted in saved session snapshots, it will be fetched
6
- * from msaFilehandle at startup
7
- */
8
- export declare function DataModelF(): import("mobx-state-tree").IModelType<{
9
- /**
10
- * #property
11
- */
12
- tree: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
13
- /**
14
- * #property
15
- */
16
- msa: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
17
- /**
18
- * #property
19
- */
20
- treeMetadata: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
21
- }, {
22
- /**
23
- * #action
24
- */
25
- setTree(tree?: string): void;
26
- /**
27
- * #action
28
- */
29
- setMSA(msa?: string): void;
30
- /**
31
- * #action
32
- */
33
- setTreeMetadata(treeMetadata?: string): void;
34
- }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
package/dist/DataModel.js DELETED
@@ -1,46 +0,0 @@
1
- import { types } from 'mobx-state-tree';
2
- /**
3
- * #stateModel DataModel
4
- * the data stored for the model. this is sometimes temporary in the case that
5
- * e.g. msaFilehandle is available on the parent model, because then the msa
6
- * data will not be persisted in saved session snapshots, it will be fetched
7
- * from msaFilehandle at startup
8
- */
9
- export function DataModelF() {
10
- return types
11
- .model({
12
- /**
13
- * #property
14
- */
15
- tree: types.maybe(types.string),
16
- /**
17
- * #property
18
- */
19
- msa: types.maybe(types.string),
20
- /**
21
- * #property
22
- */
23
- treeMetadata: types.maybe(types.string),
24
- })
25
- .actions(self => ({
26
- /**
27
- * #action
28
- */
29
- setTree(tree) {
30
- self.tree = tree;
31
- },
32
- /**
33
- * #action
34
- */
35
- setMSA(msa) {
36
- self.msa = msa;
37
- },
38
- /**
39
- * #action
40
- */
41
- setTreeMetadata(treeMetadata) {
42
- self.treeMetadata = treeMetadata;
43
- },
44
- }));
45
- }
46
- //# sourceMappingURL=DataModel.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DataModel.js","sourceRoot":"","sources":["../src/DataModel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAEvC;;;;;;GAMG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO,KAAK;SACT,KAAK,CAAC;QACL;;WAEG;QACH,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;QAC/B;;WAEG;QACH,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;QAC9B;;WAEG;QACH,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;KACxC,CAAC;SACD,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChB;;WAEG;QACH,OAAO,CAAC,IAAa;YACnB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAClB,CAAC;QACD;;WAEG;QACH,MAAM,CAAC,GAAY;YACjB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QAChB,CAAC;QACD;;WAEG;QACH,eAAe,CAAC,YAAqB;YACnC,IAAI,CAAC,YAAY,GAAG,YAAY,CAAA;QAClC,CAAC;KACF,CAAC,CAAC,CAAA;AACP,CAAC"}
@@ -1,25 +0,0 @@
1
- import { DialogComponentType } from '@jbrowse/core/util';
2
- /**
3
- * #stateModel DialogQueueSessionMixin
4
- */
5
- export declare function DialogQueueSessionMixin(): import("mobx-state-tree").IModelType<{}, {
6
- queueOfDialogs: [DialogComponentType, any][];
7
- } & {
8
- /**
9
- * #getter
10
- */
11
- readonly DialogComponent: DialogComponentType;
12
- /**
13
- * #getter
14
- */
15
- readonly DialogProps: any;
16
- } & {
17
- /**
18
- * #action
19
- */
20
- removeActiveDialog(): void;
21
- /**
22
- * #action
23
- */
24
- queueDialog(cb: (doneCallback: () => void) => [DialogComponentType, unknown]): void;
25
- }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
@@ -1,44 +0,0 @@
1
- import { types } from 'mobx-state-tree';
2
- /**
3
- * #stateModel DialogQueueSessionMixin
4
- */
5
- export function DialogQueueSessionMixin() {
6
- return types
7
- .model('DialogQueueSessionMixin', {})
8
- .volatile(() => ({
9
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
- queueOfDialogs: [],
11
- }))
12
- .views(self => ({
13
- /**
14
- * #getter
15
- */
16
- get DialogComponent() {
17
- return self.queueOfDialogs[0]?.[0];
18
- },
19
- /**
20
- * #getter
21
- */
22
- get DialogProps() {
23
- return self.queueOfDialogs[0]?.[1];
24
- },
25
- }))
26
- .actions(self => ({
27
- /**
28
- * #action
29
- */
30
- removeActiveDialog() {
31
- self.queueOfDialogs = self.queueOfDialogs.slice(1);
32
- },
33
- /**
34
- * #action
35
- */
36
- queueDialog(cb) {
37
- const [component, props] = cb(() => {
38
- this.removeActiveDialog();
39
- });
40
- self.queueOfDialogs = [...self.queueOfDialogs, [component, props]];
41
- },
42
- }));
43
- }
44
- //# sourceMappingURL=DialogQueue.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DialogQueue.js","sourceRoot":"","sources":["../src/DialogQueue.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAEvC;;GAEG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO,KAAK;SACT,KAAK,CAAC,yBAAyB,EAAE,EAAE,CAAC;SACpC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;QACf,8DAA8D;QAC9D,cAAc,EAAE,EAAkC;KACnD,CAAC,CAAC;SACF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACd;;WAEG;QACH,IAAI,eAAe;YACjB,OAAO,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QACpC,CAAC;QACD;;WAEG;QACH,IAAI,WAAW;YACb,OAAO,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QACpC,CAAC;KACF,CAAC,CAAC;SACF,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChB;;WAEG;QACH,kBAAkB;YAChB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QACpD,CAAC;QACD;;WAEG;QACH,WAAW,CACT,EAAgE;YAEhE,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE;gBACjC,IAAI,CAAC,kBAAkB,EAAE,CAAA;YAC3B,CAAC,CAAC,CAAA;YACF,IAAI,CAAC,cAAc,GAAG,CAAC,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAA;QACpE,CAAC;KACF,CAAC,CAAC,CAAA;AACP,CAAC"}
@@ -1,46 +0,0 @@
1
- import { SnapshotIn } from 'mobx-state-tree';
2
- import { StructureModel } from './StructureModel';
3
- export type StructureSnap = SnapshotIn<typeof StructureModel>;
4
- export declare function SelectedStructuresMixin(): import("mobx-state-tree").IModelType<{
5
- /**
6
- * #property
7
- * currently "selected" structures, generally PDB 3-D protein structures
8
- */
9
- selectedStructures: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IModelType<{
10
- id: import("mobx-state-tree").ISimpleType<string>;
11
- structure: import("mobx-state-tree").IModelType<{
12
- pdb: import("mobx-state-tree").ISimpleType<string>;
13
- startPos: import("mobx-state-tree").ISimpleType<number>;
14
- endPos: import("mobx-state-tree").ISimpleType<number>;
15
- }, {}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
16
- range: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
17
- }, {}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
18
- }, {
19
- /**
20
- * #action
21
- * add to the selected structures
22
- */
23
- addStructureToSelection(elt: StructureSnap): void;
24
- /**
25
- * #action
26
- * remove from the selected structures
27
- */
28
- removeStructureFromSelection(elt: StructureSnap): void;
29
- /**
30
- * #action
31
- * toggle a structure from the selected structures list
32
- */
33
- toggleStructureSelection(elt: {
34
- id: string;
35
- structure: {
36
- startPos: number;
37
- endPos: number;
38
- pdb: string;
39
- };
40
- }): void;
41
- /**
42
- * #action
43
- * clear all selected structures
44
- */
45
- clearSelectedStructures(): void;
46
- }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
@@ -1,52 +0,0 @@
1
- import { cast, types } from 'mobx-state-tree';
2
- import { StructureModel } from './StructureModel';
3
- export function SelectedStructuresMixin() {
4
- return types
5
- .model({
6
- /**
7
- * #property
8
- * currently "selected" structures, generally PDB 3-D protein structures
9
- */
10
- selectedStructures: types.array(StructureModel),
11
- })
12
- .actions(self => ({
13
- /**
14
- * #action
15
- * add to the selected structures
16
- */
17
- addStructureToSelection(elt) {
18
- self.selectedStructures.push(elt);
19
- },
20
- /**
21
- * #action
22
- * remove from the selected structures
23
- */
24
- removeStructureFromSelection(elt) {
25
- const r = self.selectedStructures.find(node => node.id === elt.id);
26
- if (r) {
27
- self.selectedStructures.remove(r);
28
- }
29
- },
30
- /**
31
- * #action
32
- * toggle a structure from the selected structures list
33
- */
34
- toggleStructureSelection(elt) {
35
- const r = self.selectedStructures.find(node => node.id === elt.id);
36
- if (r) {
37
- self.selectedStructures.remove(r);
38
- }
39
- else {
40
- self.selectedStructures.push(elt);
41
- }
42
- },
43
- /**
44
- * #action
45
- * clear all selected structures
46
- */
47
- clearSelectedStructures() {
48
- self.selectedStructures = cast([]);
49
- },
50
- }));
51
- }
52
- //# sourceMappingURL=SelectedStructuresMixin.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SelectedStructuresMixin.js","sourceRoot":"","sources":["../src/SelectedStructuresMixin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,IAAI,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAIjD,MAAM,UAAU,uBAAuB;IACrC,OAAO,KAAK;SACT,KAAK,CAAC;QACL;;;WAGG;QACH,kBAAkB,EAAE,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC;KAChD,CAAC;SACD,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChB;;;WAGG;QACH,uBAAuB,CAAC,GAAkB;YACxC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACnC,CAAC;QAED;;;WAGG;QACH,4BAA4B,CAAC,GAAkB;YAC7C,MAAM,CAAC,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,CAAA;YAClE,IAAI,CAAC,EAAE,CAAC;gBACN,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;YACnC,CAAC;QACH,CAAC;QAED;;;WAGG;QACH,wBAAwB,CAAC,GAGxB;YACC,MAAM,CAAC,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,CAAA;YAClE,IAAI,CAAC,EAAE,CAAC;gBACN,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;YACnC,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACnC,CAAC;QACH,CAAC;QAED;;;WAGG;QACH,uBAAuB;YACrB,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,EAAE,CAAC,CAAA;QACpC,CAAC;KACF,CAAC,CAAC,CAAA;AACP,CAAC"}
@@ -1,9 +0,0 @@
1
- export declare const StructureModel: import("mobx-state-tree").IModelType<{
2
- id: import("mobx-state-tree").ISimpleType<string>;
3
- structure: import("mobx-state-tree").IModelType<{
4
- pdb: import("mobx-state-tree").ISimpleType<string>;
5
- startPos: import("mobx-state-tree").ISimpleType<number>;
6
- endPos: import("mobx-state-tree").ISimpleType<number>;
7
- }, {}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
8
- range: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
9
- }, {}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;