jbrowse-plugin-mafviewer 1.2.2 → 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/README.md +6 -1
- package/dist/BgzipTaffyAdapter/BgzipTaffyAdapter.d.ts +12 -3
- package/dist/BgzipTaffyAdapter/BgzipTaffyAdapter.js +123 -94
- package/dist/BgzipTaffyAdapter/BgzipTaffyAdapter.js.map +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 +9 -11
- package/dist/LinearMafRenderer/LinearMafRenderer.js.map +1 -1
- package/dist/LinearMafRenderer/makeImageData.js +35 -17
- package/dist/LinearMafRenderer/makeImageData.js.map +1 -1
- package/dist/MafAddTrackWorkflow/AddTrackWorkflow.js +1 -1
- package/dist/MafAddTrackWorkflow/AddTrackWorkflow.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 -19
- 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 +11 -10
- package/src/BgzipTaffyAdapter/BgzipTaffyAdapter.ts +135 -99
- 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 +10 -15
- package/src/LinearMafRenderer/makeImageData.ts +48 -18
- package/src/MafAddTrackWorkflow/AddTrackWorkflow.tsx +9 -11
- 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
|
@@ -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
|
+
}
|
|
@@ -42,25 +42,20 @@ export default class LinearMafRenderer extends FeatureRendererType {
|
|
|
42
42
|
rowHeight,
|
|
43
43
|
} = renderProps
|
|
44
44
|
const region = regions[0]!
|
|
45
|
-
const height = samples.length *
|
|
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,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RenderArgsDeserialized } from '@jbrowse/core/pluggableElementTypes/renderers/BoxRendererType'
|
|
2
2
|
import { createJBrowseTheme } from '@jbrowse/core/ui'
|
|
3
|
-
import { Feature, featureSpanPx } from '@jbrowse/core/util'
|
|
3
|
+
import { Feature, featureSpanPx, measureText } from '@jbrowse/core/util'
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
6
|
fillRect,
|
|
@@ -74,11 +74,12 @@ export function makeImageData({
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
const t = rowHeight * row
|
|
77
|
+
const t2 = offset + t
|
|
77
78
|
|
|
78
79
|
// gaps
|
|
79
80
|
ctx.beginPath()
|
|
80
81
|
ctx.fillStyle = 'black'
|
|
81
|
-
for (let i = 0, o = 0
|
|
82
|
+
for (let i = 0, o = 0, l = alignment.length; i < l; i++) {
|
|
82
83
|
if (seq[i] !== '-') {
|
|
83
84
|
if (alignment[i] === '-') {
|
|
84
85
|
const l = leftPx + scale * o
|
|
@@ -93,12 +94,12 @@ export function makeImageData({
|
|
|
93
94
|
if (!showAllLetters) {
|
|
94
95
|
// matches
|
|
95
96
|
ctx.fillStyle = 'lightgrey'
|
|
96
|
-
for (let i = 0, o = 0
|
|
97
|
+
for (let i = 0, o = 0, l = alignment.length; i < l; i++) {
|
|
97
98
|
if (seq[i] !== '-') {
|
|
98
99
|
const c = alignment[i]
|
|
99
100
|
const l = leftPx + scale * o
|
|
100
|
-
if (seq[i] === c && c !== '-') {
|
|
101
|
-
fillRect(ctx, l,
|
|
101
|
+
if (seq[i] === c && c !== '-' && c !== ' ') {
|
|
102
|
+
fillRect(ctx, l, t2, scale + f, h, canvasWidth)
|
|
102
103
|
}
|
|
103
104
|
o++
|
|
104
105
|
}
|
|
@@ -106,7 +107,7 @@ export function makeImageData({
|
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
// mismatches
|
|
109
|
-
for (let i = 0, o = 0
|
|
110
|
+
for (let i = 0, o = 0, l = alignment.length; i < l; i++) {
|
|
110
111
|
const c = alignment[i]
|
|
111
112
|
if (seq[i] !== '-') {
|
|
112
113
|
if (c !== '-') {
|
|
@@ -115,7 +116,7 @@ export function makeImageData({
|
|
|
115
116
|
fillRect(
|
|
116
117
|
ctx,
|
|
117
118
|
l,
|
|
118
|
-
|
|
119
|
+
t2,
|
|
119
120
|
scale + f,
|
|
120
121
|
h,
|
|
121
122
|
canvasWidth,
|
|
@@ -128,7 +129,7 @@ export function makeImageData({
|
|
|
128
129
|
fillRect(
|
|
129
130
|
ctx,
|
|
130
131
|
l,
|
|
131
|
-
|
|
132
|
+
t2,
|
|
132
133
|
scale + f,
|
|
133
134
|
h,
|
|
134
135
|
canvasWidth,
|
|
@@ -146,7 +147,7 @@ export function makeImageData({
|
|
|
146
147
|
// font
|
|
147
148
|
const charSizeW = 10
|
|
148
149
|
if (scale >= charSizeW) {
|
|
149
|
-
for (let i = 0, o = 0
|
|
150
|
+
for (let i = 0, o = 0, l = alignment.length; i < l; i++) {
|
|
150
151
|
if (seq[i] !== '-') {
|
|
151
152
|
const l = leftPx + scale * o
|
|
152
153
|
const offset = (scale - charSizeW) / 2 + 1
|
|
@@ -182,10 +183,8 @@ export function makeImageData({
|
|
|
182
183
|
}
|
|
183
184
|
|
|
184
185
|
const t = rowHeight * row
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
ctx.fillStyle = 'purple'
|
|
188
|
-
for (let i = 0, o = 0; i < alignment.length; i++) {
|
|
186
|
+
const t2 = offset + t
|
|
187
|
+
for (let i = 0, o = 0, l = alignment.length; i < l; i++) {
|
|
189
188
|
let ins = ''
|
|
190
189
|
while (seq[i] === '-') {
|
|
191
190
|
if (alignment[i] !== '-' && alignment[i] !== ' ') {
|
|
@@ -196,15 +195,46 @@ export function makeImageData({
|
|
|
196
195
|
if (ins.length > 0) {
|
|
197
196
|
const l = leftPx + scale * o - 1
|
|
198
197
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
198
|
+
if (ins.length > 10) {
|
|
199
|
+
const txt = `${ins.length}`
|
|
200
|
+
if (bpPerPx > 10) {
|
|
201
|
+
fillRect(ctx, l - 1, t2, 2, h, canvasWidth, 'purple')
|
|
202
|
+
} else if (h > charHeight) {
|
|
203
|
+
const rwidth = measureText(txt, 10)
|
|
204
|
+
const padding = 2
|
|
205
|
+
fillRect(
|
|
206
|
+
ctx,
|
|
207
|
+
l - rwidth / 2 - padding,
|
|
208
|
+
t2,
|
|
209
|
+
rwidth + 2 * padding,
|
|
210
|
+
h,
|
|
211
|
+
canvasWidth,
|
|
212
|
+
'purple',
|
|
213
|
+
)
|
|
214
|
+
ctx.fillStyle = 'white'
|
|
215
|
+
ctx.fillText(txt, l - rwidth / 2, t + h)
|
|
216
|
+
} else {
|
|
217
|
+
const padding = 2
|
|
218
|
+
fillRect(
|
|
219
|
+
ctx,
|
|
220
|
+
l - padding,
|
|
221
|
+
t2,
|
|
222
|
+
2 * padding,
|
|
223
|
+
h,
|
|
224
|
+
canvasWidth,
|
|
225
|
+
'purple',
|
|
226
|
+
)
|
|
227
|
+
}
|
|
228
|
+
} else {
|
|
229
|
+
fillRect(ctx, l, t2, 1, h, canvasWidth, 'purple')
|
|
230
|
+
if (bpPerPx < 0.2 && rowHeight > 5) {
|
|
231
|
+
fillRect(ctx, l - 2, t2, 5, 1, canvasWidth)
|
|
232
|
+
fillRect(ctx, l - 2, t2 + h - 1, 5, 1, canvasWidth)
|
|
233
|
+
}
|
|
203
234
|
}
|
|
204
235
|
}
|
|
205
236
|
o++
|
|
206
237
|
}
|
|
207
|
-
ctx.fill()
|
|
208
238
|
}
|
|
209
239
|
}
|
|
210
240
|
}
|
|
@@ -69,17 +69,15 @@ export default function MultiMAFWidget({ model }: { model: AddTrackModel }) {
|
|
|
69
69
|
setFileTypeChoice(event.target.value as AdapterTypeOptions)
|
|
70
70
|
}}
|
|
71
71
|
>
|
|
72
|
-
{['BigMafAdapter', 'MafTabixAdapter'
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
),
|
|
82
|
-
)}
|
|
72
|
+
{['BigMafAdapter', 'MafTabixAdapter'].map(r => (
|
|
73
|
+
<FormControlLabel
|
|
74
|
+
key={r}
|
|
75
|
+
value={r}
|
|
76
|
+
control={<Radio />}
|
|
77
|
+
checked={fileTypeChoice === r}
|
|
78
|
+
label={r}
|
|
79
|
+
/>
|
|
80
|
+
))}
|
|
83
81
|
</RadioGroup>
|
|
84
82
|
</FormControl>
|
|
85
83
|
{fileTypeChoice === 'BigMafAdapter' ? (
|
|
@@ -2,7 +2,6 @@ import PluginManager from '@jbrowse/core/PluginManager'
|
|
|
2
2
|
import { AddTrackWorkflowType } from '@jbrowse/core/pluggableElementTypes'
|
|
3
3
|
import { types } from 'mobx-state-tree'
|
|
4
4
|
|
|
5
|
-
// locals
|
|
6
5
|
import MultiMAFWidget from './AddTrackWorkflow'
|
|
7
6
|
|
|
8
7
|
export default function MafAddTrackWorkflowF(pluginManager: PluginManager) {
|
|
@@ -29,16 +29,16 @@ export default class MafTabixAdapter extends BaseFeatureDataAdapter {
|
|
|
29
29
|
public setupP?: Promise<{ adapter: BaseFeatureDataAdapter }>
|
|
30
30
|
|
|
31
31
|
async setupPre() {
|
|
32
|
-
const config = this.config
|
|
33
32
|
if (!this.getSubAdapter) {
|
|
34
33
|
throw new Error('no getSubAdapter available')
|
|
35
34
|
}
|
|
36
|
-
const adapter = await this.getSubAdapter({
|
|
37
|
-
...getSnapshot(config),
|
|
38
|
-
type: 'BedTabixAdapter',
|
|
39
|
-
})
|
|
40
35
|
return {
|
|
41
|
-
adapter:
|
|
36
|
+
adapter: (
|
|
37
|
+
await this.getSubAdapter({
|
|
38
|
+
...getSnapshot(this.config),
|
|
39
|
+
type: 'BedTabixAdapter',
|
|
40
|
+
})
|
|
41
|
+
).dataAdapter as BaseFeatureDataAdapter,
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
async setupPre2() {
|
|
@@ -86,7 +86,8 @@ export default class MafTabixAdapter extends BaseFeatureDataAdapter {
|
|
|
86
86
|
const alignments = {} as Record<string, OrganismRecord>
|
|
87
87
|
|
|
88
88
|
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
|
89
|
-
|
|
89
|
+
const len = data.length
|
|
90
|
+
for (let j = 0; j < len; j++) {
|
|
90
91
|
const elt = data[j]!
|
|
91
92
|
const seq = elt.split(':')[5]!
|
|
92
93
|
const ad = elt.split(':')
|
|
@@ -106,6 +107,7 @@ export default class MafTabixAdapter extends BaseFeatureDataAdapter {
|
|
|
106
107
|
}
|
|
107
108
|
if (assemblyName) {
|
|
108
109
|
firstAssemblyNameFound = firstAssemblyNameFound || assemblyName
|
|
110
|
+
|
|
109
111
|
alignments[assemblyName] = {
|
|
110
112
|
chr: last,
|
|
111
113
|
start: +ad[1]!,
|
|
@@ -63,7 +63,35 @@ const configSchema = ConfigurationSchema(
|
|
|
63
63
|
},
|
|
64
64
|
},
|
|
65
65
|
},
|
|
66
|
-
{
|
|
66
|
+
{
|
|
67
|
+
explicitlyTyped: true,
|
|
68
|
+
preProcessSnapshot: snap => {
|
|
69
|
+
// populate from just snap.uri
|
|
70
|
+
return snap.uri
|
|
71
|
+
? {
|
|
72
|
+
...snap,
|
|
73
|
+
...(snap.nhUri
|
|
74
|
+
? {
|
|
75
|
+
nhLocation: {
|
|
76
|
+
uri: snap.nhUri,
|
|
77
|
+
baseUri: snap.baseUri,
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
: {}),
|
|
81
|
+
bedGzLocation: {
|
|
82
|
+
uri: snap.uri,
|
|
83
|
+
baseUri: snap.baseUri,
|
|
84
|
+
},
|
|
85
|
+
index: {
|
|
86
|
+
location: {
|
|
87
|
+
uri: `${snap.uri}.tbi`,
|
|
88
|
+
baseUri: snap.baseUri,
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
: snap
|
|
93
|
+
},
|
|
94
|
+
},
|
|
67
95
|
)
|
|
68
96
|
|
|
69
97
|
export default configSchema
|
package/src/util.ts
CHANGED
|
@@ -3,9 +3,13 @@ function isStrs(array: unknown[]): array is string[] {
|
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
export function normalize(
|
|
6
|
-
r: string[] | { id: string; label
|
|
6
|
+
r: string[] | { id: string; label?: string; color?: string }[],
|
|
7
7
|
) {
|
|
8
8
|
return isStrs(r)
|
|
9
|
-
? r.map(elt => ({
|
|
9
|
+
? r.map(elt => ({
|
|
10
|
+
id: elt,
|
|
11
|
+
label: elt,
|
|
12
|
+
color: undefined,
|
|
13
|
+
}))
|
|
10
14
|
: r
|
|
11
15
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ReactComponent.js","sourceRoot":"","sources":["../../../src/LinearMafDisplay/components/ReactComponent.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
2
|
-
import { Dialog } from '@jbrowse/core/ui';
|
|
3
|
-
import { Button, DialogActions, DialogContent, TextField, Typography, } from '@mui/material';
|
|
4
|
-
import { observer } from 'mobx-react';
|
|
5
|
-
import { makeStyles } from 'tss-react/mui';
|
|
6
|
-
const useStyles = makeStyles()({
|
|
7
|
-
root: {
|
|
8
|
-
width: 500,
|
|
9
|
-
},
|
|
10
|
-
});
|
|
11
|
-
const SetRowHeightDialog = observer(function (props) {
|
|
12
|
-
const { model, handleClose } = props;
|
|
13
|
-
const { classes } = useStyles();
|
|
14
|
-
const [rowHeight, setRowHeight] = useState(`${model.rowHeight}`);
|
|
15
|
-
const [rowProportion, setRowProportion] = useState(`${model.rowProportion}`);
|
|
16
|
-
return (React.createElement(Dialog, { open: true, onClose: handleClose, title: "Set row height" },
|
|
17
|
-
React.createElement(DialogContent, { className: classes.root },
|
|
18
|
-
React.createElement(Typography, null, "Set row height and the proportion of the row height to use for drawing each row"),
|
|
19
|
-
React.createElement(TextField, { value: rowHeight, helperText: "Enter row height", onChange: event => {
|
|
20
|
-
setRowHeight(event.target.value);
|
|
21
|
-
} }),
|
|
22
|
-
React.createElement(TextField, { value: rowProportion, helperText: "Enter row proportion", onChange: event => {
|
|
23
|
-
setRowProportion(event.target.value);
|
|
24
|
-
} }),
|
|
25
|
-
React.createElement(DialogActions, null,
|
|
26
|
-
React.createElement(Button, { variant: "contained", color: "primary", type: "submit", autoFocus: true, onClick: () => {
|
|
27
|
-
model.setRowProportion(+rowProportion);
|
|
28
|
-
model.setRowHeight(+rowHeight);
|
|
29
|
-
handleClose();
|
|
30
|
-
} }, "Submit"),
|
|
31
|
-
React.createElement(Button, { variant: "contained", color: "secondary", onClick: () => {
|
|
32
|
-
handleClose();
|
|
33
|
-
} }, "Cancel")))));
|
|
34
|
-
});
|
|
35
|
-
export default SetRowHeightDialog;
|
|
36
|
-
//# sourceMappingURL=SetRowHeight.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SetRowHeight.js","sourceRoot":"","sources":["../../../src/LinearMafDisplay/components/SetRowHeight.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEvC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EACL,MAAM,EACN,aAAa,EACb,aAAa,EACb,SAAS,EACT,UAAU,GACX,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE1C,MAAM,SAAS,GAAG,UAAU,EAAE,CAAC;IAC7B,IAAI,EAAE;QACJ,KAAK,EAAE,GAAG;KACX;CACF,CAAC,CAAA;AAEF,MAAM,kBAAkB,GAAG,QAAQ,CAAC,UAAU,KAQ7C;IACC,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,KAAK,CAAA;IACpC,MAAM,EAAE,OAAO,EAAE,GAAG,SAAS,EAAE,CAAA;IAC/B,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC,CAAA;IAChE,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC,CAAA;IAE5E,OAAO,CACL,oBAAC,MAAM,IAAC,IAAI,QAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAC,gBAAgB;QACvD,oBAAC,aAAa,IAAC,SAAS,EAAE,OAAO,CAAC,IAAI;YACpC,oBAAC,UAAU,0FAGE;YACb,oBAAC,SAAS,IACR,KAAK,EAAE,SAAS,EAChB,UAAU,EAAC,kBAAkB,EAC7B,QAAQ,EAAE,KAAK,CAAC,EAAE;oBAChB,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;gBAClC,CAAC,GACD;YACF,oBAAC,SAAS,IACR,KAAK,EAAE,aAAa,EACpB,UAAU,EAAC,sBAAsB,EACjC,QAAQ,EAAE,KAAK,CAAC,EAAE;oBAChB,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;gBACtC,CAAC,GACD;YACF,oBAAC,aAAa;gBACZ,oBAAC,MAAM,IACL,OAAO,EAAC,WAAW,EACnB,KAAK,EAAC,SAAS,EACf,IAAI,EAAC,QAAQ,EACb,SAAS,QACT,OAAO,EAAE,GAAG,EAAE;wBACZ,KAAK,CAAC,gBAAgB,CAAC,CAAC,aAAa,CAAC,CAAA;wBACtC,KAAK,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,CAAA;wBAC9B,WAAW,EAAE,CAAA;oBACf,CAAC,aAGM;gBACT,oBAAC,MAAM,IACL,OAAO,EAAC,WAAW,EACnB,KAAK,EAAC,WAAW,EACjB,OAAO,EAAE,GAAG,EAAE;wBACZ,WAAW,EAAE,CAAA;oBACf,CAAC,aAGM,CACK,CACF,CACT,CACV,CAAA;AACH,CAAC,CAAC,CAAA;AACF,eAAe,kBAAkB,CAAA"}
|
|
@@ -1,83 +0,0 @@
|
|
|
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
|
-
<DialogContent className={classes.root}>
|
|
37
|
-
<Typography>
|
|
38
|
-
Set row height and the proportion of the row height to use for drawing
|
|
39
|
-
each row
|
|
40
|
-
</Typography>
|
|
41
|
-
<TextField
|
|
42
|
-
value={rowHeight}
|
|
43
|
-
helperText="Enter row height"
|
|
44
|
-
onChange={event => {
|
|
45
|
-
setRowHeight(event.target.value)
|
|
46
|
-
}}
|
|
47
|
-
/>
|
|
48
|
-
<TextField
|
|
49
|
-
value={rowProportion}
|
|
50
|
-
helperText="Enter row proportion"
|
|
51
|
-
onChange={event => {
|
|
52
|
-
setRowProportion(event.target.value)
|
|
53
|
-
}}
|
|
54
|
-
/>
|
|
55
|
-
<DialogActions>
|
|
56
|
-
<Button
|
|
57
|
-
variant="contained"
|
|
58
|
-
color="primary"
|
|
59
|
-
type="submit"
|
|
60
|
-
autoFocus
|
|
61
|
-
onClick={() => {
|
|
62
|
-
model.setRowProportion(+rowProportion)
|
|
63
|
-
model.setRowHeight(+rowHeight)
|
|
64
|
-
handleClose()
|
|
65
|
-
}}
|
|
66
|
-
>
|
|
67
|
-
Submit
|
|
68
|
-
</Button>
|
|
69
|
-
<Button
|
|
70
|
-
variant="contained"
|
|
71
|
-
color="secondary"
|
|
72
|
-
onClick={() => {
|
|
73
|
-
handleClose()
|
|
74
|
-
}}
|
|
75
|
-
>
|
|
76
|
-
Cancel
|
|
77
|
-
</Button>
|
|
78
|
-
</DialogActions>
|
|
79
|
-
</DialogContent>
|
|
80
|
-
</Dialog>
|
|
81
|
-
)
|
|
82
|
-
})
|
|
83
|
-
export default SetRowHeightDialog
|
|
File without changes
|