@jbrowse/plugin-alignments 1.6.9 → 1.7.3
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/AlignmentsFeatureDetail/AlignmentsFeatureDetail.d.ts +6 -6
- package/dist/AlignmentsFeatureDetail/AlignmentsFeatureDetail.js +216 -0
- package/dist/AlignmentsFeatureDetail/index.d.ts +13 -13
- package/dist/AlignmentsFeatureDetail/index.js +63 -0
- package/dist/AlignmentsFeatureDetail/index.test.js +60 -0
- package/dist/AlignmentsTrack/index.d.ts +2 -2
- package/dist/AlignmentsTrack/index.js +37 -0
- package/dist/BamAdapter/BamAdapter.d.ts +40 -30
- package/dist/BamAdapter/BamAdapter.js +598 -0
- package/dist/BamAdapter/BamAdapter.test.js +177 -0
- package/dist/BamAdapter/BamSlightlyLazyFeature.d.ts +33 -33
- package/dist/BamAdapter/BamSlightlyLazyFeature.js +176 -0
- package/dist/BamAdapter/MismatchParser.d.ts +28 -28
- package/dist/BamAdapter/MismatchParser.js +384 -0
- package/dist/BamAdapter/MismatchParser.test.js +259 -0
- package/dist/BamAdapter/configSchema.d.ts +2 -2
- package/dist/BamAdapter/configSchema.js +48 -0
- package/dist/BamAdapter/index.d.ts +3 -3
- package/dist/BamAdapter/index.js +36 -0
- package/dist/CramAdapter/CramAdapter.d.ts +52 -43
- package/dist/CramAdapter/CramAdapter.js +660 -0
- package/dist/CramAdapter/CramAdapter.test.js +138 -0
- package/dist/CramAdapter/CramSlightlyLazyFeature.d.ts +49 -49
- package/dist/CramAdapter/CramSlightlyLazyFeature.js +447 -0
- package/dist/CramAdapter/CramTestAdapters.d.ts +29 -29
- package/dist/CramAdapter/CramTestAdapters.js +234 -0
- package/dist/CramAdapter/configSchema.d.ts +3 -3
- package/dist/CramAdapter/configSchema.js +40 -0
- package/dist/CramAdapter/index.d.ts +3 -3
- package/dist/CramAdapter/index.js +36 -0
- package/dist/HtsgetBamAdapter/HtsgetBamAdapter.d.ts +9 -9
- package/dist/HtsgetBamAdapter/HtsgetBamAdapter.js +97 -0
- package/dist/HtsgetBamAdapter/configSchema.d.ts +2 -2
- package/dist/HtsgetBamAdapter/configSchema.js +31 -0
- package/dist/HtsgetBamAdapter/index.d.ts +3 -3
- package/dist/HtsgetBamAdapter/index.js +42 -0
- package/dist/LinearAlignmentsDisplay/components/AlignmentsDisplay.d.ts +7 -7
- package/dist/LinearAlignmentsDisplay/components/AlignmentsDisplay.js +69 -0
- package/dist/LinearAlignmentsDisplay/index.d.ts +2 -2
- package/dist/LinearAlignmentsDisplay/index.js +31 -0
- package/dist/LinearAlignmentsDisplay/models/configSchema.d.ts +4 -4
- package/dist/LinearAlignmentsDisplay/models/configSchema.js +25 -0
- package/dist/LinearAlignmentsDisplay/models/configSchema.test.js +83 -0
- package/dist/LinearAlignmentsDisplay/models/model.d.ts +105 -105
- package/dist/LinearAlignmentsDisplay/models/model.js +250 -0
- package/dist/LinearPileupDisplay/components/ColorByModifications.d.ts +14 -14
- package/dist/LinearPileupDisplay/components/ColorByModifications.js +123 -0
- package/dist/LinearPileupDisplay/components/ColorByTag.d.ts +9 -9
- package/dist/LinearPileupDisplay/components/ColorByTag.js +98 -0
- package/dist/LinearPileupDisplay/components/FilterByTag.d.ts +18 -18
- package/dist/LinearPileupDisplay/components/FilterByTag.js +203 -0
- package/dist/LinearPileupDisplay/components/LinearPileupDisplayBlurb.d.ts +13 -13
- package/dist/LinearPileupDisplay/components/LinearPileupDisplayBlurb.js +32 -0
- package/dist/LinearPileupDisplay/components/SetFeatureHeight.d.ts +16 -16
- package/dist/LinearPileupDisplay/components/SetFeatureHeight.js +99 -0
- package/dist/LinearPileupDisplay/components/SetMaxHeight.d.ts +10 -10
- package/dist/LinearPileupDisplay/components/SetMaxHeight.js +90 -0
- package/dist/LinearPileupDisplay/components/SortByTag.d.ts +9 -9
- package/dist/LinearPileupDisplay/components/SortByTag.js +95 -0
- package/dist/LinearPileupDisplay/configSchema.d.ts +6 -6
- package/dist/LinearPileupDisplay/configSchema.js +47 -0
- package/dist/LinearPileupDisplay/configSchema.test.js +92 -0
- package/dist/LinearPileupDisplay/index.d.ts +2 -2
- package/dist/LinearPileupDisplay/index.js +30 -0
- package/dist/LinearPileupDisplay/model.d.ts +319 -321
- package/dist/LinearPileupDisplay/model.js +602 -0
- package/dist/LinearSNPCoverageDisplay/components/Tooltip.d.ts +10 -10
- package/dist/LinearSNPCoverageDisplay/components/Tooltip.js +63 -0
- package/dist/LinearSNPCoverageDisplay/index.d.ts +2 -2
- package/dist/LinearSNPCoverageDisplay/index.js +30 -0
- package/dist/LinearSNPCoverageDisplay/models/configSchema.d.ts +2 -2
- package/dist/LinearSNPCoverageDisplay/models/configSchema.js +57 -0
- package/dist/LinearSNPCoverageDisplay/models/configSchema.test.js +62 -0
- package/dist/LinearSNPCoverageDisplay/models/model.d.ts +346 -96
- package/dist/LinearSNPCoverageDisplay/models/model.js +237 -0
- package/dist/NestedFrequencyTable.d.ts +14 -14
- package/dist/NestedFrequencyTable.js +152 -0
- package/dist/PileupRPC/rpcMethods.d.ts +34 -34
- package/dist/PileupRPC/rpcMethods.js +285 -0
- package/dist/PileupRenderer/PileupLayoutSession.d.ts +29 -29
- package/dist/PileupRenderer/PileupLayoutSession.js +79 -0
- package/dist/PileupRenderer/PileupRenderer.d.ts +125 -125
- package/dist/PileupRenderer/PileupRenderer.js +1220 -0
- package/dist/PileupRenderer/components/PileupRendering.d.ts +23 -23
- package/dist/PileupRenderer/components/PileupRendering.js +270 -0
- package/dist/PileupRenderer/components/PileupRendering.test.js +36 -0
- package/dist/PileupRenderer/configSchema.d.ts +2 -2
- package/dist/PileupRenderer/configSchema.js +72 -0
- package/dist/PileupRenderer/index.d.ts +2 -2
- package/dist/PileupRenderer/index.js +25 -0
- package/dist/PileupRenderer/sortUtil.d.ts +8 -8
- package/dist/PileupRenderer/sortUtil.js +112 -0
- package/dist/SNPCoverageAdapter/SNPCoverageAdapter.d.ts +67 -71
- package/dist/SNPCoverageAdapter/SNPCoverageAdapter.js +606 -0
- package/dist/SNPCoverageAdapter/configSchema.d.ts +3 -3
- package/dist/SNPCoverageAdapter/configSchema.js +22 -0
- package/dist/SNPCoverageAdapter/index.d.ts +3 -3
- package/dist/SNPCoverageAdapter/index.js +45 -0
- package/dist/SNPCoverageRenderer/SNPCoverageRenderer.d.ts +20 -20
- package/dist/SNPCoverageRenderer/SNPCoverageRenderer.js +296 -0
- package/dist/SNPCoverageRenderer/configSchema.d.ts +2 -2
- package/dist/SNPCoverageRenderer/configSchema.js +40 -0
- package/dist/SNPCoverageRenderer/index.d.ts +3 -3
- package/dist/SNPCoverageRenderer/index.js +34 -0
- package/dist/declare.d.js +1 -0
- package/dist/index.d.ts +10 -10
- package/dist/index.js +154 -6
- package/dist/index.test.js +26 -0
- package/dist/shared.d.ts +25 -25
- package/dist/shared.js +96 -0
- package/dist/util.d.ts +19 -19
- package/dist/util.js +135 -0
- package/package.json +5 -8
- package/src/BamAdapter/BamAdapter.ts +35 -8
- package/src/CramAdapter/CramAdapter.ts +42 -15
- package/src/LinearPileupDisplay/components/SetMaxHeight.tsx +1 -1
- package/src/LinearPileupDisplay/model.ts +2 -22
- package/src/LinearSNPCoverageDisplay/models/model.ts +6 -36
- package/src/PileupRenderer/PileupRenderer.tsx +3 -6
- package/src/SNPCoverageAdapter/SNPCoverageAdapter.ts +11 -17
- package/dist/AlignmentsFeatureDetail/index.test.d.ts +0 -1
- package/dist/LinearAlignmentsDisplay/models/configSchema.test.d.ts +0 -1
- package/dist/LinearPileupDisplay/configSchema.test.d.ts +0 -1
- package/dist/LinearSNPCoverageDisplay/models/configSchema.test.d.ts +0 -1
- package/dist/PileupRenderer/components/PileupRendering.test.d.ts +0 -1
- package/dist/plugin-alignments.cjs.development.js +0 -8438
- package/dist/plugin-alignments.cjs.development.js.map +0 -1
- package/dist/plugin-alignments.cjs.production.min.js +0 -2
- package/dist/plugin-alignments.cjs.production.min.js.map +0 -1
- package/dist/plugin-alignments.esm.js +0 -8430
- package/dist/plugin-alignments.esm.js.map +0 -1
|
@@ -0,0 +1,1220 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports["default"] = void 0;
|
|
9
|
+
|
|
10
|
+
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
11
|
+
|
|
12
|
+
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
13
|
+
|
|
14
|
+
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
15
|
+
|
|
16
|
+
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
17
|
+
|
|
18
|
+
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
|
|
19
|
+
|
|
20
|
+
var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get"));
|
|
21
|
+
|
|
22
|
+
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
|
|
23
|
+
|
|
24
|
+
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
|
|
25
|
+
|
|
26
|
+
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
|
|
27
|
+
|
|
28
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
29
|
+
|
|
30
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
31
|
+
|
|
32
|
+
var _color = _interopRequireDefault(require("color"));
|
|
33
|
+
|
|
34
|
+
var _BoxRendererType2 = _interopRequireDefault(require("@jbrowse/core/pluggableElementTypes/renderers/BoxRendererType"));
|
|
35
|
+
|
|
36
|
+
var _ui = require("@jbrowse/core/ui");
|
|
37
|
+
|
|
38
|
+
var _util = require("@jbrowse/core/util");
|
|
39
|
+
|
|
40
|
+
var _offscreenCanvasUtils = require("@jbrowse/core/util/offscreenCanvasUtils");
|
|
41
|
+
|
|
42
|
+
var _dataAdapterCache = require("@jbrowse/core/data_adapters/dataAdapterCache");
|
|
43
|
+
|
|
44
|
+
var _configuration = require("@jbrowse/core/configuration");
|
|
45
|
+
|
|
46
|
+
var _MismatchParser = require("../BamAdapter/MismatchParser");
|
|
47
|
+
|
|
48
|
+
var _sortUtil = require("./sortUtil");
|
|
49
|
+
|
|
50
|
+
var _util2 = require("../util");
|
|
51
|
+
|
|
52
|
+
var _PileupLayoutSession = require("./PileupLayoutSession");
|
|
53
|
+
|
|
54
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
|
|
55
|
+
|
|
56
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
57
|
+
|
|
58
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
|
|
59
|
+
|
|
60
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
61
|
+
|
|
62
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
63
|
+
|
|
64
|
+
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; }
|
|
65
|
+
|
|
66
|
+
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
|
|
67
|
+
|
|
68
|
+
function getColorBaseMap(theme) {
|
|
69
|
+
return {
|
|
70
|
+
A: theme.palette.bases.A.main,
|
|
71
|
+
C: theme.palette.bases.C.main,
|
|
72
|
+
G: theme.palette.bases.G.main,
|
|
73
|
+
T: theme.palette.bases.T.main,
|
|
74
|
+
deletion: '#808080' // gray
|
|
75
|
+
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function getContrastBaseMap(theme) {
|
|
80
|
+
return Object.fromEntries(Object.entries(getColorBaseMap(theme)).map(function (_ref) {
|
|
81
|
+
var _ref2 = (0, _slicedToArray2["default"])(_ref, 2),
|
|
82
|
+
key = _ref2[0],
|
|
83
|
+
value = _ref2[1];
|
|
84
|
+
|
|
85
|
+
return [key, theme.palette.getContrastText(value)];
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
var alignmentColoring = {
|
|
90
|
+
color_fwd_strand_not_proper: '#ECC8C8',
|
|
91
|
+
color_rev_strand_not_proper: '#BEBED8',
|
|
92
|
+
color_fwd_strand: '#EC8B8B',
|
|
93
|
+
color_rev_strand: '#8F8FD8',
|
|
94
|
+
color_fwd_missing_mate: '#D11919',
|
|
95
|
+
color_rev_missing_mate: '#1919D1',
|
|
96
|
+
color_fwd_diff_chr: '#000',
|
|
97
|
+
color_rev_diff_chr: '#969696',
|
|
98
|
+
color_pair_lr: '#c8c8c8',
|
|
99
|
+
color_pair_rr: 'navy',
|
|
100
|
+
color_pair_rl: 'teal',
|
|
101
|
+
color_pair_ll: 'green',
|
|
102
|
+
color_nostrand: '#c8c8c8',
|
|
103
|
+
color_interchrom: 'orange',
|
|
104
|
+
color_longinsert: 'red',
|
|
105
|
+
color_shortinsert: 'pink'
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
function shouldDrawMismatches(type) {
|
|
109
|
+
return !['methylation', 'modifications'].includes(type || '');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
var PileupRenderer = /*#__PURE__*/function (_BoxRendererType) {
|
|
113
|
+
(0, _inherits2["default"])(PileupRenderer, _BoxRendererType);
|
|
114
|
+
|
|
115
|
+
var _super = _createSuper(PileupRenderer);
|
|
116
|
+
|
|
117
|
+
function PileupRenderer() {
|
|
118
|
+
var _this;
|
|
119
|
+
|
|
120
|
+
(0, _classCallCheck2["default"])(this, PileupRenderer);
|
|
121
|
+
|
|
122
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
123
|
+
args[_key] = arguments[_key];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
_this = _super.call.apply(_super, [this].concat(args));
|
|
127
|
+
(0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "supportsSVG", true);
|
|
128
|
+
return _this;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
(0, _createClass2["default"])(PileupRenderer, [{
|
|
132
|
+
key: "getCharWidthHeight",
|
|
133
|
+
value: // get width and height of chars the height is an approximation: width
|
|
134
|
+
// letter M is approximately the height
|
|
135
|
+
function getCharWidthHeight(ctx) {
|
|
136
|
+
var charWidth = ctx.measureText('A').width;
|
|
137
|
+
var charHeight = ctx.measureText('M').width;
|
|
138
|
+
return {
|
|
139
|
+
charWidth: charWidth,
|
|
140
|
+
charHeight: charHeight
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}, {
|
|
144
|
+
key: "layoutFeature",
|
|
145
|
+
value: function layoutFeature(_ref3) {
|
|
146
|
+
var feature = _ref3.feature,
|
|
147
|
+
layout = _ref3.layout,
|
|
148
|
+
bpPerPx = _ref3.bpPerPx,
|
|
149
|
+
region = _ref3.region,
|
|
150
|
+
showSoftClip = _ref3.showSoftClip,
|
|
151
|
+
heightPx = _ref3.heightPx,
|
|
152
|
+
displayMode = _ref3.displayMode;
|
|
153
|
+
var expansionBefore = 0;
|
|
154
|
+
var expansionAfter = 0; // Expand the start and end of feature when softclipping enabled
|
|
155
|
+
|
|
156
|
+
if (showSoftClip) {
|
|
157
|
+
var mismatches = feature.get('mismatches');
|
|
158
|
+
var seq = feature.get('seq');
|
|
159
|
+
|
|
160
|
+
if (seq) {
|
|
161
|
+
for (var i = 0; i < mismatches.length; i += 1) {
|
|
162
|
+
var _mismatches$i = mismatches[i],
|
|
163
|
+
type = _mismatches$i.type,
|
|
164
|
+
start = _mismatches$i.start,
|
|
165
|
+
_mismatches$i$cliplen = _mismatches$i.cliplen,
|
|
166
|
+
cliplen = _mismatches$i$cliplen === void 0 ? 0 : _mismatches$i$cliplen;
|
|
167
|
+
|
|
168
|
+
if (type === 'softclip') {
|
|
169
|
+
start === 0 ? expansionBefore = cliplen : expansionAfter = cliplen;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
var _bpSpanPx = (0, _util.bpSpanPx)(feature.get('start') - expansionBefore, feature.get('end') + expansionAfter, region, bpPerPx),
|
|
176
|
+
_bpSpanPx2 = (0, _slicedToArray2["default"])(_bpSpanPx, 2),
|
|
177
|
+
leftPx = _bpSpanPx2[0],
|
|
178
|
+
rightPx = _bpSpanPx2[1];
|
|
179
|
+
|
|
180
|
+
if (displayMode === 'compact') {
|
|
181
|
+
heightPx /= 3;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (feature.get('refName') !== region.refName) {
|
|
185
|
+
throw new Error("feature ".concat(feature.id(), " is not on the current region's reference sequence ").concat(region.refName));
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
var topPx = layout.addRect(feature.id(), feature.get('start') - expansionBefore, feature.get('end') + expansionAfter, heightPx);
|
|
189
|
+
|
|
190
|
+
if (topPx === null) {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return {
|
|
195
|
+
feature: feature,
|
|
196
|
+
leftPx: leftPx,
|
|
197
|
+
rightPx: rightPx,
|
|
198
|
+
topPx: displayMode === 'collapse' ? 0 : topPx,
|
|
199
|
+
heightPx: heightPx
|
|
200
|
+
};
|
|
201
|
+
} // expands region for clipping to use. possible improvement: use average read
|
|
202
|
+
// size to set the heuristic maxClippingSize expansion (e.g. short reads
|
|
203
|
+
// don't have to expand a softclipping size a lot, but long reads might)
|
|
204
|
+
|
|
205
|
+
}, {
|
|
206
|
+
key: "getExpandedRegion",
|
|
207
|
+
value: function getExpandedRegion(region, renderArgs) {
|
|
208
|
+
var config = renderArgs.config,
|
|
209
|
+
showSoftClip = renderArgs.showSoftClip;
|
|
210
|
+
var maxClippingSize = (0, _configuration.readConfObject)(config, 'maxClippingSize');
|
|
211
|
+
var start = region.start,
|
|
212
|
+
end = region.end;
|
|
213
|
+
var len = end - start;
|
|
214
|
+
var bpExpansion = Math.max(len, showSoftClip ? Math.round(maxClippingSize) : 0);
|
|
215
|
+
return _objectSpread(_objectSpread({}, region), {}, {
|
|
216
|
+
start: Math.floor(Math.max(start - bpExpansion, 0)),
|
|
217
|
+
end: Math.ceil(end + bpExpansion)
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}, {
|
|
221
|
+
key: "colorByOrientation",
|
|
222
|
+
value: function colorByOrientation(feature, config) {
|
|
223
|
+
return alignmentColoring[this.getOrientation(feature, config) || 'color_nostrand'];
|
|
224
|
+
}
|
|
225
|
+
}, {
|
|
226
|
+
key: "getOrientation",
|
|
227
|
+
value: function getOrientation(feature, config) {
|
|
228
|
+
var orientationType = (0, _configuration.readConfObject)(config, 'orientationType');
|
|
229
|
+
var type = _util2.orientationTypes[orientationType];
|
|
230
|
+
var orientation = type[feature.get('pair_orientation')];
|
|
231
|
+
var map = {
|
|
232
|
+
LR: 'color_pair_lr',
|
|
233
|
+
RR: 'color_pair_rr',
|
|
234
|
+
RL: 'color_pair_rl',
|
|
235
|
+
LL: 'color_pair_ll'
|
|
236
|
+
};
|
|
237
|
+
return map[orientation];
|
|
238
|
+
}
|
|
239
|
+
}, {
|
|
240
|
+
key: "colorByInsertSize",
|
|
241
|
+
value: function colorByInsertSize(feature, _config) {
|
|
242
|
+
return feature.get('is_paired') && feature.get('seq_id') !== feature.get('next_seq_id') ? '#555' : "hsl(".concat(Math.abs(feature.get('template_length')) / 10, ",50%,50%)");
|
|
243
|
+
}
|
|
244
|
+
}, {
|
|
245
|
+
key: "colorByStranded",
|
|
246
|
+
value: function colorByStranded(feature, _config) {
|
|
247
|
+
var flags = feature.get('flags');
|
|
248
|
+
var strand = feature.get('strand'); // is paired
|
|
249
|
+
|
|
250
|
+
if (flags & 1) {
|
|
251
|
+
var revflag = flags & 64;
|
|
252
|
+
var flipper = revflag ? -1 : 1; // proper pairing
|
|
253
|
+
|
|
254
|
+
if (flags & 2) {
|
|
255
|
+
return strand * flipper === 1 ? 'color_rev_strand' : 'color_fwd_strand';
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (feature.get('multi_segment_next_segment_unmapped')) {
|
|
259
|
+
return strand * flipper === 1 ? 'color_rev_missing_mate' : 'color_fwd_missing_mate';
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (feature.get('seq_id') === feature.get('next_seq_id')) {
|
|
263
|
+
return strand * flipper === 1 ? 'color_rev_strand_not_proper' : 'color_fwd_strand_not_proper';
|
|
264
|
+
} // should only leave aberrant chr
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
return strand === 1 ? 'color_fwd_diff_chr' : 'color_rev_diff_chr';
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return strand === 1 ? 'color_fwd_strand' : 'color_rev_strand';
|
|
271
|
+
}
|
|
272
|
+
}, {
|
|
273
|
+
key: "colorByPerBaseLettering",
|
|
274
|
+
value: function colorByPerBaseLettering(ctx, feat, _config, region, bpPerPx, props) {
|
|
275
|
+
var colorForBase = props.colorForBase,
|
|
276
|
+
contrastForBase = props.contrastForBase,
|
|
277
|
+
charWidth = props.charWidth,
|
|
278
|
+
charHeight = props.charHeight;
|
|
279
|
+
var heightLim = charHeight - 2;
|
|
280
|
+
var feature = feat.feature,
|
|
281
|
+
topPx = feat.topPx,
|
|
282
|
+
heightPx = feat.heightPx;
|
|
283
|
+
var seq = feature.get('seq');
|
|
284
|
+
var cigarOps = (0, _MismatchParser.parseCigar)(feature.get('CIGAR'));
|
|
285
|
+
var widthPx = 1 / bpPerPx;
|
|
286
|
+
var start = feature.get('start');
|
|
287
|
+
var soffset = 0; // sequence offset
|
|
288
|
+
|
|
289
|
+
var roffset = 0; // reference offset
|
|
290
|
+
|
|
291
|
+
for (var i = 0; i < cigarOps.length; i += 2) {
|
|
292
|
+
var len = +cigarOps[i];
|
|
293
|
+
var op = cigarOps[i + 1];
|
|
294
|
+
|
|
295
|
+
if (op === 'S' || op === 'I') {
|
|
296
|
+
soffset += len;
|
|
297
|
+
} else if (op === 'D' || op === 'N') {
|
|
298
|
+
roffset += len;
|
|
299
|
+
} else if (op === 'M' || op === 'X' || op === '=') {
|
|
300
|
+
for (var m = 0; m < len; m++) {
|
|
301
|
+
var letter = seq[soffset + m];
|
|
302
|
+
ctx.fillStyle = colorForBase[letter];
|
|
303
|
+
|
|
304
|
+
var _bpSpanPx3 = (0, _util.bpSpanPx)(start + roffset + m, start + roffset + m + 1, region, bpPerPx),
|
|
305
|
+
_bpSpanPx4 = (0, _slicedToArray2["default"])(_bpSpanPx3, 1),
|
|
306
|
+
leftPx = _bpSpanPx4[0];
|
|
307
|
+
|
|
308
|
+
ctx.fillRect(leftPx, topPx, widthPx + 0.5, heightPx);
|
|
309
|
+
|
|
310
|
+
if (widthPx >= charWidth && heightPx >= heightLim) {
|
|
311
|
+
// normal SNP coloring
|
|
312
|
+
ctx.fillStyle = contrastForBase[letter];
|
|
313
|
+
ctx.fillText(letter, leftPx + (widthPx - charWidth) / 2 + 1, topPx + heightPx);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
soffset += len;
|
|
318
|
+
roffset += len;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}, {
|
|
323
|
+
key: "colorByPerBaseQuality",
|
|
324
|
+
value: function colorByPerBaseQuality(ctx, feat, _config, region, bpPerPx) {
|
|
325
|
+
var feature = feat.feature,
|
|
326
|
+
topPx = feat.topPx,
|
|
327
|
+
heightPx = feat.heightPx;
|
|
328
|
+
var qual = feature.get('qual') || '';
|
|
329
|
+
var scores = qual.split(' ').map(function (val) {
|
|
330
|
+
return +val;
|
|
331
|
+
});
|
|
332
|
+
var cigarOps = (0, _MismatchParser.parseCigar)(feature.get('CIGAR'));
|
|
333
|
+
var width = 1 / bpPerPx;
|
|
334
|
+
var start = feature.get('start');
|
|
335
|
+
var soffset = 0; // sequence offset
|
|
336
|
+
|
|
337
|
+
var roffset = 0; // reference offset
|
|
338
|
+
|
|
339
|
+
for (var i = 0; i < cigarOps.length; i += 2) {
|
|
340
|
+
var len = +cigarOps[i];
|
|
341
|
+
var op = cigarOps[i + 1];
|
|
342
|
+
|
|
343
|
+
if (op === 'S' || op === 'I') {
|
|
344
|
+
soffset += len;
|
|
345
|
+
} else if (op === 'D' || op === 'N') {
|
|
346
|
+
roffset += len;
|
|
347
|
+
} else if (op === 'M' || op === 'X' || op === '=') {
|
|
348
|
+
for (var m = 0; m < len; m++) {
|
|
349
|
+
var score = scores[soffset + m];
|
|
350
|
+
ctx.fillStyle = "hsl(".concat(score === 255 ? 150 : score * 1.5, ",55%,50%)");
|
|
351
|
+
|
|
352
|
+
var _bpSpanPx5 = (0, _util.bpSpanPx)(start + roffset + m, start + roffset + m + 1, region, bpPerPx),
|
|
353
|
+
_bpSpanPx6 = (0, _slicedToArray2["default"])(_bpSpanPx5, 1),
|
|
354
|
+
leftPx = _bpSpanPx6[0];
|
|
355
|
+
|
|
356
|
+
ctx.fillRect(leftPx, topPx, width + 0.5, heightPx);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
soffset += len;
|
|
360
|
+
roffset += len;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
} // ML stores probabilities as array of numerics and MP is scaled phred scores
|
|
364
|
+
// https://github.com/samtools/hts-specs/pull/418/files#diff-e765c6479316309f56b636f88189cdde8c40b854c7bdcce9ee7fe87a4e76febcR596
|
|
365
|
+
//
|
|
366
|
+
// if we have ML or Ml, it is an 8bit probability, divide by 255
|
|
367
|
+
//
|
|
368
|
+
// if we have MP or Mp it is phred scaled ASCII, which can go up to 90 but
|
|
369
|
+
// has very high likelihood basecalls at that point, we really only care
|
|
370
|
+
// about low qual calls <20 approx
|
|
371
|
+
//
|
|
372
|
+
|
|
373
|
+
}, {
|
|
374
|
+
key: "colorByModifications",
|
|
375
|
+
value: function colorByModifications(ctx, layoutFeature, _config, region, bpPerPx, props) {
|
|
376
|
+
var feature = layoutFeature.feature,
|
|
377
|
+
topPx = layoutFeature.topPx,
|
|
378
|
+
heightPx = layoutFeature.heightPx;
|
|
379
|
+
var _props$modificationTa = props.modificationTagMap,
|
|
380
|
+
modificationTagMap = _props$modificationTa === void 0 ? {} : _props$modificationTa;
|
|
381
|
+
var mm = (0, _util2.getTagAlt)(feature, 'MM', 'Mm') || '';
|
|
382
|
+
var ml = (0, _util2.getTagAlt)(feature, 'ML', 'Ml') || [];
|
|
383
|
+
var probabilities = ml ? (typeof ml === 'string' ? ml.split(',').map(function (e) {
|
|
384
|
+
return +e;
|
|
385
|
+
}) : ml).map(function (e) {
|
|
386
|
+
return e / 255;
|
|
387
|
+
}) : (0, _util2.getTagAlt)(feature, 'MP', 'Mp').split('').map(function (s) {
|
|
388
|
+
return s.charCodeAt(0) - 33;
|
|
389
|
+
}).map(function (elt) {
|
|
390
|
+
return Math.min(1, elt / 50);
|
|
391
|
+
});
|
|
392
|
+
var cigar = feature.get('CIGAR');
|
|
393
|
+
var start = feature.get('start');
|
|
394
|
+
var end = feature.get('end');
|
|
395
|
+
var seq = feature.get('seq');
|
|
396
|
+
var strand = feature.get('strand');
|
|
397
|
+
var cigarOps = (0, _MismatchParser.parseCigar)(cigar);
|
|
398
|
+
var modifications = (0, _MismatchParser.getModificationPositions)(mm, seq, strand); // probIndex applies across multiple modifications e.g.
|
|
399
|
+
|
|
400
|
+
var probIndex = 0;
|
|
401
|
+
|
|
402
|
+
for (var i = 0; i < modifications.length; i++) {
|
|
403
|
+
var _modifications$i = modifications[i],
|
|
404
|
+
type = _modifications$i.type,
|
|
405
|
+
positions = _modifications$i.positions;
|
|
406
|
+
var col = modificationTagMap[type] || 'black';
|
|
407
|
+
var base = (0, _color["default"])(col);
|
|
408
|
+
|
|
409
|
+
var _iterator = _createForOfIteratorHelper((0, _MismatchParser.getNextRefPos)(cigarOps, positions)),
|
|
410
|
+
_step;
|
|
411
|
+
|
|
412
|
+
try {
|
|
413
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
414
|
+
var readPos = _step.value;
|
|
415
|
+
|
|
416
|
+
if (readPos >= 0 && start + readPos < end) {
|
|
417
|
+
var _bpSpanPx7 = (0, _util.bpSpanPx)(start + readPos, start + readPos + 1, region, bpPerPx),
|
|
418
|
+
_bpSpanPx8 = (0, _slicedToArray2["default"])(_bpSpanPx7, 2),
|
|
419
|
+
leftPx = _bpSpanPx8[0],
|
|
420
|
+
rightPx = _bpSpanPx8[1]; // give it a little boost of 0.1 to not make them fully
|
|
421
|
+
// invisible to avoid confusion
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
ctx.fillStyle = base.alpha(probabilities[probIndex] + 0.1).hsl().string();
|
|
425
|
+
ctx.fillRect(leftPx, topPx, rightPx - leftPx + 0.5, heightPx);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
probIndex++;
|
|
429
|
+
}
|
|
430
|
+
} catch (err) {
|
|
431
|
+
_iterator.e(err);
|
|
432
|
+
} finally {
|
|
433
|
+
_iterator.f();
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
} // Color by methylation is slightly modified version of color by
|
|
437
|
+
// modifications that focuses on CpG sites, with non-methylated CpG colored
|
|
438
|
+
// blue
|
|
439
|
+
|
|
440
|
+
}, {
|
|
441
|
+
key: "colorByMethylation",
|
|
442
|
+
value: function colorByMethylation(ctx, layoutFeature, _config, region, bpPerPx, props) {
|
|
443
|
+
var regionSequence = props.regionSequence;
|
|
444
|
+
var feature = layoutFeature.feature,
|
|
445
|
+
topPx = layoutFeature.topPx,
|
|
446
|
+
heightPx = layoutFeature.heightPx;
|
|
447
|
+
var mm = (0, _util2.getTagAlt)(feature, 'MM', 'Mm') || '';
|
|
448
|
+
|
|
449
|
+
if (!regionSequence) {
|
|
450
|
+
throw new Error('region sequence required for methylation');
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
var cigar = feature.get('CIGAR');
|
|
454
|
+
var fstart = feature.get('start');
|
|
455
|
+
var fend = feature.get('end');
|
|
456
|
+
var seq = feature.get('seq');
|
|
457
|
+
var strand = feature.get('strand');
|
|
458
|
+
var cigarOps = (0, _MismatchParser.parseCigar)(cigar);
|
|
459
|
+
var rstart = region.start,
|
|
460
|
+
rend = region.end;
|
|
461
|
+
var methBins = new Array(rend - rstart).fill(0);
|
|
462
|
+
var modifications = (0, _MismatchParser.getModificationPositions)(mm, seq, strand);
|
|
463
|
+
|
|
464
|
+
for (var i = 0; i < modifications.length; i++) {
|
|
465
|
+
var _modifications$i2 = modifications[i],
|
|
466
|
+
type = _modifications$i2.type,
|
|
467
|
+
positions = _modifications$i2.positions;
|
|
468
|
+
|
|
469
|
+
if (type === 'm' && positions) {
|
|
470
|
+
var _iterator2 = _createForOfIteratorHelper((0, _MismatchParser.getNextRefPos)(cigarOps, positions)),
|
|
471
|
+
_step2;
|
|
472
|
+
|
|
473
|
+
try {
|
|
474
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
475
|
+
var pos = _step2.value;
|
|
476
|
+
var epos = pos + fstart - rstart;
|
|
477
|
+
|
|
478
|
+
if (epos >= 0 && epos < methBins.length) {
|
|
479
|
+
methBins[epos] = 1;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
} catch (err) {
|
|
483
|
+
_iterator2.e(err);
|
|
484
|
+
} finally {
|
|
485
|
+
_iterator2.f();
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
for (var j = fstart; j < fend; j++) {
|
|
491
|
+
var _i = j - rstart;
|
|
492
|
+
|
|
493
|
+
if (_i >= 0 && _i < methBins.length) {
|
|
494
|
+
var l1 = regionSequence[_i].toLowerCase();
|
|
495
|
+
|
|
496
|
+
var l2 = regionSequence[_i + 1].toLowerCase(); // if we are zoomed out, display just a block over the cpg
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
if (bpPerPx > 2) {
|
|
500
|
+
if (l1 === 'c' && l2 === 'g') {
|
|
501
|
+
var s = rstart + _i;
|
|
502
|
+
|
|
503
|
+
var _bpSpanPx9 = (0, _util.bpSpanPx)(s, s + 2, region, bpPerPx),
|
|
504
|
+
_bpSpanPx10 = (0, _slicedToArray2["default"])(_bpSpanPx9, 2),
|
|
505
|
+
leftPx = _bpSpanPx10[0],
|
|
506
|
+
rightPx = _bpSpanPx10[1];
|
|
507
|
+
|
|
508
|
+
if (methBins[_i] || methBins[_i + 1]) {
|
|
509
|
+
ctx.fillStyle = 'red';
|
|
510
|
+
} else {
|
|
511
|
+
ctx.fillStyle = 'blue';
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
ctx.fillRect(leftPx, topPx, rightPx - leftPx + 0.5, heightPx);
|
|
515
|
+
}
|
|
516
|
+
} // if we are zoomed in, color the c inside the cpg
|
|
517
|
+
else {
|
|
518
|
+
// color
|
|
519
|
+
if (l1 === 'c' && l2 === 'g') {
|
|
520
|
+
var _s = rstart + _i;
|
|
521
|
+
|
|
522
|
+
var _bpSpanPx11 = (0, _util.bpSpanPx)(_s, _s + 1, region, bpPerPx),
|
|
523
|
+
_bpSpanPx12 = (0, _slicedToArray2["default"])(_bpSpanPx11, 2),
|
|
524
|
+
_leftPx = _bpSpanPx12[0],
|
|
525
|
+
_rightPx = _bpSpanPx12[1];
|
|
526
|
+
|
|
527
|
+
if (methBins[_i]) {
|
|
528
|
+
ctx.fillStyle = 'red';
|
|
529
|
+
} else {
|
|
530
|
+
ctx.fillStyle = 'blue';
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
ctx.fillRect(_leftPx, topPx, _rightPx - _leftPx + 0.5, heightPx);
|
|
534
|
+
|
|
535
|
+
var _bpSpanPx13 = (0, _util.bpSpanPx)(_s + 1, _s + 2, region, bpPerPx),
|
|
536
|
+
_bpSpanPx14 = (0, _slicedToArray2["default"])(_bpSpanPx13, 2),
|
|
537
|
+
leftPx2 = _bpSpanPx14[0],
|
|
538
|
+
rightPx2 = _bpSpanPx14[1];
|
|
539
|
+
|
|
540
|
+
if (methBins[_i + 1]) {
|
|
541
|
+
ctx.fillStyle = 'red';
|
|
542
|
+
} else {
|
|
543
|
+
ctx.fillStyle = 'blue';
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
ctx.fillRect(leftPx2, topPx, rightPx2 - leftPx2 + 0.5, heightPx);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}, {
|
|
553
|
+
key: "drawRect",
|
|
554
|
+
value: function drawRect(ctx, feat, props) {
|
|
555
|
+
var regions = props.regions,
|
|
556
|
+
bpPerPx = props.bpPerPx;
|
|
557
|
+
var heightPx = feat.heightPx,
|
|
558
|
+
topPx = feat.topPx,
|
|
559
|
+
feature = feat.feature;
|
|
560
|
+
|
|
561
|
+
var _regions = (0, _slicedToArray2["default"])(regions, 1),
|
|
562
|
+
region = _regions[0];
|
|
563
|
+
|
|
564
|
+
var _bpSpanPx15 = (0, _util.bpSpanPx)(feature.get('start'), feature.get('end'), region, bpPerPx),
|
|
565
|
+
_bpSpanPx16 = (0, _slicedToArray2["default"])(_bpSpanPx15, 2),
|
|
566
|
+
leftPx = _bpSpanPx16[0],
|
|
567
|
+
rightPx = _bpSpanPx16[1];
|
|
568
|
+
|
|
569
|
+
var flip = region.reversed ? -1 : 1;
|
|
570
|
+
var strand = feature.get('strand') * flip;
|
|
571
|
+
|
|
572
|
+
if (bpPerPx < 10) {
|
|
573
|
+
if (strand === -1) {
|
|
574
|
+
ctx.beginPath();
|
|
575
|
+
ctx.moveTo(leftPx - 5, topPx + heightPx / 2);
|
|
576
|
+
ctx.lineTo(leftPx, topPx + heightPx);
|
|
577
|
+
ctx.lineTo(rightPx, topPx + heightPx);
|
|
578
|
+
ctx.lineTo(rightPx, topPx);
|
|
579
|
+
ctx.lineTo(leftPx, topPx);
|
|
580
|
+
ctx.closePath();
|
|
581
|
+
ctx.fill();
|
|
582
|
+
} else {
|
|
583
|
+
ctx.beginPath();
|
|
584
|
+
ctx.moveTo(leftPx, topPx);
|
|
585
|
+
ctx.lineTo(leftPx, topPx + heightPx);
|
|
586
|
+
ctx.lineTo(rightPx, topPx + heightPx);
|
|
587
|
+
ctx.lineTo(rightPx + 5, topPx + heightPx / 2);
|
|
588
|
+
ctx.lineTo(rightPx, topPx);
|
|
589
|
+
ctx.closePath();
|
|
590
|
+
ctx.fill();
|
|
591
|
+
}
|
|
592
|
+
} else {
|
|
593
|
+
ctx.fillRect(leftPx, topPx, rightPx - leftPx, heightPx);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
}, {
|
|
597
|
+
key: "drawAlignmentRect",
|
|
598
|
+
value: function drawAlignmentRect(ctx, feat, props) {
|
|
599
|
+
var defaultColor = props.defaultColor,
|
|
600
|
+
config = props.config,
|
|
601
|
+
bpPerPx = props.bpPerPx,
|
|
602
|
+
regions = props.regions,
|
|
603
|
+
colorBy = props.colorBy,
|
|
604
|
+
_props$colorTagMap = props.colorTagMap,
|
|
605
|
+
colorTagMap = _props$colorTagMap === void 0 ? {} : _props$colorTagMap,
|
|
606
|
+
colorForBase = props.colorForBase,
|
|
607
|
+
contrastForBase = props.contrastForBase,
|
|
608
|
+
charWidth = props.charWidth,
|
|
609
|
+
charHeight = props.charHeight;
|
|
610
|
+
|
|
611
|
+
var _ref4 = colorBy || {},
|
|
612
|
+
_ref4$tag = _ref4.tag,
|
|
613
|
+
tag = _ref4$tag === void 0 ? '' : _ref4$tag,
|
|
614
|
+
_ref4$type = _ref4.type,
|
|
615
|
+
colorType = _ref4$type === void 0 ? '' : _ref4$type;
|
|
616
|
+
|
|
617
|
+
var feature = feat.feature;
|
|
618
|
+
var region = regions[0]; // first pass for simple color changes that change the color of the
|
|
619
|
+
// alignment
|
|
620
|
+
|
|
621
|
+
switch (colorType) {
|
|
622
|
+
case 'insertSize':
|
|
623
|
+
ctx.fillStyle = this.colorByInsertSize(feature, config);
|
|
624
|
+
break;
|
|
625
|
+
|
|
626
|
+
case 'strand':
|
|
627
|
+
ctx.fillStyle = feature.get('strand') === -1 ? '#8F8FD8' : '#EC8B8B';
|
|
628
|
+
break;
|
|
629
|
+
|
|
630
|
+
case 'mappingQuality':
|
|
631
|
+
ctx.fillStyle = "hsl(".concat(feature.get('mq'), ",50%,50%)");
|
|
632
|
+
break;
|
|
633
|
+
|
|
634
|
+
case 'pairOrientation':
|
|
635
|
+
ctx.fillStyle = this.colorByOrientation(feature, config);
|
|
636
|
+
break;
|
|
637
|
+
|
|
638
|
+
case 'stranded':
|
|
639
|
+
ctx.fillStyle = alignmentColoring[this.colorByStranded(feature, config)];
|
|
640
|
+
break;
|
|
641
|
+
|
|
642
|
+
case 'xs':
|
|
643
|
+
case 'tag':
|
|
644
|
+
{
|
|
645
|
+
var tags = feature.get('tags');
|
|
646
|
+
var val = tags ? tags[tag] : feature.get(tag); // special for for XS/TS tag
|
|
647
|
+
|
|
648
|
+
if (tag === 'XS' || tag === 'TS') {
|
|
649
|
+
var map = {
|
|
650
|
+
'-': 'color_rev_strand',
|
|
651
|
+
'+': 'color_fwd_strand'
|
|
652
|
+
};
|
|
653
|
+
ctx.fillStyle = alignmentColoring[map[val] || 'color_nostrand'];
|
|
654
|
+
} // lower case 'ts' from minimap2 is flipped from xs
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
if (tag === 'ts') {
|
|
658
|
+
var _map = {
|
|
659
|
+
'-': feature.get('strand') === -1 ? 'color_fwd_strand' : 'color_rev_strand',
|
|
660
|
+
'+': feature.get('strand') === -1 ? 'color_rev_strand' : 'color_fwd_strand'
|
|
661
|
+
};
|
|
662
|
+
ctx.fillStyle = alignmentColoring[_map[val] || 'color_nostrand'];
|
|
663
|
+
} // tag is not one of the autofilled tags, has color-value pairs from
|
|
664
|
+
// fetchValues
|
|
665
|
+
else {
|
|
666
|
+
var foundValue = colorTagMap[val];
|
|
667
|
+
ctx.fillStyle = foundValue || alignmentColoring['color_nostrand'];
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
break;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
case 'insertSizeAndPairOrientation':
|
|
674
|
+
break;
|
|
675
|
+
|
|
676
|
+
case 'modifications':
|
|
677
|
+
case 'methylation':
|
|
678
|
+
// this coloring is similar to igv.js, and is helpful to color negative
|
|
679
|
+
// strand reads differently because their c-g will be flipped (e.g. g-c
|
|
680
|
+
// read right to left)
|
|
681
|
+
if (feature.get('flags') & 16) {
|
|
682
|
+
ctx.fillStyle = '#c8dcc8';
|
|
683
|
+
} else {
|
|
684
|
+
ctx.fillStyle = '#c8c8c8';
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
break;
|
|
688
|
+
|
|
689
|
+
case 'normal':
|
|
690
|
+
default:
|
|
691
|
+
if (defaultColor) {
|
|
692
|
+
// avoid a readConfObject call here
|
|
693
|
+
ctx.fillStyle = '#c8c8c8';
|
|
694
|
+
} else {
|
|
695
|
+
ctx.fillStyle = (0, _configuration.readConfObject)(config, 'color', {
|
|
696
|
+
feature: feature
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
break;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
this.drawRect(ctx, feat, props); // second pass for color types that render per-base things that go over the
|
|
704
|
+
// existing drawing
|
|
705
|
+
|
|
706
|
+
switch (colorType) {
|
|
707
|
+
case 'perBaseQuality':
|
|
708
|
+
this.colorByPerBaseQuality(ctx, feat, config, region, bpPerPx);
|
|
709
|
+
break;
|
|
710
|
+
|
|
711
|
+
case 'perBaseLettering':
|
|
712
|
+
this.colorByPerBaseLettering(ctx, feat, config, region, bpPerPx, {
|
|
713
|
+
colorForBase: colorForBase,
|
|
714
|
+
contrastForBase: contrastForBase,
|
|
715
|
+
charWidth: charWidth,
|
|
716
|
+
charHeight: charHeight
|
|
717
|
+
});
|
|
718
|
+
break;
|
|
719
|
+
|
|
720
|
+
case 'modifications':
|
|
721
|
+
this.colorByModifications(ctx, feat, config, region, bpPerPx, props);
|
|
722
|
+
break;
|
|
723
|
+
|
|
724
|
+
case 'methylation':
|
|
725
|
+
this.colorByMethylation(ctx, feat, config, region, bpPerPx, props);
|
|
726
|
+
break;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
}, {
|
|
730
|
+
key: "drawMismatches",
|
|
731
|
+
value: function drawMismatches(ctx, feat, props, opts) {
|
|
732
|
+
var minSubfeatureWidth = opts.minSubfeatureWidth,
|
|
733
|
+
largeInsertionIndicatorScale = opts.largeInsertionIndicatorScale,
|
|
734
|
+
mismatchAlpha = opts.mismatchAlpha,
|
|
735
|
+
_opts$drawSNPs = opts.drawSNPs,
|
|
736
|
+
drawSNPs = _opts$drawSNPs === void 0 ? true : _opts$drawSNPs,
|
|
737
|
+
_opts$drawIndels = opts.drawIndels,
|
|
738
|
+
drawIndels = _opts$drawIndels === void 0 ? true : _opts$drawIndels,
|
|
739
|
+
charWidth = opts.charWidth,
|
|
740
|
+
charHeight = opts.charHeight,
|
|
741
|
+
colorForBase = opts.colorForBase,
|
|
742
|
+
contrastForBase = opts.contrastForBase;
|
|
743
|
+
var bpPerPx = props.bpPerPx,
|
|
744
|
+
regions = props.regions;
|
|
745
|
+
var heightPx = feat.heightPx,
|
|
746
|
+
topPx = feat.topPx,
|
|
747
|
+
feature = feat.feature;
|
|
748
|
+
|
|
749
|
+
var _regions2 = (0, _slicedToArray2["default"])(regions, 1),
|
|
750
|
+
region = _regions2[0];
|
|
751
|
+
|
|
752
|
+
var start = feature.get('start');
|
|
753
|
+
var pxPerBp = Math.min(1 / bpPerPx, 2);
|
|
754
|
+
var w = Math.max(minSubfeatureWidth, pxPerBp);
|
|
755
|
+
var mismatches = feature.get('mismatches');
|
|
756
|
+
var heightLim = charHeight - 2;
|
|
757
|
+
|
|
758
|
+
function getAlphaColor(baseColor, mismatch) {
|
|
759
|
+
var color = baseColor;
|
|
760
|
+
|
|
761
|
+
if (mismatchAlpha && mismatch.qual !== undefined) {
|
|
762
|
+
color = (0, _color["default"])(baseColor).alpha(Math.min(1, mismatch.qual / 50)).hsl().string();
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
return color;
|
|
766
|
+
} // extraHorizontallyFlippedOffset is used to draw interbase items, which
|
|
767
|
+
// are located to the left when forward and right when reversed
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
var extraHorizontallyFlippedOffset = region.reversed ? 1 / bpPerPx + 1 : -1; // two pass rendering: first pass, draw all the mismatches except wide
|
|
771
|
+
// insertion markers
|
|
772
|
+
|
|
773
|
+
for (var i = 0; i < mismatches.length; i += 1) {
|
|
774
|
+
var mismatch = mismatches[i];
|
|
775
|
+
var mstart = start + mismatch.start;
|
|
776
|
+
var mlen = mismatch.length;
|
|
777
|
+
var mbase = mismatch.base;
|
|
778
|
+
|
|
779
|
+
var _bpSpanPx17 = (0, _util.bpSpanPx)(mstart, mstart + mlen, region, bpPerPx),
|
|
780
|
+
_bpSpanPx18 = (0, _slicedToArray2["default"])(_bpSpanPx17, 2),
|
|
781
|
+
leftPx = _bpSpanPx18[0],
|
|
782
|
+
rightPx = _bpSpanPx18[1];
|
|
783
|
+
|
|
784
|
+
var widthPx = Math.max(minSubfeatureWidth, Math.abs(leftPx - rightPx));
|
|
785
|
+
|
|
786
|
+
if (mismatch.type === 'mismatch' && drawSNPs) {
|
|
787
|
+
var baseColor = colorForBase[mismatch.base] || '#888';
|
|
788
|
+
ctx.fillStyle = getAlphaColor(baseColor, mismatch);
|
|
789
|
+
ctx.fillRect(leftPx, topPx, widthPx, heightPx);
|
|
790
|
+
|
|
791
|
+
if (widthPx >= charWidth && heightPx >= heightLim) {
|
|
792
|
+
// normal SNP coloring
|
|
793
|
+
var contrast = contrastForBase[mismatch.base] || 'black';
|
|
794
|
+
ctx.fillStyle = getAlphaColor(contrast, mismatch);
|
|
795
|
+
ctx.fillText(mbase, leftPx + (widthPx - charWidth) / 2 + 1, topPx + heightPx);
|
|
796
|
+
}
|
|
797
|
+
} else if (mismatch.type === 'deletion' && drawIndels) {
|
|
798
|
+
var _baseColor = colorForBase.deletion;
|
|
799
|
+
ctx.fillStyle = _baseColor;
|
|
800
|
+
ctx.fillRect(leftPx, topPx, widthPx, heightPx);
|
|
801
|
+
var txt = "".concat(mismatch.length);
|
|
802
|
+
var rwidth = (0, _util.measureText)(txt, 10);
|
|
803
|
+
|
|
804
|
+
if (widthPx >= rwidth && heightPx >= heightLim) {
|
|
805
|
+
ctx.fillStyle = contrastForBase.deletion;
|
|
806
|
+
ctx.fillText(txt, (leftPx + rightPx) / 2 - rwidth / 2, topPx + heightPx);
|
|
807
|
+
}
|
|
808
|
+
} else if (mismatch.type === 'insertion' && drawIndels) {
|
|
809
|
+
ctx.fillStyle = 'purple';
|
|
810
|
+
var pos = leftPx + extraHorizontallyFlippedOffset;
|
|
811
|
+
var len = +mismatch.base || mismatch.length;
|
|
812
|
+
var insW = Math.max(minSubfeatureWidth, Math.min(1.2, 1 / bpPerPx));
|
|
813
|
+
|
|
814
|
+
if (len < 10) {
|
|
815
|
+
ctx.fillRect(pos, topPx, insW, heightPx);
|
|
816
|
+
|
|
817
|
+
if (1 / bpPerPx >= charWidth && heightPx >= heightLim) {
|
|
818
|
+
ctx.fillRect(pos - insW, topPx, insW * 3, 1);
|
|
819
|
+
ctx.fillRect(pos - insW, topPx + heightPx - 1, insW * 3, 1);
|
|
820
|
+
ctx.fillText("(".concat(mismatch.base, ")"), pos + 3, topPx + heightPx);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
} else if (mismatch.type === 'hardclip' || mismatch.type === 'softclip') {
|
|
824
|
+
ctx.fillStyle = mismatch.type === 'hardclip' ? 'red' : 'blue';
|
|
825
|
+
|
|
826
|
+
var _pos = leftPx + extraHorizontallyFlippedOffset;
|
|
827
|
+
|
|
828
|
+
ctx.fillRect(_pos, topPx, w, heightPx);
|
|
829
|
+
|
|
830
|
+
if (1 / bpPerPx >= charWidth && heightPx >= heightLim) {
|
|
831
|
+
ctx.fillRect(_pos - w, topPx, w * 3, 1);
|
|
832
|
+
ctx.fillRect(_pos - w, topPx + heightPx - 1, w * 3, 1);
|
|
833
|
+
ctx.fillText("(".concat(mismatch.base, ")"), _pos + 3, topPx + heightPx);
|
|
834
|
+
}
|
|
835
|
+
} else if (mismatch.type === 'skip') {
|
|
836
|
+
// fix to avoid bad rendering note that this was also related to chrome
|
|
837
|
+
// bug https://bugs.chromium.org/p/chromium/issues/detail?id=1131528
|
|
838
|
+
// also affected firefox ref #1236 #2750
|
|
839
|
+
if (leftPx + widthPx > 0) {
|
|
840
|
+
// make small exons more visible when zoomed far out
|
|
841
|
+
var adjustPx = widthPx - (bpPerPx > 10 ? 1.5 : 0);
|
|
842
|
+
ctx.clearRect(leftPx, topPx, adjustPx, heightPx);
|
|
843
|
+
ctx.fillStyle = '#333';
|
|
844
|
+
ctx.fillRect(Math.max(0, leftPx), topPx + heightPx / 2 - 1, adjustPx + (leftPx < 0 ? leftPx : 0), 2);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
} // second pass, draw wide insertion markers on top
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
if (drawIndels) {
|
|
851
|
+
for (var _i2 = 0; _i2 < mismatches.length; _i2 += 1) {
|
|
852
|
+
var _mismatch = mismatches[_i2];
|
|
853
|
+
|
|
854
|
+
var _mstart = start + _mismatch.start;
|
|
855
|
+
|
|
856
|
+
var _mlen = _mismatch.length;
|
|
857
|
+
|
|
858
|
+
var _bpSpanPx19 = (0, _util.bpSpanPx)(_mstart, _mstart + _mlen, region, bpPerPx),
|
|
859
|
+
_bpSpanPx20 = (0, _slicedToArray2["default"])(_bpSpanPx19, 1),
|
|
860
|
+
_leftPx2 = _bpSpanPx20[0];
|
|
861
|
+
|
|
862
|
+
var _len2 = +_mismatch.base || _mismatch.length;
|
|
863
|
+
|
|
864
|
+
var _txt = "".concat(_len2);
|
|
865
|
+
|
|
866
|
+
if (_mismatch.type === 'insertion' && _len2 >= 10) {
|
|
867
|
+
if (bpPerPx > largeInsertionIndicatorScale) {
|
|
868
|
+
ctx.fillStyle = 'purple';
|
|
869
|
+
ctx.fillRect(_leftPx2 - 1, topPx, 2, heightPx);
|
|
870
|
+
} else if (heightPx > charHeight) {
|
|
871
|
+
var rect = ctx.measureText(_txt);
|
|
872
|
+
var padding = 5;
|
|
873
|
+
ctx.fillStyle = 'purple';
|
|
874
|
+
ctx.fillRect(_leftPx2 - rect.width / 2 - padding, topPx, rect.width + 2 * padding, heightPx);
|
|
875
|
+
ctx.fillStyle = 'white';
|
|
876
|
+
ctx.fillText(_txt, _leftPx2 - rect.width / 2, topPx + heightPx);
|
|
877
|
+
} else {
|
|
878
|
+
var _padding = 2;
|
|
879
|
+
ctx.fillStyle = 'purple';
|
|
880
|
+
ctx.fillRect(_leftPx2 - _padding, topPx, 2 * _padding, heightPx);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
}, {
|
|
887
|
+
key: "drawSoftClipping",
|
|
888
|
+
value: function drawSoftClipping(ctx, feat, props, config, theme) {
|
|
889
|
+
var feature = feat.feature,
|
|
890
|
+
topPx = feat.topPx,
|
|
891
|
+
heightPx = feat.heightPx;
|
|
892
|
+
var regions = props.regions,
|
|
893
|
+
bpPerPx = props.bpPerPx;
|
|
894
|
+
|
|
895
|
+
var _regions3 = (0, _slicedToArray2["default"])(regions, 1),
|
|
896
|
+
region = _regions3[0];
|
|
897
|
+
|
|
898
|
+
var minFeatWidth = (0, _configuration.readConfObject)(config, 'minSubfeatureWidth');
|
|
899
|
+
var mismatches = feature.get('mismatches');
|
|
900
|
+
var seq = feature.get('seq');
|
|
901
|
+
|
|
902
|
+
var _this$getCharWidthHei = this.getCharWidthHeight(ctx),
|
|
903
|
+
charWidth = _this$getCharWidthHei.charWidth,
|
|
904
|
+
charHeight = _this$getCharWidthHei.charHeight;
|
|
905
|
+
|
|
906
|
+
var colorForBase = {
|
|
907
|
+
A: theme.palette.bases.A.main,
|
|
908
|
+
C: theme.palette.bases.C.main,
|
|
909
|
+
G: theme.palette.bases.G.main,
|
|
910
|
+
T: theme.palette.bases.T.main,
|
|
911
|
+
deletion: '#808080' // gray
|
|
912
|
+
|
|
913
|
+
}; // Display all bases softclipped off in lightened colors
|
|
914
|
+
|
|
915
|
+
if (seq) {
|
|
916
|
+
mismatches.filter(function (mismatch) {
|
|
917
|
+
return mismatch.type === 'softclip';
|
|
918
|
+
}).forEach(function (mismatch) {
|
|
919
|
+
var softClipLength = mismatch.cliplen || 0;
|
|
920
|
+
var s = feature.get('start');
|
|
921
|
+
var softClipStart = mismatch.start === 0 ? s - softClipLength : s + mismatch.start;
|
|
922
|
+
|
|
923
|
+
for (var k = 0; k < softClipLength; k += 1) {
|
|
924
|
+
var base = seq.charAt(k + mismatch.start); // If softclip length+start is longer than sequence, no need to
|
|
925
|
+
// continue showing base
|
|
926
|
+
|
|
927
|
+
if (!base) {
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
var _bpSpanPx21 = (0, _util.bpSpanPx)(softClipStart + k, softClipStart + k + 1, region, bpPerPx),
|
|
932
|
+
_bpSpanPx22 = (0, _slicedToArray2["default"])(_bpSpanPx21, 2),
|
|
933
|
+
softClipLeftPx = _bpSpanPx22[0],
|
|
934
|
+
softClipRightPx = _bpSpanPx22[1];
|
|
935
|
+
|
|
936
|
+
var softClipWidthPx = Math.max(minFeatWidth, Math.abs(softClipLeftPx - softClipRightPx)); // Black accounts for IUPAC ambiguity code bases such as N that
|
|
937
|
+
// show in soft clipping
|
|
938
|
+
|
|
939
|
+
var baseColor = colorForBase[base] || '#000000';
|
|
940
|
+
ctx.fillStyle = baseColor;
|
|
941
|
+
ctx.fillRect(softClipLeftPx, topPx, softClipWidthPx, heightPx);
|
|
942
|
+
|
|
943
|
+
if (softClipWidthPx >= charWidth && heightPx >= charHeight - 5) {
|
|
944
|
+
ctx.fillStyle = theme.palette.getContrastText(baseColor);
|
|
945
|
+
ctx.fillText(base, softClipLeftPx + (softClipWidthPx - charWidth) / 2 + 1, topPx + heightPx);
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
});
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
}, {
|
|
952
|
+
key: "makeImageData",
|
|
953
|
+
value: function () {
|
|
954
|
+
var _makeImageData = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(ctx, layoutRecords, props) {
|
|
955
|
+
var _this2 = this;
|
|
956
|
+
|
|
957
|
+
var layout, config, showSoftClip, colorBy, configTheme, mismatchAlpha, minSubfeatureWidth, insertScale, defaultColor, theme, colorForBase, contrastForBase, _this$getCharWidthHei2, charWidth, charHeight;
|
|
958
|
+
|
|
959
|
+
return _regenerator["default"].wrap(function _callee$(_context) {
|
|
960
|
+
while (1) {
|
|
961
|
+
switch (_context.prev = _context.next) {
|
|
962
|
+
case 0:
|
|
963
|
+
layout = props.layout, config = props.config, showSoftClip = props.showSoftClip, colorBy = props.colorBy, configTheme = props.theme;
|
|
964
|
+
mismatchAlpha = (0, _configuration.readConfObject)(config, 'mismatchAlpha');
|
|
965
|
+
minSubfeatureWidth = (0, _configuration.readConfObject)(config, 'minSubfeatureWidth');
|
|
966
|
+
insertScale = (0, _configuration.readConfObject)(config, 'largeInsertionIndicatorScale');
|
|
967
|
+
defaultColor = (0, _configuration.readConfObject)(config, 'color') === '#f0f';
|
|
968
|
+
theme = (0, _ui.createJBrowseTheme)(configTheme);
|
|
969
|
+
colorForBase = getColorBaseMap(theme);
|
|
970
|
+
contrastForBase = getContrastBaseMap(theme);
|
|
971
|
+
|
|
972
|
+
if (layout) {
|
|
973
|
+
_context.next = 10;
|
|
974
|
+
break;
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
throw new Error("layout required");
|
|
978
|
+
|
|
979
|
+
case 10:
|
|
980
|
+
if (layout.addRect) {
|
|
981
|
+
_context.next = 12;
|
|
982
|
+
break;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
throw new Error('invalid layout object');
|
|
986
|
+
|
|
987
|
+
case 12:
|
|
988
|
+
ctx.font = 'bold 10px Courier New,monospace';
|
|
989
|
+
_this$getCharWidthHei2 = this.getCharWidthHeight(ctx), charWidth = _this$getCharWidthHei2.charWidth, charHeight = _this$getCharWidthHei2.charHeight;
|
|
990
|
+
layoutRecords.forEach(function (feat) {
|
|
991
|
+
if (feat === null) {
|
|
992
|
+
return;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
_this2.drawAlignmentRect(ctx, feat, _objectSpread(_objectSpread({}, props), {}, {
|
|
996
|
+
defaultColor: defaultColor,
|
|
997
|
+
colorForBase: colorForBase,
|
|
998
|
+
contrastForBase: contrastForBase,
|
|
999
|
+
charWidth: charWidth,
|
|
1000
|
+
charHeight: charHeight
|
|
1001
|
+
}));
|
|
1002
|
+
|
|
1003
|
+
_this2.drawMismatches(ctx, feat, props, {
|
|
1004
|
+
mismatchAlpha: mismatchAlpha,
|
|
1005
|
+
drawSNPs: shouldDrawMismatches(colorBy === null || colorBy === void 0 ? void 0 : colorBy.type),
|
|
1006
|
+
drawIndels: shouldDrawMismatches(colorBy === null || colorBy === void 0 ? void 0 : colorBy.type),
|
|
1007
|
+
largeInsertionIndicatorScale: insertScale,
|
|
1008
|
+
minSubfeatureWidth: minSubfeatureWidth,
|
|
1009
|
+
charWidth: charWidth,
|
|
1010
|
+
charHeight: charHeight,
|
|
1011
|
+
colorForBase: colorForBase,
|
|
1012
|
+
contrastForBase: contrastForBase
|
|
1013
|
+
});
|
|
1014
|
+
|
|
1015
|
+
if (showSoftClip) {
|
|
1016
|
+
_this2.drawSoftClipping(ctx, feat, props, config, theme);
|
|
1017
|
+
}
|
|
1018
|
+
});
|
|
1019
|
+
|
|
1020
|
+
case 15:
|
|
1021
|
+
case "end":
|
|
1022
|
+
return _context.stop();
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
}, _callee, this);
|
|
1026
|
+
}));
|
|
1027
|
+
|
|
1028
|
+
function makeImageData(_x, _x2, _x3) {
|
|
1029
|
+
return _makeImageData.apply(this, arguments);
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
return makeImageData;
|
|
1033
|
+
}() // we perform a full layout before render as a separate method because the
|
|
1034
|
+
// layout determines the height of the canvas that we use to render
|
|
1035
|
+
|
|
1036
|
+
}, {
|
|
1037
|
+
key: "layoutFeats",
|
|
1038
|
+
value: function layoutFeats(props) {
|
|
1039
|
+
var _this3 = this;
|
|
1040
|
+
|
|
1041
|
+
var layout = props.layout,
|
|
1042
|
+
features = props.features,
|
|
1043
|
+
sortedBy = props.sortedBy,
|
|
1044
|
+
config = props.config,
|
|
1045
|
+
bpPerPx = props.bpPerPx,
|
|
1046
|
+
showSoftClip = props.showSoftClip,
|
|
1047
|
+
regions = props.regions;
|
|
1048
|
+
|
|
1049
|
+
var _regions4 = (0, _slicedToArray2["default"])(regions, 1),
|
|
1050
|
+
region = _regions4[0];
|
|
1051
|
+
|
|
1052
|
+
if (!layout) {
|
|
1053
|
+
throw new Error("layout required");
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
if (!layout.addRect) {
|
|
1057
|
+
throw new Error('invalid layout object');
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
var featureMap = sortedBy !== null && sortedBy !== void 0 && sortedBy.type && region.start === sortedBy.pos ? (0, _sortUtil.sortFeature)(features, sortedBy) : features;
|
|
1061
|
+
var heightPx = (0, _configuration.readConfObject)(config, 'height');
|
|
1062
|
+
var displayMode = (0, _configuration.readConfObject)(config, 'displayMode');
|
|
1063
|
+
var layoutRecords = (0, _util.iterMap)(featureMap.values(), function (feature) {
|
|
1064
|
+
return _this3.layoutFeature({
|
|
1065
|
+
feature: feature,
|
|
1066
|
+
layout: layout,
|
|
1067
|
+
bpPerPx: bpPerPx,
|
|
1068
|
+
region: region,
|
|
1069
|
+
showSoftClip: showSoftClip,
|
|
1070
|
+
heightPx: heightPx,
|
|
1071
|
+
displayMode: displayMode
|
|
1072
|
+
});
|
|
1073
|
+
}, featureMap.size);
|
|
1074
|
+
return layoutRecords;
|
|
1075
|
+
}
|
|
1076
|
+
}, {
|
|
1077
|
+
key: "fetchSequence",
|
|
1078
|
+
value: function () {
|
|
1079
|
+
var _fetchSequence2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(renderProps) {
|
|
1080
|
+
var sessionId, regions, adapterConfig, sequenceAdapter, _yield$getAdapter, dataAdapter, _regions5, region;
|
|
1081
|
+
|
|
1082
|
+
return _regenerator["default"].wrap(function _callee2$(_context2) {
|
|
1083
|
+
while (1) {
|
|
1084
|
+
switch (_context2.prev = _context2.next) {
|
|
1085
|
+
case 0:
|
|
1086
|
+
sessionId = renderProps.sessionId, regions = renderProps.regions, adapterConfig = renderProps.adapterConfig;
|
|
1087
|
+
sequenceAdapter = adapterConfig.sequenceAdapter;
|
|
1088
|
+
|
|
1089
|
+
if (sequenceAdapter) {
|
|
1090
|
+
_context2.next = 4;
|
|
1091
|
+
break;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
return _context2.abrupt("return", undefined);
|
|
1095
|
+
|
|
1096
|
+
case 4:
|
|
1097
|
+
_context2.next = 6;
|
|
1098
|
+
return (0, _dataAdapterCache.getAdapter)(this.pluginManager, sessionId, sequenceAdapter);
|
|
1099
|
+
|
|
1100
|
+
case 6:
|
|
1101
|
+
_yield$getAdapter = _context2.sent;
|
|
1102
|
+
dataAdapter = _yield$getAdapter.dataAdapter;
|
|
1103
|
+
_regions5 = (0, _slicedToArray2["default"])(regions, 1), region = _regions5[0];
|
|
1104
|
+
return _context2.abrupt("return", (0, _util2.fetchSequence)(region, dataAdapter));
|
|
1105
|
+
|
|
1106
|
+
case 10:
|
|
1107
|
+
case "end":
|
|
1108
|
+
return _context2.stop();
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
}, _callee2, this);
|
|
1112
|
+
}));
|
|
1113
|
+
|
|
1114
|
+
function fetchSequence(_x4) {
|
|
1115
|
+
return _fetchSequence2.apply(this, arguments);
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
return fetchSequence;
|
|
1119
|
+
}()
|
|
1120
|
+
}, {
|
|
1121
|
+
key: "render",
|
|
1122
|
+
value: function () {
|
|
1123
|
+
var _render = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3(renderProps) {
|
|
1124
|
+
var _renderProps$colorBy,
|
|
1125
|
+
_this4 = this;
|
|
1126
|
+
|
|
1127
|
+
var features, layout, regions, bpPerPx, layoutRecords, _regions6, region, regionSequence, end, start, width, height, res, results;
|
|
1128
|
+
|
|
1129
|
+
return _regenerator["default"].wrap(function _callee3$(_context3) {
|
|
1130
|
+
while (1) {
|
|
1131
|
+
switch (_context3.prev = _context3.next) {
|
|
1132
|
+
case 0:
|
|
1133
|
+
_context3.next = 2;
|
|
1134
|
+
return this.getFeatures(renderProps);
|
|
1135
|
+
|
|
1136
|
+
case 2:
|
|
1137
|
+
features = _context3.sent;
|
|
1138
|
+
layout = this.createLayoutInWorker(renderProps);
|
|
1139
|
+
regions = renderProps.regions, bpPerPx = renderProps.bpPerPx;
|
|
1140
|
+
layoutRecords = this.layoutFeats(_objectSpread(_objectSpread({}, renderProps), {}, {
|
|
1141
|
+
features: features,
|
|
1142
|
+
layout: layout
|
|
1143
|
+
}));
|
|
1144
|
+
_regions6 = (0, _slicedToArray2["default"])(regions, 1), region = _regions6[0]; // only need reference sequence if there are features and only for some
|
|
1145
|
+
// cases
|
|
1146
|
+
|
|
1147
|
+
if (!(features.size && (0, _util2.shouldFetchReferenceSequence)((_renderProps$colorBy = renderProps.colorBy) === null || _renderProps$colorBy === void 0 ? void 0 : _renderProps$colorBy.type))) {
|
|
1148
|
+
_context3.next = 13;
|
|
1149
|
+
break;
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
_context3.next = 10;
|
|
1153
|
+
return this.fetchSequence(renderProps);
|
|
1154
|
+
|
|
1155
|
+
case 10:
|
|
1156
|
+
_context3.t0 = _context3.sent;
|
|
1157
|
+
_context3.next = 14;
|
|
1158
|
+
break;
|
|
1159
|
+
|
|
1160
|
+
case 13:
|
|
1161
|
+
_context3.t0 = undefined;
|
|
1162
|
+
|
|
1163
|
+
case 14:
|
|
1164
|
+
regionSequence = _context3.t0;
|
|
1165
|
+
end = region.end, start = region.start;
|
|
1166
|
+
width = (end - start) / bpPerPx;
|
|
1167
|
+
height = Math.max(layout.getTotalHeight(), 1);
|
|
1168
|
+
_context3.next = 20;
|
|
1169
|
+
return (0, _offscreenCanvasUtils.renderToAbstractCanvas)(width, height, renderProps, function (ctx) {
|
|
1170
|
+
return _this4.makeImageData(ctx, layoutRecords, _objectSpread(_objectSpread({}, renderProps), {}, {
|
|
1171
|
+
layout: layout,
|
|
1172
|
+
features: features,
|
|
1173
|
+
regionSequence: regionSequence
|
|
1174
|
+
}));
|
|
1175
|
+
});
|
|
1176
|
+
|
|
1177
|
+
case 20:
|
|
1178
|
+
res = _context3.sent;
|
|
1179
|
+
_context3.next = 23;
|
|
1180
|
+
return (0, _get2["default"])((0, _getPrototypeOf2["default"])(PileupRenderer.prototype), "render", this).call(this, _objectSpread(_objectSpread(_objectSpread({}, renderProps), res), {}, {
|
|
1181
|
+
features: features,
|
|
1182
|
+
layout: layout,
|
|
1183
|
+
height: height,
|
|
1184
|
+
width: width
|
|
1185
|
+
}));
|
|
1186
|
+
|
|
1187
|
+
case 23:
|
|
1188
|
+
results = _context3.sent;
|
|
1189
|
+
return _context3.abrupt("return", _objectSpread(_objectSpread(_objectSpread({}, results), res), {}, {
|
|
1190
|
+
features: features,
|
|
1191
|
+
layout: layout,
|
|
1192
|
+
height: height,
|
|
1193
|
+
width: width,
|
|
1194
|
+
maxHeightReached: layout.maxHeightReached
|
|
1195
|
+
}));
|
|
1196
|
+
|
|
1197
|
+
case 25:
|
|
1198
|
+
case "end":
|
|
1199
|
+
return _context3.stop();
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
}, _callee3, this);
|
|
1203
|
+
}));
|
|
1204
|
+
|
|
1205
|
+
function render(_x5) {
|
|
1206
|
+
return _render.apply(this, arguments);
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
return render;
|
|
1210
|
+
}()
|
|
1211
|
+
}, {
|
|
1212
|
+
key: "createSession",
|
|
1213
|
+
value: function createSession(args) {
|
|
1214
|
+
return new _PileupLayoutSession.PileupLayoutSession(args);
|
|
1215
|
+
}
|
|
1216
|
+
}]);
|
|
1217
|
+
return PileupRenderer;
|
|
1218
|
+
}(_BoxRendererType2["default"]);
|
|
1219
|
+
|
|
1220
|
+
exports["default"] = PileupRenderer;
|