jbrowse-plugin-mafviewer 1.0.6 → 1.1.1

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 (154) hide show
  1. package/README.md +71 -22
  2. package/dist/BgzipTaffyAdapter/BgzipTaffyAdapter.d.ts +20 -0
  3. package/dist/BgzipTaffyAdapter/BgzipTaffyAdapter.js +197 -0
  4. package/dist/BgzipTaffyAdapter/BgzipTaffyAdapter.js.map +1 -0
  5. package/dist/BgzipTaffyAdapter/configSchema.d.ts +44 -0
  6. package/dist/BgzipTaffyAdapter/configSchema.js +53 -0
  7. package/dist/BgzipTaffyAdapter/configSchema.js.map +1 -0
  8. package/dist/BgzipTaffyAdapter/index.d.ts +2 -0
  9. package/dist/BgzipTaffyAdapter/index.js +11 -0
  10. package/dist/BgzipTaffyAdapter/index.js.map +1 -0
  11. package/dist/BgzipTaffyAdapter/rowInstructions.d.ts +35 -0
  12. package/dist/BgzipTaffyAdapter/rowInstructions.js +55 -0
  13. package/dist/BgzipTaffyAdapter/rowInstructions.js.map +1 -0
  14. package/dist/BgzipTaffyAdapter/types.d.ts +13 -0
  15. package/dist/BgzipTaffyAdapter/types.js +2 -0
  16. package/dist/BgzipTaffyAdapter/types.js.map +1 -0
  17. package/dist/BgzipTaffyAdapter/virtualOffset.d.ts +8 -0
  18. package/dist/BgzipTaffyAdapter/virtualOffset.js +23 -0
  19. package/dist/BgzipTaffyAdapter/virtualOffset.js.map +1 -0
  20. package/dist/BigMafAdapter/BigMafAdapter.d.ts +17 -0
  21. package/dist/BigMafAdapter/BigMafAdapter.js +92 -0
  22. package/dist/BigMafAdapter/BigMafAdapter.js.map +1 -0
  23. package/dist/BigMafAdapter/configSchema.d.ts +32 -0
  24. package/dist/BigMafAdapter/configSchema.js +39 -0
  25. package/dist/BigMafAdapter/configSchema.js.map +1 -0
  26. package/dist/BigMafAdapter/index.d.ts +2 -0
  27. package/dist/BigMafAdapter/index.js +11 -0
  28. package/dist/BigMafAdapter/index.js.map +1 -0
  29. package/dist/LinearMafDisplay/components/ColorLegend.d.ts +8 -0
  30. package/dist/LinearMafDisplay/components/ColorLegend.js +19 -0
  31. package/dist/LinearMafDisplay/components/ColorLegend.js.map +1 -0
  32. package/dist/LinearMafDisplay/components/ReactComponent.d.ts +6 -0
  33. package/dist/LinearMafDisplay/components/ReactComponent.js +50 -0
  34. package/dist/LinearMafDisplay/components/ReactComponent.js.map +1 -0
  35. package/dist/LinearMafDisplay/components/RectBg.d.ts +9 -0
  36. package/dist/LinearMafDisplay/components/RectBg.js +7 -0
  37. package/dist/LinearMafDisplay/components/RectBg.js.map +1 -0
  38. package/dist/LinearMafDisplay/components/SetRowHeight.d.ts +11 -0
  39. package/dist/LinearMafDisplay/components/SetRowHeight.js +36 -0
  40. package/dist/LinearMafDisplay/components/SetRowHeight.js.map +1 -0
  41. package/dist/LinearMafDisplay/components/SvgWrapper.d.ts +8 -0
  42. package/dist/LinearMafDisplay/components/SvgWrapper.js +21 -0
  43. package/dist/LinearMafDisplay/components/SvgWrapper.js.map +1 -0
  44. package/dist/LinearMafDisplay/components/Tree.d.ts +5 -0
  45. package/dist/LinearMafDisplay/components/Tree.js +22 -0
  46. package/dist/LinearMafDisplay/components/Tree.js.map +1 -0
  47. package/dist/LinearMafDisplay/components/YScaleBars.d.ts +8 -0
  48. package/dist/LinearMafDisplay/components/YScaleBars.js +20 -0
  49. package/dist/LinearMafDisplay/components/YScaleBars.js.map +1 -0
  50. package/dist/LinearMafDisplay/components/util.d.ts +1 -0
  51. package/dist/LinearMafDisplay/components/util.js +8 -0
  52. package/dist/LinearMafDisplay/components/util.js.map +1 -0
  53. package/dist/LinearMafDisplay/configSchema.d.ts +34 -0
  54. package/dist/LinearMafDisplay/configSchema.js +15 -0
  55. package/dist/LinearMafDisplay/configSchema.js.map +1 -0
  56. package/dist/LinearMafDisplay/index.d.ts +2 -0
  57. package/dist/LinearMafDisplay/index.js +20 -0
  58. package/dist/LinearMafDisplay/index.js.map +1 -0
  59. package/dist/LinearMafDisplay/renderSvg.d.ts +4 -0
  60. package/dist/LinearMafDisplay/renderSvg.js +18 -0
  61. package/dist/LinearMafDisplay/renderSvg.js.map +1 -0
  62. package/dist/LinearMafDisplay/stateModel.d.ts +426 -0
  63. package/dist/LinearMafDisplay/stateModel.js +276 -0
  64. package/dist/LinearMafDisplay/stateModel.js.map +1 -0
  65. package/dist/LinearMafDisplay/types.d.ts +17 -0
  66. package/dist/LinearMafDisplay/types.js +16 -0
  67. package/dist/LinearMafDisplay/types.js.map +1 -0
  68. package/dist/LinearMafRenderer/LinearMafRenderer.d.ts +45 -0
  69. package/dist/LinearMafRenderer/LinearMafRenderer.js +183 -0
  70. package/dist/LinearMafRenderer/LinearMafRenderer.js.map +1 -0
  71. package/dist/LinearMafRenderer/components/ReactComponent.d.ts +6 -0
  72. package/dist/LinearMafRenderer/components/ReactComponent.js +8 -0
  73. package/dist/LinearMafRenderer/components/ReactComponent.js.map +1 -0
  74. package/dist/LinearMafRenderer/configSchema.d.ts +2 -0
  75. package/dist/LinearMafRenderer/configSchema.js +13 -0
  76. package/dist/LinearMafRenderer/configSchema.js.map +1 -0
  77. package/dist/LinearMafRenderer/index.d.ts +2 -0
  78. package/dist/LinearMafRenderer/index.js +12 -0
  79. package/dist/LinearMafRenderer/index.js.map +1 -0
  80. package/dist/LinearMafRenderer/util.d.ts +10 -0
  81. package/dist/LinearMafRenderer/util.js +16 -0
  82. package/dist/LinearMafRenderer/util.js.map +1 -0
  83. package/dist/MafAddTrackWorkflow/AddTrackWorkflow.d.ts +5 -0
  84. package/dist/MafAddTrackWorkflow/AddTrackWorkflow.js +128 -0
  85. package/dist/MafAddTrackWorkflow/AddTrackWorkflow.js.map +1 -0
  86. package/dist/MafAddTrackWorkflow/index.d.ts +2 -0
  87. package/dist/MafAddTrackWorkflow/index.js +12 -0
  88. package/dist/MafAddTrackWorkflow/index.js.map +1 -0
  89. package/dist/MafRPC/index.d.ts +16 -0
  90. package/dist/MafRPC/index.js +19 -0
  91. package/dist/MafRPC/index.js.map +1 -0
  92. package/dist/MafTabixAdapter/MafTabixAdapter.d.ts +25 -0
  93. package/dist/MafTabixAdapter/MafTabixAdapter.js +95 -0
  94. package/dist/MafTabixAdapter/MafTabixAdapter.js.map +1 -0
  95. package/dist/MafTabixAdapter/configSchema.d.ts +50 -0
  96. package/dist/MafTabixAdapter/configSchema.js +56 -0
  97. package/dist/MafTabixAdapter/configSchema.js.map +1 -0
  98. package/dist/MafTabixAdapter/index.d.ts +2 -0
  99. package/dist/MafTabixAdapter/index.js +11 -0
  100. package/dist/MafTabixAdapter/index.js.map +1 -0
  101. package/dist/MafTrack/configSchema.d.ts +79 -0
  102. package/dist/MafTrack/configSchema.js +15 -0
  103. package/dist/MafTrack/configSchema.js.map +1 -0
  104. package/dist/MafTrack/index.d.ts +2 -0
  105. package/dist/MafTrack/index.js +14 -0
  106. package/dist/MafTrack/index.js.map +1 -0
  107. package/dist/index.d.ts +8 -0
  108. package/dist/index.js +26 -0
  109. package/dist/index.js.map +1 -0
  110. package/dist/jbrowse-plugin-mafviewer.umd.production.min.js +65 -1
  111. package/dist/jbrowse-plugin-mafviewer.umd.production.min.js.map +7 -1
  112. package/dist/parseNewick.d.ts +60 -0
  113. package/dist/parseNewick.js +95 -0
  114. package/dist/parseNewick.js.map +1 -0
  115. package/dist/util.d.ts +9 -0
  116. package/dist/util.js +9 -0
  117. package/dist/util.js.map +1 -0
  118. package/package.json +37 -41
  119. package/src/BgzipTaffyAdapter/BgzipTaffyAdapter.ts +227 -0
  120. package/src/BgzipTaffyAdapter/configSchema.ts +59 -0
  121. package/src/BgzipTaffyAdapter/index.ts +16 -0
  122. package/src/BgzipTaffyAdapter/rowInstructions.ts +91 -0
  123. package/src/BgzipTaffyAdapter/types.ts +16 -0
  124. package/src/BgzipTaffyAdapter/virtualOffset.ts +29 -0
  125. package/src/BigMafAdapter/BigMafAdapter.ts +12 -13
  126. package/src/BigMafAdapter/configSchema.ts +11 -0
  127. package/src/BigMafAdapter/index.ts +2 -1
  128. package/src/LinearMafDisplay/components/ColorLegend.tsx +38 -27
  129. package/src/LinearMafDisplay/components/ReactComponent.tsx +68 -3
  130. package/src/LinearMafDisplay/components/SetRowHeight.tsx +15 -8
  131. package/src/LinearMafDisplay/components/SvgWrapper.tsx +39 -0
  132. package/src/LinearMafDisplay/components/Tree.tsx +33 -0
  133. package/src/LinearMafDisplay/components/YScaleBars.tsx +11 -38
  134. package/src/LinearMafDisplay/components/util.ts +7 -0
  135. package/src/LinearMafDisplay/index.ts +2 -1
  136. package/src/LinearMafDisplay/renderSvg.tsx +2 -1
  137. package/src/LinearMafDisplay/stateModel.ts +169 -18
  138. package/src/LinearMafDisplay/types.ts +41 -0
  139. package/src/LinearMafRenderer/LinearMafRenderer.ts +51 -44
  140. package/src/LinearMafRenderer/components/ReactComponent.tsx +2 -1
  141. package/src/LinearMafRenderer/index.ts +2 -1
  142. package/src/LinearMafRenderer/util.ts +20 -0
  143. package/src/MafAddTrackWorkflow/AddTrackWorkflow.tsx +133 -51
  144. package/src/MafRPC/index.ts +39 -0
  145. package/src/MafTabixAdapter/MafTabixAdapter.ts +33 -27
  146. package/src/MafTabixAdapter/configSchema.ts +17 -1
  147. package/src/MafTabixAdapter/index.ts +2 -1
  148. package/src/MafTrack/index.ts +1 -0
  149. package/src/index.ts +6 -2
  150. package/src/parseNewick.ts +94 -0
  151. package/src/util.ts +11 -0
  152. package/LICENSE +0 -201
  153. package/dist/jbrowse-plugin-mafviewer.umd.development.js +0 -1439
  154. package/dist/jbrowse-plugin-mafviewer.umd.development.js.map +0 -1
