@jbrowse/plugin-linear-comparative-view 2.6.1 → 2.6.2
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/LGVSyntenyDisplay/configSchemaF.d.ts +1 -3
- package/dist/LGVSyntenyDisplay/configSchemaF.js +0 -1
- package/dist/LGVSyntenyDisplay/index.js +0 -1
- package/dist/LGVSyntenyDisplay/model.d.ts +4 -2
- package/dist/LGVSyntenyDisplay/model.js +0 -1
- package/dist/LaunchLinearSyntenyView.js +0 -1
- package/dist/LinearComparativeDisplay/configSchemaF.js +0 -1
- package/dist/LinearComparativeDisplay/index.js +0 -1
- package/dist/LinearComparativeDisplay/stateModelFactory.js +0 -1
- package/dist/LinearComparativeView/components/Header.js +11 -2
- package/dist/LinearComparativeView/components/LinearComparativeView.js +0 -1
- package/dist/LinearComparativeView/components/Rubberband.js +11 -33
- package/dist/LinearComparativeView/components/VerticalGuide.d.ts +8 -0
- package/dist/LinearComparativeView/components/VerticalGuide.js +33 -0
- package/dist/LinearComparativeView/index.js +0 -1
- package/dist/LinearComparativeView/model.d.ts +9 -15
- package/dist/LinearComparativeView/model.js +0 -1
- package/dist/LinearReadVsRef/LinearReadVsRef.js +0 -1
- package/dist/LinearReadVsRef/index.js +0 -1
- package/dist/LinearSyntenyDisplay/afterAttach.js +0 -1
- package/dist/LinearSyntenyDisplay/components/Component.js +0 -1
- package/dist/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +0 -1
- package/dist/LinearSyntenyDisplay/components/SyntenyTooltip.js +0 -1
- package/dist/LinearSyntenyDisplay/components/util.js +0 -1
- package/dist/LinearSyntenyDisplay/configSchemaF.js +0 -1
- package/dist/LinearSyntenyDisplay/drawSynteny.js +0 -1
- package/dist/LinearSyntenyDisplay/index.js +0 -1
- package/dist/LinearSyntenyDisplay/model.js +0 -1
- package/dist/LinearSyntenyView/components/ExportSvgDialog.js +0 -1
- package/dist/LinearSyntenyView/components/Icons.js +0 -1
- package/dist/LinearSyntenyView/components/ImportCustomTrack.js +0 -1
- package/dist/LinearSyntenyView/components/ImportForm.js +0 -1
- package/dist/LinearSyntenyView/components/ImportSyntenyTrackSelector.js +0 -1
- package/dist/LinearSyntenyView/components/LinearSyntenyView.js +0 -1
- package/dist/LinearSyntenyView/index.js +0 -1
- package/dist/LinearSyntenyView/model.d.ts +9 -9
- package/dist/LinearSyntenyView/model.js +0 -1
- package/dist/LinearSyntenyView/svgcomponents/SVGBackground.js +0 -1
- package/dist/LinearSyntenyView/svgcomponents/SVGLinearSyntenyView.js +0 -1
- package/dist/SyntenyFeatureDetail/SyntenyFeatureDetail.js +0 -1
- package/dist/SyntenyFeatureDetail/index.js +0 -1
- package/dist/SyntenyTrack/configSchema.js +0 -1
- package/dist/SyntenyTrack/index.js +0 -1
- package/dist/index.js +0 -1
- package/dist/util.js +0 -1
- package/esm/LGVSyntenyDisplay/configSchemaF.d.ts +1 -3
- package/esm/LGVSyntenyDisplay/configSchemaF.js +0 -1
- package/esm/LGVSyntenyDisplay/index.js +0 -1
- package/esm/LGVSyntenyDisplay/model.d.ts +4 -2
- package/esm/LGVSyntenyDisplay/model.js +0 -1
- package/esm/LaunchLinearSyntenyView.js +0 -1
- package/esm/LinearComparativeDisplay/configSchemaF.js +0 -1
- package/esm/LinearComparativeDisplay/index.js +0 -1
- package/esm/LinearComparativeDisplay/stateModelFactory.js +0 -1
- package/esm/LinearComparativeView/components/Header.js +11 -2
- package/esm/LinearComparativeView/components/LinearComparativeView.js +0 -1
- package/esm/LinearComparativeView/components/Rubberband.js +8 -33
- package/esm/LinearComparativeView/components/VerticalGuide.d.ts +8 -0
- package/esm/LinearComparativeView/components/VerticalGuide.js +28 -0
- package/esm/LinearComparativeView/index.js +0 -1
- package/esm/LinearComparativeView/model.d.ts +9 -15
- package/esm/LinearComparativeView/model.js +0 -1
- package/esm/LinearReadVsRef/LinearReadVsRef.js +0 -1
- package/esm/LinearReadVsRef/index.js +0 -1
- package/esm/LinearSyntenyDisplay/afterAttach.js +0 -1
- package/esm/LinearSyntenyDisplay/components/Component.js +0 -1
- package/esm/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +0 -1
- package/esm/LinearSyntenyDisplay/components/SyntenyTooltip.js +0 -1
- package/esm/LinearSyntenyDisplay/components/util.js +0 -1
- package/esm/LinearSyntenyDisplay/configSchemaF.js +0 -1
- package/esm/LinearSyntenyDisplay/drawSynteny.js +0 -1
- package/esm/LinearSyntenyDisplay/index.js +0 -1
- package/esm/LinearSyntenyDisplay/model.js +0 -1
- package/esm/LinearSyntenyView/components/ExportSvgDialog.js +0 -1
- package/esm/LinearSyntenyView/components/Icons.js +0 -1
- package/esm/LinearSyntenyView/components/ImportCustomTrack.js +0 -1
- package/esm/LinearSyntenyView/components/ImportForm.js +0 -1
- package/esm/LinearSyntenyView/components/ImportSyntenyTrackSelector.js +0 -1
- package/esm/LinearSyntenyView/components/LinearSyntenyView.js +0 -1
- package/esm/LinearSyntenyView/index.js +0 -1
- package/esm/LinearSyntenyView/model.d.ts +9 -9
- package/esm/LinearSyntenyView/model.js +0 -1
- package/esm/LinearSyntenyView/svgcomponents/SVGBackground.js +0 -1
- package/esm/LinearSyntenyView/svgcomponents/SVGLinearSyntenyView.js +0 -1
- package/esm/SyntenyFeatureDetail/SyntenyFeatureDetail.js +0 -1
- package/esm/SyntenyFeatureDetail/index.js +0 -1
- package/esm/SyntenyTrack/configSchema.js +0 -1
- package/esm/SyntenyTrack/index.js +0 -1
- package/esm/index.js +0 -1
- package/esm/util.js +0 -1
- package/package.json +3 -4
- package/dist/LGVSyntenyDisplay/configSchemaF.js.map +0 -1
- package/dist/LGVSyntenyDisplay/index.js.map +0 -1
- package/dist/LGVSyntenyDisplay/model.js.map +0 -1
- package/dist/LaunchLinearSyntenyView.js.map +0 -1
- package/dist/LinearComparativeDisplay/configSchemaF.js.map +0 -1
- package/dist/LinearComparativeDisplay/index.js.map +0 -1
- package/dist/LinearComparativeDisplay/stateModelFactory.js.map +0 -1
- package/dist/LinearComparativeView/components/Header.js.map +0 -1
- package/dist/LinearComparativeView/components/LinearComparativeView.js.map +0 -1
- package/dist/LinearComparativeView/components/Rubberband.js.map +0 -1
- package/dist/LinearComparativeView/index.js.map +0 -1
- package/dist/LinearComparativeView/model.js.map +0 -1
- package/dist/LinearReadVsRef/LinearReadVsRef.js.map +0 -1
- package/dist/LinearReadVsRef/index.js.map +0 -1
- package/dist/LinearSyntenyDisplay/afterAttach.js.map +0 -1
- package/dist/LinearSyntenyDisplay/components/Component.js.map +0 -1
- package/dist/LinearSyntenyDisplay/components/LinearSyntenyRendering.js.map +0 -1
- package/dist/LinearSyntenyDisplay/components/SyntenyTooltip.js.map +0 -1
- package/dist/LinearSyntenyDisplay/components/util.js.map +0 -1
- package/dist/LinearSyntenyDisplay/configSchemaF.js.map +0 -1
- package/dist/LinearSyntenyDisplay/drawSynteny.js.map +0 -1
- package/dist/LinearSyntenyDisplay/index.js.map +0 -1
- package/dist/LinearSyntenyDisplay/model.js.map +0 -1
- package/dist/LinearSyntenyView/components/ExportSvgDialog.js.map +0 -1
- package/dist/LinearSyntenyView/components/Icons.js.map +0 -1
- package/dist/LinearSyntenyView/components/ImportCustomTrack.js.map +0 -1
- package/dist/LinearSyntenyView/components/ImportForm.js.map +0 -1
- package/dist/LinearSyntenyView/components/ImportSyntenyTrackSelector.js.map +0 -1
- package/dist/LinearSyntenyView/components/LinearSyntenyView.js.map +0 -1
- package/dist/LinearSyntenyView/index.js.map +0 -1
- package/dist/LinearSyntenyView/model.js.map +0 -1
- package/dist/LinearSyntenyView/svgcomponents/SVGBackground.js.map +0 -1
- package/dist/LinearSyntenyView/svgcomponents/SVGLinearSyntenyView.js.map +0 -1
- package/dist/SyntenyFeatureDetail/SyntenyFeatureDetail.js.map +0 -1
- package/dist/SyntenyFeatureDetail/index.js.map +0 -1
- package/dist/SyntenyTrack/configSchema.js.map +0 -1
- package/dist/SyntenyTrack/index.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/util.js.map +0 -1
- package/esm/LGVSyntenyDisplay/configSchemaF.js.map +0 -1
- package/esm/LGVSyntenyDisplay/index.js.map +0 -1
- package/esm/LGVSyntenyDisplay/model.js.map +0 -1
- package/esm/LaunchLinearSyntenyView.js.map +0 -1
- package/esm/LinearComparativeDisplay/configSchemaF.js.map +0 -1
- package/esm/LinearComparativeDisplay/index.js.map +0 -1
- package/esm/LinearComparativeDisplay/stateModelFactory.js.map +0 -1
- package/esm/LinearComparativeView/components/Header.js.map +0 -1
- package/esm/LinearComparativeView/components/LinearComparativeView.js.map +0 -1
- package/esm/LinearComparativeView/components/Rubberband.js.map +0 -1
- package/esm/LinearComparativeView/index.js.map +0 -1
- package/esm/LinearComparativeView/model.js.map +0 -1
- package/esm/LinearReadVsRef/LinearReadVsRef.js.map +0 -1
- package/esm/LinearReadVsRef/index.js.map +0 -1
- package/esm/LinearSyntenyDisplay/afterAttach.js.map +0 -1
- package/esm/LinearSyntenyDisplay/components/Component.js.map +0 -1
- package/esm/LinearSyntenyDisplay/components/LinearSyntenyRendering.js.map +0 -1
- package/esm/LinearSyntenyDisplay/components/SyntenyTooltip.js.map +0 -1
- package/esm/LinearSyntenyDisplay/components/util.js.map +0 -1
- package/esm/LinearSyntenyDisplay/configSchemaF.js.map +0 -1
- package/esm/LinearSyntenyDisplay/drawSynteny.js.map +0 -1
- package/esm/LinearSyntenyDisplay/index.js.map +0 -1
- package/esm/LinearSyntenyDisplay/model.js.map +0 -1
- package/esm/LinearSyntenyView/components/ExportSvgDialog.js.map +0 -1
- package/esm/LinearSyntenyView/components/Icons.js.map +0 -1
- package/esm/LinearSyntenyView/components/ImportCustomTrack.js.map +0 -1
- package/esm/LinearSyntenyView/components/ImportForm.js.map +0 -1
- package/esm/LinearSyntenyView/components/ImportSyntenyTrackSelector.js.map +0 -1
- package/esm/LinearSyntenyView/components/LinearSyntenyView.js.map +0 -1
- package/esm/LinearSyntenyView/index.js.map +0 -1
- package/esm/LinearSyntenyView/model.js.map +0 -1
- package/esm/LinearSyntenyView/svgcomponents/SVGBackground.js.map +0 -1
- package/esm/LinearSyntenyView/svgcomponents/SVGLinearSyntenyView.js.map +0 -1
- package/esm/SyntenyFeatureDetail/SyntenyFeatureDetail.js.map +0 -1
- package/esm/SyntenyFeatureDetail/index.js.map +0 -1
- package/esm/SyntenyTrack/configSchema.js.map +0 -1
- package/esm/SyntenyTrack/index.js.map +0 -1
- package/esm/index.js.map +0 -1
- package/esm/util.js.map +0 -1
- package/src/LGVSyntenyDisplay/configSchemaF.ts +0 -22
- package/src/LGVSyntenyDisplay/index.ts +0 -20
- package/src/LGVSyntenyDisplay/model.ts +0 -177
- package/src/LaunchLinearSyntenyView.ts +0 -86
- package/src/LinearComparativeDisplay/configSchemaF.ts +0 -22
- package/src/LinearComparativeDisplay/index.ts +0 -21
- package/src/LinearComparativeDisplay/stateModelFactory.ts +0 -212
- package/src/LinearComparativeView/components/Header.tsx +0 -103
- package/src/LinearComparativeView/components/LinearComparativeView.tsx +0 -152
- package/src/LinearComparativeView/components/Rubberband.tsx +0 -329
- package/src/LinearComparativeView/index.ts +0 -15
- package/src/LinearComparativeView/model.ts +0 -395
- package/src/LinearReadVsRef/LinearReadVsRef.tsx +0 -360
- package/src/LinearReadVsRef/index.ts +0 -58
- package/src/LinearSyntenyDisplay/afterAttach.ts +0 -149
- package/src/LinearSyntenyDisplay/components/Component.tsx +0 -75
- package/src/LinearSyntenyDisplay/components/LinearSyntenyRendering.tsx +0 -200
- package/src/LinearSyntenyDisplay/components/SyntenyTooltip.tsx +0 -82
- package/src/LinearSyntenyDisplay/components/util.ts +0 -142
- package/src/LinearSyntenyDisplay/configSchemaF.ts +0 -38
- package/src/LinearSyntenyDisplay/drawSynteny.ts +0 -266
- package/src/LinearSyntenyDisplay/index.ts +0 -21
- package/src/LinearSyntenyDisplay/model.ts +0 -187
- package/src/LinearSyntenyView/components/ExportSvgDialog.tsx +0 -148
- package/src/LinearSyntenyView/components/Icons.tsx +0 -24
- package/src/LinearSyntenyView/components/ImportCustomTrack.tsx +0 -262
- package/src/LinearSyntenyView/components/ImportForm.tsx +0 -221
- package/src/LinearSyntenyView/components/ImportSyntenyTrackSelector.tsx +0 -82
- package/src/LinearSyntenyView/components/LinearSyntenyView.tsx +0 -20
- package/src/LinearSyntenyView/index.ts +0 -15
- package/src/LinearSyntenyView/model.test.ts +0 -1605
- package/src/LinearSyntenyView/model.ts +0 -169
- package/src/LinearSyntenyView/svgcomponents/SVGBackground.tsx +0 -21
- package/src/LinearSyntenyView/svgcomponents/SVGLinearSyntenyView.tsx +0 -176
- package/src/SyntenyFeatureDetail/SyntenyFeatureDetail.tsx +0 -64
- package/src/SyntenyFeatureDetail/index.ts +0 -36
- package/src/SyntenyTrack/configSchema.ts +0 -23
- package/src/SyntenyTrack/index.tsx +0 -15
- package/src/index.tsx +0 -42
- package/src/util.ts +0 -124
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
import { doesIntersect2, getContainingView } from '@jbrowse/core/util'
|
|
2
|
-
import { LinearSyntenyViewModel } from '../LinearSyntenyView/model'
|
|
3
|
-
import { LinearSyntenyDisplayModel } from './model'
|
|
4
|
-
import { draw, drawMatchSimple } from './components/util'
|
|
5
|
-
|
|
6
|
-
export const MAX_COLOR_RANGE = 255 * 255 * 255 // max color range
|
|
7
|
-
|
|
8
|
-
function makeColor(idx: number) {
|
|
9
|
-
const r = Math.floor(idx / (255 * 255)) % 255
|
|
10
|
-
const g = Math.floor(idx / 255) % 255
|
|
11
|
-
const b = idx % 255
|
|
12
|
-
return `rgb(${r},${g},${b})`
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const colorMap = {
|
|
16
|
-
I: '#ff03',
|
|
17
|
-
N: '#0a03',
|
|
18
|
-
D: '#00f3',
|
|
19
|
-
X: 'brown',
|
|
20
|
-
M: '#f003',
|
|
21
|
-
'=': '#f003',
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const lineLimit = 3
|
|
25
|
-
|
|
26
|
-
const oobLimit = 1600
|
|
27
|
-
|
|
28
|
-
export function getId(r: number, g: number, b: number, unitMultiplier: number) {
|
|
29
|
-
return Math.floor((r * 255 * 255 + g * 255 + b - 1) / unitMultiplier)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function drawRef(
|
|
33
|
-
model: LinearSyntenyDisplayModel,
|
|
34
|
-
ctx1: CanvasRenderingContext2D,
|
|
35
|
-
ctx3?: CanvasRenderingContext2D,
|
|
36
|
-
) {
|
|
37
|
-
const view = getContainingView(model) as LinearSyntenyViewModel
|
|
38
|
-
const drawCurves = view.drawCurves
|
|
39
|
-
const drawCIGAR = view.drawCIGAR
|
|
40
|
-
const height = view.middleComparativeHeight
|
|
41
|
-
const width = view.width
|
|
42
|
-
const bpPerPxs = view.views.map(v => v.bpPerPx)
|
|
43
|
-
|
|
44
|
-
if (ctx3) {
|
|
45
|
-
ctx3.imageSmoothingEnabled = false
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
ctx1.beginPath()
|
|
49
|
-
const featPos = model.featPositions
|
|
50
|
-
const offsets = view.views.map(v => v.offsetPx)
|
|
51
|
-
|
|
52
|
-
const unitMultiplier = Math.floor(MAX_COLOR_RANGE / featPos.length)
|
|
53
|
-
|
|
54
|
-
// this loop is optimized to draw many thin lines with a single ctx.stroke
|
|
55
|
-
// call, a separate loop below draws larger boxes
|
|
56
|
-
ctx1.fillStyle = colorMap.M
|
|
57
|
-
ctx1.strokeStyle = colorMap.M
|
|
58
|
-
for (let i = 0; i < featPos.length; i++) {
|
|
59
|
-
const { p11, p12, p21, p22 } = featPos[i]
|
|
60
|
-
const x11 = p11.offsetPx - offsets[0]
|
|
61
|
-
const x12 = p12.offsetPx - offsets[0]
|
|
62
|
-
const x21 = p21.offsetPx - offsets[1]
|
|
63
|
-
const x22 = p22.offsetPx - offsets[1]
|
|
64
|
-
const l1 = Math.abs(x12 - x11)
|
|
65
|
-
const l2 = Math.abs(x22 - x21)
|
|
66
|
-
const y1 = 0
|
|
67
|
-
const y2 = height
|
|
68
|
-
const mid = (y2 - y1) / 2
|
|
69
|
-
|
|
70
|
-
// drawing a line if the results are thin results in much less pixellation
|
|
71
|
-
// than filling in a thin polygon
|
|
72
|
-
if (
|
|
73
|
-
l1 <= lineLimit &&
|
|
74
|
-
l2 <= lineLimit &&
|
|
75
|
-
x21 < width + oobLimit &&
|
|
76
|
-
x21 > -oobLimit
|
|
77
|
-
) {
|
|
78
|
-
ctx1.moveTo(x11, y1)
|
|
79
|
-
if (drawCurves) {
|
|
80
|
-
ctx1.bezierCurveTo(x11, mid, x21, mid, x21, y2)
|
|
81
|
-
} else {
|
|
82
|
-
ctx1.lineTo(x21, y2)
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
ctx1.stroke()
|
|
87
|
-
|
|
88
|
-
// this loop only draws small lines as a polyline, the polyline calls
|
|
89
|
-
// ctx.stroke once is much more efficient than calling stroke() many times
|
|
90
|
-
ctx1.fillStyle = colorMap.M
|
|
91
|
-
ctx1.strokeStyle = colorMap.M
|
|
92
|
-
for (let i = 0; i < featPos.length; i++) {
|
|
93
|
-
const { p11, p12, p21, p22, f, cigar } = featPos[i]
|
|
94
|
-
const x11 = p11.offsetPx - offsets[0]
|
|
95
|
-
const x12 = p12.offsetPx - offsets[0]
|
|
96
|
-
const x21 = p21.offsetPx - offsets[1]
|
|
97
|
-
const x22 = p22.offsetPx - offsets[1]
|
|
98
|
-
const l1 = Math.abs(x12 - x11)
|
|
99
|
-
const l2 = Math.abs(x22 - x21)
|
|
100
|
-
const minX = Math.min(x21, x22)
|
|
101
|
-
const maxX = Math.max(x21, x22)
|
|
102
|
-
const y1 = 0
|
|
103
|
-
const y2 = height
|
|
104
|
-
const mid = (y2 - y1) / 2
|
|
105
|
-
|
|
106
|
-
if (
|
|
107
|
-
!(l1 <= lineLimit && l2 <= lineLimit) &&
|
|
108
|
-
doesIntersect2(minX, maxX, -oobLimit, view.width + oobLimit)
|
|
109
|
-
) {
|
|
110
|
-
const s1 = f.get('strand')
|
|
111
|
-
const k1 = s1 === -1 ? x12 : x11
|
|
112
|
-
const k2 = s1 === -1 ? x11 : x12
|
|
113
|
-
|
|
114
|
-
// rev1/rev2 flip the direction of the CIGAR drawing in horizontally flipped
|
|
115
|
-
// modes. somewhat heuristically determined, but tested for
|
|
116
|
-
const rev1 = k1 < k2 ? 1 : -1
|
|
117
|
-
const rev2 = (x21 < x22 ? 1 : -1) * s1
|
|
118
|
-
|
|
119
|
-
// cx1/cx2 are the current x positions on top and bottom rows
|
|
120
|
-
let cx1 = k1
|
|
121
|
-
let cx2 = s1 === -1 ? x22 : x21
|
|
122
|
-
if (cigar?.length && drawCIGAR) {
|
|
123
|
-
// continuingFlag skips drawing commands on very small CIGAR features
|
|
124
|
-
let continuingFlag = false
|
|
125
|
-
|
|
126
|
-
// px1/px2 are the previous x positions on the top and bottom rows
|
|
127
|
-
let px1 = 0
|
|
128
|
-
let px2 = 0
|
|
129
|
-
const unitMultiplier2 = Math.floor(MAX_COLOR_RANGE / cigar.length)
|
|
130
|
-
for (let j = 0; j < cigar.length; j += 2) {
|
|
131
|
-
const idx = j * unitMultiplier2 + 1
|
|
132
|
-
|
|
133
|
-
const len = +cigar[j]
|
|
134
|
-
const op = cigar[j + 1] as keyof typeof colorMap
|
|
135
|
-
|
|
136
|
-
if (!continuingFlag) {
|
|
137
|
-
px1 = cx1
|
|
138
|
-
px2 = cx2
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const d1 = len / bpPerPxs[0]
|
|
142
|
-
const d2 = len / bpPerPxs[1]
|
|
143
|
-
|
|
144
|
-
if (op === 'M' || op === '=' || op === 'X') {
|
|
145
|
-
cx1 += d1 * rev1
|
|
146
|
-
cx2 += d2 * rev2
|
|
147
|
-
} else if (op === 'D' || op === 'N') {
|
|
148
|
-
cx1 += d1 * rev1
|
|
149
|
-
} else if (op === 'I') {
|
|
150
|
-
cx2 += d2 * rev2
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// check that we are even drawing in view here, e.g. that all
|
|
154
|
-
// points are not all less than 0 or greater than width
|
|
155
|
-
if (
|
|
156
|
-
!(
|
|
157
|
-
Math.max(px1, px2, cx1, cx2) < 0 ||
|
|
158
|
-
Math.min(px1, px2, cx1, cx2) > width
|
|
159
|
-
)
|
|
160
|
-
) {
|
|
161
|
-
// if it is a small feature and not the last element of the
|
|
162
|
-
// CIGAR (which could skip rendering it entire if we did turn
|
|
163
|
-
// it on), then turn on continuing flag
|
|
164
|
-
const isNotLast = j < cigar.length - 2
|
|
165
|
-
if (
|
|
166
|
-
Math.abs(cx1 - px1) <= 1 &&
|
|
167
|
-
Math.abs(cx2 - px2) <= 1 &&
|
|
168
|
-
isNotLast
|
|
169
|
-
) {
|
|
170
|
-
continuingFlag = true
|
|
171
|
-
} else {
|
|
172
|
-
continuingFlag = false
|
|
173
|
-
|
|
174
|
-
// allow rendering the dominant color when using continuing
|
|
175
|
-
// flag if the last element of continuing was a large
|
|
176
|
-
// feature, else just use match
|
|
177
|
-
ctx1.fillStyle =
|
|
178
|
-
colorMap[(continuingFlag && d1 > 1) || d2 > 1 ? op : 'M']
|
|
179
|
-
|
|
180
|
-
draw(ctx1, px1, cx1, y1, cx2, px2, y2, mid, drawCurves)
|
|
181
|
-
if (ctx3) {
|
|
182
|
-
ctx3.fillStyle = makeColor(idx)
|
|
183
|
-
draw(ctx3, px1, cx1, y1, cx2, px2, y2, mid, drawCurves)
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
} else {
|
|
189
|
-
draw(ctx1, x11, x12, y1, x22, x21, y2, mid, drawCurves)
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// draw click map
|
|
195
|
-
const ctx2 = model.clickMapCanvas?.getContext('2d')
|
|
196
|
-
if (!ctx2) {
|
|
197
|
-
return
|
|
198
|
-
}
|
|
199
|
-
ctx2.imageSmoothingEnabled = false
|
|
200
|
-
ctx2.clearRect(0, 0, width, height)
|
|
201
|
-
for (let i = 0; i < featPos.length; i++) {
|
|
202
|
-
const feature = featPos[i]
|
|
203
|
-
const idx = i * unitMultiplier + 1
|
|
204
|
-
ctx2.fillStyle = makeColor(idx)
|
|
205
|
-
|
|
206
|
-
// too many click map false positives with colored stroked lines
|
|
207
|
-
drawMatchSimple({
|
|
208
|
-
cb: ctx => ctx.fill(),
|
|
209
|
-
feature,
|
|
210
|
-
ctx: ctx2,
|
|
211
|
-
drawCurves,
|
|
212
|
-
offsets,
|
|
213
|
-
oobLimit,
|
|
214
|
-
viewWidth: view.width,
|
|
215
|
-
hideTiny: true,
|
|
216
|
-
height,
|
|
217
|
-
})
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
export function drawMouseoverSynteny(model: LinearSyntenyDisplayModel) {
|
|
222
|
-
const { clickId, mouseoverId } = model
|
|
223
|
-
const highResolutionScaling = 1
|
|
224
|
-
const view = getContainingView(model) as LinearSyntenyViewModel
|
|
225
|
-
const drawCurves = view.drawCurves
|
|
226
|
-
const height = view.middleComparativeHeight
|
|
227
|
-
const width = view.width
|
|
228
|
-
const ctx = model.mouseoverCanvas?.getContext('2d')
|
|
229
|
-
const offsets = view.views.map(v => v.offsetPx)
|
|
230
|
-
|
|
231
|
-
if (!ctx) {
|
|
232
|
-
return
|
|
233
|
-
}
|
|
234
|
-
ctx.resetTransform()
|
|
235
|
-
ctx.scale(highResolutionScaling, highResolutionScaling)
|
|
236
|
-
ctx.clearRect(0, 0, width, height)
|
|
237
|
-
const feature1 = model.featMap[mouseoverId || '']
|
|
238
|
-
if (feature1) {
|
|
239
|
-
ctx.fillStyle = 'rgb(0,0,0,0.1)'
|
|
240
|
-
drawMatchSimple({
|
|
241
|
-
cb: ctx => ctx.fill(),
|
|
242
|
-
feature: feature1,
|
|
243
|
-
ctx,
|
|
244
|
-
oobLimit,
|
|
245
|
-
viewWidth: view.width,
|
|
246
|
-
drawCurves,
|
|
247
|
-
offsets,
|
|
248
|
-
height,
|
|
249
|
-
})
|
|
250
|
-
}
|
|
251
|
-
const feature2 = model.featMap[clickId || '']
|
|
252
|
-
if (feature2) {
|
|
253
|
-
ctx.strokeStyle = 'rgb(0, 0, 0, 0.9)'
|
|
254
|
-
|
|
255
|
-
drawMatchSimple({
|
|
256
|
-
cb: ctx => ctx.stroke(),
|
|
257
|
-
feature: feature2,
|
|
258
|
-
ctx,
|
|
259
|
-
oobLimit,
|
|
260
|
-
viewWidth: view.width,
|
|
261
|
-
drawCurves,
|
|
262
|
-
offsets,
|
|
263
|
-
height,
|
|
264
|
-
})
|
|
265
|
-
}
|
|
266
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import DisplayType from '@jbrowse/core/pluggableElementTypes/DisplayType'
|
|
2
|
-
import PluginManager from '@jbrowse/core/PluginManager'
|
|
3
|
-
|
|
4
|
-
// locals
|
|
5
|
-
import configSchemaF from './configSchemaF'
|
|
6
|
-
import stateModelFactory from './model'
|
|
7
|
-
import { lazy } from 'react'
|
|
8
|
-
|
|
9
|
-
export default (pluginManager: PluginManager) => {
|
|
10
|
-
pluginManager.addDisplayType(() => {
|
|
11
|
-
const configSchema = configSchemaF(pluginManager)
|
|
12
|
-
return new DisplayType({
|
|
13
|
-
name: 'LinearSyntenyDisplay',
|
|
14
|
-
configSchema,
|
|
15
|
-
stateModel: stateModelFactory(configSchema),
|
|
16
|
-
trackType: 'SyntenyTrack',
|
|
17
|
-
viewType: 'LinearSyntenyView',
|
|
18
|
-
ReactComponent: lazy(() => import('./components/Component')),
|
|
19
|
-
})
|
|
20
|
-
})
|
|
21
|
-
}
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
import { types, Instance } from 'mobx-state-tree'
|
|
2
|
-
import {
|
|
3
|
-
getConf,
|
|
4
|
-
ConfigurationReference,
|
|
5
|
-
AnyConfigurationSchemaType,
|
|
6
|
-
} from '@jbrowse/core/configuration'
|
|
7
|
-
import { Feature } from '@jbrowse/core/util'
|
|
8
|
-
|
|
9
|
-
// locals
|
|
10
|
-
import baseModelFactory from '../LinearComparativeDisplay/stateModelFactory'
|
|
11
|
-
|
|
12
|
-
interface Pos {
|
|
13
|
-
offsetPx: number
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
interface FeatPos {
|
|
17
|
-
p11: Pos
|
|
18
|
-
p12: Pos
|
|
19
|
-
p21: Pos
|
|
20
|
-
p22: Pos
|
|
21
|
-
f: Feature
|
|
22
|
-
cigar: string[]
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* #stateModel LinearSyntenyDisplay
|
|
27
|
-
* extends `LinearComparativeDisplay` model
|
|
28
|
-
*/
|
|
29
|
-
function stateModelFactory(configSchema: AnyConfigurationSchemaType) {
|
|
30
|
-
return types
|
|
31
|
-
.compose(
|
|
32
|
-
'LinearSyntenyDisplay',
|
|
33
|
-
baseModelFactory(configSchema),
|
|
34
|
-
types.model({
|
|
35
|
-
/**
|
|
36
|
-
* #property
|
|
37
|
-
*/
|
|
38
|
-
type: types.literal('LinearSyntenyDisplay'),
|
|
39
|
-
/**
|
|
40
|
-
* #property
|
|
41
|
-
*/
|
|
42
|
-
configuration: ConfigurationReference(configSchema),
|
|
43
|
-
}),
|
|
44
|
-
)
|
|
45
|
-
.volatile(() => ({
|
|
46
|
-
// canvas used for drawing visible screen
|
|
47
|
-
mainCanvas: null as HTMLCanvasElement | null,
|
|
48
|
-
|
|
49
|
-
// canvas used for drawing click map with feature ids
|
|
50
|
-
// this renders a unique color per alignment, so that it can be re-traced
|
|
51
|
-
// after a feature click with getImageData at that pixel
|
|
52
|
-
clickMapCanvas: null as HTMLCanvasElement | null,
|
|
53
|
-
|
|
54
|
-
// canvas used for drawing click map with cigar data
|
|
55
|
-
// this can show if you are mousing over a insertion/deletion. it is similar
|
|
56
|
-
// in purpose to the clickMapRef but was not feasible to pack this into the
|
|
57
|
-
// clickMapRef
|
|
58
|
-
cigarClickMapCanvas: null as HTMLCanvasElement | null,
|
|
59
|
-
|
|
60
|
-
// canvas for drawing mouseover shading
|
|
61
|
-
// this is separate from the other code for speed: don't have to redraw
|
|
62
|
-
// entire canvas to do a feature's mouseover shading
|
|
63
|
-
mouseoverCanvas: null as HTMLCanvasElement | null,
|
|
64
|
-
|
|
65
|
-
// assigned by reaction
|
|
66
|
-
featPositions: [] as FeatPos[],
|
|
67
|
-
|
|
68
|
-
// currently mouse'd over feature
|
|
69
|
-
mouseoverId: undefined as string | undefined,
|
|
70
|
-
|
|
71
|
-
// currently click'd over feature
|
|
72
|
-
clickId: undefined as string | undefined,
|
|
73
|
-
|
|
74
|
-
// currently mouseover'd CIGAR subfeature
|
|
75
|
-
cigarMouseoverId: -1,
|
|
76
|
-
}))
|
|
77
|
-
.actions(self => ({
|
|
78
|
-
/**
|
|
79
|
-
* #action
|
|
80
|
-
*/
|
|
81
|
-
setFeatPositions(arg: FeatPos[]) {
|
|
82
|
-
self.featPositions = arg
|
|
83
|
-
},
|
|
84
|
-
/**
|
|
85
|
-
* #action
|
|
86
|
-
*/
|
|
87
|
-
setMainCanvasRef(ref: HTMLCanvasElement | null) {
|
|
88
|
-
self.mainCanvas = ref
|
|
89
|
-
},
|
|
90
|
-
/**
|
|
91
|
-
* #action
|
|
92
|
-
*/
|
|
93
|
-
setClickMapCanvasRef(ref: HTMLCanvasElement | null) {
|
|
94
|
-
self.clickMapCanvas = ref
|
|
95
|
-
},
|
|
96
|
-
/**
|
|
97
|
-
* #action
|
|
98
|
-
*/
|
|
99
|
-
setCigarClickMapCanvasRef(ref: HTMLCanvasElement | null) {
|
|
100
|
-
self.cigarClickMapCanvas = ref
|
|
101
|
-
},
|
|
102
|
-
/**
|
|
103
|
-
* #action
|
|
104
|
-
*/
|
|
105
|
-
setMouseoverCanvasRef(ref: HTMLCanvasElement | null) {
|
|
106
|
-
self.mouseoverCanvas = ref
|
|
107
|
-
},
|
|
108
|
-
/**
|
|
109
|
-
* #action
|
|
110
|
-
*/
|
|
111
|
-
setMouseoverId(arg?: string) {
|
|
112
|
-
self.mouseoverId = arg
|
|
113
|
-
},
|
|
114
|
-
/**
|
|
115
|
-
* #action
|
|
116
|
-
*/
|
|
117
|
-
setCigarMouseoverId(arg: number) {
|
|
118
|
-
self.cigarMouseoverId = arg
|
|
119
|
-
},
|
|
120
|
-
/**
|
|
121
|
-
* #action
|
|
122
|
-
*/
|
|
123
|
-
setClickId(arg?: string) {
|
|
124
|
-
self.clickId = arg
|
|
125
|
-
},
|
|
126
|
-
}))
|
|
127
|
-
|
|
128
|
-
.views(self => ({
|
|
129
|
-
/**
|
|
130
|
-
* #getter
|
|
131
|
-
*/
|
|
132
|
-
get adapterConfig() {
|
|
133
|
-
return {
|
|
134
|
-
name: self.parentTrack.configuration.adapter.type,
|
|
135
|
-
assemblyNames: getConf(self, 'assemblyNames'),
|
|
136
|
-
...getConf(self.parentTrack, 'adapter'),
|
|
137
|
-
}
|
|
138
|
-
},
|
|
139
|
-
/**
|
|
140
|
-
* #getter
|
|
141
|
-
*/
|
|
142
|
-
get trackIds() {
|
|
143
|
-
return getConf(self, 'trackIds') as string[]
|
|
144
|
-
},
|
|
145
|
-
/**
|
|
146
|
-
* #getter
|
|
147
|
-
*/
|
|
148
|
-
get numFeats() {
|
|
149
|
-
return self.featPositions.length
|
|
150
|
-
},
|
|
151
|
-
/**
|
|
152
|
-
* #getter
|
|
153
|
-
* used for synteny svg rendering
|
|
154
|
-
*/
|
|
155
|
-
get ready() {
|
|
156
|
-
return this.numFeats > 0
|
|
157
|
-
},
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* #getter
|
|
161
|
-
*/
|
|
162
|
-
get featMap() {
|
|
163
|
-
return Object.fromEntries(self.featPositions.map(f => [f.f.id(), f]))
|
|
164
|
-
},
|
|
165
|
-
}))
|
|
166
|
-
.actions(self => ({
|
|
167
|
-
afterAttach() {
|
|
168
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
169
|
-
;(async () => {
|
|
170
|
-
try {
|
|
171
|
-
const { doAfterAttach } = await import('./afterAttach')
|
|
172
|
-
doAfterAttach(self)
|
|
173
|
-
} catch (e) {
|
|
174
|
-
console.error(e)
|
|
175
|
-
self.setError(e)
|
|
176
|
-
}
|
|
177
|
-
})()
|
|
178
|
-
},
|
|
179
|
-
}))
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
export type LinearSyntenyDisplayStateModel = ReturnType<
|
|
183
|
-
typeof stateModelFactory
|
|
184
|
-
>
|
|
185
|
-
export type LinearSyntenyDisplayModel = Instance<LinearSyntenyDisplayStateModel>
|
|
186
|
-
|
|
187
|
-
export default stateModelFactory
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import React, { useState } from 'react'
|
|
2
|
-
import {
|
|
3
|
-
Button,
|
|
4
|
-
Checkbox,
|
|
5
|
-
CircularProgress,
|
|
6
|
-
DialogActions,
|
|
7
|
-
DialogContent,
|
|
8
|
-
FormControlLabel,
|
|
9
|
-
MenuItem,
|
|
10
|
-
TextField,
|
|
11
|
-
Typography,
|
|
12
|
-
} from '@mui/material'
|
|
13
|
-
import { Dialog, ErrorMessage } from '@jbrowse/core/ui'
|
|
14
|
-
import { ExportSvgOptions } from '../model'
|
|
15
|
-
import { getSession, useLocalStorage } from '@jbrowse/core/util'
|
|
16
|
-
|
|
17
|
-
function LoadingMessage() {
|
|
18
|
-
return (
|
|
19
|
-
<div>
|
|
20
|
-
<CircularProgress size={20} style={{ marginRight: 20 }} />
|
|
21
|
-
<Typography display="inline">Creating SVG</Typography>
|
|
22
|
-
</div>
|
|
23
|
-
)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function useSvgLocal<T>(key: string, val: T) {
|
|
27
|
-
return useLocalStorage('svg-' + key, val)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export default function ExportSvgDlg({
|
|
31
|
-
model,
|
|
32
|
-
handleClose,
|
|
33
|
-
}: {
|
|
34
|
-
model: { exportSvg(opts: ExportSvgOptions): Promise<void> }
|
|
35
|
-
handleClose: () => void
|
|
36
|
-
}) {
|
|
37
|
-
const session = getSession(model)
|
|
38
|
-
const offscreenCanvas = typeof OffscreenCanvas !== 'undefined'
|
|
39
|
-
const [rasterizeLayers, setRasterizeLayers] = useState(offscreenCanvas)
|
|
40
|
-
const [loading, setLoading] = useState(false)
|
|
41
|
-
const [filename, setFilename] = useSvgLocal('file', 'jbrowse.svg')
|
|
42
|
-
const [trackLabels, setTrackLabels] = useSvgLocal('tracklabels', 'offset')
|
|
43
|
-
const [themeName, setThemeName] = useSvgLocal(
|
|
44
|
-
'theme',
|
|
45
|
-
session.themeName || 'default',
|
|
46
|
-
)
|
|
47
|
-
const [error, setError] = useState<unknown>()
|
|
48
|
-
return (
|
|
49
|
-
<Dialog open onClose={handleClose} title="Export SVG">
|
|
50
|
-
<DialogContent>
|
|
51
|
-
{error ? (
|
|
52
|
-
<ErrorMessage error={error} />
|
|
53
|
-
) : loading ? (
|
|
54
|
-
<LoadingMessage />
|
|
55
|
-
) : null}
|
|
56
|
-
<TextField
|
|
57
|
-
helperText="filename"
|
|
58
|
-
value={filename}
|
|
59
|
-
onChange={event => setFilename(event.target.value)}
|
|
60
|
-
/>
|
|
61
|
-
<br />
|
|
62
|
-
|
|
63
|
-
<TextField
|
|
64
|
-
select
|
|
65
|
-
label="Track label positioning"
|
|
66
|
-
variant="outlined"
|
|
67
|
-
value={trackLabels}
|
|
68
|
-
style={{ width: 150 }}
|
|
69
|
-
onChange={event => setTrackLabels(event.target.value)}
|
|
70
|
-
>
|
|
71
|
-
<MenuItem value="offset">Offset</MenuItem>
|
|
72
|
-
<MenuItem value="overlay">Overlay</MenuItem>
|
|
73
|
-
<MenuItem value="left">Left</MenuItem>
|
|
74
|
-
<MenuItem value="none">None</MenuItem>
|
|
75
|
-
</TextField>
|
|
76
|
-
<br />
|
|
77
|
-
{session.allThemes ? (
|
|
78
|
-
<TextField
|
|
79
|
-
select
|
|
80
|
-
label="Theme"
|
|
81
|
-
variant="outlined"
|
|
82
|
-
value={themeName}
|
|
83
|
-
onChange={event => setThemeName(event.target.value)}
|
|
84
|
-
>
|
|
85
|
-
{Object.entries(session.allThemes()).map(([key, val]) => (
|
|
86
|
-
<MenuItem key={key} value={key}>
|
|
87
|
-
{
|
|
88
|
-
// @ts-expect-error
|
|
89
|
-
val.name || '(Unknown name)'
|
|
90
|
-
}
|
|
91
|
-
</MenuItem>
|
|
92
|
-
))}
|
|
93
|
-
</TextField>
|
|
94
|
-
) : null}
|
|
95
|
-
{offscreenCanvas ? (
|
|
96
|
-
<FormControlLabel
|
|
97
|
-
control={
|
|
98
|
-
<Checkbox
|
|
99
|
-
checked={rasterizeLayers}
|
|
100
|
-
onChange={() => setRasterizeLayers(val => !val)}
|
|
101
|
-
/>
|
|
102
|
-
}
|
|
103
|
-
label="Rasterize canvas based tracks? File may be much larger if this is turned off"
|
|
104
|
-
/>
|
|
105
|
-
) : (
|
|
106
|
-
<Typography>
|
|
107
|
-
Note: rasterizing layers not yet supported in this browser, so SVG
|
|
108
|
-
size may be large
|
|
109
|
-
</Typography>
|
|
110
|
-
)}
|
|
111
|
-
</DialogContent>
|
|
112
|
-
<DialogActions>
|
|
113
|
-
<Button
|
|
114
|
-
variant="contained"
|
|
115
|
-
color="secondary"
|
|
116
|
-
onClick={() => handleClose()}
|
|
117
|
-
>
|
|
118
|
-
Cancel
|
|
119
|
-
</Button>
|
|
120
|
-
<Button
|
|
121
|
-
variant="contained"
|
|
122
|
-
color="primary"
|
|
123
|
-
type="submit"
|
|
124
|
-
onClick={async () => {
|
|
125
|
-
setLoading(true)
|
|
126
|
-
setError(undefined)
|
|
127
|
-
try {
|
|
128
|
-
await model.exportSvg({
|
|
129
|
-
rasterizeLayers,
|
|
130
|
-
filename,
|
|
131
|
-
themeName,
|
|
132
|
-
trackLabels,
|
|
133
|
-
})
|
|
134
|
-
handleClose()
|
|
135
|
-
} catch (e) {
|
|
136
|
-
console.error(e)
|
|
137
|
-
setError(e)
|
|
138
|
-
} finally {
|
|
139
|
-
setLoading(false)
|
|
140
|
-
}
|
|
141
|
-
}}
|
|
142
|
-
>
|
|
143
|
-
Submit
|
|
144
|
-
</Button>
|
|
145
|
-
</DialogActions>
|
|
146
|
-
</Dialog>
|
|
147
|
-
)
|
|
148
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { SvgIcon, SvgIconProps } from '@mui/material'
|
|
3
|
-
|
|
4
|
-
export function Curves(props: SvgIconProps) {
|
|
5
|
-
return (
|
|
6
|
-
<SvgIcon {...props}>
|
|
7
|
-
<path
|
|
8
|
-
fill="currentColor"
|
|
9
|
-
d="M16.5,21C13.5,21 12.31,16.76 11.05,12.28C10.14,9.04 9,5 7.5,5C4.11,5 4,11.93 4,12H2C2,11.63 2.06,3 7.5,3C10.5,3 11.71,7.25 12.97,11.74C13.83,14.8 15,19 16.5,19C19.94,19 20.03,12.07 20.03,12H22.03C22.03,12.37 21.97,21 16.5,21Z"
|
|
10
|
-
/>
|
|
11
|
-
</SvgIcon>
|
|
12
|
-
)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function StraightLines(props: SvgIconProps) {
|
|
16
|
-
return (
|
|
17
|
-
<SvgIcon {...props}>
|
|
18
|
-
<path
|
|
19
|
-
fill="currentColor"
|
|
20
|
-
d="M22 12L17 22L7.1 6.04L4.24 12H2L7 2L16.9 17.96L19.76 12H22Z"
|
|
21
|
-
/>
|
|
22
|
-
</SvgIcon>
|
|
23
|
-
)
|
|
24
|
-
}
|