@jbrowse/plugin-linear-comparative-view 2.15.4 → 2.16.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/dist/LGVSyntenyDisplay/components/LaunchSyntenyViewDialog.d.ts +2 -1
- package/dist/LGVSyntenyDisplay/components/LaunchSyntenyViewDialog.js +4 -2
- package/dist/LGVSyntenyDisplay/components/util.d.ts +4 -1
- package/dist/LGVSyntenyDisplay/components/util.js +7 -15
- package/dist/LGVSyntenyDisplay/model.d.ts +26 -14
- package/dist/LGVSyntenyDisplay/model.js +23 -1
- package/dist/LaunchLinearSyntenyView.js +41 -11
- package/dist/LinearComparativeDisplay/stateModelFactory.d.ts +42 -14
- package/dist/LinearComparativeDisplay/stateModelFactory.js +20 -10
- package/dist/LinearComparativeView/components/Header.d.ts +2 -3
- package/dist/LinearComparativeView/components/Header.js +72 -62
- package/dist/LinearComparativeView/components/HeaderSearchBoxes.d.ts +6 -0
- package/dist/LinearComparativeView/components/HeaderSearchBoxes.js +34 -0
- package/dist/LinearComparativeView/components/LinearComparativeRenderArea.d.ts +6 -0
- package/dist/LinearComparativeView/components/LinearComparativeRenderArea.js +61 -0
- package/dist/LinearComparativeView/components/LinearComparativeView.d.ts +2 -4
- package/dist/LinearComparativeView/components/LinearComparativeView.js +3 -67
- package/dist/LinearComparativeView/components/Rubberband.js +1 -1
- package/dist/LinearComparativeView/index.js +3 -0
- package/dist/LinearComparativeView/model.d.ts +265 -12
- package/dist/LinearComparativeView/model.js +45 -75
- package/dist/LinearSyntenyDisplay/afterAttach.js +5 -4
- package/dist/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +47 -32
- package/dist/LinearSyntenyDisplay/components/SyntenyContextMenu.js +10 -6
- package/dist/LinearSyntenyDisplay/components/util.d.ts +7 -2
- package/dist/LinearSyntenyDisplay/components/util.js +12 -14
- package/dist/LinearSyntenyDisplay/drawSynteny.d.ts +1 -1
- package/dist/LinearSyntenyDisplay/drawSynteny.js +29 -25
- package/dist/LinearSyntenyDisplay/index.js +1 -1
- package/dist/LinearSyntenyDisplay/model.d.ts +48 -10
- package/dist/LinearSyntenyDisplay/model.js +38 -15
- package/dist/LinearSyntenyView/components/ImportForm/{ImportCustomTrack.d.ts → AddCustomTrack.d.ts} +2 -3
- package/dist/LinearSyntenyView/components/ImportForm/{ImportCustomTrack.js → AddCustomTrack.js} +3 -3
- package/dist/LinearSyntenyView/components/ImportForm/LinearSyntenyImportForm.js +195 -0
- package/dist/LinearSyntenyView/components/ImportForm/Spacer.d.ts +2 -0
- package/dist/LinearSyntenyView/components/ImportForm/Spacer.js +10 -0
- package/dist/LinearSyntenyView/components/ImportForm/TrackSelector.d.ts +10 -0
- package/dist/LinearSyntenyView/components/ImportForm/{ImportSyntenyTrackSelector.js → TrackSelector.js} +15 -20
- package/dist/LinearSyntenyView/components/ImportForm/TrackSelectorUtil.d.ts +14 -0
- package/dist/LinearSyntenyView/components/ImportForm/TrackSelectorUtil.js +52 -0
- package/dist/LinearSyntenyView/components/LinearSyntenyView.js +3 -3
- package/dist/LinearSyntenyView/index.js +1 -1
- package/dist/LinearSyntenyView/model.d.ts +267 -9
- package/dist/LinearSyntenyView/model.js +2 -2
- package/dist/LinearSyntenyView/svgcomponents/SVGLinearGenomeView.d.ts +12 -0
- package/dist/LinearSyntenyView/svgcomponents/SVGLinearGenomeView.js +19 -0
- package/dist/LinearSyntenyView/svgcomponents/SVGLinearSyntenyView.d.ts +1 -3
- package/dist/LinearSyntenyView/svgcomponents/SVGLinearSyntenyView.js +36 -27
- package/dist/LinearSyntenyViewHelper/index.d.ts +2 -0
- package/dist/LinearSyntenyViewHelper/index.js +25 -0
- package/dist/LinearSyntenyViewHelper/stateModelFactory.d.ts +30 -0
- package/dist/LinearSyntenyViewHelper/stateModelFactory.js +105 -0
- package/dist/SyntenyFeatureDetail/SyntenyFeatureDetail.d.ts +14 -0
- package/dist/SyntenyFeatureDetail/SyntenyFeatureDetail.js +100 -0
- package/dist/SyntenyFeatureDetail/index.d.ts +2 -0
- package/dist/SyntenyFeatureDetail/index.js +56 -0
- package/dist/index.js +4 -0
- package/esm/LGVSyntenyDisplay/components/LaunchSyntenyViewDialog.d.ts +2 -1
- package/esm/LGVSyntenyDisplay/components/LaunchSyntenyViewDialog.js +4 -2
- package/esm/LGVSyntenyDisplay/components/util.d.ts +4 -1
- package/esm/LGVSyntenyDisplay/components/util.js +8 -16
- package/esm/LGVSyntenyDisplay/model.d.ts +26 -14
- package/esm/LGVSyntenyDisplay/model.js +25 -3
- package/esm/LaunchLinearSyntenyView.js +41 -11
- package/esm/LinearComparativeDisplay/stateModelFactory.d.ts +42 -14
- package/esm/LinearComparativeDisplay/stateModelFactory.js +21 -11
- package/esm/LinearComparativeView/components/Header.d.ts +2 -3
- package/esm/LinearComparativeView/components/Header.js +73 -63
- package/esm/LinearComparativeView/components/HeaderSearchBoxes.d.ts +6 -0
- package/esm/LinearComparativeView/components/HeaderSearchBoxes.js +29 -0
- package/esm/LinearComparativeView/components/LinearComparativeRenderArea.d.ts +6 -0
- package/esm/LinearComparativeView/components/LinearComparativeRenderArea.js +56 -0
- package/esm/LinearComparativeView/components/LinearComparativeView.d.ts +2 -4
- package/esm/LinearComparativeView/components/LinearComparativeView.js +3 -67
- package/esm/LinearComparativeView/components/Rubberband.js +1 -1
- package/esm/LinearComparativeView/index.js +3 -0
- package/esm/LinearComparativeView/model.d.ts +265 -12
- package/esm/LinearComparativeView/model.js +47 -77
- package/esm/LinearSyntenyDisplay/afterAttach.js +5 -4
- package/esm/LinearSyntenyDisplay/components/LinearSyntenyRendering.js +48 -33
- package/esm/LinearSyntenyDisplay/components/SyntenyContextMenu.js +10 -6
- package/esm/LinearSyntenyDisplay/components/util.d.ts +7 -2
- package/esm/LinearSyntenyDisplay/components/util.js +12 -14
- package/esm/LinearSyntenyDisplay/drawSynteny.d.ts +1 -1
- package/esm/LinearSyntenyDisplay/drawSynteny.js +29 -25
- package/esm/LinearSyntenyDisplay/index.js +1 -1
- package/esm/LinearSyntenyDisplay/model.d.ts +48 -10
- package/esm/LinearSyntenyDisplay/model.js +38 -15
- package/esm/LinearSyntenyView/components/ImportForm/{ImportCustomTrack.d.ts → AddCustomTrack.d.ts} +2 -3
- package/esm/LinearSyntenyView/components/ImportForm/{ImportCustomTrack.js → AddCustomTrack.js} +3 -3
- package/esm/LinearSyntenyView/components/ImportForm/LinearSyntenyImportForm.js +167 -0
- package/esm/LinearSyntenyView/components/ImportForm/Spacer.d.ts +2 -0
- package/esm/LinearSyntenyView/components/ImportForm/Spacer.js +4 -0
- package/esm/LinearSyntenyView/components/ImportForm/TrackSelector.d.ts +10 -0
- package/esm/LinearSyntenyView/components/ImportForm/{ImportSyntenyTrackSelector.js → TrackSelector.js} +15 -20
- package/esm/LinearSyntenyView/components/ImportForm/TrackSelectorUtil.d.ts +14 -0
- package/esm/LinearSyntenyView/components/ImportForm/TrackSelectorUtil.js +23 -0
- package/esm/LinearSyntenyView/components/LinearSyntenyView.js +3 -3
- package/esm/LinearSyntenyView/index.js +1 -1
- package/esm/LinearSyntenyView/model.d.ts +267 -9
- package/esm/LinearSyntenyView/model.js +2 -2
- package/esm/LinearSyntenyView/svgcomponents/SVGLinearGenomeView.d.ts +12 -0
- package/esm/LinearSyntenyView/svgcomponents/SVGLinearGenomeView.js +13 -0
- package/esm/LinearSyntenyView/svgcomponents/SVGLinearSyntenyView.d.ts +1 -3
- package/esm/LinearSyntenyView/svgcomponents/SVGLinearSyntenyView.js +38 -29
- package/esm/LinearSyntenyViewHelper/index.d.ts +2 -0
- package/esm/LinearSyntenyViewHelper/index.js +19 -0
- package/esm/LinearSyntenyViewHelper/stateModelFactory.d.ts +30 -0
- package/esm/LinearSyntenyViewHelper/stateModelFactory.js +102 -0
- package/esm/SyntenyFeatureDetail/SyntenyFeatureDetail.d.ts +14 -0
- package/esm/SyntenyFeatureDetail/SyntenyFeatureDetail.js +72 -0
- package/esm/SyntenyFeatureDetail/index.d.ts +2 -0
- package/esm/SyntenyFeatureDetail/index.js +27 -0
- package/esm/index.js +4 -0
- package/package.json +3 -3
- package/dist/LinearSyntenyView/components/ImportForm/ImportSyntenyTrackSelector.d.ts +0 -9
- package/dist/LinearSyntenyView/components/ImportForm/index.js +0 -138
- package/esm/LinearSyntenyView/components/ImportForm/ImportSyntenyTrackSelector.d.ts +0 -9
- package/esm/LinearSyntenyView/components/ImportForm/index.js +0 -110
- /package/dist/LinearSyntenyView/components/ImportForm/{index.d.ts → LinearSyntenyImportForm.d.ts} +0 -0
- /package/esm/LinearSyntenyView/components/ImportForm/{index.d.ts → LinearSyntenyImportForm.d.ts} +0 -0
|
@@ -45,21 +45,23 @@ const useStyles = (0, mui_1.makeStyles)()({
|
|
|
45
45
|
rel: {
|
|
46
46
|
position: 'relative',
|
|
47
47
|
},
|
|
48
|
-
|
|
48
|
+
mouseoverCanvas: {
|
|
49
|
+
imageRendering: 'pixelated',
|
|
49
50
|
position: 'absolute',
|
|
50
|
-
},
|
|
51
|
-
none: {
|
|
52
51
|
pointEvents: 'none',
|
|
53
52
|
},
|
|
53
|
+
mainCanvas: {
|
|
54
|
+
position: 'absolute',
|
|
55
|
+
},
|
|
54
56
|
});
|
|
55
57
|
const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, }) {
|
|
56
|
-
const { classes
|
|
58
|
+
const { classes } = useStyles();
|
|
59
|
+
const { mouseoverId, height } = model;
|
|
57
60
|
const xOffset = (0, react_1.useRef)(0);
|
|
58
|
-
const currScrollFrame = (0, react_1.useRef)();
|
|
59
61
|
const view = (0, util_1.getContainingView)(model);
|
|
60
|
-
const height = view.middleComparativeHeight;
|
|
61
62
|
const width = view.width;
|
|
62
63
|
const delta = (0, react_1.useRef)(0);
|
|
64
|
+
const scheduled = (0, react_1.useRef)(false);
|
|
63
65
|
const timeout = (0, react_1.useRef)();
|
|
64
66
|
const [anchorEl, setAnchorEl] = (0, react_1.useState)();
|
|
65
67
|
const [tooltip, setTooltip] = (0, react_1.useState)('');
|
|
@@ -67,18 +69,25 @@ const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, })
|
|
|
67
69
|
const [mouseCurrDownX, setMouseCurrDownX] = (0, react_1.useState)();
|
|
68
70
|
const [mouseInitialDownX, setMouseInitialDownX] = (0, react_1.useState)();
|
|
69
71
|
const [currY, setCurrY] = (0, react_1.useState)();
|
|
70
|
-
const
|
|
72
|
+
const mainSyntenyCanvasRefp = (0, react_1.useRef)();
|
|
71
73
|
// these useCallbacks avoid new refs from being created on any mouseover,
|
|
72
74
|
// etc.
|
|
73
75
|
// biome-ignore lint/correctness/useExhaustiveDependencies:
|
|
74
|
-
const
|
|
76
|
+
const mouseoverDetectionCanvasRef = (0, react_1.useCallback)((ref) => {
|
|
75
77
|
model.setMouseoverCanvasRef(ref);
|
|
76
78
|
},
|
|
77
79
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
78
80
|
[model, height, width]);
|
|
79
81
|
// biome-ignore lint/correctness/useExhaustiveDependencies:
|
|
80
|
-
const
|
|
82
|
+
const mainSyntenyCanvasRef = (0, react_1.useCallback)((ref) => {
|
|
81
83
|
model.setMainCanvasRef(ref);
|
|
84
|
+
mainSyntenyCanvasRefp.current = ref; // this ref is additionally used in useEffect below
|
|
85
|
+
},
|
|
86
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
87
|
+
[model, height, width]);
|
|
88
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies:
|
|
89
|
+
(0, react_1.useEffect)(() => {
|
|
90
|
+
var _a;
|
|
82
91
|
function onWheel(event) {
|
|
83
92
|
event.preventDefault();
|
|
84
93
|
if (event.ctrlKey) {
|
|
@@ -90,11 +99,14 @@ const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, })
|
|
|
90
99
|
clearTimeout(timeout.current);
|
|
91
100
|
}
|
|
92
101
|
timeout.current = setTimeout(() => {
|
|
102
|
+
var _a;
|
|
93
103
|
for (const v of view.views) {
|
|
94
104
|
v.setScaleFactor(1);
|
|
95
105
|
v.zoomTo(delta.current > 0
|
|
96
106
|
? v.bpPerPx * (1 + delta.current)
|
|
97
|
-
: v.bpPerPx / (1 - delta.current), event.clientX -
|
|
107
|
+
: v.bpPerPx / (1 - delta.current), event.clientX -
|
|
108
|
+
(((_a = mainSyntenyCanvasRefp.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().left) ||
|
|
109
|
+
0));
|
|
98
110
|
}
|
|
99
111
|
delta.current = 0;
|
|
100
112
|
}, 300);
|
|
@@ -103,56 +115,55 @@ const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, })
|
|
|
103
115
|
if (Math.abs(event.deltaY) < Math.abs(event.deltaX)) {
|
|
104
116
|
xOffset.current += event.deltaX / 2;
|
|
105
117
|
}
|
|
106
|
-
if (
|
|
107
|
-
|
|
118
|
+
if (!scheduled.current) {
|
|
119
|
+
scheduled.current = true;
|
|
120
|
+
window.requestAnimationFrame(() => {
|
|
108
121
|
(0, mobx_1.transaction)(() => {
|
|
109
122
|
for (const v of view.views) {
|
|
110
123
|
v.horizontalScroll(xOffset.current);
|
|
111
124
|
}
|
|
112
125
|
xOffset.current = 0;
|
|
113
|
-
|
|
126
|
+
scheduled.current = false;
|
|
114
127
|
});
|
|
115
128
|
});
|
|
116
129
|
}
|
|
117
130
|
}
|
|
118
131
|
}
|
|
119
|
-
|
|
120
|
-
// this is a react 19-ism to have a cleanup in the ref callback
|
|
121
|
-
// https://react.dev/blog/2024/04/25/react-19#cleanup-functions-for-refs
|
|
122
|
-
// note: it warns in earlier versions of react
|
|
132
|
+
(_a = mainSyntenyCanvasRefp.current) === null || _a === void 0 ? void 0 : _a.addEventListener('wheel', onWheel);
|
|
123
133
|
return () => {
|
|
124
|
-
|
|
134
|
+
var _a;
|
|
135
|
+
(_a = mainSyntenyCanvasRefp.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('wheel', onWheel);
|
|
125
136
|
};
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
[model, height, width]);
|
|
137
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
138
|
+
}, [model, height, width]);
|
|
129
139
|
// biome-ignore lint/correctness/useExhaustiveDependencies:
|
|
130
|
-
const
|
|
140
|
+
const clickMapCanvasRef = (0, react_1.useCallback)((ref) => {
|
|
131
141
|
model.setClickMapCanvasRef(ref);
|
|
132
142
|
},
|
|
133
143
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
134
144
|
[model, height, width]);
|
|
135
145
|
// biome-ignore lint/correctness/useExhaustiveDependencies:
|
|
136
|
-
const
|
|
146
|
+
const cigarClickMapCanvasRef = (0, react_1.useCallback)((ref) => {
|
|
137
147
|
model.setCigarClickMapCanvasRef(ref);
|
|
138
148
|
},
|
|
139
149
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
140
150
|
[model, height, width]);
|
|
141
151
|
return (react_1.default.createElement("div", { className: classes.rel },
|
|
142
|
-
react_1.default.createElement("canvas", { ref:
|
|
143
|
-
react_1.default.createElement("canvas", { ref:
|
|
152
|
+
react_1.default.createElement("canvas", { ref: mouseoverDetectionCanvasRef, width: width, height: height, className: classes.mouseoverCanvas }),
|
|
153
|
+
react_1.default.createElement("canvas", { ref: mainSyntenyCanvasRef, onMouseMove: event => {
|
|
144
154
|
var _a;
|
|
145
155
|
if (mouseCurrDownX !== undefined) {
|
|
146
156
|
xOffset.current += mouseCurrDownX - event.clientX;
|
|
147
157
|
setMouseCurrDownX(event.clientX);
|
|
148
|
-
if (
|
|
149
|
-
|
|
158
|
+
if (!scheduled.current) {
|
|
159
|
+
scheduled.current = true;
|
|
160
|
+
window.requestAnimationFrame(() => {
|
|
150
161
|
(0, mobx_1.transaction)(() => {
|
|
151
162
|
for (const v of view.views) {
|
|
152
163
|
v.horizontalScroll(xOffset.current);
|
|
153
164
|
}
|
|
154
165
|
xOffset.current = 0;
|
|
155
|
-
|
|
166
|
+
scheduled.current = false;
|
|
156
167
|
});
|
|
157
168
|
});
|
|
158
169
|
}
|
|
@@ -186,7 +197,11 @@ const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, })
|
|
|
186
197
|
const { f, cigar } = model.featPositions[id];
|
|
187
198
|
const unitMultiplier2 = Math.floor(drawSynteny_1.MAX_COLOR_RANGE / cigar.length);
|
|
188
199
|
const cigarIdx = (0, drawSynteny_1.getId)(r2, g2, b2, unitMultiplier2);
|
|
189
|
-
setTooltip((0, util_2.getTooltip)(
|
|
200
|
+
setTooltip((0, util_2.getTooltip)({
|
|
201
|
+
feature: f,
|
|
202
|
+
cigarOp: cigar[cigarIdx],
|
|
203
|
+
cigarOpLen: cigar[cigarIdx + 1],
|
|
204
|
+
}));
|
|
190
205
|
}
|
|
191
206
|
}
|
|
192
207
|
}, onMouseLeave: () => {
|
|
@@ -204,9 +219,9 @@ const LinearSyntenyRendering = (0, mobx_react_1.observer)(function ({ model, })
|
|
|
204
219
|
}
|
|
205
220
|
}, onContextMenu: evt => {
|
|
206
221
|
(0, util_2.onSynContextClick)(evt, model, setAnchorEl);
|
|
207
|
-
}, "data-testid": "synteny_canvas", className: classes.
|
|
208
|
-
react_1.default.createElement("canvas", { ref:
|
|
209
|
-
react_1.default.createElement("canvas", { ref:
|
|
222
|
+
}, "data-testid": "synteny_canvas", className: classes.mainCanvas, width: width, height: height }),
|
|
223
|
+
react_1.default.createElement("canvas", { ref: clickMapCanvasRef, className: classes.pix, width: width, height: height }),
|
|
224
|
+
react_1.default.createElement("canvas", { ref: cigarClickMapCanvasRef, className: classes.pix, width: width, height: height }),
|
|
210
225
|
mouseoverId && tooltip && currX && currY ? (react_1.default.createElement(SyntenyTooltip, { title: tooltip })) : null,
|
|
211
226
|
anchorEl ? (react_1.default.createElement(SyntenyContextMenu_1.default, { model: model, anchorEl: anchorEl, onClose: () => {
|
|
212
227
|
setAnchorEl(undefined);
|
|
@@ -39,13 +39,17 @@ function SyntenyContextMenu({ model, onClose, anchorEl, }) {
|
|
|
39
39
|
const end = f.get('end');
|
|
40
40
|
const refName = f.get('refName');
|
|
41
41
|
const mate = f.get('mate');
|
|
42
|
-
view.views[
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
const l1 = view.views[model.level];
|
|
43
|
+
const l2 = view.views[model.level + 1];
|
|
44
|
+
l1.navToLocString(`${refName}:${start}-${end}`).catch((e) => {
|
|
45
|
+
const err = `${l1.assemblyNames[0]}:${e}`;
|
|
46
|
+
console.error(err);
|
|
47
|
+
(0, util_1.getSession)(model).notifyError(err, e);
|
|
45
48
|
});
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
+
l2.navToLocString(`${mate.refName}:${mate.start}-${mate.end}`).catch((e) => {
|
|
50
|
+
const err = `${l2.assemblyNames[0]}:${e}`;
|
|
51
|
+
console.error(err);
|
|
52
|
+
(0, util_1.getSession)(model).notifyError(err, e);
|
|
49
53
|
});
|
|
50
54
|
},
|
|
51
55
|
},
|
|
@@ -19,10 +19,11 @@ interface FeatPos {
|
|
|
19
19
|
f: Feature;
|
|
20
20
|
cigar: string[];
|
|
21
21
|
}
|
|
22
|
-
export declare function drawMatchSimple({ feature, ctx, offsets, cb, height, drawCurves, oobLimit, viewWidth, hideTiny, }: {
|
|
22
|
+
export declare function drawMatchSimple({ feature, ctx, offsets, level, cb, height, drawCurves, oobLimit, viewWidth, hideTiny, }: {
|
|
23
23
|
feature: FeatPos;
|
|
24
24
|
ctx: CanvasRenderingContext2D;
|
|
25
25
|
offsets: number[];
|
|
26
|
+
level: number;
|
|
26
27
|
oobLimit: number;
|
|
27
28
|
viewWidth: number;
|
|
28
29
|
cb: (ctx: CanvasRenderingContext2D) => void;
|
|
@@ -35,5 +36,9 @@ export declare function drawBox(ctx: CanvasRenderingContext2D, x1: number, x2: n
|
|
|
35
36
|
export declare function drawBezierBox(ctx: CanvasRenderingContext2D, x1: number, x2: number, y1: number, x3: number, x4: number, y2: number, mid: number): void;
|
|
36
37
|
export declare function onSynClick(event: React.MouseEvent, model: LinearSyntenyDisplayModel): import("../model").FeatPos | undefined;
|
|
37
38
|
export declare function onSynContextClick(event: React.MouseEvent, model: LinearSyntenyDisplayModel, setAnchorEl: (arg: ClickCoord) => void): void;
|
|
38
|
-
export declare function getTooltip(
|
|
39
|
+
export declare function getTooltip({ feature, cigarOp, cigarOpLen, }: {
|
|
40
|
+
feature: Feature;
|
|
41
|
+
cigarOp?: string;
|
|
42
|
+
cigarOpLen?: string;
|
|
43
|
+
}): string;
|
|
39
44
|
export {};
|
|
@@ -10,12 +10,12 @@ exports.getTooltip = getTooltip;
|
|
|
10
10
|
const util_1 = require("@jbrowse/core/util");
|
|
11
11
|
// locals
|
|
12
12
|
const drawSynteny_1 = require("../drawSynteny");
|
|
13
|
-
function drawMatchSimple({ feature, ctx, offsets, cb, height, drawCurves, oobLimit, viewWidth, hideTiny, }) {
|
|
13
|
+
function drawMatchSimple({ feature, ctx, offsets, level, cb, height, drawCurves, oobLimit, viewWidth, hideTiny, }) {
|
|
14
14
|
const { p11, p12, p21, p22 } = feature;
|
|
15
|
-
const x11 = p11.offsetPx - offsets[
|
|
16
|
-
const x12 = p12.offsetPx - offsets[
|
|
17
|
-
const x21 = p21.offsetPx - offsets[1];
|
|
18
|
-
const x22 = p22.offsetPx - offsets[1];
|
|
15
|
+
const x11 = p11.offsetPx - offsets[level];
|
|
16
|
+
const x12 = p12.offsetPx - offsets[level];
|
|
17
|
+
const x21 = p21.offsetPx - offsets[level + 1];
|
|
18
|
+
const x22 = p22.offsetPx - offsets[level + 1];
|
|
19
19
|
const l1 = Math.abs(x12 - x11);
|
|
20
20
|
const l2 = Math.abs(x22 - x21);
|
|
21
21
|
const y1 = 0;
|
|
@@ -63,7 +63,6 @@ function drawBox(ctx, x1, x2, y1, x3, x4, y2) {
|
|
|
63
63
|
ctx.lineTo(x3, y2);
|
|
64
64
|
ctx.lineTo(x4, y2);
|
|
65
65
|
ctx.closePath();
|
|
66
|
-
ctx.fill();
|
|
67
66
|
}
|
|
68
67
|
function drawBezierBox(ctx, x1, x2, y1, x3, x4, y2, mid) {
|
|
69
68
|
const len1 = Math.abs(x1 - x2);
|
|
@@ -83,13 +82,11 @@ function drawBezierBox(ctx, x1, x2, y1, x3, x4, y2, mid) {
|
|
|
83
82
|
ctx.lineTo(x4, y2);
|
|
84
83
|
ctx.bezierCurveTo(x4, mid, x1, mid, x1, y1);
|
|
85
84
|
ctx.closePath();
|
|
86
|
-
ctx.fill();
|
|
87
85
|
}
|
|
88
86
|
function onSynClick(event, model) {
|
|
89
87
|
const view = (0, util_1.getContainingView)(model);
|
|
90
88
|
const track = (0, util_1.getContainingTrack)(model);
|
|
91
|
-
const ref1 = model
|
|
92
|
-
const ref2 = model.cigarClickMapCanvas;
|
|
89
|
+
const { featPositions, numFeats, clickMapCanvas: ref1, cigarClickMapCanvas: ref2, level, } = model;
|
|
93
90
|
if (!ref1 || !ref2) {
|
|
94
91
|
return;
|
|
95
92
|
}
|
|
@@ -102,18 +99,19 @@ function onSynClick(event, model) {
|
|
|
102
99
|
const x = event.clientX - rect.left;
|
|
103
100
|
const y = event.clientY - rect.top;
|
|
104
101
|
const [r1, g1, b1] = ctx1.getImageData(x, y, 1, 1).data;
|
|
105
|
-
const unitMultiplier = Math.floor(drawSynteny_1.MAX_COLOR_RANGE /
|
|
102
|
+
const unitMultiplier = Math.floor(drawSynteny_1.MAX_COLOR_RANGE / numFeats);
|
|
106
103
|
const id = (0, drawSynteny_1.getId)(r1, g1, b1, unitMultiplier);
|
|
107
|
-
const feat =
|
|
104
|
+
const feat = featPositions[id];
|
|
108
105
|
if (feat) {
|
|
109
106
|
const { f } = feat;
|
|
110
107
|
model.setClickId(f.id());
|
|
111
108
|
const session = (0, util_1.getSession)(model);
|
|
112
109
|
if ((0, util_1.isSessionModelWithWidgets)(session)) {
|
|
113
|
-
session.showWidget(session.addWidget('
|
|
110
|
+
session.showWidget(session.addWidget('SyntenyFeatureWidget', 'syntenyFeature', {
|
|
114
111
|
view,
|
|
115
112
|
track,
|
|
116
113
|
featureData: f.toJSON(),
|
|
114
|
+
level,
|
|
117
115
|
}));
|
|
118
116
|
}
|
|
119
117
|
}
|
|
@@ -144,9 +142,9 @@ function onSynContextClick(event, model, setAnchorEl) {
|
|
|
144
142
|
setAnchorEl({ clientX, clientY, feature: f });
|
|
145
143
|
}
|
|
146
144
|
}
|
|
147
|
-
function getTooltip(
|
|
145
|
+
function getTooltip({ feature, cigarOp, cigarOpLen, }) {
|
|
148
146
|
// @ts-expect-error
|
|
149
|
-
const f1 =
|
|
147
|
+
const f1 = feature.toJSON();
|
|
150
148
|
const f2 = f1.mate;
|
|
151
149
|
const l1 = f1.end - f1.start;
|
|
152
150
|
const l2 = f2.end - f2.start;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LinearSyntenyDisplayModel } from './model';
|
|
2
2
|
export declare const MAX_COLOR_RANGE: number;
|
|
3
3
|
export declare function getId(r: number, g: number, b: number, unitMultiplier: number): number;
|
|
4
|
-
export declare function drawRef(model: LinearSyntenyDisplayModel, ctx1: CanvasRenderingContext2D, ctx3?: CanvasRenderingContext2D):
|
|
4
|
+
export declare function drawRef(model: LinearSyntenyDisplayModel, ctx1: CanvasRenderingContext2D, ctx3?: CanvasRenderingContext2D): void;
|
|
5
5
|
export declare function drawMouseoverSynteny(model: LinearSyntenyDisplayModel): void;
|
|
@@ -31,25 +31,24 @@ function drawRef(model, ctx1, ctx3) {
|
|
|
31
31
|
const view = (0, util_1.getContainingView)(model);
|
|
32
32
|
const drawCurves = view.drawCurves;
|
|
33
33
|
const drawCIGAR = view.drawCIGAR;
|
|
34
|
-
const height =
|
|
34
|
+
const { level, height, featPositions } = model;
|
|
35
35
|
const width = view.width;
|
|
36
36
|
const bpPerPxs = view.views.map(v => v.bpPerPx);
|
|
37
37
|
if (ctx3) {
|
|
38
38
|
ctx3.imageSmoothingEnabled = false;
|
|
39
39
|
}
|
|
40
40
|
ctx1.beginPath();
|
|
41
|
-
const featPos = model.featPositions;
|
|
42
41
|
const offsets = view.views.map(v => v.offsetPx);
|
|
43
|
-
const unitMultiplier = Math.floor(exports.MAX_COLOR_RANGE /
|
|
42
|
+
const unitMultiplier = Math.floor(exports.MAX_COLOR_RANGE / featPositions.length);
|
|
44
43
|
// this loop is optimized to draw many thin lines with a single ctx.stroke
|
|
45
44
|
// call, a separate loop below draws larger boxes
|
|
46
45
|
ctx1.fillStyle = colorMap.M;
|
|
47
46
|
ctx1.strokeStyle = colorMap.M;
|
|
48
|
-
for (const { p11, p12, p21, p22 } of
|
|
49
|
-
const x11 = p11.offsetPx - offsets[
|
|
50
|
-
const x12 = p12.offsetPx - offsets[
|
|
51
|
-
const x21 = p21.offsetPx - offsets[1];
|
|
52
|
-
const x22 = p22.offsetPx - offsets[1];
|
|
47
|
+
for (const { p11, p12, p21, p22 } of featPositions) {
|
|
48
|
+
const x11 = p11.offsetPx - offsets[level];
|
|
49
|
+
const x12 = p12.offsetPx - offsets[level];
|
|
50
|
+
const x21 = p21.offsetPx - offsets[level + 1];
|
|
51
|
+
const x22 = p22.offsetPx - offsets[level + 1];
|
|
53
52
|
const l1 = Math.abs(x12 - x11);
|
|
54
53
|
const l2 = Math.abs(x22 - x21);
|
|
55
54
|
const y1 = 0;
|
|
@@ -75,11 +74,11 @@ function drawRef(model, ctx1, ctx3) {
|
|
|
75
74
|
// ctx.stroke once is much more efficient than calling stroke() many times
|
|
76
75
|
ctx1.fillStyle = colorMap.M;
|
|
77
76
|
ctx1.strokeStyle = colorMap.M;
|
|
78
|
-
for (const { p11, p12, p21, p22, f, cigar } of
|
|
79
|
-
const x11 = p11.offsetPx - offsets[
|
|
80
|
-
const x12 = p12.offsetPx - offsets[
|
|
81
|
-
const x21 = p21.offsetPx - offsets[1];
|
|
82
|
-
const x22 = p22.offsetPx - offsets[1];
|
|
77
|
+
for (const { p11, p12, p21, p22, f, cigar } of featPositions) {
|
|
78
|
+
const x11 = p11.offsetPx - offsets[level];
|
|
79
|
+
const x12 = p12.offsetPx - offsets[level];
|
|
80
|
+
const x21 = p21.offsetPx - offsets[level + 1];
|
|
81
|
+
const x22 = p22.offsetPx - offsets[level + 1];
|
|
83
82
|
const l1 = Math.abs(x12 - x11);
|
|
84
83
|
const l2 = Math.abs(x22 - x21);
|
|
85
84
|
const minX = Math.min(x21, x22);
|
|
@@ -114,8 +113,8 @@ function drawRef(model, ctx1, ctx3) {
|
|
|
114
113
|
px1 = cx1;
|
|
115
114
|
px2 = cx2;
|
|
116
115
|
}
|
|
117
|
-
const d1 = len / bpPerPxs[
|
|
118
|
-
const d2 = len / bpPerPxs[1];
|
|
116
|
+
const d1 = len / bpPerPxs[level];
|
|
117
|
+
const d2 = len / bpPerPxs[level + 1];
|
|
119
118
|
if (op === 'M' || op === '=' || op === 'X') {
|
|
120
119
|
cx1 += d1 * rev1;
|
|
121
120
|
cx2 += d2 * rev2;
|
|
@@ -141,16 +140,18 @@ function drawRef(model, ctx1, ctx3) {
|
|
|
141
140
|
continuingFlag = true;
|
|
142
141
|
}
|
|
143
142
|
else {
|
|
144
|
-
// allow rendering the dominant color when using continuing
|
|
145
|
-
// if the last element of continuing was a large
|
|
146
|
-
// just use match
|
|
143
|
+
// allow rendering the dominant color when using continuing
|
|
144
|
+
// flag if the last element of continuing was a large
|
|
145
|
+
// feature, else just use match
|
|
147
146
|
ctx1.fillStyle =
|
|
148
147
|
colorMap[(continuingFlag && d1 > 1) || d2 > 1 ? op : 'M'];
|
|
149
148
|
continuingFlag = false;
|
|
150
149
|
(0, util_2.draw)(ctx1, px1, cx1, y1, cx2, px2, y2, mid, drawCurves);
|
|
150
|
+
ctx1.fill();
|
|
151
151
|
if (ctx3) {
|
|
152
152
|
ctx3.fillStyle = makeColor(idx);
|
|
153
153
|
(0, util_2.draw)(ctx3, px1, cx1, y1, cx2, px2, y2, mid, drawCurves);
|
|
154
|
+
ctx3.fill();
|
|
154
155
|
}
|
|
155
156
|
}
|
|
156
157
|
}
|
|
@@ -158,6 +159,7 @@ function drawRef(model, ctx1, ctx3) {
|
|
|
158
159
|
}
|
|
159
160
|
else {
|
|
160
161
|
(0, util_2.draw)(ctx1, x11, x12, y1, x22, x21, y2, mid, drawCurves);
|
|
162
|
+
ctx1.fill();
|
|
161
163
|
}
|
|
162
164
|
}
|
|
163
165
|
}
|
|
@@ -168,8 +170,8 @@ function drawRef(model, ctx1, ctx3) {
|
|
|
168
170
|
}
|
|
169
171
|
ctx2.imageSmoothingEnabled = false;
|
|
170
172
|
ctx2.clearRect(0, 0, width, height);
|
|
171
|
-
for (let i = 0; i <
|
|
172
|
-
const feature =
|
|
173
|
+
for (let i = 0; i < featPositions.length; i++) {
|
|
174
|
+
const feature = featPositions[i];
|
|
173
175
|
const idx = i * unitMultiplier + 1;
|
|
174
176
|
ctx2.fillStyle = makeColor(idx);
|
|
175
177
|
// too many click map false positives with colored stroked lines
|
|
@@ -180,6 +182,7 @@ function drawRef(model, ctx1, ctx3) {
|
|
|
180
182
|
feature,
|
|
181
183
|
ctx: ctx2,
|
|
182
184
|
drawCurves,
|
|
185
|
+
level,
|
|
183
186
|
offsets,
|
|
184
187
|
oobLimit,
|
|
185
188
|
viewWidth: view.width,
|
|
@@ -187,15 +190,14 @@ function drawRef(model, ctx1, ctx3) {
|
|
|
187
190
|
height,
|
|
188
191
|
});
|
|
189
192
|
}
|
|
190
|
-
return undefined;
|
|
191
193
|
}
|
|
192
194
|
function drawMouseoverSynteny(model) {
|
|
193
195
|
var _a;
|
|
194
|
-
const { clickId, mouseoverId } = model;
|
|
196
|
+
const { level, clickId, mouseoverId } = model;
|
|
195
197
|
const highResolutionScaling = 1;
|
|
196
198
|
const view = (0, util_1.getContainingView)(model);
|
|
197
199
|
const drawCurves = view.drawCurves;
|
|
198
|
-
const height =
|
|
200
|
+
const height = model.height;
|
|
199
201
|
const width = view.width;
|
|
200
202
|
const ctx = (_a = model.mouseoverCanvas) === null || _a === void 0 ? void 0 : _a.getContext('2d');
|
|
201
203
|
const offsets = view.views.map(v => v.offsetPx);
|
|
@@ -205,14 +207,16 @@ function drawMouseoverSynteny(model) {
|
|
|
205
207
|
ctx.resetTransform();
|
|
206
208
|
ctx.scale(highResolutionScaling, highResolutionScaling);
|
|
207
209
|
ctx.clearRect(0, 0, width, height);
|
|
210
|
+
ctx.strokeStyle = 'rgba(0, 0, 0, 0.9)';
|
|
211
|
+
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
|
|
208
212
|
const feature1 = model.featMap[mouseoverId || ''];
|
|
209
213
|
if (feature1) {
|
|
210
|
-
ctx.fillStyle = 'rgb(0,0,0,0.1)';
|
|
211
214
|
(0, util_2.drawMatchSimple)({
|
|
212
215
|
cb: ctx => {
|
|
213
216
|
ctx.fill();
|
|
214
217
|
},
|
|
215
218
|
feature: feature1,
|
|
219
|
+
level,
|
|
216
220
|
ctx,
|
|
217
221
|
oobLimit,
|
|
218
222
|
viewWidth: view.width,
|
|
@@ -223,13 +227,13 @@ function drawMouseoverSynteny(model) {
|
|
|
223
227
|
}
|
|
224
228
|
const feature2 = model.featMap[clickId || ''];
|
|
225
229
|
if (feature2) {
|
|
226
|
-
ctx.strokeStyle = 'rgb(0, 0, 0, 0.9)';
|
|
227
230
|
(0, util_2.drawMatchSimple)({
|
|
228
231
|
cb: ctx => {
|
|
229
232
|
ctx.stroke();
|
|
230
233
|
},
|
|
231
234
|
feature: feature2,
|
|
232
235
|
ctx,
|
|
236
|
+
level,
|
|
233
237
|
oobLimit,
|
|
234
238
|
viewWidth: view.width,
|
|
235
239
|
drawCurves,
|
|
@@ -40,7 +40,7 @@ function LinearSyntenyDisplayF(pluginManager) {
|
|
|
40
40
|
configSchema,
|
|
41
41
|
stateModel: (0, model_1.default)(configSchema),
|
|
42
42
|
trackType: 'SyntenyTrack',
|
|
43
|
-
viewType: '
|
|
43
|
+
viewType: 'LinearSyntenyViewHelper',
|
|
44
44
|
ReactComponent: (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./components/Component')))),
|
|
45
45
|
});
|
|
46
46
|
});
|
|
@@ -24,7 +24,6 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
24
24
|
} & {
|
|
25
25
|
type: import("mobx-state-tree").ISimpleType<"LinearComparativeDisplay">;
|
|
26
26
|
configuration: AnyConfigurationSchemaType;
|
|
27
|
-
height: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
28
27
|
} & {
|
|
29
28
|
/**
|
|
30
29
|
* #property
|
|
@@ -77,9 +76,7 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
77
76
|
rendererTypeName: string;
|
|
78
77
|
error: unknown;
|
|
79
78
|
message: string | undefined;
|
|
80
|
-
}, import("mobx-state-tree"
|
|
81
|
-
* #action
|
|
82
|
-
*/)._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
79
|
+
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
83
80
|
}> | null;
|
|
84
81
|
readonly adapterConfig: any;
|
|
85
82
|
readonly parentTrack: any;
|
|
@@ -99,6 +96,8 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
99
96
|
features: Feature[] | undefined;
|
|
100
97
|
message: string | undefined;
|
|
101
98
|
} & {
|
|
99
|
+
readonly level: number;
|
|
100
|
+
readonly height: number;
|
|
102
101
|
renderProps(): {
|
|
103
102
|
rpcDriverName: string | undefined;
|
|
104
103
|
displayModel: {
|
|
@@ -114,9 +113,13 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
114
113
|
setSubschema(slotName: string, data: Record<string, unknown>): Record<string, unknown> | ({
|
|
115
114
|
[x: string]: any;
|
|
116
115
|
} & import("mobx-state-tree/dist/internal").NonEmptyObject & any & import("mobx-state-tree").IStateTreeNode<AnyConfigurationSchemaType>);
|
|
117
|
-
} & import("mobx-state-tree"
|
|
116
|
+
} & import("mobx-state-tree" /**
|
|
117
|
+
* #volatile
|
|
118
|
+
* canvas for drawing mouseover shading this is separate from the other
|
|
119
|
+
* code for speed: don't have to redraw entire canvas to do a feature's
|
|
120
|
+
* mouseover shading
|
|
121
|
+
*/).IStateTreeNode<AnyConfigurationSchemaType>);
|
|
118
122
|
} & import("mobx-state-tree").IStateTreeNode<AnyConfigurationSchemaType>;
|
|
119
|
-
height: number;
|
|
120
123
|
} & import("mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
121
124
|
rendererTypeName: string;
|
|
122
125
|
error: unknown;
|
|
@@ -160,9 +163,7 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
160
163
|
rendererTypeName: string;
|
|
161
164
|
error: unknown;
|
|
162
165
|
message: string | undefined;
|
|
163
|
-
}, import("mobx-state-tree"
|
|
164
|
-
* #action
|
|
165
|
-
*/)._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
166
|
+
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
166
167
|
}> | null;
|
|
167
168
|
readonly adapterConfig: any;
|
|
168
169
|
readonly parentTrack: any;
|
|
@@ -188,7 +189,6 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
188
189
|
} & {
|
|
189
190
|
type: import("mobx-state-tree").ISimpleType<"LinearComparativeDisplay">;
|
|
190
191
|
configuration: AnyConfigurationSchemaType;
|
|
191
|
-
height: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
192
192
|
}, {
|
|
193
193
|
rendererTypeName: string;
|
|
194
194
|
error: unknown;
|
|
@@ -264,13 +264,51 @@ declare function stateModelFactory(configSchema: AnyConfigurationSchemaType): im
|
|
|
264
264
|
} & {
|
|
265
265
|
afterAttach(): void;
|
|
266
266
|
} & {
|
|
267
|
+
/**
|
|
268
|
+
* #volatile
|
|
269
|
+
* canvas used for drawing visible screen
|
|
270
|
+
*/
|
|
267
271
|
mainCanvas: HTMLCanvasElement | null;
|
|
272
|
+
/**
|
|
273
|
+
* #volatile
|
|
274
|
+
* canvas used for drawing click map with feature ids this renders a
|
|
275
|
+
* unique color per alignment, so that it can be re-traced after a
|
|
276
|
+
* feature click with getImageData at that pixel
|
|
277
|
+
*/
|
|
268
278
|
clickMapCanvas: HTMLCanvasElement | null;
|
|
279
|
+
/**
|
|
280
|
+
* #volatile
|
|
281
|
+
* canvas used for drawing click map with cigar data this can show if you
|
|
282
|
+
* are mousing over a insertion/deletion. it is similar in purpose to the
|
|
283
|
+
* clickMapRef but was not feasible to pack this into the clickMapRef
|
|
284
|
+
*/
|
|
269
285
|
cigarClickMapCanvas: HTMLCanvasElement | null;
|
|
286
|
+
/**
|
|
287
|
+
* #volatile
|
|
288
|
+
* canvas for drawing mouseover shading this is separate from the other
|
|
289
|
+
* code for speed: don't have to redraw entire canvas to do a feature's
|
|
290
|
+
* mouseover shading
|
|
291
|
+
*/
|
|
270
292
|
mouseoverCanvas: HTMLCanvasElement | null;
|
|
293
|
+
/**
|
|
294
|
+
* #volatile
|
|
295
|
+
* assigned by reaction
|
|
296
|
+
*/
|
|
271
297
|
featPositions: FeatPos[];
|
|
298
|
+
/**
|
|
299
|
+
* #volatile
|
|
300
|
+
* currently mouse'd over feature
|
|
301
|
+
*/
|
|
272
302
|
mouseoverId: string | undefined;
|
|
303
|
+
/**
|
|
304
|
+
* #volatile
|
|
305
|
+
* currently click'd over feature
|
|
306
|
+
*/
|
|
273
307
|
clickId: string | undefined;
|
|
308
|
+
/**
|
|
309
|
+
* #volatile
|
|
310
|
+
* currently mouseover'd CIGAR subfeature
|
|
311
|
+
*/
|
|
274
312
|
cigarMouseoverId: number;
|
|
275
313
|
} & {
|
|
276
314
|
/**
|
|
@@ -48,28 +48,51 @@ function stateModelFactory(configSchema) {
|
|
|
48
48
|
configuration: (0, configuration_1.ConfigurationReference)(configSchema),
|
|
49
49
|
}))
|
|
50
50
|
.volatile(() => ({
|
|
51
|
-
|
|
51
|
+
/**
|
|
52
|
+
* #volatile
|
|
53
|
+
* canvas used for drawing visible screen
|
|
54
|
+
*/
|
|
52
55
|
mainCanvas: null,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
/**
|
|
57
|
+
* #volatile
|
|
58
|
+
* canvas used for drawing click map with feature ids this renders a
|
|
59
|
+
* unique color per alignment, so that it can be re-traced after a
|
|
60
|
+
* feature click with getImageData at that pixel
|
|
61
|
+
*/
|
|
56
62
|
clickMapCanvas: null,
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
63
|
+
/**
|
|
64
|
+
* #volatile
|
|
65
|
+
* canvas used for drawing click map with cigar data this can show if you
|
|
66
|
+
* are mousing over a insertion/deletion. it is similar in purpose to the
|
|
67
|
+
* clickMapRef but was not feasible to pack this into the clickMapRef
|
|
68
|
+
*/
|
|
61
69
|
cigarClickMapCanvas: null,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
70
|
+
/**
|
|
71
|
+
* #volatile
|
|
72
|
+
* canvas for drawing mouseover shading this is separate from the other
|
|
73
|
+
* code for speed: don't have to redraw entire canvas to do a feature's
|
|
74
|
+
* mouseover shading
|
|
75
|
+
*/
|
|
65
76
|
mouseoverCanvas: null,
|
|
66
|
-
|
|
77
|
+
/**
|
|
78
|
+
* #volatile
|
|
79
|
+
* assigned by reaction
|
|
80
|
+
*/
|
|
67
81
|
featPositions: [],
|
|
68
|
-
|
|
82
|
+
/**
|
|
83
|
+
* #volatile
|
|
84
|
+
* currently mouse'd over feature
|
|
85
|
+
*/
|
|
69
86
|
mouseoverId: undefined,
|
|
70
|
-
|
|
87
|
+
/**
|
|
88
|
+
* #volatile
|
|
89
|
+
* currently click'd over feature
|
|
90
|
+
*/
|
|
71
91
|
clickId: undefined,
|
|
72
|
-
|
|
92
|
+
/**
|
|
93
|
+
* #volatile
|
|
94
|
+
* currently mouseover'd CIGAR subfeature
|
|
95
|
+
*/
|
|
73
96
|
cigarMouseoverId: -1,
|
|
74
97
|
}))
|
|
75
98
|
.actions(self => ({
|