@@ -0,0 +1,16 @@
1
+ import VirtualOffset from './virtualOffset'
2
+
3
+ export interface OrganismRecord {
4
+ chr: string
5
+ start: number
6
+ srcSize: number
7
+ strand: number
8
+ data: string
9
+ }
10
+
11
+ export interface ByteRange {
12
+ chrStart: number
13
+ virtualOffset: VirtualOffset
14
+ }
15
+
16
+ export type IndexData = Record<string, ByteRange[]>
@@ -0,0 +1,29 @@
1
+ export default class VirtualOffset {
2
+ public blockPosition: number
3
+ public dataPosition: number
4
+ constructor(blockPosition: number, dataPosition: number) {
5
+ this.blockPosition = blockPosition // < offset of the compressed data block
6
+ this.dataPosition = dataPosition // < offset into the uncompressed data
7
+ }
8
+
9
+ toString() {
10
+ return `${this.blockPosition}:${this.dataPosition}`
11
+ }
12
+
13
+ compareTo(b: VirtualOffset) {
14
+ return (
15
+ this.blockPosition - b.blockPosition || this.dataPosition - b.dataPosition
16
+ )
17
+ }
18
+ }
19
+ export function fromBytes(bytes: Uint8Array, offset = 0) {
20
+ return new VirtualOffset(
21
+ bytes[offset + 7]! * 0x10000000000 +
22
+ bytes[offset + 6]! * 0x100000000 +
23
+ bytes[offset + 5]! * 0x1000000 +
24
+ bytes[offset + 4]! * 0x10000 +
25
+ bytes[offset + 3]! * 0x100 +
26
+ bytes[offset + 2]!,
27
+ (bytes[offset + 1]! << 8) | bytes[offset]!,
28
+ )
29
+ }
@@ -1,7 +1,7 @@
1
1
  import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter'
