jbrowse-plugin-mafviewer 1.2.3 → 1.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BgzipTaffyAdapter/BgzipTaffyAdapter.d.ts +1 -1
- package/dist/BigMafAdapter/BigMafAdapter.d.ts +1 -1
- package/dist/BigMafAdapter/BigMafAdapter.js +50 -49
- package/dist/BigMafAdapter/BigMafAdapter.js.map +1 -1
- package/dist/LinearMafDisplay/components/ColorLegend.d.ts +2 -4
- package/dist/LinearMafDisplay/components/ColorLegend.js +2 -3
- package/dist/LinearMafDisplay/components/ColorLegend.js.map +1 -1
- package/dist/LinearMafDisplay/components/{ReactComponent.d.ts → LinearMafDisplayComponent.d.ts} +1 -1
- package/dist/LinearMafDisplay/components/{ReactComponent.js → LinearMafDisplayComponent.js} +2 -2
- package/dist/LinearMafDisplay/components/LinearMafDisplayComponent.js.map +1 -0
- package/dist/LinearMafDisplay/components/SetRowHeightDialog.js +38 -0
- package/dist/LinearMafDisplay/components/SetRowHeightDialog.js.map +1 -0
- package/dist/LinearMafDisplay/components/SvgWrapper.d.ts +1 -1
- package/dist/LinearMafDisplay/components/SvgWrapper.js.map +1 -1
- package/dist/LinearMafDisplay/components/Tree.d.ts +2 -1
- package/dist/LinearMafDisplay/components/Tree.js +2 -0
- package/dist/LinearMafDisplay/components/Tree.js.map +1 -1
- package/dist/LinearMafDisplay/components/YScaleBars.d.ts +1 -1
- package/dist/LinearMafDisplay/components/YScaleBars.js +1 -10
- package/dist/LinearMafDisplay/components/YScaleBars.js.map +1 -1
- package/dist/LinearMafDisplay/index.js +1 -1
- package/dist/LinearMafDisplay/index.js.map +1 -1
- package/dist/LinearMafDisplay/stateModel.d.ts +20 -19
- package/dist/LinearMafDisplay/stateModel.js +42 -7
- package/dist/LinearMafDisplay/stateModel.js.map +1 -1
- package/dist/LinearMafDisplay/types.d.ts +5 -3
- package/dist/LinearMafDisplay/types.js +1 -15
- package/dist/LinearMafDisplay/types.js.map +1 -1
- package/dist/LinearMafDisplay/util.d.ts +4 -0
- package/dist/LinearMafDisplay/util.js +16 -0
- package/dist/LinearMafDisplay/util.js.map +1 -0
- package/dist/LinearMafRenderer/LinearMafRenderer.d.ts +4 -4
- package/dist/LinearMafRenderer/LinearMafRenderer.js +8 -10
- package/dist/LinearMafRenderer/LinearMafRenderer.js.map +1 -1
- package/dist/LinearMafRenderer/makeImageData.js +18 -16
- package/dist/LinearMafRenderer/makeImageData.js.map +1 -1
- package/dist/MafAddTrackWorkflow/index.js +0 -1
- package/dist/MafAddTrackWorkflow/index.js.map +1 -1
- package/dist/MafTabixAdapter/MafTabixAdapter.d.ts +1 -1
- package/dist/MafTabixAdapter/MafTabixAdapter.js +6 -7
- package/dist/MafTabixAdapter/MafTabixAdapter.js.map +1 -1
- package/dist/MafTabixAdapter/configSchema.js +29 -1
- package/dist/MafTabixAdapter/configSchema.js.map +1 -1
- package/dist/jbrowse-plugin-mafviewer.umd.production.min.js +7 -20
- package/dist/jbrowse-plugin-mafviewer.umd.production.min.js.map +4 -4
- package/dist/util.d.ts +2 -2
- package/dist/util.js +5 -1
- package/dist/util.js.map +1 -1
- package/package.json +10 -10
- package/src/BigMafAdapter/BigMafAdapter.ts +52 -49
- package/src/LinearMafDisplay/components/ColorLegend.tsx +11 -7
- package/src/LinearMafDisplay/components/{ReactComponent.tsx → LinearMafDisplayComponent.tsx} +2 -2
- package/src/LinearMafDisplay/components/SetRowHeightDialog.tsx +83 -0
- package/src/LinearMafDisplay/components/SvgWrapper.tsx +1 -2
- package/src/LinearMafDisplay/components/Tree.tsx +5 -1
- package/src/LinearMafDisplay/components/YScaleBars.tsx +3 -21
- package/src/LinearMafDisplay/index.ts +1 -1
- package/src/LinearMafDisplay/stateModel.ts +49 -18
- package/src/LinearMafDisplay/types.ts +4 -24
- package/src/LinearMafDisplay/util.ts +27 -0
- package/src/LinearMafRenderer/LinearMafRenderer.ts +9 -14
- package/src/LinearMafRenderer/makeImageData.ts +18 -17
- package/src/MafAddTrackWorkflow/index.ts +0 -1
- package/src/MafTabixAdapter/MafTabixAdapter.ts +9 -7
- package/src/MafTabixAdapter/configSchema.ts +29 -1
- package/src/util.ts +6 -2
- package/dist/LinearMafDisplay/components/ReactComponent.js.map +0 -1
- package/dist/LinearMafDisplay/components/SetRowHeight.js +0 -36
- package/dist/LinearMafDisplay/components/SetRowHeight.js.map +0 -1
- package/src/LinearMafDisplay/components/SetRowHeight.tsx +0 -83
- /package/dist/LinearMafDisplay/components/{SetRowHeight.d.ts → SetRowHeightDialog.d.ts} +0 -0
package/dist/util.d.ts
CHANGED
package/dist/util.js
CHANGED
|
@@ -3,7 +3,11 @@ function isStrs(array) {
|
|
|
3
3
|
}
|
|
4
4
|
export function normalize(r) {
|
|
5
5
|
return isStrs(r)
|
|
6
|
-
? r.map(elt => ({
|
|
6
|
+
? r.map(elt => ({
|
|
7
|
+
id: elt,
|
|
8
|
+
label: elt,
|
|
9
|
+
color: undefined,
|
|
10
|
+
}))
|
|
7
11
|
: r;
|
|
8
12
|
}
|
|
9
13
|
//# sourceMappingURL=util.js.map
|
package/dist/util.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,SAAS,MAAM,CAAC,KAAgB;IAC9B,OAAO,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAA;AACrC,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,SAAS,MAAM,CAAC,KAAgB;IAC9B,OAAO,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAA;AACrC,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,CAA8D;IAE9D,OAAO,MAAM,CAAC,CAAC,CAAC;QACd,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACZ,EAAE,EAAE,GAAG;YACP,KAAK,EAAE,GAAG;YACV,KAAK,EAAE,SAAS;SACjB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC,CAAA;AACP,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.2.
|
|
2
|
+
"version": "1.2.4",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"name": "jbrowse-plugin-mafviewer",
|
|
5
5
|
"keywords": [
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
"@jbrowse/core": "^3.0.1",
|
|
32
32
|
"@jbrowse/plugin-data-management": "^3.0.1",
|
|
33
33
|
"@jbrowse/plugin-linear-genome-view": "^3.0.1",
|
|
34
|
-
"@mui/material": "^
|
|
35
|
-
"@mui/system": "^
|
|
36
|
-
"@mui/x-data-grid": "^
|
|
34
|
+
"@mui/material": "^7.0.1",
|
|
35
|
+
"@mui/system": "^7.0.1",
|
|
36
|
+
"@mui/x-data-grid": "^8.2.0",
|
|
37
37
|
"@types/d3-array": "^3.2.1",
|
|
38
38
|
"@types/d3-hierarchy": "^3.1.7",
|
|
39
|
-
"@types/node": "^22.
|
|
39
|
+
"@types/node": "^22.15.16",
|
|
40
40
|
"@types/react": "^19.0.1",
|
|
41
41
|
"@typescript-eslint/eslint-plugin": "^8.18.0",
|
|
42
42
|
"@typescript-eslint/parser": "^8.18.0",
|
|
@@ -46,29 +46,29 @@
|
|
|
46
46
|
"eslint-plugin-import": "^2.31.0",
|
|
47
47
|
"eslint-plugin-react": "^7.20.3",
|
|
48
48
|
"eslint-plugin-react-hooks": "^5.1.0",
|
|
49
|
-
"eslint-plugin-unicorn": "^
|
|
49
|
+
"eslint-plugin-unicorn": "^59.0.1",
|
|
50
50
|
"mobx": "^6.0.0",
|
|
51
51
|
"mobx-react": "^9.0.1",
|
|
52
52
|
"mobx-state-tree": "^5.4.1",
|
|
53
53
|
"prettier": "^3.4.2",
|
|
54
|
-
"pretty-bytes": "^
|
|
54
|
+
"pretty-bytes": "^7.0.0",
|
|
55
55
|
"react": "^19.0.0",
|
|
56
56
|
"react-dom": "^19.0.0",
|
|
57
57
|
"rimraf": "^6.0.1",
|
|
58
58
|
"rxjs": "^7.8.1",
|
|
59
59
|
"serve": "^14.2.0",
|
|
60
|
-
"tss-react": "^4.
|
|
60
|
+
"tss-react": "^4.9.18",
|
|
61
61
|
"typescript": "^5.1.6",
|
|
62
62
|
"typescript-eslint": "^8.18.0"
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@gmod/bgzf-filehandle": "^
|
|
65
|
+
"@gmod/bgzf-filehandle": "^3.0.2",
|
|
66
66
|
"abortable-promise-cache": "^1.5.0",
|
|
67
67
|
"buffer": "^6.0.3",
|
|
68
68
|
"d3-array": "^3.2.4",
|
|
69
69
|
"d3-hierarchy": "^3.1.2",
|
|
70
70
|
"fast-deep-equal": "^3.1.3",
|
|
71
|
-
"generic-filehandle2": "^
|
|
71
|
+
"generic-filehandle2": "^2.0.1",
|
|
72
72
|
"long": "^5.2.3"
|
|
73
73
|
}
|
|
74
74
|
}
|
|
@@ -26,12 +26,13 @@ export default class BigMafAdapter extends BaseFeatureDataAdapter {
|
|
|
26
26
|
if (!this.getSubAdapter) {
|
|
27
27
|
throw new Error('no getSubAdapter available')
|
|
28
28
|
}
|
|
29
|
-
const adapter = await this.getSubAdapter({
|
|
30
|
-
...getSnapshot(this.config),
|
|
31
|
-
type: 'BigBedAdapter',
|
|
32
|
-
})
|
|
33
29
|
return {
|
|
34
|
-
adapter:
|
|
30
|
+
adapter: (
|
|
31
|
+
await this.getSubAdapter({
|
|
32
|
+
...getSnapshot(this.config),
|
|
33
|
+
type: 'BigBedAdapter',
|
|
34
|
+
})
|
|
35
|
+
).dataAdapter as BaseFeatureDataAdapter,
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
38
|
async setupPre() {
|
|
@@ -59,59 +60,61 @@ export default class BigMafAdapter extends BaseFeatureDataAdapter {
|
|
|
59
60
|
return ObservableCreate<Feature>(async observer => {
|
|
60
61
|
const { adapter } = await this.setup()
|
|
61
62
|
const features = await updateStatus(
|
|
62
|
-
'Downloading
|
|
63
|
+
'Downloading alignments',
|
|
63
64
|
statusCallback,
|
|
64
65
|
() => firstValueFrom(adapter.getFeatures(query).pipe(toArray())),
|
|
65
66
|
)
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
67
|
+
await updateStatus('Processing alignments', statusCallback, () => {
|
|
68
|
+
for (const feature of features) {
|
|
69
|
+
const maf = feature.get('mafBlock') as string
|
|
70
|
+
const blocks = maf.split(';')
|
|
71
|
+
let aln: string | undefined
|
|
72
|
+
const alns = [] as string[]
|
|
73
|
+
const alignments = {} as Record<string, OrganismRecord>
|
|
74
|
+
const blocks2 = [] as string[]
|
|
75
|
+
for (const block of blocks) {
|
|
76
|
+
if (block.startsWith('s')) {
|
|
77
|
+
if (aln) {
|
|
78
|
+
alns.push(block.split(/ +/)[6]!)
|
|
79
|
+
blocks2.push(block)
|
|
80
|
+
} else {
|
|
81
|
+
aln = block.split(/ +/)[6]
|
|
82
|
+
alns.push(aln!)
|
|
83
|
+
blocks2.push(block)
|
|
84
|
+
}
|
|
82
85
|
}
|
|
83
86
|
}
|
|
84
|
-
}
|
|
85
87
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
for (let i = 0; i < blocks2.length; i++) {
|
|
89
|
+
const elt = blocks2[i]!
|
|
90
|
+
const ad = elt.split(/ +/)
|
|
91
|
+
const y = ad[1]!.split('.')
|
|
92
|
+
const org = y[0]!
|
|
93
|
+
const chr = y[1]!
|
|
92
94
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
95
|
+
alignments[org] = {
|
|
96
|
+
chr: chr,
|
|
97
|
+
start: +ad[1]!,
|
|
98
|
+
srcSize: +ad[2]!,
|
|
99
|
+
strand: ad[3] === '+' ? 1 : -1,
|
|
100
|
+
unknown: +ad[4]!,
|
|
101
|
+
data: alns[i]!,
|
|
102
|
+
}
|
|
100
103
|
}
|
|
104
|
+
observer.next(
|
|
105
|
+
new SimpleFeature({
|
|
106
|
+
id: feature.id(),
|
|
107
|
+
data: {
|
|
108
|
+
start: feature.get('start'),
|
|
109
|
+
end: feature.get('end'),
|
|
110
|
+
refName: feature.get('refName'),
|
|
111
|
+
seq: alns[0],
|
|
112
|
+
alignments: alignments,
|
|
113
|
+
},
|
|
114
|
+
}),
|
|
115
|
+
)
|
|
101
116
|
}
|
|
102
|
-
|
|
103
|
-
new SimpleFeature({
|
|
104
|
-
id: feature.id(),
|
|
105
|
-
data: {
|
|
106
|
-
start: feature.get('start'),
|
|
107
|
-
end: feature.get('end'),
|
|
108
|
-
refName: feature.get('refName'),
|
|
109
|
-
seq: alns[0],
|
|
110
|
-
alignments: alignments,
|
|
111
|
-
},
|
|
112
|
-
}),
|
|
113
|
-
)
|
|
114
|
-
}
|
|
117
|
+
})
|
|
115
118
|
observer.complete()
|
|
116
119
|
})
|
|
117
120
|
}
|
|
@@ -2,21 +2,25 @@ import React from 'react'
|
|
|
2
2
|
|
|
3
3
|
import { observer } from 'mobx-react'
|
|
4
4
|
|
|
5
|
-
import { LinearMafDisplayModel } from '../stateModel'
|
|
6
5
|
import RectBg from './RectBg'
|
|
7
6
|
import Tree from './Tree'
|
|
8
7
|
|
|
8
|
+
import type { LinearMafDisplayModel } from '../stateModel'
|
|
9
|
+
|
|
9
10
|
const ColorLegend = observer(function ({
|
|
10
11
|
model,
|
|
11
|
-
labelWidth,
|
|
12
|
-
svgFontSize,
|
|
13
12
|
}: {
|
|
14
13
|
model: LinearMafDisplayModel
|
|
15
|
-
svgFontSize: number
|
|
16
|
-
labelWidth: number
|
|
17
14
|
}) {
|
|
18
|
-
const {
|
|
19
|
-
|
|
15
|
+
const {
|
|
16
|
+
labelWidth,
|
|
17
|
+
canDisplayLabel,
|
|
18
|
+
totalHeight,
|
|
19
|
+
treeWidth,
|
|
20
|
+
samples = [],
|
|
21
|
+
rowHeight,
|
|
22
|
+
svgFontSize,
|
|
23
|
+
} = model
|
|
20
24
|
const boxHeight = Math.min(20, rowHeight)
|
|
21
25
|
|
|
22
26
|
return (
|
package/src/LinearMafDisplay/components/{ReactComponent.tsx → LinearMafDisplayComponent.tsx}
RENAMED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import React, { useRef, useState } from 'react'
|
|
2
2
|
|
|
3
|
+
import { SanitizedHTML } from '@jbrowse/core/ui'
|
|
3
4
|
import BaseTooltip from '@jbrowse/core/ui/BaseTooltip'
|
|
4
|
-
import SanitizedHTML from '@jbrowse/core/ui/SanitizedHTML'
|
|
5
5
|
import { getContainingView, getEnv } from '@jbrowse/core/util'
|
|
6
6
|
import { observer } from 'mobx-react'
|
|
7
7
|
import { makeStyles } from 'tss-react/mui'
|
|
8
8
|
|
|
9
9
|
import YScaleBars from './YScaleBars'
|
|
10
|
-
import { LinearMafDisplayModel } from '../stateModel'
|
|
11
10
|
|
|
11
|
+
import type { LinearMafDisplayModel } from '../stateModel'
|
|
12
12
|
import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
|
|
13
13
|
|
|
14
14
|
const useStyles = makeStyles()({
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
|
+
|
|
3
|
+
import { Dialog } from '@jbrowse/core/ui'
|
|
4
|
+
import {
|
|
5
|
+
Button,
|
|
6
|
+
DialogActions,
|
|
7
|
+
DialogContent,
|
|
8
|
+
TextField,
|
|
9
|
+
Typography,
|
|
10
|
+
} from '@mui/material'
|
|
11
|
+
import { observer } from 'mobx-react'
|
|
12
|
+
import { makeStyles } from 'tss-react/mui'
|
|
13
|
+
|
|
14
|
+
const useStyles = makeStyles()({
|
|
15
|
+
root: {
|
|
16
|
+
width: 500,
|
|
17
|
+
},
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
const SetRowHeightDialog = observer(function (props: {
|
|
21
|
+
model: {
|
|
22
|
+
rowHeight?: number
|
|
23
|
+
rowProportion?: number
|
|
24
|
+
setRowHeight: (arg: number) => void
|
|
25
|
+
setRowProportion: (arg: number) => void
|
|
26
|
+
}
|
|
27
|
+
handleClose: () => void
|
|
28
|
+
}) {
|
|
29
|
+
const { model, handleClose } = props
|
|
30
|
+
const { classes } = useStyles()
|
|
31
|
+
const [rowHeight, setRowHeight] = useState(`${model.rowHeight}`)
|
|
32
|
+
const [rowProportion, setRowProportion] = useState(`${model.rowProportion}`)
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<Dialog open onClose={handleClose} title="Set row height">
|
|
36
|
+
<form
|
|
37
|
+
onSubmit={event => {
|
|
38
|
+
event.preventDefault()
|
|
39
|
+
model.setRowProportion(+rowProportion)
|
|
40
|
+
model.setRowHeight(+rowHeight)
|
|
41
|
+
handleClose()
|
|
42
|
+
}}
|
|
43
|
+
>
|
|
44
|
+
<DialogContent className={classes.root}>
|
|
45
|
+
<Typography>
|
|
46
|
+
Set row height and the proportion of the row height to use for
|
|
47
|
+
drawing each row
|
|
48
|
+
</Typography>
|
|
49
|
+
<TextField
|
|
50
|
+
value={rowHeight}
|
|
51
|
+
helperText="Enter row height"
|
|
52
|
+
autoFocus
|
|
53
|
+
onChange={event => {
|
|
54
|
+
setRowHeight(event.target.value)
|
|
55
|
+
}}
|
|
56
|
+
/>
|
|
57
|
+
<TextField
|
|
58
|
+
value={rowProportion}
|
|
59
|
+
helperText="Enter row proportion"
|
|
60
|
+
onChange={event => {
|
|
61
|
+
setRowProportion(event.target.value)
|
|
62
|
+
}}
|
|
63
|
+
/>
|
|
64
|
+
<DialogActions>
|
|
65
|
+
<Button variant="contained" color="primary" type="submit">
|
|
66
|
+
Submit
|
|
67
|
+
</Button>
|
|
68
|
+
<Button
|
|
69
|
+
variant="contained"
|
|
70
|
+
color="secondary"
|
|
71
|
+
onClick={() => {
|
|
72
|
+
handleClose()
|
|
73
|
+
}}
|
|
74
|
+
>
|
|
75
|
+
Cancel
|
|
76
|
+
</Button>
|
|
77
|
+
</DialogActions>
|
|
78
|
+
</DialogContent>
|
|
79
|
+
</form>
|
|
80
|
+
</Dialog>
|
|
81
|
+
)
|
|
82
|
+
})
|
|
83
|
+
export default SetRowHeightDialog
|
|
@@ -3,8 +3,7 @@ import React from 'react'
|
|
|
3
3
|
import { getContainingView } from '@jbrowse/core/util'
|
|
4
4
|
import { observer } from 'mobx-react'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
import { LinearMafDisplayModel } from '../stateModel'
|
|
6
|
+
import type { LinearMafDisplayModel } from '../stateModel'
|
|
8
7
|
|
|
9
8
|
const SvgWrapper = observer(function ({
|
|
10
9
|
children,
|
|
@@ -2,7 +2,9 @@ import React from 'react'
|
|
|
2
2
|
|
|
3
3
|
import { observer } from 'mobx-react'
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
import type { LinearMafDisplayModel } from '../stateModel'
|
|
6
|
+
|
|
7
|
+
const Tree = observer(function ({ model }: { model: LinearMafDisplayModel }) {
|
|
6
8
|
const {
|
|
7
9
|
// this is needed for redrawing after zoom change, similar to react-msaview
|
|
8
10
|
// renderTreeCanvas
|
|
@@ -20,7 +22,9 @@ const Tree = observer(function ({ model }: { model: any }) {
|
|
|
20
22
|
const { source, target } = link
|
|
21
23
|
const sy = source.x!
|
|
22
24
|
const ty = target.x!
|
|
25
|
+
// @ts-expect-error
|
|
23
26
|
const tx = showBranchLen ? target.len : target.y
|
|
27
|
+
// @ts-expect-error
|
|
24
28
|
const sx = showBranchLen ? source.len : source.y
|
|
25
29
|
|
|
26
30
|
// 1d line intersection to check if line crosses block at all, this is
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
|
|
3
|
-
import { measureText } from '@jbrowse/core/util'
|
|
4
3
|
import { observer } from 'mobx-react'
|
|
5
4
|
|
|
6
|
-
// locals
|
|
7
|
-
import { LinearMafDisplayModel } from '../stateModel'
|
|
8
5
|
import ColorLegend from './ColorLegend'
|
|
9
6
|
import SvgWrapper from './SvgWrapper'
|
|
10
|
-
|
|
7
|
+
|
|
8
|
+
import type { LinearMafDisplayModel } from '../stateModel'
|
|
11
9
|
|
|
12
10
|
export const YScaleBars = observer(function (props: {
|
|
13
11
|
model: LinearMafDisplayModel
|
|
@@ -15,25 +13,9 @@ export const YScaleBars = observer(function (props: {
|
|
|
15
13
|
exportSVG?: boolean
|
|
16
14
|
}) {
|
|
17
15
|
const { model } = props
|
|
18
|
-
const { rowHeight, samples } = model
|
|
19
|
-
const svgFontSize = Math.min(Math.max(rowHeight, 8), 14)
|
|
20
|
-
const canDisplayLabel = rowHeight >= 8
|
|
21
|
-
const minWidth = 20
|
|
22
|
-
|
|
23
|
-
const labelWidth = max(
|
|
24
|
-
samples
|
|
25
|
-
?.map(s => measureText(s.label, svgFontSize))
|
|
26
|
-
.map(width => (canDisplayLabel ? width : minWidth)) || [],
|
|
27
|
-
0,
|
|
28
|
-
)
|
|
29
|
-
|
|
30
16
|
return (
|
|
31
17
|
<SvgWrapper {...props}>
|
|
32
|
-
<ColorLegend
|
|
33
|
-
model={model}
|
|
34
|
-
labelWidth={labelWidth}
|
|
35
|
-
svgFontSize={svgFontSize}
|
|
36
|
-
/>
|
|
18
|
+
<ColorLegend model={model} />
|
|
37
19
|
</SvgWrapper>
|
|
38
20
|
)
|
|
39
21
|
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import PluginManager from '@jbrowse/core/PluginManager'
|
|
2
2
|
import { DisplayType } from '@jbrowse/core/pluggableElementTypes'
|
|
3
3
|
|
|
4
|
-
import ReactComponent from './components/
|
|
4
|
+
import ReactComponent from './components/LinearMafDisplayComponent'
|
|
5
5
|
import configSchemaF from './configSchema'
|
|
6
6
|
import stateModelFactory from './stateModel'
|
|
7
7
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { lazy } from 'react'
|
|
2
|
+
|
|
1
3
|
import { ConfigurationReference, getConf } from '@jbrowse/core/configuration'
|
|
2
|
-
import { getEnv, getSession } from '@jbrowse/core/util'
|
|
4
|
+
import { getEnv, getSession, max, measureText } from '@jbrowse/core/util'
|
|
3
5
|
import { getRpcSessionId } from '@jbrowse/core/util/tracks'
|
|
4
6
|
import { ascending } from 'd3-array'
|
|
5
7
|
import { cluster, hierarchy } from 'd3-hierarchy'
|
|
@@ -7,11 +9,10 @@ import deepEqual from 'fast-deep-equal'
|
|
|
7
9
|
import { autorun } from 'mobx'
|
|
8
10
|
import { addDisposer, isAlive, types } from 'mobx-state-tree'
|
|
9
11
|
|
|
10
|
-
import
|
|
11
|
-
import { maxLength, setBrLength } from './types'
|
|
12
|
+
import { maxLength, setBrLength } from './util'
|
|
12
13
|
import { normalize } from '../util'
|
|
13
14
|
|
|
14
|
-
import type { NodeWithIds, NodeWithIdsAndLength } from './types'
|
|
15
|
+
import type { NodeWithIds, NodeWithIdsAndLength, Sample } from './types'
|
|
15
16
|
import type PluginManager from '@jbrowse/core/PluginManager'
|
|
16
17
|
import type {
|
|
17
18
|
AnyConfigurationModel,
|
|
@@ -21,11 +22,7 @@ import type { ExportSvgDisplayOptions } from '@jbrowse/plugin-linear-genome-view
|
|
|
21
22
|
import type { HierarchyNode } from 'd3-hierarchy'
|
|
22
23
|
import type { Instance } from 'mobx-state-tree'
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
id: string
|
|
26
|
-
label: string
|
|
27
|
-
color?: string
|
|
28
|
-
}
|
|
25
|
+
const SetRowHeightDialog = lazy(() => import('./components/SetRowHeightDialog'))
|
|
29
26
|
|
|
30
27
|
/**
|
|
31
28
|
* #stateModel LinearMafDisplay
|
|
@@ -193,8 +190,20 @@ export default function stateModelFactory(
|
|
|
193
190
|
* #getter
|
|
194
191
|
*/
|
|
195
192
|
get samples() {
|
|
196
|
-
|
|
193
|
+
if (this.rowNames) {
|
|
194
|
+
const volatileSamplesMap = self.volatileSamples
|
|
195
|
+
? Object.fromEntries(self.volatileSamples.map(e => [e.id, e]))
|
|
196
|
+
: undefined
|
|
197
|
+
return normalize(this.rowNames).map(r => ({
|
|
198
|
+
...r,
|
|
199
|
+
label: volatileSamplesMap?.[r.id]?.label || r.label,
|
|
200
|
+
color: volatileSamplesMap?.[r.id]?.color || r.color,
|
|
201
|
+
}))
|
|
202
|
+
} else {
|
|
203
|
+
return self.volatileSamples
|
|
204
|
+
}
|
|
197
205
|
},
|
|
206
|
+
|
|
198
207
|
/**
|
|
199
208
|
* #getter
|
|
200
209
|
*/
|
|
@@ -311,6 +320,32 @@ export default function stateModelFactory(
|
|
|
311
320
|
},
|
|
312
321
|
}
|
|
313
322
|
})
|
|
323
|
+
.views(self => ({
|
|
324
|
+
/**
|
|
325
|
+
* #getter
|
|
326
|
+
*/
|
|
327
|
+
get svgFontSize() {
|
|
328
|
+
return Math.min(Math.max(self.rowHeight, 8), 14)
|
|
329
|
+
},
|
|
330
|
+
/**
|
|
331
|
+
* #getter
|
|
332
|
+
*/
|
|
333
|
+
get canDisplayLabel() {
|
|
334
|
+
return self.rowHeight >= 7
|
|
335
|
+
},
|
|
336
|
+
/**
|
|
337
|
+
* #getter
|
|
338
|
+
*/
|
|
339
|
+
get labelWidth() {
|
|
340
|
+
const minWidth = 20
|
|
341
|
+
return max(
|
|
342
|
+
self.samples
|
|
343
|
+
?.map(s => measureText(s.label, this.svgFontSize))
|
|
344
|
+
.map(width => (this.canDisplayLabel ? width : minWidth)) || [],
|
|
345
|
+
0,
|
|
346
|
+
)
|
|
347
|
+
},
|
|
348
|
+
}))
|
|
314
349
|
.actions(self => ({
|
|
315
350
|
afterCreate() {
|
|
316
351
|
addDisposer(
|
|
@@ -319,11 +354,8 @@ export default function stateModelFactory(
|
|
|
319
354
|
try {
|
|
320
355
|
const { rpcManager } = getSession(self)
|
|
321
356
|
const sessionId = getRpcSessionId(self)
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
sessionId,
|
|
325
|
-
'MafGetSamples',
|
|
326
|
-
{
|
|
357
|
+
self.setSamples(
|
|
358
|
+
(await rpcManager.call(sessionId, 'MafGetSamples', {
|
|
327
359
|
sessionId,
|
|
328
360
|
adapterConfig: self.adapterConfig,
|
|
329
361
|
statusCallback: (message: string) => {
|
|
@@ -331,9 +363,8 @@ export default function stateModelFactory(
|
|
|
331
363
|
self.setMessage(message)
|
|
332
364
|
}
|
|
333
365
|
},
|
|
334
|
-
},
|
|
335
|
-
)
|
|
336
|
-
self.setSamples(results)
|
|
366
|
+
})) as { samples: Sample[]; tree: unknown },
|
|
367
|
+
)
|
|
337
368
|
} catch (e) {
|
|
338
369
|
console.error(e)
|
|
339
370
|
getSession(self).notifyError(`${e}`, e)
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import { max } from 'd3-array'
|
|
2
|
-
|
|
3
|
-
import type { HierarchyNode } from 'd3-hierarchy'
|
|
4
|
-
|
|
5
1
|
export interface NodeWithIds {
|
|
6
2
|
id: string
|
|
7
3
|
name: string
|
|
@@ -18,24 +14,8 @@ export interface NodeWithIdsAndLength {
|
|
|
18
14
|
length: number
|
|
19
15
|
}
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
)
|
|
26
|
-
}
|
|
27
|
-
// basically same as setRadius from https://observablehq.com/@d3/tree-of-life
|
|
28
|
-
export function setBrLength(
|
|
29
|
-
d: HierarchyNode<NodeWithIds>,
|
|
30
|
-
y0: number,
|
|
31
|
-
k: number,
|
|
32
|
-
) {
|
|
33
|
-
// @ts-expect-error
|
|
34
|
-
d.len = (y0 += Math.max(d.data.length || 0, 0)) * k
|
|
35
|
-
|
|
36
|
-
if (d.children) {
|
|
37
|
-
d.children.forEach(d => {
|
|
38
|
-
setBrLength(d, y0, k)
|
|
39
|
-
})
|
|
40
|
-
}
|
|
17
|
+
export interface Sample {
|
|
18
|
+
id: string
|
|
19
|
+
label: string
|
|
20
|
+
color?: string
|
|
41
21
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { max } from 'd3-array'
|
|
2
|
+
|
|
3
|
+
import type { NodeWithIds } from './types'
|
|
4
|
+
import type { HierarchyNode } from 'd3-hierarchy'
|
|
5
|
+
|
|
6
|
+
// basically same as maxLength from https://observablehq.com/@d3/tree-of-life
|
|
7
|
+
export function maxLength(d: HierarchyNode<NodeWithIds>): number {
|
|
8
|
+
return (
|
|
9
|
+
(d.data.length || 0) + (d.children ? max(d.children, maxLength) || 0 : 0)
|
|
10
|
+
)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// basically same as setRadius from https://observablehq.com/@d3/tree-of-life
|
|
14
|
+
export function setBrLength(
|
|
15
|
+
d: HierarchyNode<NodeWithIds>,
|
|
16
|
+
y0: number,
|
|
17
|
+
k: number,
|
|
18
|
+
) {
|
|
19
|
+
// @ts-expect-error
|
|
20
|
+
d.len = (y0 += Math.max(d.data.length || 0, 0)) * k
|
|
21
|
+
|
|
22
|
+
if (d.children) {
|
|
23
|
+
d.children.forEach(d => {
|
|
24
|
+
setBrLength(d, y0, k)
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -45,22 +45,17 @@ export default class LinearMafRenderer extends FeatureRendererType {
|
|
|
45
45
|
const height = samples.length * rowHeight + 100
|
|
46
46
|
const width = (region.end - region.start) / bpPerPx
|
|
47
47
|
const features = await this.getFeatures(renderProps)
|
|
48
|
-
const res = await
|
|
49
|
-
width,
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
renderArgs: {
|
|
57
|
-
...renderProps,
|
|
58
|
-
features,
|
|
59
|
-
},
|
|
60
|
-
})
|
|
48
|
+
const res = await updateStatus('Rendering alignment', statusCallback, () =>
|
|
49
|
+
renderToAbstractCanvas(width, height, renderProps, ctx => {
|
|
50
|
+
makeImageData({
|
|
51
|
+
ctx,
|
|
52
|
+
renderArgs: {
|
|
53
|
+
...renderProps,
|
|
54
|
+
features,
|
|
55
|
+
},
|
|
61
56
|
})
|
|
62
57
|
return undefined
|
|
63
|
-
},
|
|
58
|
+
}),
|
|
64
59
|
)
|
|
65
60
|
const results = await super.render({
|
|
66
61
|
...renderProps,
|