@jbrowse/plugin-arc 2.7.1 → 2.8.0
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/LinearPairedArcDisplay/afterAttach.d.ts +2 -0
- package/dist/LinearPairedArcDisplay/afterAttach.js +11 -0
- package/dist/LinearPairedArcDisplay/components/Arcs.d.ts +7 -0
- package/dist/LinearPairedArcDisplay/components/Arcs.js +138 -0
- package/dist/LinearPairedArcDisplay/components/BaseDisplayComponent.d.ts +7 -0
- package/dist/LinearPairedArcDisplay/components/BaseDisplayComponent.js +40 -0
- package/dist/LinearPairedArcDisplay/components/ReactComponent.d.ts +7 -0
- package/dist/LinearPairedArcDisplay/components/ReactComponent.js +14 -0
- package/dist/LinearPairedArcDisplay/configSchema.d.ts +36 -0
- package/dist/LinearPairedArcDisplay/configSchema.js +28 -0
- package/dist/LinearPairedArcDisplay/fetchChains.d.ts +27 -0
- package/dist/LinearPairedArcDisplay/fetchChains.js +22 -0
- package/dist/LinearPairedArcDisplay/index.d.ts +2 -0
- package/dist/LinearPairedArcDisplay/index.js +44 -0
- package/dist/LinearPairedArcDisplay/model.d.ts +161 -0
- package/dist/LinearPairedArcDisplay/model.js +129 -0
- package/dist/LinearPairedArcDisplay/renderSvg.d.ts +5 -0
- package/dist/LinearPairedArcDisplay/renderSvg.js +23 -0
- package/dist/LinearPairedArcDisplay/util.d.ts +27 -0
- package/dist/LinearPairedArcDisplay/util.js +131 -0
- package/dist/index.js +23 -2
- package/esm/LinearPairedArcDisplay/afterAttach.d.ts +2 -0
- package/esm/LinearPairedArcDisplay/afterAttach.js +7 -0
- package/esm/LinearPairedArcDisplay/components/Arcs.d.ts +7 -0
- package/esm/LinearPairedArcDisplay/components/Arcs.js +113 -0
- package/esm/LinearPairedArcDisplay/components/BaseDisplayComponent.d.ts +7 -0
- package/esm/LinearPairedArcDisplay/components/BaseDisplayComponent.js +35 -0
- package/esm/LinearPairedArcDisplay/components/ReactComponent.d.ts +7 -0
- package/esm/LinearPairedArcDisplay/components/ReactComponent.js +9 -0
- package/esm/LinearPairedArcDisplay/configSchema.d.ts +36 -0
- package/esm/LinearPairedArcDisplay/configSchema.js +24 -0
- package/esm/LinearPairedArcDisplay/fetchChains.d.ts +27 -0
- package/esm/LinearPairedArcDisplay/fetchChains.js +18 -0
- package/esm/LinearPairedArcDisplay/index.d.ts +2 -0
- package/esm/LinearPairedArcDisplay/index.js +18 -0
- package/esm/LinearPairedArcDisplay/model.d.ts +161 -0
- package/esm/LinearPairedArcDisplay/model.js +102 -0
- package/esm/LinearPairedArcDisplay/renderSvg.d.ts +5 -0
- package/esm/LinearPairedArcDisplay/renderSvg.js +16 -0
- package/esm/LinearPairedArcDisplay/util.d.ts +27 -0
- package/esm/LinearPairedArcDisplay/util.js +121 -0
- package/esm/index.js +23 -2
- package/package.json +2 -2
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.stateModelFactory = void 0;
|
|
27
|
+
const configuration_1 = require("@jbrowse/core/configuration");
|
|
28
|
+
const mobx_state_tree_1 = require("mobx-state-tree");
|
|
29
|
+
const util_1 = require("@jbrowse/core/util");
|
|
30
|
+
const pluggableElementTypes_1 = require("@jbrowse/core/pluggableElementTypes");
|
|
31
|
+
const plugin_linear_genome_view_1 = require("@jbrowse/plugin-linear-genome-view");
|
|
32
|
+
/**
|
|
33
|
+
* #stateModel LinearPairedArcDisplay
|
|
34
|
+
* extends BaseDisplay, TrackHeightMixin, FeatureDensityMixin
|
|
35
|
+
*/
|
|
36
|
+
function stateModelFactory(configSchema) {
|
|
37
|
+
return mobx_state_tree_1.types
|
|
38
|
+
.compose('LinearPairedArcDisplay', pluggableElementTypes_1.BaseDisplay, (0, plugin_linear_genome_view_1.TrackHeightMixin)(), (0, plugin_linear_genome_view_1.FeatureDensityMixin)(), mobx_state_tree_1.types.model({
|
|
39
|
+
/**
|
|
40
|
+
* #property
|
|
41
|
+
*/
|
|
42
|
+
type: mobx_state_tree_1.types.literal('LinearPairedArcDisplay'),
|
|
43
|
+
/**
|
|
44
|
+
* #property
|
|
45
|
+
*/
|
|
46
|
+
configuration: (0, configuration_1.ConfigurationReference)(configSchema),
|
|
47
|
+
/**
|
|
48
|
+
* #property
|
|
49
|
+
*/
|
|
50
|
+
displayMode: mobx_state_tree_1.types.maybe(mobx_state_tree_1.types.string),
|
|
51
|
+
}))
|
|
52
|
+
.volatile(() => ({
|
|
53
|
+
lastDrawnOffsetPx: 0,
|
|
54
|
+
features: undefined,
|
|
55
|
+
loading: false,
|
|
56
|
+
drawn: true,
|
|
57
|
+
}))
|
|
58
|
+
.views(self => ({
|
|
59
|
+
/**
|
|
60
|
+
* #getter
|
|
61
|
+
*/
|
|
62
|
+
get displayModeSetting() {
|
|
63
|
+
var _a;
|
|
64
|
+
return (_a = self.displayMode) !== null && _a !== void 0 ? _a : (0, configuration_1.getConf)(self, ['renderer', 'displayMode']);
|
|
65
|
+
},
|
|
66
|
+
}))
|
|
67
|
+
.actions(self => ({
|
|
68
|
+
/**
|
|
69
|
+
* #action
|
|
70
|
+
*/
|
|
71
|
+
selectFeature(feature) {
|
|
72
|
+
const session = (0, util_1.getSession)(self);
|
|
73
|
+
if ((0, util_1.isSessionModelWithWidgets)(session)) {
|
|
74
|
+
const featureWidget = session.addWidget('VariantFeatureWidget', 'variantFeature', {
|
|
75
|
+
view: (0, util_1.getContainingView)(self),
|
|
76
|
+
track: (0, util_1.getContainingTrack)(self),
|
|
77
|
+
featureData: feature.toJSON(),
|
|
78
|
+
});
|
|
79
|
+
session.showWidget(featureWidget);
|
|
80
|
+
}
|
|
81
|
+
if ((0, util_1.isSelectionContainer)(session)) {
|
|
82
|
+
session.setSelection(feature);
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
/**
|
|
86
|
+
* #action
|
|
87
|
+
*/
|
|
88
|
+
setLoading(flag) {
|
|
89
|
+
self.loading = flag;
|
|
90
|
+
},
|
|
91
|
+
/**
|
|
92
|
+
* #action
|
|
93
|
+
*/
|
|
94
|
+
setFeatures(f) {
|
|
95
|
+
self.features = f;
|
|
96
|
+
},
|
|
97
|
+
/**
|
|
98
|
+
* #action
|
|
99
|
+
*/
|
|
100
|
+
setDisplayMode(flag) {
|
|
101
|
+
self.displayMode = flag;
|
|
102
|
+
},
|
|
103
|
+
}))
|
|
104
|
+
.actions(self => ({
|
|
105
|
+
afterAttach() {
|
|
106
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
107
|
+
;
|
|
108
|
+
(async () => {
|
|
109
|
+
try {
|
|
110
|
+
const { doAfterAttach } = await Promise.resolve().then(() => __importStar(require('./afterAttach')));
|
|
111
|
+
doAfterAttach(self);
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
console.error(e);
|
|
115
|
+
self.setError(e);
|
|
116
|
+
}
|
|
117
|
+
})();
|
|
118
|
+
},
|
|
119
|
+
/**
|
|
120
|
+
* #action
|
|
121
|
+
*/
|
|
122
|
+
async renderSvg(opts) {
|
|
123
|
+
const { renderArcSvg } = await Promise.resolve().then(() => __importStar(require('./renderSvg')));
|
|
124
|
+
// @ts-expect-error
|
|
125
|
+
return renderArcSvg(self, opts);
|
|
126
|
+
},
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
129
|
+
exports.stateModelFactory = stateModelFactory;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.renderArcSvg = void 0;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const util_1 = require("@jbrowse/core/util");
|
|
9
|
+
const Arcs_1 = __importDefault(require("./components/Arcs"));
|
|
10
|
+
async function renderArcSvg(model, _opts) {
|
|
11
|
+
await (0, util_1.when)(() => !model.loading);
|
|
12
|
+
const view = (0, util_1.getContainingView)(model);
|
|
13
|
+
const width = view.dynamicBlocks.totalWidthPx;
|
|
14
|
+
const height = model.height;
|
|
15
|
+
const clipid = 'arc-' + model.id;
|
|
16
|
+
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
17
|
+
react_1.default.createElement("defs", null,
|
|
18
|
+
react_1.default.createElement("clipPath", { id: clipid },
|
|
19
|
+
react_1.default.createElement("rect", { x: 0, y: 0, width: width, height: height }))),
|
|
20
|
+
react_1.default.createElement("g", { clipPath: `url(#${clipid})` },
|
|
21
|
+
react_1.default.createElement(Arcs_1.default, { model: model, exportSVG: true }))));
|
|
22
|
+
}
|
|
23
|
+
exports.renderArcSvg = renderArcSvg;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter';
|
|
2
|
+
import { Feature, AugmentedRegion } from '@jbrowse/core/util';
|
|
3
|
+
import { IAnyStateTreeNode } from 'mobx-state-tree';
|
|
4
|
+
import { IAutorunOptions } from 'mobx';
|
|
5
|
+
export declare function getTag(feature: Feature, tag: string): any;
|
|
6
|
+
export declare function getTagAlt(feature: Feature, tag: string, alt: string): any;
|
|
7
|
+
export declare const orientationTypes: {
|
|
8
|
+
fr: Record<string, string>;
|
|
9
|
+
rf: Record<string, string>;
|
|
10
|
+
ff: Record<string, string>;
|
|
11
|
+
};
|
|
12
|
+
export declare const pairMap: {
|
|
13
|
+
readonly LR: "color_pair_lr";
|
|
14
|
+
readonly LL: "color_pair_ll";
|
|
15
|
+
readonly RR: "color_pair_rr";
|
|
16
|
+
readonly RL: "color_pair_rl";
|
|
17
|
+
};
|
|
18
|
+
export declare function getColorWGBS(strand: number, base: string): "#f00" | "#00f" | "#888";
|
|
19
|
+
export declare function fetchSequence(region: AugmentedRegion, adapter: BaseFeatureDataAdapter): Promise<any>;
|
|
20
|
+
export declare function shouldFetchReferenceSequence(type?: string): boolean;
|
|
21
|
+
export declare const modificationColors: Record<string, string | undefined>;
|
|
22
|
+
type DisplayModel = IAnyStateTreeNode & {
|
|
23
|
+
setError: (arg: unknown) => void;
|
|
24
|
+
};
|
|
25
|
+
export declare function createAutorun(self: DisplayModel, cb: () => Promise<void>, opts?: IAutorunOptions): void;
|
|
26
|
+
export declare function randomColor(): string;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.randomColor = exports.createAutorun = exports.modificationColors = exports.shouldFetchReferenceSequence = exports.fetchSequence = exports.getColorWGBS = exports.pairMap = exports.orientationTypes = exports.getTagAlt = exports.getTag = void 0;
|
|
4
|
+
const operators_1 = require("rxjs/operators");
|
|
5
|
+
const rxjs_1 = require("rxjs");
|
|
6
|
+
const mobx_state_tree_1 = require("mobx-state-tree");
|
|
7
|
+
const mobx_1 = require("mobx");
|
|
8
|
+
// get tag from BAM or CRAM feature, where CRAM uses feature.get('tags') and
|
|
9
|
+
// BAM does not
|
|
10
|
+
function getTag(feature, tag) {
|
|
11
|
+
const tags = feature.get('tags');
|
|
12
|
+
return tags !== undefined ? tags[tag] : feature.get(tag);
|
|
13
|
+
}
|
|
14
|
+
exports.getTag = getTag;
|
|
15
|
+
// use fallback alt tag, used in situations where upper case/lower case tags
|
|
16
|
+
// exist e.g. Mm/MM for base modifications
|
|
17
|
+
function getTagAlt(feature, tag, alt) {
|
|
18
|
+
var _a;
|
|
19
|
+
return (_a = getTag(feature, tag)) !== null && _a !== void 0 ? _a : getTag(feature, alt);
|
|
20
|
+
}
|
|
21
|
+
exports.getTagAlt = getTagAlt;
|
|
22
|
+
// orientation definitions from igv.js, see also
|
|
23
|
+
// https://software.broadinstitute.org/software/igv/interpreting_pair_orientations
|
|
24
|
+
exports.orientationTypes = {
|
|
25
|
+
fr: {
|
|
26
|
+
F1R2: 'LR',
|
|
27
|
+
F2R1: 'LR',
|
|
28
|
+
F1F2: 'LL',
|
|
29
|
+
F2F1: 'LL',
|
|
30
|
+
R1R2: 'RR',
|
|
31
|
+
R2R1: 'RR',
|
|
32
|
+
R1F2: 'RL',
|
|
33
|
+
R2F1: 'RL',
|
|
34
|
+
},
|
|
35
|
+
rf: {
|
|
36
|
+
R1F2: 'LR',
|
|
37
|
+
R2F1: 'LR',
|
|
38
|
+
R1R2: 'LL',
|
|
39
|
+
R2R1: 'LL',
|
|
40
|
+
F1F2: 'RR',
|
|
41
|
+
F2F1: 'RR',
|
|
42
|
+
F1R2: 'RL',
|
|
43
|
+
F2R1: 'RL',
|
|
44
|
+
},
|
|
45
|
+
ff: {
|
|
46
|
+
F2F1: 'LR',
|
|
47
|
+
R1R2: 'LR',
|
|
48
|
+
F2R1: 'LL',
|
|
49
|
+
R1F2: 'LL',
|
|
50
|
+
R2F1: 'RR',
|
|
51
|
+
F1R2: 'RR',
|
|
52
|
+
R2R1: 'RL',
|
|
53
|
+
F1F2: 'RL',
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
exports.pairMap = {
|
|
57
|
+
LR: 'color_pair_lr',
|
|
58
|
+
LL: 'color_pair_ll',
|
|
59
|
+
RR: 'color_pair_rr',
|
|
60
|
+
RL: 'color_pair_rl',
|
|
61
|
+
};
|
|
62
|
+
function getColorWGBS(strand, base) {
|
|
63
|
+
if (strand === 1) {
|
|
64
|
+
if (base === 'C') {
|
|
65
|
+
return '#f00';
|
|
66
|
+
}
|
|
67
|
+
if (base === 'T') {
|
|
68
|
+
return '#00f';
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else if (strand === -1) {
|
|
72
|
+
if (base === 'G') {
|
|
73
|
+
return '#f00';
|
|
74
|
+
}
|
|
75
|
+
if (base === 'A') {
|
|
76
|
+
return '#00f';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return '#888';
|
|
80
|
+
}
|
|
81
|
+
exports.getColorWGBS = getColorWGBS;
|
|
82
|
+
// fetches region sequence augmenting by +/- 1bp for CpG on either side of
|
|
83
|
+
// requested region
|
|
84
|
+
async function fetchSequence(region, adapter) {
|
|
85
|
+
var _a;
|
|
86
|
+
const { start, end, originalRefName, refName } = region;
|
|
87
|
+
const feats = await (0, rxjs_1.firstValueFrom)(adapter
|
|
88
|
+
.getFeatures({
|
|
89
|
+
...region,
|
|
90
|
+
refName: originalRefName || refName,
|
|
91
|
+
end: end + 1,
|
|
92
|
+
start: Math.max(0, start - 1),
|
|
93
|
+
})
|
|
94
|
+
.pipe((0, operators_1.toArray)()));
|
|
95
|
+
return (_a = feats[0]) === null || _a === void 0 ? void 0 : _a.get('seq');
|
|
96
|
+
}
|
|
97
|
+
exports.fetchSequence = fetchSequence;
|
|
98
|
+
// has to check underlying C-G (aka CpG) on the reference sequence
|
|
99
|
+
function shouldFetchReferenceSequence(type) {
|
|
100
|
+
return type === 'methylation';
|
|
101
|
+
}
|
|
102
|
+
exports.shouldFetchReferenceSequence = shouldFetchReferenceSequence;
|
|
103
|
+
// adapted from IGV
|
|
104
|
+
// https://github.com/igvteam/igv/blob/e803e3af2d8c9ea049961dfd4628146bdde9a574/src/main/java/org/broad/igv/sam/mods/BaseModificationColors.java#L27
|
|
105
|
+
exports.modificationColors = {
|
|
106
|
+
m: 'rgb(255,0,0)',
|
|
107
|
+
h: 'rgb(11, 132, 165)',
|
|
108
|
+
o: 'rgb(111, 78, 129)',
|
|
109
|
+
f: 'rgb(246, 200, 95)',
|
|
110
|
+
c: 'rgb(157, 216, 102)',
|
|
111
|
+
g: 'rgb(255, 160, 86)',
|
|
112
|
+
e: 'rgb(141, 221, 208)',
|
|
113
|
+
b: 'rgb(202, 71, 47)',
|
|
114
|
+
};
|
|
115
|
+
function createAutorun(self, cb, opts) {
|
|
116
|
+
(0, mobx_state_tree_1.addDisposer)(self, (0, mobx_1.autorun)(async () => {
|
|
117
|
+
try {
|
|
118
|
+
await cb();
|
|
119
|
+
}
|
|
120
|
+
catch (e) {
|
|
121
|
+
if ((0, mobx_state_tree_1.isAlive)(self)) {
|
|
122
|
+
self.setError(e);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}, opts));
|
|
126
|
+
}
|
|
127
|
+
exports.createAutorun = createAutorun;
|
|
128
|
+
function randomColor() {
|
|
129
|
+
return `hsl(${Math.random() * 200}, 50%, 50%)`;
|
|
130
|
+
}
|
|
131
|
+
exports.randomColor = randomColor;
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const Plugin_1 = __importDefault(require("@jbrowse/core/Plugin"));
|
|
7
7
|
const LinearArcDisplay_1 = __importDefault(require("./LinearArcDisplay"));
|
|
8
|
+
const LinearPairedArcDisplay_1 = __importDefault(require("./LinearPairedArcDisplay"));
|
|
8
9
|
const ArcRenderer_1 = __importDefault(require("./ArcRenderer"));
|
|
10
|
+
const colors_1 = require("@jbrowse/core/ui/colors");
|
|
9
11
|
class ArcPlugin extends Plugin_1.default {
|
|
10
12
|
constructor() {
|
|
11
13
|
super(...arguments);
|
|
@@ -14,8 +16,27 @@ class ArcPlugin extends Plugin_1.default {
|
|
|
14
16
|
install(pluginManager) {
|
|
15
17
|
(0, ArcRenderer_1.default)(pluginManager);
|
|
16
18
|
(0, LinearArcDisplay_1.default)(pluginManager);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
(0, LinearPairedArcDisplay_1.default)(pluginManager);
|
|
20
|
+
pluginManager.jexl.addFunction('logThickness', (feature, attributeName) => Math.log(feature.get(attributeName) + 1));
|
|
21
|
+
pluginManager.jexl.addFunction('defaultPairedArcColor', (_feature, alt) => {
|
|
22
|
+
if (alt === null || alt === void 0 ? void 0 : alt.startsWith('<DEL')) {
|
|
23
|
+
return colors_1.set1[0];
|
|
24
|
+
}
|
|
25
|
+
else if (alt === null || alt === void 0 ? void 0 : alt.startsWith('<DUP')) {
|
|
26
|
+
return colors_1.set1[1];
|
|
27
|
+
}
|
|
28
|
+
else if (alt === null || alt === void 0 ? void 0 : alt.startsWith('<INV')) {
|
|
29
|
+
return colors_1.set1[2];
|
|
30
|
+
}
|
|
31
|
+
else if (alt === null || alt === void 0 ? void 0 : alt.startsWith('<TRA')) {
|
|
32
|
+
return colors_1.set1[3];
|
|
33
|
+
}
|
|
34
|
+
else if (alt === null || alt === void 0 ? void 0 : alt.startsWith('<CNV')) {
|
|
35
|
+
return colors_1.set1[4];
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
return colors_1.set1[6]; // skip 5, yellow
|
|
39
|
+
}
|
|
19
40
|
});
|
|
20
41
|
}
|
|
21
42
|
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import React, { useRef, useState } from 'react';
|
|
2
|
+
import { observer } from 'mobx-react';
|
|
3
|
+
import { assembleLocString, getContainingView, getSession, measureText, } from '@jbrowse/core/util';
|
|
4
|
+
import { getConf } from '@jbrowse/core/configuration';
|
|
5
|
+
import { parseBreakend } from '@gmod/vcf';
|
|
6
|
+
import { Tooltip } from 'react-svg-tooltip';
|
|
7
|
+
function f(feature, alt) {
|
|
8
|
+
var _a, _b, _c, _d, _e;
|
|
9
|
+
const bnd = alt ? parseBreakend(alt) : undefined;
|
|
10
|
+
let start = feature.get('start');
|
|
11
|
+
let end = feature.get('end');
|
|
12
|
+
const strand = feature.get('strand');
|
|
13
|
+
const mate = feature.get('mate');
|
|
14
|
+
const refName = feature.get('refName');
|
|
15
|
+
let mateRefName;
|
|
16
|
+
let mateEnd = 0;
|
|
17
|
+
let mateStart = 0;
|
|
18
|
+
// one sided bracket used, because there could be <INS:ME> and we just check
|
|
19
|
+
// startswith below
|
|
20
|
+
const symbolicAlleles = ['<TRA', '<DEL', '<INV', '<INS', '<DUP', '<CNV'];
|
|
21
|
+
if (symbolicAlleles.some(a => alt === null || alt === void 0 ? void 0 : alt.startsWith(a))) {
|
|
22
|
+
// END is defined to be a single value, not an array. CHR2 not defined in
|
|
23
|
+
// VCF spec, but should be similar
|
|
24
|
+
const e = ((_b = (_a = feature.get('INFO')) === null || _a === void 0 ? void 0 : _a.END) === null || _b === void 0 ? void 0 : _b[0]) || feature.get('end');
|
|
25
|
+
mateEnd = e;
|
|
26
|
+
mateStart = e - 1;
|
|
27
|
+
mateRefName = (_e = (_d = (_c = feature.get('INFO')) === null || _c === void 0 ? void 0 : _c.CHR2) === null || _d === void 0 ? void 0 : _d[0]) !== null && _e !== void 0 ? _e : refName;
|
|
28
|
+
// re-adjust the arc to be from start to end of feature by re-assigning end
|
|
29
|
+
// to the 'mate'
|
|
30
|
+
start = feature.get('start');
|
|
31
|
+
end = feature.get('start') + 1;
|
|
32
|
+
}
|
|
33
|
+
else if (bnd === null || bnd === void 0 ? void 0 : bnd.MatePosition) {
|
|
34
|
+
const matePosition = bnd.MatePosition.split(':');
|
|
35
|
+
mateEnd = +matePosition[1];
|
|
36
|
+
mateStart = +matePosition[1] - 1;
|
|
37
|
+
mateRefName = matePosition[0];
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
k1: { refName, start, end, strand },
|
|
41
|
+
k2: mate !== null && mate !== void 0 ? mate : { refName: mateRefName, end: mateEnd, start: mateStart },
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function makeSummary(feature, alt) {
|
|
45
|
+
var _a;
|
|
46
|
+
const { k1, k2 } = f(feature, alt);
|
|
47
|
+
return [
|
|
48
|
+
feature.get('name'),
|
|
49
|
+
feature.get('id'),
|
|
50
|
+
assembleLocString(k1),
|
|
51
|
+
assembleLocString(k2),
|
|
52
|
+
(_a = feature.get('INFO')) === null || _a === void 0 ? void 0 : _a.SVTYPE,
|
|
53
|
+
alt,
|
|
54
|
+
]
|
|
55
|
+
.filter(f => !!f)
|
|
56
|
+
.join(' - ');
|
|
57
|
+
}
|
|
58
|
+
// conditionally rendered tooltip only on mouseover, speeds up
|
|
59
|
+
const SvgTooltip = React.forwardRef(function SvgTooltip2({ feature, alt }, ref) {
|
|
60
|
+
const caption = makeSummary(feature, alt);
|
|
61
|
+
const tooltipWidth = 20 + measureText(caption);
|
|
62
|
+
return ref !== null ? (
|
|
63
|
+
// @ts-expect-error
|
|
64
|
+
React.createElement(Tooltip, { triggerRef: ref },
|
|
65
|
+
React.createElement("rect", { x: 12, y: 0, width: tooltipWidth, height: 20, rx: 5, ry: 5, fill: "black", fillOpacity: "50%" }),
|
|
66
|
+
React.createElement("text", { x: 22, y: 14, fontSize: 10, fill: "white", textLength: tooltipWidth - 20 }, caption))) : null;
|
|
67
|
+
});
|
|
68
|
+
const Arc = observer(function ({ model, feature, alt, assembly, view, }) {
|
|
69
|
+
var _a, _b;
|
|
70
|
+
const [mouseOvered, setMouseOvered] = useState(false);
|
|
71
|
+
const { height } = model;
|
|
72
|
+
const { k1, k2 } = f(feature, alt);
|
|
73
|
+
const ref = useRef(null);
|
|
74
|
+
const c = getConf(model, 'color', { feature, alt });
|
|
75
|
+
const ra1 = assembly.getCanonicalRefName(k1.refName) || k1.refName;
|
|
76
|
+
const ra2 = assembly.getCanonicalRefName(k2.refName) || k2.refName;
|
|
77
|
+
const p1 = k1.start;
|
|
78
|
+
const p2 = k2.start;
|
|
79
|
+
const r1 = (_a = view.bpToPx({ refName: ra1, coord: p1 })) === null || _a === void 0 ? void 0 : _a.offsetPx;
|
|
80
|
+
const r2 = (_b = view.bpToPx({ refName: ra2, coord: p2 })) === null || _b === void 0 ? void 0 : _b.offsetPx;
|
|
81
|
+
if (r1 !== undefined && r2 !== undefined) {
|
|
82
|
+
const radius = (r2 - r1) / 2;
|
|
83
|
+
const absrad = Math.abs(radius);
|
|
84
|
+
const destY = Math.min(height, absrad);
|
|
85
|
+
const p1 = r1 - view.offsetPx;
|
|
86
|
+
const p2 = r2 - view.offsetPx;
|
|
87
|
+
const left = p1;
|
|
88
|
+
const right = p2;
|
|
89
|
+
return absrad > 1 ? (React.createElement(React.Fragment, null,
|
|
90
|
+
React.createElement("path", { d: `M ${left} 0 C ${left} ${destY}, ${right} ${destY}, ${right} 0`, ref: ref, stroke: mouseOvered ? 'black' : c, strokeWidth: 3, onMouseOut: () => setMouseOvered(false), onMouseOver: () => setMouseOvered(true), onClick: () => model.selectFeature(feature), fill: "none", pointerEvents: "stroke" }),
|
|
91
|
+
mouseOvered ? (React.createElement(SvgTooltip, { feature: feature, alt: alt, ref: ref })) : null)) : null;
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
});
|
|
95
|
+
const Wrapper = observer(function ({ model, exportSVG, children, }) {
|
|
96
|
+
const { height } = model;
|
|
97
|
+
const view = getContainingView(model);
|
|
98
|
+
const width = Math.round(view.dynamicBlocks.totalWidthPx);
|
|
99
|
+
return exportSVG ? (React.createElement(React.Fragment, null, children)) : (React.createElement("svg", { width: width, height: height }, children));
|
|
100
|
+
});
|
|
101
|
+
const Arcs = observer(function ({ model, exportSVG, }) {
|
|
102
|
+
const view = getContainingView(model);
|
|
103
|
+
const session = getSession(model);
|
|
104
|
+
const { assemblyManager } = session;
|
|
105
|
+
const { features } = model;
|
|
106
|
+
const assembly = assemblyManager.get(view.assemblyNames[0]);
|
|
107
|
+
return assembly ? (React.createElement(Wrapper, { model: model, exportSVG: exportSVG }, features === null || features === void 0 ? void 0 : features.map(f => {
|
|
108
|
+
var _a;
|
|
109
|
+
const alts = f.get('ALT');
|
|
110
|
+
return ((_a = alts === null || alts === void 0 ? void 0 : alts.map(a => (React.createElement(Arc, { key: f.id() + '-' + a, session: session, feature: f, alt: a, view: view, model: model, assembly: assembly })))) !== null && _a !== void 0 ? _a : (React.createElement(Arc, { key: f.id(), session: session, feature: f, view: view, model: model, assembly: assembly })));
|
|
111
|
+
}))) : null;
|
|
112
|
+
});
|
|
113
|
+
export default Arcs;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { LinearArcDisplayModel } from '../model';
|
|
3
|
+
declare const BaseDisplayComponent: ({ model, children, }: {
|
|
4
|
+
model: LinearArcDisplayModel;
|
|
5
|
+
children?: React.ReactNode;
|
|
6
|
+
}) => React.JSX.Element | null;
|
|
7
|
+
export default BaseDisplayComponent;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { LoadingEllipses } from '@jbrowse/core/ui';
|
|
3
|
+
import { BlockMsg } from '@jbrowse/plugin-linear-genome-view';
|
|
4
|
+
import { makeStyles } from 'tss-react/mui';
|
|
5
|
+
import { observer } from 'mobx-react';
|
|
6
|
+
const useStyles = makeStyles()(theme => ({
|
|
7
|
+
loading: {
|
|
8
|
+
backgroundColor: theme.palette.background.default,
|
|
9
|
+
backgroundImage: `repeating-linear-gradient(45deg, transparent, transparent 5px, ${theme.palette.action.disabledBackground} 5px, ${theme.palette.action.disabledBackground} 10px)`,
|
|
10
|
+
position: 'absolute',
|
|
11
|
+
bottom: 0,
|
|
12
|
+
height: 50,
|
|
13
|
+
width: 300,
|
|
14
|
+
right: 0,
|
|
15
|
+
pointerEvents: 'none',
|
|
16
|
+
textAlign: 'center',
|
|
17
|
+
},
|
|
18
|
+
}));
|
|
19
|
+
const BaseDisplayComponent = observer(function ({ model, children, }) {
|
|
20
|
+
const { error, regionTooLarge } = model;
|
|
21
|
+
return error ? (React.createElement(BlockMsg, { message: `${error}`, severity: "error", buttonText: "Reload", action: model.reload })) : regionTooLarge ? (model.regionCannotBeRendered()) : (React.createElement(DataDisplay, { model: model }, children));
|
|
22
|
+
});
|
|
23
|
+
const DataDisplay = observer(function ({ model, children, }) {
|
|
24
|
+
const { loading } = model;
|
|
25
|
+
return (React.createElement("div", null,
|
|
26
|
+
children,
|
|
27
|
+
loading ? React.createElement(LoadingBar, { model: model }) : null));
|
|
28
|
+
});
|
|
29
|
+
const LoadingBar = observer(function ({ model, }) {
|
|
30
|
+
const { classes } = useStyles();
|
|
31
|
+
const { message } = model;
|
|
32
|
+
return (React.createElement("div", { className: classes.loading },
|
|
33
|
+
React.createElement(LoadingEllipses, { message: message })));
|
|
34
|
+
});
|
|
35
|
+
export default BaseDisplayComponent;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { LinearArcDisplayModel } from '../model';
|
|
3
|
+
declare const LinearArcReactComponent: ({ model, exportSVG, }: {
|
|
4
|
+
model: LinearArcDisplayModel;
|
|
5
|
+
exportSVG?: boolean | undefined;
|
|
6
|
+
}) => React.JSX.Element;
|
|
7
|
+
export default LinearArcReactComponent;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { observer } from 'mobx-react';
|
|
3
|
+
import BaseDisplayComponent from './BaseDisplayComponent';
|
|
4
|
+
import Arcs from './Arcs';
|
|
5
|
+
const LinearArcReactComponent = observer(function ({ model, exportSVG, }) {
|
|
6
|
+
return (React.createElement(BaseDisplayComponent, { model: model },
|
|
7
|
+
React.createElement(Arcs, { model: model, exportSVG: exportSVG })));
|
|
8
|
+
});
|
|
9
|
+
export default LinearArcReactComponent;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #config LinearPairedArcDisplay
|
|
3
|
+
*/
|
|
4
|
+
export declare function configSchemaFactory(): import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
5
|
+
/**
|
|
6
|
+
* #slot
|
|
7
|
+
*/
|
|
8
|
+
color: {
|
|
9
|
+
type: string;
|
|
10
|
+
description: string;
|
|
11
|
+
defaultValue: string;
|
|
12
|
+
contextVariable: string[];
|
|
13
|
+
};
|
|
14
|
+
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
15
|
+
maxFeatureScreenDensity: {
|
|
16
|
+
type: string;
|
|
17
|
+
description: string;
|
|
18
|
+
defaultValue: number;
|
|
19
|
+
};
|
|
20
|
+
fetchSizeLimit: {
|
|
21
|
+
type: string;
|
|
22
|
+
defaultValue: number;
|
|
23
|
+
description: string;
|
|
24
|
+
};
|
|
25
|
+
height: {
|
|
26
|
+
type: string;
|
|
27
|
+
defaultValue: number;
|
|
28
|
+
description: string;
|
|
29
|
+
};
|
|
30
|
+
mouseover: {
|
|
31
|
+
type: string;
|
|
32
|
+
description: string;
|
|
33
|
+
defaultValue: string;
|
|
34
|
+
contextVariable: string[];
|
|
35
|
+
};
|
|
36
|
+
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "displayId">>, undefined>>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ConfigurationSchema } from '@jbrowse/core/configuration';
|
|
2
|
+
import { baseLinearDisplayConfigSchema } from '@jbrowse/plugin-linear-genome-view';
|
|
3
|
+
/**
|
|
4
|
+
* #config LinearPairedArcDisplay
|
|
5
|
+
*/
|
|
6
|
+
export function configSchemaFactory() {
|
|
7
|
+
return ConfigurationSchema('LinearPairedArcDisplay', {
|
|
8
|
+
/**
|
|
9
|
+
* #slot
|
|
10
|
+
*/
|
|
11
|
+
color: {
|
|
12
|
+
type: 'color',
|
|
13
|
+
description: 'the color of the arcs',
|
|
14
|
+
defaultValue: 'jexl:defaultPairedArcColor(feature,alt)',
|
|
15
|
+
contextVariable: ['feature', 'alt'],
|
|
16
|
+
},
|
|
17
|
+
}, {
|
|
18
|
+
/**
|
|
19
|
+
* #baseConfiguration
|
|
20
|
+
*/
|
|
21
|
+
baseConfiguration: baseLinearDisplayConfigSchema,
|
|
22
|
+
explicitlyTyped: true,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { LinearArcDisplayModel } from './model';
|
|
2
|
+
export interface ReducedFeature {
|
|
3
|
+
name: string;
|
|
4
|
+
strand: number;
|
|
5
|
+
refName: string;
|
|
6
|
+
start: number;
|
|
7
|
+
end: number;
|
|
8
|
+
id: string;
|
|
9
|
+
flags: number;
|
|
10
|
+
tlen: number;
|
|
11
|
+
pair_orientation: string;
|
|
12
|
+
next_ref?: string;
|
|
13
|
+
next_pos?: number;
|
|
14
|
+
clipPos: number;
|
|
15
|
+
SA?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ChainStats {
|
|
18
|
+
max: number;
|
|
19
|
+
min: number;
|
|
20
|
+
upper: number;
|
|
21
|
+
lower: number;
|
|
22
|
+
}
|
|
23
|
+
export interface ChainData {
|
|
24
|
+
chains: ReducedFeature[][];
|
|
25
|
+
stats?: ChainStats;
|
|
26
|
+
}
|
|
27
|
+
export declare function fetchChains(self: LinearArcDisplayModel): Promise<void>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { getContainingTrack, getContainingView, getSession, } from '@jbrowse/core/util';
|
|
2
|
+
export async function fetchChains(self) {
|
|
3
|
+
// @ts-expect-error
|
|
4
|
+
const { rpcSessionId: sessionId } = getContainingTrack(self);
|
|
5
|
+
const { rpcManager } = getSession(self);
|
|
6
|
+
const view = getContainingView(self);
|
|
7
|
+
if (!view.initialized || self.error || self.regionTooLarge) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
self.setLoading(true);
|
|
11
|
+
const ret = (await rpcManager.call(sessionId, 'CoreGetFeatures', {
|
|
12
|
+
sessionId,
|
|
13
|
+
regions: view.staticBlocks.contentBlocks,
|
|
14
|
+
adapterConfig: self.adapterConfig,
|
|
15
|
+
}));
|
|
16
|
+
self.setFeatures(ret);
|
|
17
|
+
self.setLoading(false);
|
|
18
|
+
}
|