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.
- package/README.md +71 -22
- package/dist/BgzipTaffyAdapter/BgzipTaffyAdapter.d.ts +20 -0
- package/dist/BgzipTaffyAdapter/BgzipTaffyAdapter.js +197 -0
- package/dist/BgzipTaffyAdapter/BgzipTaffyAdapter.js.map +1 -0
- package/dist/BgzipTaffyAdapter/configSchema.d.ts +44 -0
- package/dist/BgzipTaffyAdapter/configSchema.js +53 -0
- package/dist/BgzipTaffyAdapter/configSchema.js.map +1 -0
- package/dist/BgzipTaffyAdapter/index.d.ts +2 -0
- package/dist/BgzipTaffyAdapter/index.js +11 -0
- package/dist/BgzipTaffyAdapter/index.js.map +1 -0
- package/dist/BgzipTaffyAdapter/rowInstructions.d.ts +35 -0
- package/dist/BgzipTaffyAdapter/rowInstructions.js +55 -0
- package/dist/BgzipTaffyAdapter/rowInstructions.js.map +1 -0
- package/dist/BgzipTaffyAdapter/types.d.ts +13 -0
- package/dist/BgzipTaffyAdapter/types.js +2 -0
- package/dist/BgzipTaffyAdapter/types.js.map +1 -0
- package/dist/BgzipTaffyAdapter/virtualOffset.d.ts +8 -0
- package/dist/BgzipTaffyAdapter/virtualOffset.js +23 -0
- package/dist/BgzipTaffyAdapter/virtualOffset.js.map +1 -0
- package/dist/BigMafAdapter/BigMafAdapter.d.ts +17 -0
- package/dist/BigMafAdapter/BigMafAdapter.js +92 -0
- package/dist/BigMafAdapter/BigMafAdapter.js.map +1 -0
- package/dist/BigMafAdapter/configSchema.d.ts +32 -0
- package/dist/BigMafAdapter/configSchema.js +39 -0
- package/dist/BigMafAdapter/configSchema.js.map +1 -0
- package/dist/BigMafAdapter/index.d.ts +2 -0
- package/dist/BigMafAdapter/index.js +11 -0
- package/dist/BigMafAdapter/index.js.map +1 -0
- package/dist/LinearMafDisplay/components/ColorLegend.d.ts +8 -0
- package/dist/LinearMafDisplay/components/ColorLegend.js +19 -0
- package/dist/LinearMafDisplay/components/ColorLegend.js.map +1 -0
- package/dist/LinearMafDisplay/components/ReactComponent.d.ts +6 -0
- package/dist/LinearMafDisplay/components/ReactComponent.js +50 -0
- package/dist/LinearMafDisplay/components/ReactComponent.js.map +1 -0
- package/dist/LinearMafDisplay/components/RectBg.d.ts +9 -0
- package/dist/LinearMafDisplay/components/RectBg.js +7 -0
- package/dist/LinearMafDisplay/components/RectBg.js.map +1 -0
- package/dist/LinearMafDisplay/components/SetRowHeight.d.ts +11 -0
- package/dist/LinearMafDisplay/components/SetRowHeight.js +36 -0
- package/dist/LinearMafDisplay/components/SetRowHeight.js.map +1 -0
- package/dist/LinearMafDisplay/components/SvgWrapper.d.ts +8 -0
- package/dist/LinearMafDisplay/components/SvgWrapper.js +21 -0
- package/dist/LinearMafDisplay/components/SvgWrapper.js.map +1 -0
- package/dist/LinearMafDisplay/components/Tree.d.ts +5 -0
- package/dist/LinearMafDisplay/components/Tree.js +22 -0
- package/dist/LinearMafDisplay/components/Tree.js.map +1 -0
- package/dist/LinearMafDisplay/components/YScaleBars.d.ts +8 -0
- package/dist/LinearMafDisplay/components/YScaleBars.js +20 -0
- package/dist/LinearMafDisplay/components/YScaleBars.js.map +1 -0
- package/dist/LinearMafDisplay/components/util.d.ts +1 -0
- package/dist/LinearMafDisplay/components/util.js +8 -0
- package/dist/LinearMafDisplay/components/util.js.map +1 -0
- package/dist/LinearMafDisplay/configSchema.d.ts +34 -0
- package/dist/LinearMafDisplay/configSchema.js +15 -0
- package/dist/LinearMafDisplay/configSchema.js.map +1 -0
- package/dist/LinearMafDisplay/index.d.ts +2 -0
- package/dist/LinearMafDisplay/index.js +20 -0
- package/dist/LinearMafDisplay/index.js.map +1 -0
- package/dist/LinearMafDisplay/renderSvg.d.ts +4 -0
- package/dist/LinearMafDisplay/renderSvg.js +18 -0
- package/dist/LinearMafDisplay/renderSvg.js.map +1 -0
- package/dist/LinearMafDisplay/stateModel.d.ts +426 -0
- package/dist/LinearMafDisplay/stateModel.js +276 -0
- package/dist/LinearMafDisplay/stateModel.js.map +1 -0
- package/dist/LinearMafDisplay/types.d.ts +17 -0
- package/dist/LinearMafDisplay/types.js +16 -0
- package/dist/LinearMafDisplay/types.js.map +1 -0
- package/dist/LinearMafRenderer/LinearMafRenderer.d.ts +45 -0
- package/dist/LinearMafRenderer/LinearMafRenderer.js +183 -0
- package/dist/LinearMafRenderer/LinearMafRenderer.js.map +1 -0
- package/dist/LinearMafRenderer/components/ReactComponent.d.ts +6 -0
- package/dist/LinearMafRenderer/components/ReactComponent.js +8 -0
- package/dist/LinearMafRenderer/components/ReactComponent.js.map +1 -0
- package/dist/LinearMafRenderer/configSchema.d.ts +2 -0
- package/dist/LinearMafRenderer/configSchema.js +13 -0
- package/dist/LinearMafRenderer/configSchema.js.map +1 -0
- package/dist/LinearMafRenderer/index.d.ts +2 -0
- package/dist/LinearMafRenderer/index.js +12 -0
- package/dist/LinearMafRenderer/index.js.map +1 -0
- package/dist/LinearMafRenderer/util.d.ts +10 -0
- package/dist/LinearMafRenderer/util.js +16 -0
- package/dist/LinearMafRenderer/util.js.map +1 -0
- package/dist/MafAddTrackWorkflow/AddTrackWorkflow.d.ts +5 -0
- package/dist/MafAddTrackWorkflow/AddTrackWorkflow.js +128 -0
- package/dist/MafAddTrackWorkflow/AddTrackWorkflow.js.map +1 -0
- package/dist/MafAddTrackWorkflow/index.d.ts +2 -0
- package/dist/MafAddTrackWorkflow/index.js +12 -0
- package/dist/MafAddTrackWorkflow/index.js.map +1 -0
- package/dist/MafRPC/index.d.ts +16 -0
- package/dist/MafRPC/index.js +19 -0
- package/dist/MafRPC/index.js.map +1 -0
- package/dist/MafTabixAdapter/MafTabixAdapter.d.ts +25 -0
- package/dist/MafTabixAdapter/MafTabixAdapter.js +95 -0
- package/dist/MafTabixAdapter/MafTabixAdapter.js.map +1 -0
- package/dist/MafTabixAdapter/configSchema.d.ts +50 -0
- package/dist/MafTabixAdapter/configSchema.js +56 -0
- package/dist/MafTabixAdapter/configSchema.js.map +1 -0
- package/dist/MafTabixAdapter/index.d.ts +2 -0
- package/dist/MafTabixAdapter/index.js +11 -0
- package/dist/MafTabixAdapter/index.js.map +1 -0
- package/dist/MafTrack/configSchema.d.ts +79 -0
- package/dist/MafTrack/configSchema.js +15 -0
- package/dist/MafTrack/configSchema.js.map +1 -0
- package/dist/MafTrack/index.d.ts +2 -0
- package/dist/MafTrack/index.js +14 -0
- package/dist/MafTrack/index.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/jbrowse-plugin-mafviewer.umd.production.min.js +65 -1
- package/dist/jbrowse-plugin-mafviewer.umd.production.min.js.map +7 -1
- package/dist/parseNewick.d.ts +60 -0
- package/dist/parseNewick.js +95 -0
- package/dist/parseNewick.js.map +1 -0
- package/dist/util.d.ts +9 -0
- package/dist/util.js +9 -0
- package/dist/util.js.map +1 -0
- package/package.json +37 -41
- package/src/BgzipTaffyAdapter/BgzipTaffyAdapter.ts +227 -0
- package/src/BgzipTaffyAdapter/configSchema.ts +59 -0
- package/src/BgzipTaffyAdapter/index.ts +16 -0
- package/src/BgzipTaffyAdapter/rowInstructions.ts +91 -0
- package/src/BgzipTaffyAdapter/types.ts +16 -0
- package/src/BgzipTaffyAdapter/virtualOffset.ts +29 -0
- package/src/BigMafAdapter/BigMafAdapter.ts +12 -13
- package/src/BigMafAdapter/configSchema.ts +11 -0
- package/src/BigMafAdapter/index.ts +2 -1
- package/src/LinearMafDisplay/components/ColorLegend.tsx +38 -27
- package/src/LinearMafDisplay/components/ReactComponent.tsx +68 -3
- package/src/LinearMafDisplay/components/SetRowHeight.tsx +15 -8
- package/src/LinearMafDisplay/components/SvgWrapper.tsx +39 -0
- package/src/LinearMafDisplay/components/Tree.tsx +33 -0
- package/src/LinearMafDisplay/components/YScaleBars.tsx +11 -38
- package/src/LinearMafDisplay/components/util.ts +7 -0
- package/src/LinearMafDisplay/index.ts +2 -1
- package/src/LinearMafDisplay/renderSvg.tsx +2 -1
- package/src/LinearMafDisplay/stateModel.ts +169 -18
- package/src/LinearMafDisplay/types.ts +41 -0
- package/src/LinearMafRenderer/LinearMafRenderer.ts +51 -44
- package/src/LinearMafRenderer/components/ReactComponent.tsx +2 -1
- package/src/LinearMafRenderer/index.ts +2 -1
- package/src/LinearMafRenderer/util.ts +20 -0
- package/src/MafAddTrackWorkflow/AddTrackWorkflow.tsx +133 -51
- package/src/MafRPC/index.ts +39 -0
- package/src/MafTabixAdapter/MafTabixAdapter.ts +33 -27
- package/src/MafTabixAdapter/configSchema.ts +17 -1
- package/src/MafTabixAdapter/index.ts +2 -1
- package/src/MafTrack/index.ts +1 -0
- package/src/index.ts +6 -2
- package/src/parseNewick.ts +94 -0
- package/src/util.ts +11 -0
- package/LICENSE +0 -201
- package/dist/jbrowse-plugin-mafviewer.umd.development.js +0 -1439
- package/dist/jbrowse-plugin-mafviewer.umd.development.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import PluginManager from '@jbrowse/core/PluginManager'
|
|
2
2
|
import {
|
|
3
3
|
AnyConfigurationModel,
|
|
4
4
|
AnyConfigurationSchemaType,
|
|
@@ -6,12 +6,26 @@ import {
|
|
|
6
6
|
getConf,
|
|
7
7
|
} from '@jbrowse/core/configuration'
|
|
8
8
|
import { getEnv, getSession } from '@jbrowse/core/util'
|
|
9
|
-
import
|
|
9
|
+
import { getRpcSessionId } from '@jbrowse/core/util/tracks'
|
|
10
10
|
import { ExportSvgDisplayOptions } from '@jbrowse/plugin-linear-genome-view'
|
|
11
|
+
import { ascending } from 'd3-array'
|
|
12
|
+
import { type HierarchyNode, cluster, hierarchy } from 'd3-hierarchy'
|
|
13
|
+
import { autorun } from 'mobx'
|
|
14
|
+
import { Instance, addDisposer, isAlive, types } from 'mobx-state-tree'
|
|
15
|
+
|
|
11
16
|
import SetRowHeightDialog from './components/SetRowHeight'
|
|
17
|
+
import {
|
|
18
|
+
NodeWithIds,
|
|
19
|
+
NodeWithIdsAndLength,
|
|
20
|
+
maxLength,
|
|
21
|
+
setBrLength,
|
|
22
|
+
} from './types'
|
|
23
|
+
import { normalize } from '../util'
|
|
12
24
|
|
|
13
|
-
|
|
14
|
-
|
|
25
|
+
interface Sample {
|
|
26
|
+
id: string
|
|
27
|
+
label: string
|
|
28
|
+
color?: string
|
|
15
29
|
}
|
|
16
30
|
|
|
17
31
|
/**
|
|
@@ -52,10 +66,35 @@ export default function stateModelFactory(
|
|
|
52
66
|
* #property
|
|
53
67
|
*/
|
|
54
68
|
showAllLetters: false,
|
|
69
|
+
/**
|
|
70
|
+
* #property
|
|
71
|
+
*/
|
|
72
|
+
mismatchRendering: true,
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* #property
|
|
76
|
+
*/
|
|
77
|
+
showBranchLen: false,
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* #property
|
|
81
|
+
*/
|
|
82
|
+
treeAreaWidth: 80,
|
|
55
83
|
}),
|
|
56
84
|
)
|
|
57
85
|
.volatile(() => ({
|
|
86
|
+
/**
|
|
87
|
+
* #volatile
|
|
88
|
+
*/
|
|
58
89
|
prefersOffset: true,
|
|
90
|
+
/**
|
|
91
|
+
* #volatile
|
|
92
|
+
*/
|
|
93
|
+
volatileSamples: [] as Sample[],
|
|
94
|
+
/**
|
|
95
|
+
* #volatile
|
|
96
|
+
*/
|
|
97
|
+
tree: undefined as any,
|
|
59
98
|
}))
|
|
60
99
|
.actions(self => ({
|
|
61
100
|
/**
|
|
@@ -76,26 +115,28 @@ export default function stateModelFactory(
|
|
|
76
115
|
setShowAllLetters(f: boolean) {
|
|
77
116
|
self.showAllLetters = f
|
|
78
117
|
},
|
|
79
|
-
}))
|
|
80
|
-
.views(self => ({
|
|
81
118
|
/**
|
|
82
|
-
* #
|
|
119
|
+
* #action
|
|
83
120
|
*/
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
| string[]
|
|
87
|
-
| { id: string; label: string; color?: string }[]
|
|
88
|
-
return isStrs(r)
|
|
89
|
-
? r.map(elt => ({ id: elt, label: elt, color: undefined }))
|
|
90
|
-
: r
|
|
121
|
+
setMismatchRendering(f: boolean) {
|
|
122
|
+
self.mismatchRendering = f
|
|
91
123
|
},
|
|
92
|
-
|
|
124
|
+
/**
|
|
125
|
+
* #action
|
|
126
|
+
*/
|
|
127
|
+
setSamples({ samples, tree }: { samples: Sample[]; tree: unknown }) {
|
|
128
|
+
self.volatileSamples = samples
|
|
129
|
+
self.tree = tree
|
|
130
|
+
},
|
|
131
|
+
}))
|
|
132
|
+
.views(self => ({
|
|
93
133
|
/**
|
|
94
134
|
* #getter
|
|
95
135
|
*/
|
|
96
136
|
get rendererTypeName() {
|
|
97
137
|
return 'LinearMafRenderer'
|
|
98
138
|
},
|
|
139
|
+
|
|
99
140
|
/**
|
|
100
141
|
* #getter
|
|
101
142
|
*/
|
|
@@ -112,12 +153,77 @@ export default function stateModelFactory(
|
|
|
112
153
|
)
|
|
113
154
|
},
|
|
114
155
|
}))
|
|
156
|
+
|
|
157
|
+
.views(self => ({
|
|
158
|
+
/**
|
|
159
|
+
* #getter
|
|
160
|
+
*/
|
|
161
|
+
get root() {
|
|
162
|
+
return self.tree
|
|
163
|
+
? hierarchy(self.tree, d => d.children)
|
|
164
|
+
// todo: investigate whether needed, typescript says children always true
|
|
165
|
+
.sum(d => (d.children ? 0 : 1))
|
|
166
|
+
.sort((a, b) => ascending(a.data.length || 1, b.data.length || 1))
|
|
167
|
+
: undefined
|
|
168
|
+
},
|
|
169
|
+
}))
|
|
170
|
+
.views(self => ({
|
|
171
|
+
/**
|
|
172
|
+
* #getter
|
|
173
|
+
* generates a new tree that is clustered with x,y positions
|
|
174
|
+
*/
|
|
175
|
+
get hierarchy(): HierarchyNode<NodeWithIdsAndLength> | undefined {
|
|
176
|
+
const r = self.root
|
|
177
|
+
if (r) {
|
|
178
|
+
const width = self.treeAreaWidth
|
|
179
|
+
const clust = cluster<NodeWithIds>()
|
|
180
|
+
.size([this.totalHeight, width])
|
|
181
|
+
.separation(() => 1)
|
|
182
|
+
clust(r)
|
|
183
|
+
setBrLength(r, (r.data.length = 0), width / maxLength(r))
|
|
184
|
+
return r as HierarchyNode<NodeWithIdsAndLength>
|
|
185
|
+
} else {
|
|
186
|
+
return undefined
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
/**
|
|
190
|
+
* #getter
|
|
191
|
+
*/
|
|
192
|
+
get samples() {
|
|
193
|
+
return this.rowNames ? normalize(this.rowNames) : self.volatileSamples
|
|
194
|
+
},
|
|
195
|
+
/**
|
|
196
|
+
* #getter
|
|
197
|
+
*/
|
|
198
|
+
get totalHeight() {
|
|
199
|
+
return this.samples.length * self.rowHeight
|
|
200
|
+
},
|
|
201
|
+
/**
|
|
202
|
+
* #getter
|
|
203
|
+
*/
|
|
204
|
+
get leaves() {
|
|
205
|
+
return self.root?.leaves()
|
|
206
|
+
},
|
|
207
|
+
/**
|
|
208
|
+
* #getter
|
|
209
|
+
*/
|
|
210
|
+
get rowNames(): string[] | undefined {
|
|
211
|
+
return this.leaves?.map(n => n.data.name)
|
|
212
|
+
},
|
|
213
|
+
}))
|
|
115
214
|
.views(self => {
|
|
116
215
|
const {
|
|
117
216
|
trackMenuItems: superTrackMenuItems,
|
|
217
|
+
|
|
118
218
|
renderProps: superRenderProps,
|
|
119
219
|
} = self
|
|
120
220
|
return {
|
|
221
|
+
/**
|
|
222
|
+
* #getter
|
|
223
|
+
*/
|
|
224
|
+
get treeWidth() {
|
|
225
|
+
return self.hierarchy ? self.treeAreaWidth : 0
|
|
226
|
+
},
|
|
121
227
|
/**
|
|
122
228
|
* #method
|
|
123
229
|
*/
|
|
@@ -128,6 +234,7 @@ export default function stateModelFactory(
|
|
|
128
234
|
samples,
|
|
129
235
|
rowHeight,
|
|
130
236
|
rowProportion,
|
|
237
|
+
mismatchRendering,
|
|
131
238
|
} = self
|
|
132
239
|
return {
|
|
133
240
|
...superRenderProps(),
|
|
@@ -136,6 +243,7 @@ export default function stateModelFactory(
|
|
|
136
243
|
rowHeight,
|
|
137
244
|
rowProportion,
|
|
138
245
|
showAllLetters,
|
|
246
|
+
mismatchRendering,
|
|
139
247
|
}
|
|
140
248
|
},
|
|
141
249
|
/**
|
|
@@ -149,7 +257,10 @@ export default function stateModelFactory(
|
|
|
149
257
|
onClick: () => {
|
|
150
258
|
getSession(self).queueDialog(handleClose => [
|
|
151
259
|
SetRowHeightDialog,
|
|
152
|
-
{
|
|
260
|
+
{
|
|
261
|
+
model: self,
|
|
262
|
+
handleClose,
|
|
263
|
+
},
|
|
153
264
|
])
|
|
154
265
|
},
|
|
155
266
|
},
|
|
@@ -157,14 +268,54 @@ export default function stateModelFactory(
|
|
|
157
268
|
label: 'Show all letters',
|
|
158
269
|
type: 'checkbox',
|
|
159
270
|
checked: self.showAllLetters,
|
|
160
|
-
onClick: () =>
|
|
271
|
+
onClick: () => {
|
|
272
|
+
self.setShowAllLetters(!self.showAllLetters)
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
label: 'Draw mismatches as single color',
|
|
277
|
+
type: 'checkbox',
|
|
278
|
+
checked: !self.mismatchRendering,
|
|
279
|
+
onClick: () => {
|
|
280
|
+
self.setMismatchRendering(!self.mismatchRendering)
|
|
281
|
+
},
|
|
161
282
|
},
|
|
162
283
|
]
|
|
163
284
|
},
|
|
164
285
|
}
|
|
165
286
|
})
|
|
287
|
+
.actions(self => ({
|
|
288
|
+
afterCreate() {
|
|
289
|
+
addDisposer(
|
|
290
|
+
self,
|
|
291
|
+
autorun(async () => {
|
|
292
|
+
try {
|
|
293
|
+
const { rpcManager } = getSession(self)
|
|
294
|
+
const sessionId = getRpcSessionId(self)
|
|
295
|
+
|
|
296
|
+
const results = (await rpcManager.call(
|
|
297
|
+
sessionId,
|
|
298
|
+
'MafGetSamples',
|
|
299
|
+
{
|
|
300
|
+
sessionId,
|
|
301
|
+
adapterConfig: self.adapterConfig,
|
|
302
|
+
statusCallback: (message: string) => {
|
|
303
|
+
if (isAlive(self)) {
|
|
304
|
+
self.setMessage(message)
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
)) as any
|
|
309
|
+
self.setSamples(results)
|
|
310
|
+
} catch (e) {
|
|
311
|
+
console.error(e)
|
|
312
|
+
getSession(self).notifyError(`${e}`, e)
|
|
313
|
+
}
|
|
314
|
+
}),
|
|
315
|
+
)
|
|
316
|
+
},
|
|
317
|
+
}))
|
|
166
318
|
.actions(self => {
|
|
167
|
-
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
168
319
|
const { renderSvg: superRenderSvg } = self
|
|
169
320
|
return {
|
|
170
321
|
/**
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { max } from 'd3-array'
|
|
2
|
+
|
|
3
|
+
import type { HierarchyNode } from 'd3-hierarchy'
|
|
4
|
+
|
|
5
|
+
export interface NodeWithIds {
|
|
6
|
+
id: string
|
|
7
|
+
name: string
|
|
8
|
+
children: NodeWithIds[]
|
|
9
|
+
length?: number
|
|
10
|
+
noTree?: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface NodeWithIdsAndLength {
|
|
14
|
+
id: string
|
|
15
|
+
name: string
|
|
16
|
+
children: NodeWithIdsAndLength[]
|
|
17
|
+
noTree?: boolean
|
|
18
|
+
length: number
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// basically same as maxLength from https://observablehq.com/@d3/tree-of-life
|
|
22
|
+
export function maxLength(d: HierarchyNode<NodeWithIds>): number {
|
|
23
|
+
return (
|
|
24
|
+
(d.data.length || 0) + (d.children ? max(d.children, maxLength) || 0 : 0)
|
|
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
|
+
}
|
|
41
|
+
}
|
|
@@ -7,33 +7,21 @@ import {
|
|
|
7
7
|
featureSpanPx,
|
|
8
8
|
renderToAbstractCanvas,
|
|
9
9
|
} from '@jbrowse/core/util'
|
|
10
|
-
import { Theme } from '@mui/material'
|
|
11
|
-
|
|
12
|
-
export function getContrastBaseMap(theme: Theme) {
|
|
13
|
-
return Object.fromEntries(
|
|
14
|
-
Object.entries(getColorBaseMap(theme)).map(([key, value]) => [
|
|
15
|
-
key,
|
|
16
|
-
theme.palette.getContrastText(value),
|
|
17
|
-
]),
|
|
18
|
-
)
|
|
19
|
-
}
|
|
20
10
|
|
|
11
|
+
import { getColorBaseMap, getContrastBaseMap } from './util'
|
|
12
|
+
|
|
13
|
+
interface Sample {
|
|
14
|
+
id: string
|
|
15
|
+
color?: string
|
|
16
|
+
}
|
|
21
17
|
interface RenderArgs extends RenderArgsDeserialized {
|
|
22
|
-
samples:
|
|
18
|
+
samples: Sample[]
|
|
23
19
|
rowHeight: number
|
|
24
20
|
rowProportion: number
|
|
25
21
|
showAllLetters: boolean
|
|
22
|
+
mismatchRendering: boolean
|
|
26
23
|
}
|
|
27
24
|
|
|
28
|
-
export function getColorBaseMap(theme: Theme) {
|
|
29
|
-
const { bases } = theme.palette
|
|
30
|
-
return {
|
|
31
|
-
a: bases.A.main,
|
|
32
|
-
c: bases.C.main,
|
|
33
|
-
g: bases.G.main,
|
|
34
|
-
t: bases.T.main,
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
25
|
function makeImageData({
|
|
38
26
|
ctx,
|
|
39
27
|
renderArgs,
|
|
@@ -47,11 +35,12 @@ function makeImageData({
|
|
|
47
35
|
rowHeight,
|
|
48
36
|
showAllLetters,
|
|
49
37
|
theme: configTheme,
|
|
38
|
+
mismatchRendering,
|
|
50
39
|
samples,
|
|
51
40
|
rowProportion,
|
|
52
41
|
features,
|
|
53
42
|
} = renderArgs
|
|
54
|
-
const
|
|
43
|
+
const region = regions[0]!
|
|
55
44
|
const h = rowHeight * rowProportion
|
|
56
45
|
const theme = createJBrowseTheme(configTheme)
|
|
57
46
|
const colorForBase = getColorBaseMap(theme)
|
|
@@ -76,7 +65,7 @@ function makeImageData({
|
|
|
76
65
|
|
|
77
66
|
const row = sampleToRowMap.get(sample)
|
|
78
67
|
if (row === undefined) {
|
|
79
|
-
|
|
68
|
+
continue
|
|
80
69
|
}
|
|
81
70
|
|
|
82
71
|
const t = rowHeight * row
|
|
@@ -117,27 +106,39 @@ function makeImageData({
|
|
|
117
106
|
for (let i = 0, o = 0; i < alignment.length; i++) {
|
|
118
107
|
const c = alignment[i]
|
|
119
108
|
if (seq[i] !== '-') {
|
|
120
|
-
if (
|
|
109
|
+
if (c !== '-') {
|
|
121
110
|
const l = leftPx + scale * o
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
111
|
+
if (seq[i] !== c && c !== ' ') {
|
|
112
|
+
ctx.fillStyle = mismatchRendering
|
|
113
|
+
? // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
114
|
+
(colorForBase[c as keyof typeof colorForBase] ?? 'black')
|
|
115
|
+
: 'orange'
|
|
116
|
+
ctx.fillRect(l, offset + t, scale + f, h)
|
|
117
|
+
} else if (showAllLetters) {
|
|
118
|
+
ctx.fillStyle = mismatchRendering
|
|
119
|
+
? // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
120
|
+
(colorForBase[c as keyof typeof colorForBase] ?? 'black')
|
|
121
|
+
: 'lightblue'
|
|
122
|
+
ctx.fillRect(l, offset + t, scale + f, h)
|
|
123
|
+
}
|
|
125
124
|
}
|
|
126
125
|
o++
|
|
127
126
|
}
|
|
128
127
|
}
|
|
129
128
|
|
|
130
129
|
// font
|
|
131
|
-
const
|
|
132
|
-
if (scale >=
|
|
130
|
+
const charSizeW = 10
|
|
131
|
+
if (scale >= charSizeW) {
|
|
133
132
|
for (let i = 0, o = 0; i < alignment.length; i++) {
|
|
134
133
|
if (seq[i] !== '-') {
|
|
135
134
|
const l = leftPx + scale * o
|
|
136
|
-
const offset = (scale -
|
|
137
|
-
const c = alignment[i]
|
|
135
|
+
const offset = (scale - charSizeW) / 2 + 1
|
|
136
|
+
const c = alignment[i]!
|
|
138
137
|
if ((showAllLetters || seq[i] !== c) && c !== '-') {
|
|
139
|
-
ctx.fillStyle =
|
|
140
|
-
|
|
138
|
+
ctx.fillStyle = mismatchRendering
|
|
139
|
+
? (contrastForBase[c] ?? 'white')
|
|
140
|
+
: 'black'
|
|
141
|
+
ctx.fillText(origAlignment[i] || '', l + offset, hp2 + t + 3)
|
|
141
142
|
}
|
|
142
143
|
o++
|
|
143
144
|
}
|
|
@@ -158,7 +159,7 @@ function makeImageData({
|
|
|
158
159
|
const alignment = origAlignment.toLowerCase()
|
|
159
160
|
const row = sampleToRowMap.get(sample)
|
|
160
161
|
if (row === undefined) {
|
|
161
|
-
|
|
162
|
+
continue
|
|
162
163
|
}
|
|
163
164
|
|
|
164
165
|
const t = rowHeight * row
|
|
@@ -168,7 +169,7 @@ function makeImageData({
|
|
|
168
169
|
for (let i = 0, o = 0; i < alignment.length; i++) {
|
|
169
170
|
let ins = ''
|
|
170
171
|
while (seq[i] === '-') {
|
|
171
|
-
if (alignment[i] !== '-') {
|
|
172
|
+
if (alignment[i] !== '-' && alignment[i] !== ' ') {
|
|
172
173
|
ins += alignment[i]
|
|
173
174
|
}
|
|
174
175
|
i++
|
|
@@ -199,18 +200,24 @@ export default class LinearMafRenderer extends FeatureRendererType {
|
|
|
199
200
|
}
|
|
200
201
|
async render(renderProps: RenderArgs) {
|
|
201
202
|
const { regions, bpPerPx, samples, rowHeight } = renderProps
|
|
202
|
-
const
|
|
203
|
-
const height = samples.length * rowHeight + 100
|
|
203
|
+
const region = regions[0]!
|
|
204
|
+
const height = samples.length * (rowHeight + 1) + 100
|
|
204
205
|
const width = (region.end - region.start) / bpPerPx
|
|
205
206
|
const features = await this.getFeatures(renderProps)
|
|
206
|
-
const res = await renderToAbstractCanvas(
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
207
|
+
const res = await renderToAbstractCanvas(
|
|
208
|
+
width,
|
|
209
|
+
height,
|
|
210
|
+
renderProps,
|
|
211
|
+
ctx => {
|
|
212
|
+
makeImageData({
|
|
213
|
+
ctx,
|
|
214
|
+
renderArgs: {
|
|
215
|
+
...renderProps,
|
|
216
|
+
features,
|
|
217
|
+
},
|
|
218
|
+
})
|
|
219
|
+
return undefined
|
|
220
|
+
},
|
|
214
221
|
)
|
|
215
222
|
const results = await super.render({
|
|
216
223
|
...renderProps,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import PluginManager from '@jbrowse/core/PluginManager'
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import LinearMafRenderer from './LinearMafRenderer'
|
|
4
4
|
import ReactComponent from './components/ReactComponent'
|
|
5
|
+
import configSchema from './configSchema'
|
|
5
6
|
|
|
6
7
|
export default function LinearMafRendererF(pluginManager: PluginManager) {
|
|
7
8
|
pluginManager.addRendererType(
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Theme } from '@mui/material'
|
|
2
|
+
|
|
3
|
+
export function getContrastBaseMap(theme: Theme) {
|
|
4
|
+
return Object.fromEntries(
|
|
5
|
+
Object.entries(getColorBaseMap(theme)).map(([key, value]) => [
|
|
6
|
+
key,
|
|
7
|
+
theme.palette.getContrastText(value),
|
|
8
|
+
]),
|
|
9
|
+
)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function getColorBaseMap(theme: Theme) {
|
|
13
|
+
const { bases } = theme.palette
|
|
14
|
+
return {
|
|
15
|
+
a: bases.A.main,
|
|
16
|
+
c: bases.C.main,
|
|
17
|
+
g: bases.G.main,
|
|
18
|
+
t: bases.T.main,
|
|
19
|
+
}
|
|
20
|
+
}
|