2
- import { getSnapshot } from 'mobx-state-tree'
3
2
  import { Feature, Region, SimpleFeature } from '@jbrowse/core/util'
4
3
  import { ObservableCreate } from '@jbrowse/core/util/rxjs'
4
+ import { getSnapshot } from 'mobx-state-tree'
5
5
  import { firstValueFrom, toArray } from 'rxjs'
6
6
 
7
7
  interface OrganismRecord {
@@ -29,7 +29,7 @@ export default class BigMafAdapter extends BaseFeatureDataAdapter {
29
29
  }
30
30
  async setupPre() {
31
31
  if (!this.setupP) {
32
- this.setupP = this.setup().catch(e => {
32
+ this.setupP = this.setup().catch((e: unknown) => {
33
33
  this.setupP = undefined
34
34
  throw e
35
35
  })
@@ -63,31 +63,30 @@ export default class BigMafAdapter extends BaseFeatureDataAdapter {
63
63
  for (const block of blocks) {
64
64
  if (block.startsWith('s')) {
65
65
  if (aln) {
66
- alns.push(block.split(/ +/)[6])
66
+ alns.push(block.split(/ +/)[6]!)
67
67
  blocks2.push(block)
68
68
  } else {
69
69
  aln = block.split(/ +/)[6]
70
- alns.push(aln)
70
+ alns.push(aln!)
71
71
  blocks2.push(block)
72
72
  }
73
73
  }
74
74
  }
75
75
 
76
- // eslint-disable-next-line unicorn/no-for-loop
77
76
  for (let i = 0; i < blocks2.length; i++) {
78
- const elt = blocks2[i]
77
+ const elt = blocks2[i]!
79
78
  const ad = elt.split(/ +/)
80
- const y = ad[1].split('.')
81
- const org = y[0]
82
- const chr = y[1]
79
+ const y = ad[1]!.split('.')
80
+ const org = y[0]!
81
+ const chr = y[1]!
83
82
 
84
83
  alignments[org] = {
85
84
  chr: chr,
86
- start: +ad[1],
87
- srcSize: +ad[2],
85
+ start: +ad[1]!,
86
+ srcSize: +ad[2]!,
88
87
  strand: ad[3] === '+' ? 1 : -1,
89
- unknown: +ad[4],
90
- data: alns[i],
88
+ unknown: +ad[4]!,
89
+ data: alns[i]!,
91
90
  }
92
91
  }
93
92
  observer.next(
@@ -27,6 +27,17 @@ const configSchema = ConfigurationSchema(
27
27
  locationType: 'UriLocation',
28
28
  },
29
29
  },
30
+ /**
31
+ * #slot
32
+ */
33
+ nhLocation: {
34
+ type: 'fileLocation',
35
+ description: 'newick tree',
36
+ defaultValue: {
37
+ uri: '/path/to/my.nh',
38
+ locationType: 'UriLocation',
39
+ },
40
+ },
30
41
  },
31
42
  { explicitlyTyped: true },
32
43
  )
@@ -1,7 +1,8 @@
1
1
  import PluginManager from '@jbrowse/core/PluginManager'
2
2
  import { AdapterType } from '@jbrowse/core/pluggableElementTypes'
3
- import configSchema from './configSchema'
3
+
4
4
  import BigMafAdapter from './BigMafAdapter'
5
+ import configSchema from './configSchema'
5
6
 
6
7
  export default function BigMafAdapterF(pluginManager: PluginManager) {
7
8
  return pluginManager.addAdapterType(
@@ -1,9 +1,11 @@
1
1
  import React from 'react'
2
+
2
3
  import { observer } from 'mobx-react'
3
4
 
4
5
  // locals
5
6
  import { LinearMafDisplayModel } from '../stateModel'
6
7
  import RectBg from './RectBg'
8
+ import Tree from './Tree'
7
9
 
8
10
  const ColorLegend = observer(function ({
9
11
  model,
@@ -14,37 +16,46 @@ const ColorLegend = observer(function ({
14
16
  svgFontSize: number
15
17
  labelWidth: number
16
18
  }) {
17
- const { samples, rowHeight } = model
18
- const canDisplayLabel = rowHeight >= 10
19
+ const { totalHeight, treeWidth, samples, rowHeight } = model
20
+ const canDisplayLabel = rowHeight >= 8
19
21
  const boxHeight = Math.min(20, rowHeight)
20
22
 
21
- return samples ? (
23
+ return (
22
24
  <>
23
- {samples.map((sample, idx) => (
24
- <RectBg
25
- key={`${sample.id}-${idx}`}
26
- y={idx * rowHeight}
27
- x={0}
28
- width={labelWidth + 5}
29
- height={boxHeight}
30
- color={sample.color}
31
- />
32
- ))}
33
- {canDisplayLabel
34
- ? samples.map((sample, idx) => (
35
- <text
36
- key={`${sample.id}-${idx}`}
37
- y={idx * rowHeight + rowHeight / 2}
38
- dominantBaseline="middle"
39
- x={2}
40
- fontSize={svgFontSize}
41
- >
42
- {sample.label}
43
- </text>
44
- ))
45
- : null}
25
+ <RectBg
26
+ y={0}
27
+ x={0}
28
+ width={labelWidth + 5 + treeWidth}
29
+ height={totalHeight}
30
+ />
31
+ <Tree model={model} />
32
+ <g transform={`translate(${treeWidth + 5},0)`}>
33
+ {samples.map((sample, idx) => (
34
+ <RectBg
35
+ key={`${sample.id}-${idx}`}
36
+ y={idx * rowHeight}
37
+ x={0}
38
+ width={labelWidth + 5}
39
+ height={boxHeight}
40
+ color={sample.color}
41
+ />
42
+ ))}
43
+ {canDisplayLabel
44
+ ? samples.map((sample, idx) => (
45
+ <text
46
+ key={`${sample.id}-${idx}`}
47
+ y={idx * rowHeight + rowHeight / 2}
48
+ dominantBaseline="middle"
49
+ x={2}
50
+ fontSize={svgFontSize}
51
+ >
52
+ {sample.label}
53
+ </text>
54
+ ))
55
+ : null}
56
+ </g>
46
57
  </>
47
- ) : null
58
+ )
48
59
  })
49
60
 
50
61
  export default ColorLegend
@@ -1,24 +1,89 @@
1
- import React from 'react'
2
- import { getEnv } from '@jbrowse/core/util'
1
+ import React, { useRef, useState } from 'react'
2
+
3
+ import BaseTooltip from '@jbrowse/core/ui/BaseTooltip'
4
+ import SanitizedHTML from '@jbrowse/core/ui/SanitizedHTML'
5
+ import { getContainingView, getEnv } from '@jbrowse/core/util'
3
6
  import { observer } from 'mobx-react'
7
+ import { makeStyles } from 'tss-react/mui'
8
+
4
9
  import YScaleBars from './YScaleBars'
5
10
  import { LinearMafDisplayModel } from '../stateModel'
6
11
 
12
+ import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
13
+
14
+ const useStyles = makeStyles()({
15
+ cursor: {
16
+ pointerEvents: 'none',
17
+ },
18
+ })
19
+
7
20
  const LinearMafDisplay = observer(function (props: {
8
21
  model: LinearMafDisplayModel
9
22
  }) {
10
23
  const { model } = props
24
+ const { classes } = useStyles()
11
25
  const { pluginManager } = getEnv(model)
26
+ const { rowHeight, height, scrollTop, samples: sources } = model
27
+ const ref = useRef<HTMLDivElement>(null)
12
28
 
13
29
  const LinearGenomePlugin = pluginManager.getPlugin(
14
30
  'LinearGenomeViewPlugin',
15
31
  ) as import('@jbrowse/plugin-linear-genome-view').default
16
32
  const { BaseLinearDisplayComponent } = LinearGenomePlugin.exports
17
33
 
34
+ const [mouseY, setMouseY] = useState<number>()
35
+ const [mouseX, setMouseX] = useState<number>()
36
+ const { width } = getContainingView(model) as LinearGenomeViewModel
37
+
18
38
  return (
19
- <div>
39
+ <div
40
+ ref={ref}
41
+ onMouseMove={event => {
42
+ const rect = ref.current?.getBoundingClientRect()
43
+ const top = rect?.top || 0
44
+ const left = rect?.left || 0
45
+ setMouseY(event.clientY - top)
46
+ setMouseX(event.clientX - left)
47
+ }}
48
+ onMouseLeave={() => {
49
+ setMouseY(undefined)
50
+ setMouseX(undefined)
51
+ }}
52
+ >
20
53
  <BaseLinearDisplayComponent {...props} />
21
54
  <YScaleBars model={model} />
55
+ {mouseY ? (
56
+ <div style={{ position: 'relative' }}>
57
+ <svg
58
+ className={classes.cursor}
59
+ width={width}
60
+ height={height}
61
+ style={{
62
+ position: 'absolute',
63
+ top: scrollTop,
64
+ }}
65
+ >
66
+ <line
67
+ x1={0}
68
+ x2={width}
69
+ y1={mouseY - scrollTop}
70
+ y2={mouseY - scrollTop}
71
+ stroke="black"
72
+ />
73
+ <line x1={mouseX} x2={mouseX} y1={0} y2={height} stroke="black" />
74
+ </svg>
75
+ <BaseTooltip>
76
+ <SanitizedHTML
77
+ html={Object.entries(
78
+ sources[Math.floor(mouseY / rowHeight)] || {},
79
+ )
80
+ .filter(([key]) => key !== 'color' && key !== 'id')
81
+ .map(([key, value]) => `${key}:${value}`)
82
+ .join('\n')}
83
+ />
84
+ </BaseTooltip>
85
+ </div>
86
+ ) : null}
22
87
  </div>
23
88
  )
24
89
  })
@@ -1,5 +1,6 @@
1
1
  import React, { useState } from 'react'
2
- import { observer } from 'mobx-react'
2
+
3
+ import { Dialog } from '@jbrowse/core/ui'
3
4
  import {
4
5
  Button,
5
6
  DialogActions,
@@ -7,7 +8,7 @@ import {
7
8
  TextField,
8
9
  Typography,
9
10
  } from '@mui/material'
10
- import { Dialog } from '@jbrowse/core/ui'
11
+ import { observer } from 'mobx-react'
11
12
  import { makeStyles } from 'tss-react/mui'
12
13
 
13
14
  const useStyles = makeStyles()({
@@ -31,7 +32,7 @@ const SetRowHeightDialog = observer(function (props: {
31
32
  const [rowProportion, setRowProportion] = useState(`${model.rowProportion}`)
32
33
 
33
34
  return (
34
- <Dialog open onClose={handleClose} title="Filter options">
35
+ <Dialog open onClose={handleClose} title="Set row height">
35
36
  <DialogContent className={classes.root}>
36
37
  <Typography>
37
38
  Set row height and the proportion of the row height to use for drawing
@@ -39,13 +40,17 @@ const SetRowHeightDialog = observer(function (props: {
39
40
  </Typography>
40
41
  <TextField
41
42
  value={rowHeight}
42
- onChange={event => setRowHeight(event.target.value)}
43
- placeholder="Enter row height"
43
+ helperText="Enter row height"
44
+ onChange={event => {
45
+ setRowHeight(event.target.value)
46
+ }}
44
47
  />
45
48
  <TextField
46
49
  value={rowProportion}
47
- onChange={event => setRowProportion(event.target.value)}
48
- placeholder="Enter row proportion"
50
+ helperText="Enter row proportion"
51
+ onChange={event => {
52
+ setRowProportion(event.target.value)
53
+ }}
49
54
  />
50
55
  <DialogActions>
51
56
  <Button
@@ -64,7 +69,9 @@ const SetRowHeightDialog = observer(function (props: {
64
69
  <Button
65
70
  variant="contained"
66
71
  color="secondary"
67
- onClick={() => handleClose()}
72
+ onClick={() => {
73
+ handleClose()
74
+ }}
68
75
  >
69
76
  Cancel
70
77
  </Button>
@@ -0,0 +1,39 @@
1
+ import React from 'react'
2
+
3
+ import { getContainingView } from '@jbrowse/core/util'
4
+ import { observer } from 'mobx-react'
5
+
6
+ // locals
7
+ import { LinearMafDisplayModel } from '../stateModel'
8
+
9
+ const SvgWrapper = observer(function ({
10
+ children,
11
+ model,
12
+ exportSVG,
13
+ }: {
14
+ model: LinearMafDisplayModel
15
+ children: React.ReactNode
16
+ exportSVG?: boolean
17
+ }) {
18
+ if (exportSVG) {
19
+ return <>{children}</>
20
+ } else {
21
+ const { rowHeight, samples } = model
22
+ return (
23
+ <svg
24
+ style={{
25
+ position: 'absolute',
26
+ top: 0,
27
+ left: 0,
28
+ pointerEvents: 'none',
29
+ height: samples.length * rowHeight,
30
+ width: getContainingView(model).width,
31
+ }}
32
+ >
33
+ {children}
34
+ </svg>
35
+ )
36
+ }
37
+ })
38
+
39
+ export default SvgWrapper
@@ -0,0 +1,33 @@
1
+ import React from 'react'
2
+
3
+ import { observer } from 'mobx-react'
4
+
5
+ const Tree = observer(function ({ model }: { model: any }) {
6
+ const { hierarchy, showBranchLen } = model
7
+
8
+ return (
9
+ <>
10
+ {hierarchy
11
+ ? [...hierarchy.links()].map(link => {
12
+ const { source, target } = link
13
+ const sy = source.x!
14
+ const ty = target.x!
15
+ const tx = showBranchLen ? target.len : target.y
16
+ const sx = showBranchLen ? source.len : source.y
17
+
18
+ // 1d line intersection to check if line crosses block at all, this is
19
+ // an optimization that allows us to skip drawing most tree links
20
+ // outside the block
21
+ return (
22
+ <React.Fragment key={[sy, ty, tx, sx].join('-')}>
23
+ <line stroke="black" x1={sx} y1={sy} x2={sx} y2={ty} />
24
+ <line stroke="black" x1={sx} y1={ty} x2={tx} y2={ty} />
25
+ </React.Fragment>
26
+ )
27
+ })
28
+ : null}
29
+ </>
30
+ )
31
+ })
32
+
33
+ export default Tree
@@ -1,40 +1,13 @@
1
1
  import React from 'react'
2
- import { measureText, getContainingView } from '@jbrowse/core/util'
2
+
3
+ import { measureText } from '@jbrowse/core/util'
3
4
  import { observer } from 'mobx-react'
4
5
 
5
6
  // locals
6
7
  import { LinearMafDisplayModel } from '../stateModel'
7
8
  import ColorLegend from './ColorLegend'
8
-
9
- const Wrapper = observer(function ({
10
- children,
11
- model,
12
- exportSVG,
13
- }: {
14
- model: LinearMafDisplayModel
15
- children: React.ReactNode
16
- exportSVG?: boolean
17
- }) {
18
- if (exportSVG) {
19
- return <>{children}</>
20
- } else {
21
- const { rowHeight, samples } = model
22
- return (
23
- <svg
24
- style={{
25
- position: 'absolute',
26
- top: 0,
27
- left: 0,
28
- pointerEvents: 'none',
29
- height: samples.length * rowHeight,
30
- width: getContainingView(model).width,
31
- }}
32
- >
33
- {children}
34
- </svg>
35
- )
36
- }
37
- })
9
+ import SvgWrapper from './SvgWrapper'
10
+ import { max } from './util'
38
11
 
39
12
  export const YScaleBars = observer(function (props: {
40
13
  model: LinearMafDisplayModel
@@ -43,24 +16,24 @@ export const YScaleBars = observer(function (props: {
43
16
  }) {
44
17
  const { model } = props
45
18
  const { rowHeight, samples } = model
46
- const svgFontSize = Math.min(Math.max(rowHeight, 10), 14)
47
- const canDisplayLabel = rowHeight >= 10
19
+ const svgFontSize = Math.min(Math.max(rowHeight, 8), 14)
20
+ const canDisplayLabel = rowHeight >= 8
48
21
  const minWidth = 20
49
22
 
50
- const labelWidth = Math.max(
51
- ...(samples
23
+ const labelWidth = max(
24
+ samples
52
25
  .map(s => measureText(s.label, svgFontSize))
53
- .map(width => (canDisplayLabel ? width : minWidth)) || [0]),
26
+ .map(width => (canDisplayLabel ? width : minWidth)),
54
27
  )
55
28
 
56
29
  return (
57
- <Wrapper {...props}>
30
+ <SvgWrapper {...props}>
58
31
  <ColorLegend
59
32
  model={model}
60
33
  labelWidth={labelWidth}
61
34
  svgFontSize={svgFontSize}
62
35
  />
63
- </Wrapper>
36
+ </SvgWrapper>
64
37
  )
65
38
  })
66
39
 
@@ -0,0 +1,7 @@
1
+ export function max(arr: number[], init = Number.NEGATIVE_INFINITY) {
2
+ let max = init
3
+ for (const entry of arr) {
4
+ max = Math.max(entry, max)
5
+ }
6
+ return max
7
+ }
@@ -1,8 +1,9 @@
1
1
  import PluginManager from '@jbrowse/core/PluginManager'
2
2
  import { DisplayType } from '@jbrowse/core/pluggableElementTypes'
3
+
4
+ import ReactComponent from './components/ReactComponent'
3
5
  import configSchemaF from './configSchema'
4
6
  import stateModelFactory from './stateModel'
5
- import ReactComponent from './components/ReactComponent'
6
7
 
7
8
  export default function LinearMafDisplayF(pluginManager: PluginManager) {
8
9
  pluginManager.addDisplayType(() => {
@@ -1,4 +1,5 @@
1
1
  import React from 'react'
2
+
2
3
  import { getContainingView } from '@jbrowse/core/util'
3
4
  import {
4
5
  ExportSvgDisplayOptions,
@@ -6,8 +7,8 @@ import {
6
7
  } from '@jbrowse/plugin-linear-genome-view'
7
8
 
8
9
  // locals
9
- import { LinearMafDisplayModel } from './stateModel'
10
10
  import YScaleBars from './components/YScaleBars'
11
+ import { LinearMafDisplayModel } from './stateModel'
11
12
 
12
13
  export async function renderSvg(
13
14
  self: LinearMafDisplayModel,