@jbrowse/plugin-linear-genome-view 2.0.0 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BaseLinearDisplay/components/BaseLinearDisplay.js +28 -55
- package/dist/BaseLinearDisplay/components/BaseLinearDisplay.js.map +1 -1
- package/dist/BaseLinearDisplay/components/Block.js +17 -28
- package/dist/BaseLinearDisplay/components/Block.js.map +1 -1
- package/dist/BaseLinearDisplay/components/LinearBlocks.js +19 -21
- package/dist/BaseLinearDisplay/components/LinearBlocks.js.map +1 -1
- package/dist/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +28 -48
- package/dist/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js.map +1 -1
- package/dist/BaseLinearDisplay/components/Tooltip.js +29 -58
- package/dist/BaseLinearDisplay/components/Tooltip.js.map +1 -1
- package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js +242 -363
- package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js.map +1 -1
- package/dist/BaseLinearDisplay/models/baseLinearDisplayConfigSchema.js +1 -1
- package/dist/BaseLinearDisplay/models/baseLinearDisplayConfigSchema.js.map +1 -1
- package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.js +77 -129
- package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.js.map +1 -1
- package/dist/LinearBareDisplay/configSchema.js +2 -2
- package/dist/LinearBareDisplay/configSchema.js.map +1 -1
- package/dist/LinearBareDisplay/model.js +13 -19
- package/dist/LinearBareDisplay/model.js.map +1 -1
- package/dist/LinearBasicDisplay/components/SetMaxHeight.js +14 -31
- package/dist/LinearBasicDisplay/components/SetMaxHeight.js.map +1 -1
- package/dist/LinearBasicDisplay/configSchema.js +3 -3
- package/dist/LinearBasicDisplay/configSchema.js.map +1 -1
- package/dist/LinearBasicDisplay/model.js +119 -147
- package/dist/LinearBasicDisplay/model.js.map +1 -1
- package/dist/LinearGenomeView/components/CenterLine.js +11 -12
- package/dist/LinearGenomeView/components/CenterLine.js.map +1 -1
- package/dist/LinearGenomeView/components/ExportSvgDialog.js +30 -96
- package/dist/LinearGenomeView/components/ExportSvgDialog.js.map +1 -1
- package/dist/LinearGenomeView/components/GetSequenceDialog.d.ts +9 -0
- package/dist/LinearGenomeView/components/GetSequenceDialog.js +172 -0
- package/dist/LinearGenomeView/components/GetSequenceDialog.js.map +1 -0
- package/dist/LinearGenomeView/components/{VerticalGuides.d.ts → Gridlines.d.ts} +0 -0
- package/dist/LinearGenomeView/components/{VerticalGuides.js → Gridlines.js} +19 -21
- package/dist/LinearGenomeView/components/Gridlines.js.map +1 -0
- package/dist/LinearGenomeView/components/Header.js +26 -31
- package/dist/LinearGenomeView/components/Header.js.map +1 -1
- package/dist/LinearGenomeView/components/HelpDialog.js +10 -11
- package/dist/LinearGenomeView/components/HelpDialog.js.map +1 -1
- package/dist/LinearGenomeView/components/ImportForm.js +91 -154
- package/dist/LinearGenomeView/components/ImportForm.js.map +1 -1
- package/dist/LinearGenomeView/components/LinearGenomeView.js +20 -25
- package/dist/LinearGenomeView/components/LinearGenomeView.js.map +1 -1
- package/dist/LinearGenomeView/components/LinearGenomeViewSvg.js +86 -157
- package/dist/LinearGenomeView/components/LinearGenomeViewSvg.js.map +1 -1
- package/dist/LinearGenomeView/components/MiniControls.js +16 -32
- package/dist/LinearGenomeView/components/MiniControls.js.map +1 -1
- package/dist/LinearGenomeView/components/OverviewRubberBand.d.ts +0 -11
- package/dist/LinearGenomeView/components/OverviewRubberBand.js +55 -84
- package/dist/LinearGenomeView/components/OverviewRubberBand.js.map +1 -1
- package/dist/LinearGenomeView/components/OverviewScaleBar.js +94 -117
- package/dist/LinearGenomeView/components/OverviewScaleBar.js.map +1 -1
- package/dist/LinearGenomeView/components/RefNameAutocomplete.js +90 -172
- package/dist/LinearGenomeView/components/RefNameAutocomplete.js.map +1 -1
- package/dist/LinearGenomeView/components/RubberBand.js +51 -72
- package/dist/LinearGenomeView/components/RubberBand.js.map +1 -1
- package/dist/LinearGenomeView/components/Ruler.js +17 -18
- package/dist/LinearGenomeView/components/Ruler.js.map +1 -1
- package/dist/LinearGenomeView/components/ScaleBar.js +37 -58
- package/dist/LinearGenomeView/components/ScaleBar.js.map +1 -1
- package/dist/LinearGenomeView/components/SearchBox.js +69 -133
- package/dist/LinearGenomeView/components/SearchBox.js.map +1 -1
- package/dist/LinearGenomeView/components/SearchResultsDialog.js +32 -33
- package/dist/LinearGenomeView/components/SearchResultsDialog.js.map +1 -1
- package/dist/LinearGenomeView/components/{SequenceDialog.d.ts → SequenceSearchDialog.d.ts} +0 -0
- package/dist/LinearGenomeView/components/SequenceSearchDialog.js +104 -0
- package/dist/LinearGenomeView/components/SequenceSearchDialog.js.map +1 -0
- package/dist/LinearGenomeView/components/TrackContainer.d.ts +2 -1
- package/dist/LinearGenomeView/components/TrackContainer.js +36 -43
- package/dist/LinearGenomeView/components/TrackContainer.js.map +1 -1
- package/dist/LinearGenomeView/components/TrackLabel.js +50 -85
- package/dist/LinearGenomeView/components/TrackLabel.js.map +1 -1
- package/dist/LinearGenomeView/components/TracksContainer.js +33 -50
- package/dist/LinearGenomeView/components/TracksContainer.js.map +1 -1
- package/dist/LinearGenomeView/components/ZoomControls.js +15 -32
- package/dist/LinearGenomeView/components/ZoomControls.js.map +1 -1
- package/dist/LinearGenomeView/components/util.js +14 -87
- package/dist/LinearGenomeView/components/util.js.map +1 -1
- package/dist/LinearGenomeView/index.d.ts +66 -79
- package/dist/LinearGenomeView/index.js +534 -710
- package/dist/LinearGenomeView/index.js.map +1 -1
- package/dist/LinearGenomeView/util.js +17 -36
- package/dist/LinearGenomeView/util.js.map +1 -1
- package/dist/index.js +75 -146
- package/dist/index.js.map +1 -1
- package/esm/BaseLinearDisplay/components/BaseLinearDisplay.js +1 -1
- package/esm/BaseLinearDisplay/components/BaseLinearDisplay.js.map +1 -1
- package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +1 -0
- package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js.map +1 -1
- package/esm/LinearGenomeView/components/GetSequenceDialog.d.ts +9 -0
- package/esm/LinearGenomeView/components/{SequenceDialog.js → GetSequenceDialog.js} +5 -8
- package/esm/LinearGenomeView/components/GetSequenceDialog.js.map +1 -0
- package/esm/LinearGenomeView/components/{VerticalGuides.d.ts → Gridlines.d.ts} +0 -0
- package/esm/LinearGenomeView/components/{VerticalGuides.js → Gridlines.js} +1 -1
- package/esm/LinearGenomeView/components/Gridlines.js.map +1 -0
- package/esm/LinearGenomeView/components/ImportForm.js +1 -0
- package/esm/LinearGenomeView/components/ImportForm.js.map +1 -1
- package/esm/LinearGenomeView/components/LinearGenomeView.js +3 -7
- package/esm/LinearGenomeView/components/LinearGenomeView.js.map +1 -1
- package/esm/LinearGenomeView/components/OverviewRubberBand.d.ts +0 -11
- package/esm/LinearGenomeView/components/OverviewRubberBand.js +16 -21
- package/esm/LinearGenomeView/components/OverviewRubberBand.js.map +1 -1
- package/esm/LinearGenomeView/components/OverviewScaleBar.js +0 -2
- package/esm/LinearGenomeView/components/OverviewScaleBar.js.map +1 -1
- package/esm/LinearGenomeView/components/RubberBand.js +0 -2
- package/esm/LinearGenomeView/components/RubberBand.js.map +1 -1
- package/esm/LinearGenomeView/components/SearchBox.js.map +1 -1
- package/esm/LinearGenomeView/components/{SequenceDialog.d.ts → SequenceSearchDialog.d.ts} +0 -0
- package/esm/LinearGenomeView/components/SequenceSearchDialog.js +76 -0
- package/esm/LinearGenomeView/components/SequenceSearchDialog.js.map +1 -0
- package/esm/LinearGenomeView/components/TrackContainer.d.ts +2 -1
- package/esm/LinearGenomeView/components/TrackContainer.js +15 -20
- package/esm/LinearGenomeView/components/TrackContainer.js.map +1 -1
- package/esm/LinearGenomeView/components/TrackLabel.js +22 -23
- package/esm/LinearGenomeView/components/TrackLabel.js.map +1 -1
- package/esm/LinearGenomeView/components/TracksContainer.js +2 -2
- package/esm/LinearGenomeView/components/TracksContainer.js.map +1 -1
- package/esm/LinearGenomeView/index.d.ts +66 -79
- package/esm/LinearGenomeView/index.js +268 -407
- package/esm/LinearGenomeView/index.js.map +1 -1
- package/package.json +3 -4
- package/src/BaseLinearDisplay/components/BaseLinearDisplay.tsx +0 -1
- package/src/BaseLinearDisplay/components/ServerSideRenderedBlockContent.tsx +2 -1
- package/src/LinearGenomeView/components/{SequenceDialog.tsx → GetSequenceDialog.tsx} +5 -18
- package/src/LinearGenomeView/components/{VerticalGuides.tsx → Gridlines.tsx} +0 -0
- package/src/LinearGenomeView/components/ImportForm.tsx +1 -0
- package/src/LinearGenomeView/components/LinearGenomeView.tsx +4 -8
- package/src/LinearGenomeView/components/OverviewRubberBand.tsx +19 -34
- package/src/LinearGenomeView/components/OverviewScaleBar.tsx +0 -2
- package/src/LinearGenomeView/components/RubberBand.tsx +0 -2
- package/src/LinearGenomeView/components/SearchBox.tsx +1 -1
- package/src/LinearGenomeView/components/SequenceSearchDialog.tsx +165 -0
- package/src/LinearGenomeView/components/TrackContainer.tsx +18 -28
- package/src/LinearGenomeView/components/TrackLabel.tsx +60 -53
- package/src/LinearGenomeView/components/TracksContainer.tsx +2 -2
- package/src/LinearGenomeView/components/__snapshots__/LinearGenomeView.test.js.snap +14 -17
- package/src/LinearGenomeView/index.test.ts +14 -36
- package/src/LinearGenomeView/index.tsx +389 -541
- package/dist/LinearGenomeView/components/SequenceDialog.js +0 -242
- package/dist/LinearGenomeView/components/SequenceDialog.js.map +0 -1
- package/dist/LinearGenomeView/components/VerticalGuides.js.map +0 -1
- package/esm/LinearGenomeView/components/SequenceDialog.js.map +0 -1
- package/esm/LinearGenomeView/components/VerticalGuides.js.map +0 -1
|
@@ -1,130 +1,76 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
-
});
|
|
21
|
-
};
|
|
22
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
24
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
-
function step(op) {
|
|
27
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
-
while (_) try {
|
|
29
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
-
switch (op[0]) {
|
|
32
|
-
case 0: case 1: t = op; break;
|
|
33
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
-
default:
|
|
37
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
-
if (t[2]) _.ops.pop();
|
|
42
|
-
_.trys.pop(); continue;
|
|
43
|
-
}
|
|
44
|
-
op = body.call(thisArg, _);
|
|
45
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
var __read = (this && this.__read) || function (o, n) {
|
|
50
|
-
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
51
|
-
if (!m) return o;
|
|
52
|
-
var i = m.call(o), r, ar = [], e;
|
|
53
|
-
try {
|
|
54
|
-
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
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]; } };
|
|
55
7
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
73
|
-
};
|
|
74
|
-
var __values = (this && this.__values) || function(o) {
|
|
75
|
-
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
76
|
-
if (m) return m.call(o);
|
|
77
|
-
if (o && typeof o.length === "number") return {
|
|
78
|
-
next: function () {
|
|
79
|
-
if (o && i >= o.length) o = void 0;
|
|
80
|
-
return { value: o && o[i++], done: !o };
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
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;
|
|
84
24
|
};
|
|
85
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
86
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
87
27
|
};
|
|
88
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
89
29
|
exports.ReactComponent = exports.SearchBox = exports.RefNameAutocomplete = exports.renderToSvg = exports.stateModelFactory = exports.WIDGET_HEIGHT = exports.SPACING = exports.INTER_REGION_PADDING_WIDTH = exports.RESIZE_HANDLE_HEIGHT = exports.SCALE_BAR_HEIGHT = exports.HEADER_OVERVIEW_HEIGHT = exports.HEADER_BAR_HEIGHT = void 0;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
30
|
+
const react_1 = require("react");
|
|
31
|
+
const configuration_1 = require("@jbrowse/core/configuration");
|
|
32
|
+
const models_1 = require("@jbrowse/core/pluggableElementTypes/models");
|
|
33
|
+
const mst_1 = require("@jbrowse/core/util/types/mst");
|
|
34
|
+
const ui_1 = require("@jbrowse/core/ui");
|
|
35
|
+
const util_1 = require("@jbrowse/core/util");
|
|
36
|
+
const calculateDynamicBlocks_1 = __importDefault(require("@jbrowse/core/util/calculateDynamicBlocks"));
|
|
37
|
+
const calculateStaticBlocks_1 = __importDefault(require("@jbrowse/core/util/calculateStaticBlocks"));
|
|
38
|
+
const tracks_1 = require("@jbrowse/core/util/tracks");
|
|
39
|
+
const mobx_1 = require("mobx");
|
|
40
|
+
const mobx_state_tree_1 = require("mobx-state-tree");
|
|
41
|
+
const Base1DViewModel_1 = __importDefault(require("@jbrowse/core/util/Base1DViewModel"));
|
|
42
|
+
const Base1DUtils_1 = require("@jbrowse/core/util/Base1DUtils");
|
|
43
|
+
const file_saver_1 = require("file-saver");
|
|
44
|
+
const clone_1 = __importDefault(require("clone"));
|
|
103
45
|
// icons
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
46
|
+
const Icons_1 = require("@jbrowse/core/ui/Icons");
|
|
47
|
+
const SyncAlt_1 = __importDefault(require("@mui/icons-material/SyncAlt"));
|
|
48
|
+
const Visibility_1 = __importDefault(require("@mui/icons-material/Visibility"));
|
|
49
|
+
const Label_1 = __importDefault(require("@mui/icons-material/Label"));
|
|
50
|
+
const FolderOpen_1 = __importDefault(require("@mui/icons-material/FolderOpen"));
|
|
51
|
+
const PhotoCamera_1 = __importDefault(require("@mui/icons-material/PhotoCamera"));
|
|
52
|
+
const ZoomIn_1 = __importDefault(require("@mui/icons-material/ZoomIn"));
|
|
53
|
+
const MenuOpen_1 = __importDefault(require("@mui/icons-material/MenuOpen"));
|
|
112
54
|
// locals
|
|
113
|
-
|
|
55
|
+
const LinearGenomeViewSvg_1 = require("./components/LinearGenomeViewSvg");
|
|
114
56
|
Object.defineProperty(exports, "renderToSvg", { enumerable: true, get: function () { return LinearGenomeViewSvg_1.renderToSvg; } });
|
|
115
|
-
|
|
57
|
+
const RefNameAutocomplete_1 = __importDefault(require("./components/RefNameAutocomplete"));
|
|
116
58
|
exports.RefNameAutocomplete = RefNameAutocomplete_1.default;
|
|
117
|
-
|
|
59
|
+
const SearchBox_1 = __importDefault(require("./components/SearchBox"));
|
|
118
60
|
exports.SearchBox = SearchBox_1.default;
|
|
119
|
-
|
|
61
|
+
const ExportSvgDialog_1 = __importDefault(require("./components/ExportSvgDialog"));
|
|
62
|
+
const SequenceSearchDialog = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./components/SequenceSearchDialog'))));
|
|
120
63
|
function calculateVisibleLocStrings(contentBlocks) {
|
|
121
64
|
if (!contentBlocks.length) {
|
|
122
65
|
return '';
|
|
123
66
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
67
|
+
const isSingleAssemblyName = contentBlocks.every(block => block.assemblyName === contentBlocks[0].assemblyName);
|
|
68
|
+
const locs = contentBlocks.map(block => (0, util_1.assembleLocString)({
|
|
69
|
+
...block,
|
|
70
|
+
start: Math.round(block.start),
|
|
71
|
+
end: Math.round(block.end),
|
|
72
|
+
assemblyName: isSingleAssemblyName ? undefined : block.assemblyName,
|
|
73
|
+
}));
|
|
128
74
|
return locs.join(' ');
|
|
129
75
|
}
|
|
130
76
|
exports.HEADER_BAR_HEIGHT = 48;
|
|
@@ -154,17 +100,18 @@ function stateModelFactory(pluginManager) {
|
|
|
154
100
|
hideHeaderOverview: false,
|
|
155
101
|
hideNoTracksActive: false,
|
|
156
102
|
trackSelectorType: mobx_state_tree_1.types.optional(mobx_state_tree_1.types.enumeration(['hierarchical']), 'hierarchical'),
|
|
157
|
-
trackLabels: mobx_state_tree_1.types.optional(mobx_state_tree_1.types.string,
|
|
158
|
-
showCenterLine: mobx_state_tree_1.types.optional(mobx_state_tree_1.types.boolean,
|
|
159
|
-
|
|
103
|
+
trackLabels: mobx_state_tree_1.types.optional(mobx_state_tree_1.types.string, () => localStorageGetItem('lgv-trackLabels') || 'overlapping'),
|
|
104
|
+
showCenterLine: mobx_state_tree_1.types.optional(mobx_state_tree_1.types.boolean, () => {
|
|
105
|
+
const setting = localStorageGetItem('lgv-showCenterLine');
|
|
160
106
|
return setting !== undefined && setting !== null ? !!+setting : false;
|
|
161
107
|
}),
|
|
162
|
-
showCytobandsSetting: mobx_state_tree_1.types.optional(mobx_state_tree_1.types.boolean,
|
|
163
|
-
|
|
108
|
+
showCytobandsSetting: mobx_state_tree_1.types.optional(mobx_state_tree_1.types.boolean, () => {
|
|
109
|
+
const setting = localStorageGetItem('lgv-showCytobands');
|
|
164
110
|
return setting !== undefined && setting !== null ? !!+setting : true;
|
|
165
111
|
}),
|
|
112
|
+
showGridlines: true,
|
|
166
113
|
}))
|
|
167
|
-
.volatile(
|
|
114
|
+
.volatile(() => ({
|
|
168
115
|
volatileWidth: undefined,
|
|
169
116
|
minimumBlockWidth: 3,
|
|
170
117
|
draggingTrackId: undefined,
|
|
@@ -182,8 +129,8 @@ function stateModelFactory(pluginManager) {
|
|
|
182
129
|
searchResults: undefined,
|
|
183
130
|
searchQuery: undefined,
|
|
184
131
|
seqDialogDisplayed: false,
|
|
185
|
-
})
|
|
186
|
-
.views(
|
|
132
|
+
}))
|
|
133
|
+
.views(self => ({
|
|
187
134
|
get width() {
|
|
188
135
|
if (self.volatileWidth === undefined) {
|
|
189
136
|
throw new Error('width undefined, make sure to check for model.initialized');
|
|
@@ -194,22 +141,24 @@ function stateModelFactory(pluginManager) {
|
|
|
194
141
|
return exports.INTER_REGION_PADDING_WIDTH;
|
|
195
142
|
},
|
|
196
143
|
get assemblyNames() {
|
|
197
|
-
return
|
|
144
|
+
return [
|
|
145
|
+
...new Set(self.displayedRegions.map(region => region.assemblyName)),
|
|
146
|
+
];
|
|
198
147
|
},
|
|
199
|
-
})
|
|
200
|
-
.views(
|
|
148
|
+
}))
|
|
149
|
+
.views(self => ({
|
|
201
150
|
get assemblyErrors() {
|
|
202
|
-
|
|
203
|
-
|
|
151
|
+
const { assemblyManager } = (0, util_1.getSession)(self);
|
|
152
|
+
const { assemblyNames } = self;
|
|
204
153
|
return assemblyNames
|
|
205
|
-
.map(
|
|
206
|
-
.filter(
|
|
154
|
+
.map(a => { var _a; return (_a = assemblyManager.get(a)) === null || _a === void 0 ? void 0 : _a.error; })
|
|
155
|
+
.filter(f => !!f)
|
|
207
156
|
.join(', ');
|
|
208
157
|
},
|
|
209
158
|
get assembliesInitialized() {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
return assemblyNames.every(
|
|
159
|
+
const { assemblyManager } = (0, util_1.getSession)(self);
|
|
160
|
+
const { assemblyNames } = self;
|
|
161
|
+
return assemblyNames.every(a => { var _a; return (_a = assemblyManager.get(a)) === null || _a === void 0 ? void 0 : _a.initialized; });
|
|
213
162
|
},
|
|
214
163
|
get initialized() {
|
|
215
164
|
return self.volatileWidth !== undefined && this.assembliesInitialized;
|
|
@@ -234,8 +183,8 @@ function stateModelFactory(pluginManager) {
|
|
|
234
183
|
},
|
|
235
184
|
get trackHeights() {
|
|
236
185
|
return self.tracks
|
|
237
|
-
.map(
|
|
238
|
-
.reduce(
|
|
186
|
+
.map(t => t.displays[0].height)
|
|
187
|
+
.reduce((a, b) => a + b, 0);
|
|
239
188
|
},
|
|
240
189
|
get trackHeightsWithResizeHandles() {
|
|
241
190
|
return this.trackHeights + self.tracks.length * exports.RESIZE_HANDLE_HEIGHT;
|
|
@@ -246,7 +195,7 @@ function stateModelFactory(pluginManager) {
|
|
|
246
195
|
this.scaleBarHeight);
|
|
247
196
|
},
|
|
248
197
|
get totalBp() {
|
|
249
|
-
return self.displayedRegions.reduce(
|
|
198
|
+
return self.displayedRegions.reduce((a, b) => a + b.end - b.start, 0);
|
|
250
199
|
},
|
|
251
200
|
get maxBpPerPx() {
|
|
252
201
|
return this.totalBp / (self.width * 0.9);
|
|
@@ -259,99 +208,38 @@ function stateModelFactory(pluginManager) {
|
|
|
259
208
|
},
|
|
260
209
|
get maxOffset() {
|
|
261
210
|
// objectively determined to keep the linear genome on the main screen
|
|
262
|
-
|
|
211
|
+
const leftPadding = 10;
|
|
263
212
|
return this.displayedRegionsTotalPx - leftPadding;
|
|
264
213
|
},
|
|
265
214
|
get minOffset() {
|
|
266
215
|
// objectively determined to keep the linear genome on the main screen
|
|
267
|
-
|
|
216
|
+
const rightPadding = 30;
|
|
268
217
|
return -self.width + rightPadding;
|
|
269
218
|
},
|
|
270
219
|
get displayedRegionsTotalPx() {
|
|
271
220
|
return this.totalBp / self.bpPerPx;
|
|
272
221
|
},
|
|
273
|
-
renderProps
|
|
274
|
-
return __assign(__assign({}, (0, tracks_1.getParentRenderProps)(self)), { bpPerPx: self.bpPerPx, highResolutionScaling: (0, configuration_1.getConf)((0, util_1.getSession)(self), 'highResolutionScaling') });
|
|
275
|
-
},
|
|
276
|
-
searchScope: function (assemblyName) {
|
|
222
|
+
renderProps() {
|
|
277
223
|
return {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
224
|
+
...(0, tracks_1.getParentRenderProps)(self),
|
|
225
|
+
bpPerPx: self.bpPerPx,
|
|
226
|
+
highResolutionScaling: (0, configuration_1.getConf)((0, util_1.getSession)(self), 'highResolutionScaling'),
|
|
281
227
|
};
|
|
282
228
|
},
|
|
283
|
-
|
|
284
|
-
var refName = _a.refName, coord = _a.coord, regionNumber = _a.regionNumber;
|
|
285
|
-
return (0, util_1.viewBpToPx)({ refName: refName, coord: coord, regionNumber: regionNumber, self: self });
|
|
286
|
-
},
|
|
287
|
-
/**
|
|
288
|
-
*
|
|
289
|
-
* @param px - px in the view area, return value is the displayed regions
|
|
290
|
-
* @returns BpOffset of the displayed region that it lands in
|
|
291
|
-
*/
|
|
292
|
-
pxToBp: function (px) {
|
|
293
|
-
var bpSoFar = 0;
|
|
294
|
-
var bp = (self.offsetPx + px) * self.bpPerPx;
|
|
295
|
-
var n = self.displayedRegions.length;
|
|
296
|
-
if (bp < 0) {
|
|
297
|
-
var region = self.displayedRegions[0];
|
|
298
|
-
var offset = bp;
|
|
299
|
-
var snap = (0, mobx_state_tree_1.getSnapshot)(region);
|
|
300
|
-
return __assign(__assign({}, snap), { oob: true, coord: region.reversed
|
|
301
|
-
? Math.floor(region.end - offset) + 1
|
|
302
|
-
: Math.floor(region.start + offset) + 1, offset: offset, index: 0 });
|
|
303
|
-
}
|
|
304
|
-
var interRegionPaddingBp = self.interRegionPaddingWidth * self.bpPerPx;
|
|
305
|
-
var minimumBlockBp = self.minimumBlockWidth * self.bpPerPx;
|
|
306
|
-
for (var index = 0; index < self.displayedRegions.length; index += 1) {
|
|
307
|
-
var region = self.displayedRegions[index];
|
|
308
|
-
var len = region.end - region.start;
|
|
309
|
-
var offset = bp - bpSoFar;
|
|
310
|
-
if (len + bpSoFar > bp && bpSoFar <= bp) {
|
|
311
|
-
var snap = (0, mobx_state_tree_1.getSnapshot)(region);
|
|
312
|
-
return __assign(__assign({}, snap), { oob: false, offset: offset, coord: region.reversed
|
|
313
|
-
? Math.floor(region.end - offset) + 1
|
|
314
|
-
: Math.floor(region.start + offset) + 1, index: index });
|
|
315
|
-
}
|
|
316
|
-
// add the interRegionPaddingWidth if the boundary is in the screen
|
|
317
|
-
// e.g. offset>0 && offset<width
|
|
318
|
-
if (region.end - region.start > minimumBlockBp &&
|
|
319
|
-
offset / self.bpPerPx > 0 &&
|
|
320
|
-
offset / self.bpPerPx < self.width) {
|
|
321
|
-
bpSoFar += len + interRegionPaddingBp;
|
|
322
|
-
}
|
|
323
|
-
else {
|
|
324
|
-
bpSoFar += len;
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
if (bp >= bpSoFar) {
|
|
328
|
-
var region = self.displayedRegions[n - 1];
|
|
329
|
-
var len = region.end - region.start;
|
|
330
|
-
var offset = bp - bpSoFar + len;
|
|
331
|
-
var snap = (0, mobx_state_tree_1.getSnapshot)(region);
|
|
332
|
-
return __assign(__assign({}, snap), { oob: true, offset: offset, coord: region.reversed
|
|
333
|
-
? Math.floor(region.end - offset) + 1
|
|
334
|
-
: Math.floor(region.start + offset) + 1, index: n - 1 });
|
|
335
|
-
}
|
|
229
|
+
searchScope(assemblyName) {
|
|
336
230
|
return {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
oob: true,
|
|
341
|
-
assemblyName: '',
|
|
342
|
-
offset: 0,
|
|
343
|
-
start: 0,
|
|
344
|
-
end: 0,
|
|
345
|
-
reversed: false,
|
|
231
|
+
assemblyName,
|
|
232
|
+
includeAggregateIndexes: true,
|
|
233
|
+
tracks: self.tracks,
|
|
346
234
|
};
|
|
347
235
|
},
|
|
348
|
-
getTrack
|
|
349
|
-
return self.tracks.find(
|
|
236
|
+
getTrack(id) {
|
|
237
|
+
return self.tracks.find(t => t.configuration.trackId === id);
|
|
350
238
|
},
|
|
351
|
-
rankSearchResults
|
|
239
|
+
rankSearchResults(results) {
|
|
352
240
|
// order of rank
|
|
353
|
-
|
|
354
|
-
results.forEach(
|
|
241
|
+
const openTrackIds = self.tracks.map(track => track.configuration.trackId);
|
|
242
|
+
results.forEach(result => {
|
|
355
243
|
if (openTrackIds.includes(result.trackId)) {
|
|
356
244
|
result.updateScore(result.getScore() + 1);
|
|
357
245
|
}
|
|
@@ -359,23 +247,18 @@ function stateModelFactory(pluginManager) {
|
|
|
359
247
|
return results;
|
|
360
248
|
},
|
|
361
249
|
// modifies view menu action onClick to apply to all tracks of same type
|
|
362
|
-
rewriteOnClicks
|
|
363
|
-
|
|
364
|
-
viewMenuActions.forEach(function (action) {
|
|
250
|
+
rewriteOnClicks(trackType, viewMenuActions) {
|
|
251
|
+
viewMenuActions.forEach(action => {
|
|
365
252
|
// go to lowest level menu
|
|
366
253
|
if ('subMenu' in action) {
|
|
367
|
-
|
|
254
|
+
this.rewriteOnClicks(trackType, action.subMenu);
|
|
368
255
|
}
|
|
369
256
|
if ('onClick' in action) {
|
|
370
|
-
|
|
371
|
-
action.onClick =
|
|
372
|
-
|
|
373
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
374
|
-
args[_i] = arguments[_i];
|
|
375
|
-
}
|
|
376
|
-
self.tracks.forEach(function (track) {
|
|
257
|
+
const holdOnClick = action.onClick;
|
|
258
|
+
action.onClick = (...args) => {
|
|
259
|
+
self.tracks.forEach(track => {
|
|
377
260
|
if (track.type === trackType) {
|
|
378
|
-
|
|
261
|
+
holdOnClick.apply(track, [track, ...args]);
|
|
379
262
|
}
|
|
380
263
|
});
|
|
381
264
|
};
|
|
@@ -383,143 +266,145 @@ function stateModelFactory(pluginManager) {
|
|
|
383
266
|
});
|
|
384
267
|
},
|
|
385
268
|
get trackTypeActions() {
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
var trackInMap = allActions.get(track.type);
|
|
269
|
+
const allActions = new Map();
|
|
270
|
+
self.tracks.forEach(track => {
|
|
271
|
+
const trackInMap = allActions.get(track.type);
|
|
390
272
|
if (!trackInMap) {
|
|
391
|
-
|
|
392
|
-
|
|
273
|
+
const viewMenuActions = (0, clone_1.default)(track.viewMenuActions);
|
|
274
|
+
this.rewriteOnClicks(track.type, viewMenuActions);
|
|
393
275
|
allActions.set(track.type, viewMenuActions);
|
|
394
276
|
}
|
|
395
277
|
});
|
|
396
278
|
return allActions;
|
|
397
279
|
},
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
: undefined;
|
|
402
|
-
},
|
|
403
|
-
}); })
|
|
404
|
-
.actions(function (self) { return ({
|
|
405
|
-
setShowCytobands: function (flag) {
|
|
280
|
+
}))
|
|
281
|
+
.actions(self => ({
|
|
282
|
+
setShowCytobands(flag) {
|
|
406
283
|
self.showCytobandsSetting = flag;
|
|
407
|
-
localStorage.setItem('lgv-showCytobands',
|
|
284
|
+
localStorage.setItem('lgv-showCytobands', `${+flag}`);
|
|
408
285
|
},
|
|
409
|
-
setWidth
|
|
286
|
+
setWidth(newWidth) {
|
|
410
287
|
self.volatileWidth = newWidth;
|
|
411
288
|
},
|
|
412
|
-
setError
|
|
289
|
+
setError(error) {
|
|
413
290
|
self.volatileError = error;
|
|
414
291
|
},
|
|
415
|
-
toggleHeader
|
|
292
|
+
toggleHeader() {
|
|
416
293
|
self.hideHeader = !self.hideHeader;
|
|
417
294
|
},
|
|
418
|
-
toggleHeaderOverview
|
|
295
|
+
toggleHeaderOverview() {
|
|
419
296
|
self.hideHeaderOverview = !self.hideHeaderOverview;
|
|
420
297
|
},
|
|
421
|
-
toggleNoTracksActive
|
|
298
|
+
toggleNoTracksActive() {
|
|
422
299
|
self.hideNoTracksActive = !self.hideNoTracksActive;
|
|
423
300
|
},
|
|
424
|
-
|
|
425
|
-
|
|
301
|
+
toggleShowGridlines() {
|
|
302
|
+
self.showGridlines = !self.showGridlines;
|
|
303
|
+
},
|
|
304
|
+
scrollTo(offsetPx) {
|
|
305
|
+
const newOffsetPx = (0, util_1.clamp)(offsetPx, self.minOffset, self.maxOffset);
|
|
426
306
|
self.offsetPx = newOffsetPx;
|
|
427
307
|
return newOffsetPx;
|
|
428
308
|
},
|
|
429
|
-
zoomTo
|
|
430
|
-
|
|
309
|
+
zoomTo(bpPerPx) {
|
|
310
|
+
const newBpPerPx = (0, util_1.clamp)(bpPerPx, self.minBpPerPx, self.maxBpPerPx);
|
|
431
311
|
if (newBpPerPx === self.bpPerPx) {
|
|
432
312
|
return newBpPerPx;
|
|
433
313
|
}
|
|
434
|
-
|
|
314
|
+
const oldBpPerPx = self.bpPerPx;
|
|
435
315
|
self.bpPerPx = newBpPerPx;
|
|
436
316
|
if (Math.abs(oldBpPerPx - newBpPerPx) < 0.000001) {
|
|
437
317
|
console.warn('zoomTo bpPerPx rounding error');
|
|
438
318
|
return oldBpPerPx;
|
|
439
319
|
}
|
|
440
320
|
// tweak the offset so that the center of the view remains at the same coordinate
|
|
441
|
-
|
|
321
|
+
const viewWidth = self.width;
|
|
442
322
|
this.scrollTo(Math.round(((self.offsetPx + viewWidth / 2) * oldBpPerPx) / newBpPerPx -
|
|
443
323
|
viewWidth / 2));
|
|
444
324
|
return newBpPerPx;
|
|
445
325
|
},
|
|
446
|
-
setOffsets
|
|
326
|
+
setOffsets(left, right) {
|
|
447
327
|
// sets offsets used in the get sequence dialog
|
|
448
328
|
self.leftOffset = left;
|
|
449
329
|
self.rightOffset = right;
|
|
450
330
|
},
|
|
451
|
-
setSearchResults
|
|
331
|
+
setSearchResults(results, query) {
|
|
452
332
|
self.searchResults = results;
|
|
453
333
|
self.searchQuery = query;
|
|
454
334
|
},
|
|
455
|
-
|
|
335
|
+
setGetSequenceDialogOpen(open) {
|
|
456
336
|
self.seqDialogDisplayed = open;
|
|
457
337
|
},
|
|
458
|
-
setNewView
|
|
338
|
+
setNewView(bpPerPx, offsetPx) {
|
|
459
339
|
this.zoomTo(bpPerPx);
|
|
460
340
|
this.scrollTo(offsetPx);
|
|
461
341
|
},
|
|
462
|
-
horizontallyFlip
|
|
342
|
+
horizontallyFlip() {
|
|
463
343
|
self.displayedRegions = (0, mobx_state_tree_1.cast)(self.displayedRegions
|
|
464
344
|
.slice()
|
|
465
345
|
.reverse()
|
|
466
|
-
.map(
|
|
346
|
+
.map(region => ({ ...region, reversed: !region.reversed })));
|
|
467
347
|
this.scrollTo(self.totalBp / self.bpPerPx - self.offsetPx - self.width);
|
|
468
348
|
},
|
|
469
|
-
showTrack
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
var schema = pluginManager.pluggableConfigSchemaType('track');
|
|
473
|
-
var conf = (0, mobx_state_tree_1.resolveIdentifier)(schema, (0, mobx_state_tree_1.getRoot)(self), trackId);
|
|
349
|
+
showTrack(trackId, initialSnapshot = {}, displayInitialSnapshot = {}) {
|
|
350
|
+
const schema = pluginManager.pluggableConfigSchemaType('track');
|
|
351
|
+
const conf = (0, mobx_state_tree_1.resolveIdentifier)(schema, (0, mobx_state_tree_1.getRoot)(self), trackId);
|
|
474
352
|
if (!conf) {
|
|
475
|
-
throw new Error(
|
|
353
|
+
throw new Error(`Could not resolve identifier "${trackId}"`);
|
|
476
354
|
}
|
|
477
|
-
|
|
355
|
+
const trackType = pluginManager.getTrackType(conf === null || conf === void 0 ? void 0 : conf.type);
|
|
478
356
|
if (!trackType) {
|
|
479
|
-
throw new Error(
|
|
357
|
+
throw new Error(`Unknown track type ${conf.type}`);
|
|
480
358
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
return supportedDisplays.includes(d.type);
|
|
485
|
-
});
|
|
359
|
+
const viewType = pluginManager.getViewType(self.type);
|
|
360
|
+
const supportedDisplays = viewType.displayTypes.map(d => d.name);
|
|
361
|
+
const displayConf = conf.displays.find((d) => supportedDisplays.includes(d.type));
|
|
486
362
|
if (!displayConf) {
|
|
487
|
-
throw new Error(
|
|
363
|
+
throw new Error(`Could not find a compatible display for view type ${self.type}`);
|
|
488
364
|
}
|
|
489
|
-
|
|
365
|
+
const t = self.tracks.filter(t => t.configuration === conf);
|
|
490
366
|
if (t.length === 0) {
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
367
|
+
const track = trackType.stateModel.create({
|
|
368
|
+
...initialSnapshot,
|
|
369
|
+
type: conf.type,
|
|
370
|
+
configuration: conf,
|
|
371
|
+
displays: [
|
|
372
|
+
{
|
|
373
|
+
type: displayConf.type,
|
|
374
|
+
configuration: displayConf,
|
|
375
|
+
...displayInitialSnapshot,
|
|
376
|
+
},
|
|
377
|
+
],
|
|
378
|
+
});
|
|
494
379
|
self.tracks.push(track);
|
|
495
380
|
return track;
|
|
496
381
|
}
|
|
497
382
|
return t[0];
|
|
498
383
|
},
|
|
499
|
-
hideTrack
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
(0, mobx_1.transaction)(
|
|
384
|
+
hideTrack(trackId) {
|
|
385
|
+
const schema = pluginManager.pluggableConfigSchemaType('track');
|
|
386
|
+
const conf = (0, mobx_state_tree_1.resolveIdentifier)(schema, (0, mobx_state_tree_1.getRoot)(self), trackId);
|
|
387
|
+
const t = self.tracks.filter(t => t.configuration === conf);
|
|
388
|
+
(0, mobx_1.transaction)(() => t.forEach(t => self.tracks.remove(t)));
|
|
504
389
|
return t.length;
|
|
505
390
|
},
|
|
506
|
-
})
|
|
507
|
-
.actions(
|
|
508
|
-
moveTrack
|
|
509
|
-
|
|
391
|
+
}))
|
|
392
|
+
.actions(self => ({
|
|
393
|
+
moveTrack(movingId, targetId) {
|
|
394
|
+
const oldIndex = self.tracks.findIndex(track => track.id === movingId);
|
|
510
395
|
if (oldIndex === -1) {
|
|
511
|
-
throw new Error(
|
|
396
|
+
throw new Error(`Track ID ${movingId} not found`);
|
|
512
397
|
}
|
|
513
|
-
|
|
398
|
+
const newIndex = self.tracks.findIndex(track => track.id === targetId);
|
|
514
399
|
if (newIndex === -1) {
|
|
515
|
-
throw new Error(
|
|
400
|
+
throw new Error(`Track ID ${targetId} not found`);
|
|
516
401
|
}
|
|
517
|
-
|
|
402
|
+
const track = (0, mobx_state_tree_1.getSnapshot)(self.tracks[oldIndex]);
|
|
518
403
|
self.tracks.splice(oldIndex, 1);
|
|
519
404
|
self.tracks.splice(newIndex, 0, track);
|
|
520
405
|
},
|
|
521
|
-
closeView
|
|
522
|
-
|
|
406
|
+
closeView() {
|
|
407
|
+
const parent = (0, util_1.getContainingView)(self);
|
|
523
408
|
if (parent) {
|
|
524
409
|
// I am embedded in a some other view
|
|
525
410
|
if ((0, util_1.isViewContainer)(parent)) {
|
|
@@ -531,260 +416,36 @@ function stateModelFactory(pluginManager) {
|
|
|
531
416
|
(0, util_1.getSession)(self).removeView(self);
|
|
532
417
|
}
|
|
533
418
|
},
|
|
534
|
-
toggleTrack
|
|
419
|
+
toggleTrack(trackId) {
|
|
535
420
|
// if we have any tracks with that configuration, turn them off
|
|
536
|
-
|
|
421
|
+
const hiddenCount = self.hideTrack(trackId);
|
|
537
422
|
// if none had that configuration, turn one on
|
|
538
423
|
if (!hiddenCount) {
|
|
539
424
|
self.showTrack(trackId);
|
|
540
425
|
}
|
|
541
426
|
},
|
|
542
|
-
setTrackLabels
|
|
427
|
+
setTrackLabels(setting) {
|
|
543
428
|
self.trackLabels = setting;
|
|
544
429
|
localStorage.setItem('lgv-trackLabels', setting);
|
|
545
430
|
},
|
|
546
|
-
toggleCenterLine
|
|
431
|
+
toggleCenterLine() {
|
|
547
432
|
self.showCenterLine = !self.showCenterLine;
|
|
548
|
-
localStorage.setItem('lgv-showCenterLine',
|
|
433
|
+
localStorage.setItem('lgv-showCenterLine', `${+self.showCenterLine}`);
|
|
549
434
|
},
|
|
550
|
-
setDisplayedRegions
|
|
435
|
+
setDisplayedRegions(regions) {
|
|
551
436
|
self.displayedRegions = (0, mobx_state_tree_1.cast)(regions);
|
|
552
437
|
self.zoomTo(self.bpPerPx);
|
|
553
438
|
},
|
|
554
|
-
activateTrackSelector
|
|
439
|
+
activateTrackSelector() {
|
|
555
440
|
if (self.trackSelectorType === 'hierarchical') {
|
|
556
|
-
|
|
441
|
+
const session = (0, util_1.getSession)(self);
|
|
557
442
|
if ((0, util_1.isSessionModelWithWidgets)(session)) {
|
|
558
|
-
|
|
443
|
+
const selector = session.addWidget('HierarchicalTrackSelectorWidget', 'hierarchicalTrackSelector', { view: self });
|
|
559
444
|
session.showWidget(selector);
|
|
560
445
|
return selector;
|
|
561
446
|
}
|
|
562
447
|
}
|
|
563
|
-
throw new Error(
|
|
564
|
-
},
|
|
565
|
-
navToLocString: function (locString, optAssemblyName) {
|
|
566
|
-
var assemblyNames = self.assemblyNames;
|
|
567
|
-
var assemblyManager = (0, util_1.getSession)(self).assemblyManager;
|
|
568
|
-
var isValidRefName = assemblyManager.isValidRefName;
|
|
569
|
-
var assemblyName = optAssemblyName || assemblyNames[0];
|
|
570
|
-
var parsedLocStrings;
|
|
571
|
-
var inputs = locString
|
|
572
|
-
.split(/(\s+)/)
|
|
573
|
-
.map(function (f) { return f.trim(); })
|
|
574
|
-
.filter(function (f) { return !!f; });
|
|
575
|
-
// first try interpreting as a whitespace-separated sequence of
|
|
576
|
-
// multiple locstrings
|
|
577
|
-
try {
|
|
578
|
-
parsedLocStrings = inputs.map(function (l) {
|
|
579
|
-
return (0, util_1.parseLocString)(l, function (ref) { return isValidRefName(ref, assemblyName); });
|
|
580
|
-
});
|
|
581
|
-
}
|
|
582
|
-
catch (e) {
|
|
583
|
-
// if this fails, try interpreting as a whitespace-separated refname,
|
|
584
|
-
// start, end if start and end are integer inputs
|
|
585
|
-
var _a = __read(inputs, 3), refName = _a[0], start = _a[1], end = _a[2];
|
|
586
|
-
if ("".concat(e).match(/Unknown reference sequence/) &&
|
|
587
|
-
Number.isInteger(+start) &&
|
|
588
|
-
Number.isInteger(+end)) {
|
|
589
|
-
parsedLocStrings = [
|
|
590
|
-
(0, util_1.parseLocString)(refName + ':' + start + '..' + end, function (ref) {
|
|
591
|
-
return isValidRefName(ref, assemblyName);
|
|
592
|
-
}),
|
|
593
|
-
];
|
|
594
|
-
}
|
|
595
|
-
else {
|
|
596
|
-
throw e;
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
var locations = parsedLocStrings === null || parsedLocStrings === void 0 ? void 0 : parsedLocStrings.map(function (region) {
|
|
600
|
-
var asmName = region.assemblyName || assemblyName;
|
|
601
|
-
var asm = assemblyManager.get(asmName);
|
|
602
|
-
var refName = region.refName;
|
|
603
|
-
if (!asm) {
|
|
604
|
-
throw new Error("assembly ".concat(asmName, " not found"));
|
|
605
|
-
}
|
|
606
|
-
var regions = asm.regions;
|
|
607
|
-
if (!regions) {
|
|
608
|
-
throw new Error("regions not loaded yet for ".concat(asmName));
|
|
609
|
-
}
|
|
610
|
-
var canonicalRefName = asm.getCanonicalRefName(region.refName);
|
|
611
|
-
if (!canonicalRefName) {
|
|
612
|
-
throw new Error("Could not find refName ".concat(refName, " in ").concat(asm.name));
|
|
613
|
-
}
|
|
614
|
-
var parentRegion = regions.find(function (region) { return region.refName === canonicalRefName; });
|
|
615
|
-
if (!parentRegion) {
|
|
616
|
-
throw new Error("Could not find refName ".concat(refName, " in ").concat(asmName));
|
|
617
|
-
}
|
|
618
|
-
return __assign(__assign({}, region), { assemblyName: asmName, parentRegion: parentRegion });
|
|
619
|
-
});
|
|
620
|
-
if (locations.length === 1) {
|
|
621
|
-
var loc = locations[0];
|
|
622
|
-
this.setDisplayedRegions([
|
|
623
|
-
__assign({ reversed: loc.reversed }, loc.parentRegion),
|
|
624
|
-
]);
|
|
625
|
-
var start = loc.start, end = loc.end, parentRegion = loc.parentRegion;
|
|
626
|
-
this.navTo(__assign(__assign({}, loc), { start: (0, util_1.clamp)(start !== null && start !== void 0 ? start : 0, 0, parentRegion.end), end: (0, util_1.clamp)(end !== null && end !== void 0 ? end : parentRegion.end, 0, parentRegion.end) }));
|
|
627
|
-
}
|
|
628
|
-
else {
|
|
629
|
-
this.setDisplayedRegions(
|
|
630
|
-
// @ts-ignore
|
|
631
|
-
locations.map(function (r) { return (r.start === undefined ? r.parentRegion : r); }));
|
|
632
|
-
this.showAllRegions();
|
|
633
|
-
}
|
|
634
|
-
},
|
|
635
|
-
/**
|
|
636
|
-
* Navigate to a location based on its refName and optionally start, end,
|
|
637
|
-
* and assemblyName. Can handle if there are multiple displayedRegions
|
|
638
|
-
* from same refName. Only navigates to a location if it is entirely
|
|
639
|
-
* within a displayedRegion. Navigates to the first matching location
|
|
640
|
-
* encountered.
|
|
641
|
-
*
|
|
642
|
-
* Throws an error if navigation was unsuccessful
|
|
643
|
-
*
|
|
644
|
-
* @param location - a proposed location to navigate to
|
|
645
|
-
*/
|
|
646
|
-
navTo: function (query) {
|
|
647
|
-
this.navToMultiple([query]);
|
|
648
|
-
},
|
|
649
|
-
navToMultiple: function (locations) {
|
|
650
|
-
var firstLocation = locations[0];
|
|
651
|
-
var refName = firstLocation.refName;
|
|
652
|
-
var start = firstLocation.start, end = firstLocation.end, _a = firstLocation.assemblyName, assemblyName = _a === void 0 ? self.assemblyNames[0] : _a;
|
|
653
|
-
if (start !== undefined && end !== undefined && start > end) {
|
|
654
|
-
throw new Error("start \"".concat(start + 1, "\" is greater than end \"").concat(end, "\""));
|
|
655
|
-
}
|
|
656
|
-
var session = (0, util_1.getSession)(self);
|
|
657
|
-
var assemblyManager = session.assemblyManager;
|
|
658
|
-
var assembly = assemblyManager.get(assemblyName);
|
|
659
|
-
if (assembly) {
|
|
660
|
-
var canonicalRefName = assembly.getCanonicalRefName(refName);
|
|
661
|
-
if (canonicalRefName) {
|
|
662
|
-
refName = canonicalRefName;
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
var s = start;
|
|
666
|
-
var e = end;
|
|
667
|
-
var refNameMatched = false;
|
|
668
|
-
var predicate = function (r) {
|
|
669
|
-
if (refName === r.refName) {
|
|
670
|
-
refNameMatched = true;
|
|
671
|
-
if (s === undefined) {
|
|
672
|
-
s = r.start;
|
|
673
|
-
}
|
|
674
|
-
if (e === undefined) {
|
|
675
|
-
e = r.end;
|
|
676
|
-
}
|
|
677
|
-
if (s >= r.start && s <= r.end && e <= r.end && e >= r.start) {
|
|
678
|
-
return true;
|
|
679
|
-
}
|
|
680
|
-
s = start;
|
|
681
|
-
e = end;
|
|
682
|
-
}
|
|
683
|
-
return false;
|
|
684
|
-
};
|
|
685
|
-
var lastIndex = (0, util_1.findLastIndex)(self.displayedRegions, predicate);
|
|
686
|
-
var index;
|
|
687
|
-
while (index !== lastIndex) {
|
|
688
|
-
try {
|
|
689
|
-
var previousIndex = index;
|
|
690
|
-
index = self.displayedRegions
|
|
691
|
-
.slice(previousIndex === undefined ? 0 : previousIndex + 1)
|
|
692
|
-
.findIndex(predicate);
|
|
693
|
-
if (previousIndex !== undefined) {
|
|
694
|
-
index += previousIndex + 1;
|
|
695
|
-
}
|
|
696
|
-
if (!refNameMatched) {
|
|
697
|
-
throw new Error("could not find a region with refName \"".concat(refName, "\""));
|
|
698
|
-
}
|
|
699
|
-
if (s === undefined) {
|
|
700
|
-
throw new Error("could not find a region with refName \"".concat(refName, "\" that contained an end position ").concat(e));
|
|
701
|
-
}
|
|
702
|
-
if (e === undefined) {
|
|
703
|
-
throw new Error("could not find a region with refName \"".concat(refName, "\" that contained a start position ").concat(s + 1));
|
|
704
|
-
}
|
|
705
|
-
if (index === -1) {
|
|
706
|
-
throw new Error("could not find a region that completely contained \"".concat((0, util_1.assembleLocString)(firstLocation), "\""));
|
|
707
|
-
}
|
|
708
|
-
if (locations.length === 1) {
|
|
709
|
-
var f = self.displayedRegions[index];
|
|
710
|
-
this.moveTo({ index: index, offset: f.reversed ? f.end - e : s - f.start }, { index: index, offset: f.reversed ? f.end - s : e - f.start });
|
|
711
|
-
return;
|
|
712
|
-
}
|
|
713
|
-
var locationIndex = 0;
|
|
714
|
-
var locationStart = 0;
|
|
715
|
-
var locationEnd = 0;
|
|
716
|
-
for (locationIndex; locationIndex < locations.length; locationIndex++) {
|
|
717
|
-
var location_1 = locations[locationIndex];
|
|
718
|
-
var region = self.displayedRegions[index + locationIndex];
|
|
719
|
-
locationStart = location_1.start || region.start;
|
|
720
|
-
locationEnd = location_1.end || region.end;
|
|
721
|
-
if (location_1.refName !== region.refName) {
|
|
722
|
-
throw new Error("Entered location ".concat((0, util_1.assembleLocString)(location_1), " does not match with displayed regions"));
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
locationIndex -= 1;
|
|
726
|
-
var startDisplayedRegion = self.displayedRegions[index];
|
|
727
|
-
var endDisplayedRegion = self.displayedRegions[index + locationIndex];
|
|
728
|
-
this.moveTo({
|
|
729
|
-
index: index,
|
|
730
|
-
offset: startDisplayedRegion.reversed
|
|
731
|
-
? startDisplayedRegion.end - e
|
|
732
|
-
: s - startDisplayedRegion.start,
|
|
733
|
-
}, {
|
|
734
|
-
index: index + locationIndex,
|
|
735
|
-
offset: endDisplayedRegion.reversed
|
|
736
|
-
? endDisplayedRegion.end - locationStart
|
|
737
|
-
: locationEnd - endDisplayedRegion.start,
|
|
738
|
-
});
|
|
739
|
-
return;
|
|
740
|
-
}
|
|
741
|
-
catch (error) {
|
|
742
|
-
if (index === lastIndex) {
|
|
743
|
-
throw error;
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
},
|
|
748
|
-
/**
|
|
749
|
-
* Navigate to a location based on user clicking and dragging on the
|
|
750
|
-
* overview scale bar to select a region to zoom into.
|
|
751
|
-
* Can handle if there are multiple displayedRegions from same refName.
|
|
752
|
-
* Only navigates to a location if it is entirely within a displayedRegion.
|
|
753
|
-
*
|
|
754
|
-
* @param leftPx- `object as {start, end, index, offset}`, offset = start of user drag
|
|
755
|
-
* @param rightPx- `object as {start, end, index, offset}`, offset = end of user drag
|
|
756
|
-
*/
|
|
757
|
-
zoomToDisplayedRegions: function (leftPx, rightPx) {
|
|
758
|
-
var _a;
|
|
759
|
-
if (leftPx === undefined || rightPx === undefined) {
|
|
760
|
-
return;
|
|
761
|
-
}
|
|
762
|
-
var singleRefSeq = leftPx.refName === rightPx.refName && leftPx.index === rightPx.index;
|
|
763
|
-
// zooming into one displayed Region
|
|
764
|
-
if ((singleRefSeq && rightPx.offset < leftPx.offset) ||
|
|
765
|
-
leftPx.index > rightPx.index) {
|
|
766
|
-
;
|
|
767
|
-
_a = __read([rightPx, leftPx], 2), leftPx = _a[0], rightPx = _a[1];
|
|
768
|
-
}
|
|
769
|
-
var startOffset = {
|
|
770
|
-
start: leftPx.start,
|
|
771
|
-
end: leftPx.end,
|
|
772
|
-
index: leftPx.index,
|
|
773
|
-
offset: leftPx.offset,
|
|
774
|
-
};
|
|
775
|
-
var endOffset = {
|
|
776
|
-
start: rightPx.start,
|
|
777
|
-
end: rightPx.end,
|
|
778
|
-
index: rightPx.index,
|
|
779
|
-
offset: rightPx.offset,
|
|
780
|
-
};
|
|
781
|
-
if (startOffset && endOffset) {
|
|
782
|
-
this.moveTo(startOffset, endOffset);
|
|
783
|
-
}
|
|
784
|
-
else {
|
|
785
|
-
var session = (0, util_1.getSession)(self);
|
|
786
|
-
session.notify('No regions found to navigate to', 'warning');
|
|
787
|
-
}
|
|
448
|
+
throw new Error(`invalid track selector type ${self.trackSelectorType}`);
|
|
788
449
|
},
|
|
789
450
|
/**
|
|
790
451
|
* Helper method for the fetchSequence.
|
|
@@ -794,112 +455,56 @@ function stateModelFactory(pluginManager) {
|
|
|
794
455
|
* @param rightOffset - `object as {start, end, index, offset}`, offset = end of user drag
|
|
795
456
|
* @returns array of Region[]
|
|
796
457
|
*/
|
|
797
|
-
getSelectedRegions
|
|
798
|
-
|
|
799
|
-
|
|
458
|
+
getSelectedRegions(leftOffset, rightOffset) {
|
|
459
|
+
const snap = (0, mobx_state_tree_1.getSnapshot)(self);
|
|
460
|
+
const simView = Base1DViewModel_1.default.create({
|
|
461
|
+
...snap,
|
|
462
|
+
interRegionPaddingWidth: self.interRegionPaddingWidth,
|
|
463
|
+
});
|
|
800
464
|
simView.setVolatileWidth(self.width);
|
|
801
|
-
simView.
|
|
802
|
-
return simView.dynamicBlocks.contentBlocks.map(
|
|
465
|
+
simView.moveTo(leftOffset, rightOffset);
|
|
466
|
+
return simView.dynamicBlocks.contentBlocks.map(region => ({
|
|
467
|
+
...region,
|
|
468
|
+
start: Math.floor(region.start),
|
|
469
|
+
end: Math.ceil(region.end),
|
|
470
|
+
}));
|
|
803
471
|
},
|
|
804
472
|
// schedule something to be run after the next time displayedRegions is set
|
|
805
|
-
afterDisplayedRegionsSet
|
|
473
|
+
afterDisplayedRegionsSet(cb) {
|
|
806
474
|
self.afterDisplayedRegionsSetCallbacks.push(cb);
|
|
807
475
|
},
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
* displayed region in the linear genome view
|
|
811
|
-
*
|
|
812
|
-
* @param start - object as `{start, end, offset, index}`
|
|
813
|
-
* @param end - object as `{start, end, offset, index}`
|
|
814
|
-
*/
|
|
815
|
-
moveTo: function (start, end) {
|
|
816
|
-
// find locations in the modellist
|
|
817
|
-
var bpSoFar = 0;
|
|
818
|
-
if (start.index === end.index) {
|
|
819
|
-
bpSoFar += end.offset - start.offset;
|
|
820
|
-
}
|
|
821
|
-
else {
|
|
822
|
-
var s = self.displayedRegions[start.index];
|
|
823
|
-
bpSoFar += s.end - s.start - start.offset;
|
|
824
|
-
if (end.index - start.index >= 2) {
|
|
825
|
-
for (var i = start.index + 1; i < end.index; i += 1) {
|
|
826
|
-
bpSoFar +=
|
|
827
|
-
self.displayedRegions[i].end - self.displayedRegions[i].start;
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
bpSoFar += end.offset;
|
|
831
|
-
}
|
|
832
|
-
var targetBpPerPx = bpSoFar /
|
|
833
|
-
(self.width -
|
|
834
|
-
self.interRegionPaddingWidth * (end.index - start.index));
|
|
835
|
-
var newBpPerPx = self.zoomTo(targetBpPerPx);
|
|
836
|
-
// If our target bpPerPx was smaller than the allowed minBpPerPx, adjust
|
|
837
|
-
// the scroll so the requested range is in the middle of the screen
|
|
838
|
-
var extraBp = 0;
|
|
839
|
-
if (targetBpPerPx < newBpPerPx) {
|
|
840
|
-
extraBp = ((newBpPerPx - targetBpPerPx) * self.width) / 2;
|
|
841
|
-
}
|
|
842
|
-
var bpToStart = -extraBp;
|
|
843
|
-
for (var i = 0; i < self.displayedRegions.length; i += 1) {
|
|
844
|
-
var region = self.displayedRegions[i];
|
|
845
|
-
if (start.index === i) {
|
|
846
|
-
bpToStart += start.offset;
|
|
847
|
-
break;
|
|
848
|
-
}
|
|
849
|
-
else {
|
|
850
|
-
bpToStart += region.end - region.start;
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
self.scrollTo(Math.round(bpToStart / self.bpPerPx) +
|
|
854
|
-
self.interRegionPaddingWidth * start.index);
|
|
855
|
-
},
|
|
856
|
-
horizontalScroll: function (distance) {
|
|
857
|
-
var oldOffsetPx = self.offsetPx;
|
|
476
|
+
horizontalScroll(distance) {
|
|
477
|
+
const oldOffsetPx = self.offsetPx;
|
|
858
478
|
// newOffsetPx is the actual offset after the scroll is clamped
|
|
859
|
-
|
|
479
|
+
const newOffsetPx = self.scrollTo(self.offsetPx + distance);
|
|
860
480
|
return newOffsetPx - oldOffsetPx;
|
|
861
481
|
},
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
* @param refName - refName of the displayedRegion you are centering at
|
|
867
|
-
* @param regionIndex - index of the displayedRegion
|
|
868
|
-
*/
|
|
869
|
-
centerAt: function (bp, refName, regionIndex) {
|
|
870
|
-
var centerPx = self.bpToPx({
|
|
871
|
-
refName: refName,
|
|
872
|
-
coord: bp,
|
|
873
|
-
regionNumber: regionIndex,
|
|
874
|
-
});
|
|
875
|
-
if (centerPx) {
|
|
876
|
-
self.scrollTo(Math.round(centerPx.offsetPx - self.width / 2));
|
|
877
|
-
}
|
|
482
|
+
center() {
|
|
483
|
+
const centerBp = self.totalBp / 2;
|
|
484
|
+
const centerPx = centerBp / self.bpPerPx;
|
|
485
|
+
self.scrollTo(Math.round(centerPx - self.width / 2));
|
|
878
486
|
},
|
|
879
|
-
|
|
880
|
-
var centerBp = self.totalBp / 2;
|
|
881
|
-
self.scrollTo(Math.round(centerBp / self.bpPerPx - self.width / 2));
|
|
882
|
-
},
|
|
883
|
-
showAllRegions: function () {
|
|
487
|
+
showAllRegions() {
|
|
884
488
|
self.zoomTo(self.maxBpPerPx);
|
|
885
489
|
this.center();
|
|
886
490
|
},
|
|
887
|
-
showAllRegionsInAssembly
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
var assemblyManager = session.assemblyManager;
|
|
491
|
+
showAllRegionsInAssembly(assemblyName) {
|
|
492
|
+
const session = (0, util_1.getSession)(self);
|
|
493
|
+
const { assemblyManager } = session;
|
|
891
494
|
if (!assemblyName) {
|
|
892
|
-
|
|
495
|
+
const assemblyNames = [
|
|
496
|
+
...new Set(self.displayedRegions.map(region => region.assemblyName)),
|
|
497
|
+
];
|
|
893
498
|
if (assemblyNames.length > 1) {
|
|
894
|
-
session.notify(
|
|
499
|
+
session.notify(`Can't perform this with multiple assemblies currently`);
|
|
895
500
|
return;
|
|
896
501
|
}
|
|
897
502
|
;
|
|
898
|
-
|
|
503
|
+
[assemblyName] = assemblyNames;
|
|
899
504
|
}
|
|
900
|
-
|
|
505
|
+
const assembly = assemblyManager.get(assemblyName);
|
|
901
506
|
if (assembly) {
|
|
902
|
-
|
|
507
|
+
const { regions } = assembly;
|
|
903
508
|
if (regions) {
|
|
904
509
|
this.setDisplayedRegions(regions);
|
|
905
510
|
self.zoomTo(self.maxBpPerPx);
|
|
@@ -907,25 +512,25 @@ function stateModelFactory(pluginManager) {
|
|
|
907
512
|
}
|
|
908
513
|
}
|
|
909
514
|
},
|
|
910
|
-
setDraggingTrackId
|
|
515
|
+
setDraggingTrackId(idx) {
|
|
911
516
|
self.draggingTrackId = idx;
|
|
912
517
|
},
|
|
913
|
-
setScaleFactor
|
|
518
|
+
setScaleFactor(factor) {
|
|
914
519
|
self.scaleFactor = factor;
|
|
915
520
|
},
|
|
916
|
-
})
|
|
917
|
-
.actions(
|
|
918
|
-
|
|
521
|
+
}))
|
|
522
|
+
.actions(self => {
|
|
523
|
+
let cancelLastAnimation = () => { };
|
|
919
524
|
function slide(viewWidths) {
|
|
920
|
-
|
|
525
|
+
const [animate, cancelAnimation] = (0, util_1.springAnimate)(self.offsetPx, self.offsetPx + self.width * viewWidths, self.scrollTo);
|
|
921
526
|
cancelLastAnimation();
|
|
922
527
|
cancelLastAnimation = cancelAnimation;
|
|
923
528
|
animate();
|
|
924
529
|
}
|
|
925
|
-
return { slide
|
|
530
|
+
return { slide };
|
|
926
531
|
})
|
|
927
|
-
.actions(
|
|
928
|
-
|
|
532
|
+
.actions(self => {
|
|
533
|
+
let cancelLastAnimation = () => { };
|
|
929
534
|
function zoom(targetBpPerPx) {
|
|
930
535
|
self.zoomTo(self.bpPerPx);
|
|
931
536
|
if (
|
|
@@ -935,18 +540,18 @@ function stateModelFactory(pluginManager) {
|
|
|
935
540
|
(targetBpPerPx > self.bpPerPx && self.bpPerPx === self.maxBpPerPx)) {
|
|
936
541
|
return;
|
|
937
542
|
}
|
|
938
|
-
|
|
939
|
-
|
|
543
|
+
const factor = self.bpPerPx / targetBpPerPx;
|
|
544
|
+
const [animate, cancelAnimation] = (0, util_1.springAnimate)(1, factor, self.setScaleFactor, () => {
|
|
940
545
|
self.zoomTo(targetBpPerPx);
|
|
941
546
|
self.setScaleFactor(1);
|
|
942
|
-
})
|
|
547
|
+
});
|
|
943
548
|
cancelLastAnimation();
|
|
944
549
|
cancelLastAnimation = cancelAnimation;
|
|
945
550
|
animate();
|
|
946
551
|
}
|
|
947
|
-
return { zoom
|
|
552
|
+
return { zoom };
|
|
948
553
|
})
|
|
949
|
-
.views(
|
|
554
|
+
.views(self => ({
|
|
950
555
|
get canShowCytobands() {
|
|
951
556
|
return self.displayedRegions.length === 1 && this.anyCytobandsExist;
|
|
952
557
|
},
|
|
@@ -954,39 +559,47 @@ function stateModelFactory(pluginManager) {
|
|
|
954
559
|
return this.canShowCytobands && self.showCytobandsSetting;
|
|
955
560
|
},
|
|
956
561
|
get anyCytobandsExist() {
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
return assemblyNames.some(
|
|
562
|
+
const { assemblyManager } = (0, util_1.getSession)(self);
|
|
563
|
+
const { assemblyNames } = self;
|
|
564
|
+
return assemblyNames.some(asm => { var _a, _b; return (_b = (_a = assemblyManager.get(asm)) === null || _a === void 0 ? void 0 : _a.cytobands) === null || _b === void 0 ? void 0 : _b.length; });
|
|
960
565
|
},
|
|
961
566
|
get cytobandOffset() {
|
|
962
567
|
return this.showCytobands
|
|
963
568
|
? (0, util_1.measureText)(self.displayedRegions[0].refName, 12) + 15
|
|
964
569
|
: 0;
|
|
965
570
|
},
|
|
966
|
-
})
|
|
967
|
-
.views(
|
|
968
|
-
menuItems
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
var menuItems = __spreadArray([
|
|
571
|
+
}))
|
|
572
|
+
.views(self => ({
|
|
573
|
+
menuItems() {
|
|
574
|
+
const { canShowCytobands, showCytobands } = self;
|
|
575
|
+
const menuItems = [
|
|
972
576
|
{
|
|
973
577
|
label: 'Return to import form',
|
|
974
|
-
onClick:
|
|
975
|
-
(0, util_1.getSession)(self).queueDialog(
|
|
578
|
+
onClick: () => {
|
|
579
|
+
(0, util_1.getSession)(self).queueDialog(handleClose => [
|
|
976
580
|
ui_1.ReturnToImportFormDialog,
|
|
977
|
-
{ model: self, handleClose
|
|
978
|
-
]
|
|
581
|
+
{ model: self, handleClose },
|
|
582
|
+
]);
|
|
979
583
|
},
|
|
980
584
|
icon: FolderOpen_1.default,
|
|
981
585
|
},
|
|
586
|
+
{
|
|
587
|
+
label: 'Sequence search',
|
|
588
|
+
onClick: () => {
|
|
589
|
+
(0, util_1.getSession)(self).queueDialog(handleClose => [
|
|
590
|
+
SequenceSearchDialog,
|
|
591
|
+
{ model: self, handleClose },
|
|
592
|
+
]);
|
|
593
|
+
},
|
|
594
|
+
},
|
|
982
595
|
{
|
|
983
596
|
label: 'Export SVG',
|
|
984
597
|
icon: PhotoCamera_1.default,
|
|
985
|
-
onClick:
|
|
986
|
-
(0, util_1.getSession)(self).queueDialog(
|
|
598
|
+
onClick: () => {
|
|
599
|
+
(0, util_1.getSession)(self).queueDialog(handleClose => [
|
|
987
600
|
ExportSvgDialog_1.default,
|
|
988
|
-
{ model: self, handleClose
|
|
989
|
-
]
|
|
601
|
+
{ model: self, handleClose },
|
|
602
|
+
]);
|
|
990
603
|
},
|
|
991
604
|
},
|
|
992
605
|
{
|
|
@@ -1034,6 +647,24 @@ function stateModelFactory(pluginManager) {
|
|
|
1034
647
|
checked: !self.hideNoTracksActive,
|
|
1035
648
|
onClick: self.toggleNoTracksActive,
|
|
1036
649
|
},
|
|
650
|
+
{
|
|
651
|
+
label: 'Show guidelines',
|
|
652
|
+
icon: Visibility_1.default,
|
|
653
|
+
type: 'checkbox',
|
|
654
|
+
checked: self.showGridlines,
|
|
655
|
+
onClick: self.toggleShowGridlines,
|
|
656
|
+
},
|
|
657
|
+
...(canShowCytobands
|
|
658
|
+
? [
|
|
659
|
+
{
|
|
660
|
+
label: 'Show ideogram',
|
|
661
|
+
icon: Visibility_1.default,
|
|
662
|
+
type: 'checkbox',
|
|
663
|
+
checked: self.showCytobands,
|
|
664
|
+
onClick: () => self.setShowCytobands(!showCytobands),
|
|
665
|
+
},
|
|
666
|
+
]
|
|
667
|
+
: []),
|
|
1037
668
|
{
|
|
1038
669
|
label: 'Track labels',
|
|
1039
670
|
icon: Label_1.default,
|
|
@@ -1043,63 +674,42 @@ function stateModelFactory(pluginManager) {
|
|
|
1043
674
|
icon: Visibility_1.default,
|
|
1044
675
|
type: 'radio',
|
|
1045
676
|
checked: self.trackLabels === 'overlapping',
|
|
1046
|
-
onClick:
|
|
677
|
+
onClick: () => self.setTrackLabels('overlapping'),
|
|
1047
678
|
},
|
|
1048
679
|
{
|
|
1049
680
|
label: 'Offset',
|
|
1050
681
|
icon: Visibility_1.default,
|
|
1051
682
|
type: 'radio',
|
|
1052
683
|
checked: self.trackLabels === 'offset',
|
|
1053
|
-
onClick:
|
|
684
|
+
onClick: () => self.setTrackLabels('offset'),
|
|
1054
685
|
},
|
|
1055
686
|
{
|
|
1056
687
|
label: 'Hidden',
|
|
1057
688
|
icon: Visibility_1.default,
|
|
1058
689
|
type: 'radio',
|
|
1059
690
|
checked: self.trackLabels === 'hidden',
|
|
1060
|
-
onClick:
|
|
691
|
+
onClick: () => self.setTrackLabels('hidden'),
|
|
1061
692
|
},
|
|
1062
693
|
],
|
|
694
|
+
},
|
|
695
|
+
];
|
|
696
|
+
// add track's view level menu options
|
|
697
|
+
for (const [key, value] of self.trackTypeActions.entries()) {
|
|
698
|
+
if (value.length) {
|
|
699
|
+
menuItems.push({ type: 'divider' }, { type: 'subHeader', label: key });
|
|
700
|
+
value.forEach(action => menuItems.push(action));
|
|
1063
701
|
}
|
|
1064
|
-
], __read((canShowCytobands
|
|
1065
|
-
? [
|
|
1066
|
-
{
|
|
1067
|
-
label: showCytobands ? 'Hide ideogram' : 'Show ideograms',
|
|
1068
|
-
onClick: function () {
|
|
1069
|
-
self.setShowCytobands(!showCytobands);
|
|
1070
|
-
},
|
|
1071
|
-
},
|
|
1072
|
-
]
|
|
1073
|
-
: [])), false);
|
|
1074
|
-
try {
|
|
1075
|
-
// add track's view level menu options
|
|
1076
|
-
for (var _b = __values(self.trackTypeActions.entries()), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
1077
|
-
var _d = __read(_c.value, 2), key = _d[0], value = _d[1];
|
|
1078
|
-
if (value.length) {
|
|
1079
|
-
menuItems.push({ type: 'divider' }, { type: 'subHeader', label: key });
|
|
1080
|
-
value.forEach(function (action) {
|
|
1081
|
-
menuItems.push(action);
|
|
1082
|
-
});
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
}
|
|
1086
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
1087
|
-
finally {
|
|
1088
|
-
try {
|
|
1089
|
-
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
1090
|
-
}
|
|
1091
|
-
finally { if (e_1) throw e_1.error; }
|
|
1092
702
|
}
|
|
1093
703
|
return menuItems;
|
|
1094
704
|
},
|
|
1095
|
-
})
|
|
1096
|
-
.views(
|
|
1097
|
-
|
|
1098
|
-
|
|
705
|
+
}))
|
|
706
|
+
.views(self => {
|
|
707
|
+
let currentlyCalculatedStaticBlocks;
|
|
708
|
+
let stringifiedCurrentlyCalculatedStaticBlocks = '';
|
|
1099
709
|
return {
|
|
1100
710
|
get staticBlocks() {
|
|
1101
|
-
|
|
1102
|
-
|
|
711
|
+
const ret = (0, calculateStaticBlocks_1.default)(self);
|
|
712
|
+
const sret = JSON.stringify(ret);
|
|
1103
713
|
if (stringifiedCurrentlyCalculatedStaticBlocks !== sret) {
|
|
1104
714
|
currentlyCalculatedStaticBlocks = ret;
|
|
1105
715
|
stringifiedCurrentlyCalculatedStaticBlocks = sret;
|
|
@@ -1110,8 +720,12 @@ function stateModelFactory(pluginManager) {
|
|
|
1110
720
|
return (0, calculateDynamicBlocks_1.default)(self);
|
|
1111
721
|
},
|
|
1112
722
|
get roundedDynamicBlocks() {
|
|
1113
|
-
return this.dynamicBlocks.contentBlocks.map(
|
|
1114
|
-
return
|
|
723
|
+
return this.dynamicBlocks.contentBlocks.map(block => {
|
|
724
|
+
return {
|
|
725
|
+
...block,
|
|
726
|
+
start: Math.floor(block.start),
|
|
727
|
+
end: Math.ceil(block.end),
|
|
728
|
+
};
|
|
1115
729
|
});
|
|
1116
730
|
},
|
|
1117
731
|
get visibleLocStrings() {
|
|
@@ -1122,9 +736,9 @@ function stateModelFactory(pluginManager) {
|
|
|
1122
736
|
},
|
|
1123
737
|
};
|
|
1124
738
|
})
|
|
1125
|
-
.actions(
|
|
739
|
+
.actions(self => ({
|
|
1126
740
|
// this "clears the view" and makes the view return to the import form
|
|
1127
|
-
clearView
|
|
741
|
+
clearView() {
|
|
1128
742
|
self.setDisplayedRegions([]);
|
|
1129
743
|
self.tracks.clear();
|
|
1130
744
|
// it is necessary to run these after setting displayed regions empty
|
|
@@ -1133,60 +747,270 @@ function stateModelFactory(pluginManager) {
|
|
|
1133
747
|
self.scrollTo(0);
|
|
1134
748
|
self.zoomTo(10);
|
|
1135
749
|
},
|
|
1136
|
-
setCoarseDynamicBlocks
|
|
750
|
+
setCoarseDynamicBlocks(blocks) {
|
|
1137
751
|
self.coarseDynamicBlocks = blocks.contentBlocks;
|
|
1138
752
|
self.coarseTotalBp = blocks.totalBp;
|
|
1139
753
|
},
|
|
1140
|
-
afterAttach
|
|
1141
|
-
|
|
1142
|
-
(0, mobx_state_tree_1.addDisposer)(self, (0, mobx_1.autorun)(function () {
|
|
754
|
+
afterAttach() {
|
|
755
|
+
(0, mobx_state_tree_1.addDisposer)(self, (0, mobx_1.autorun)(() => {
|
|
1143
756
|
if (self.initialized) {
|
|
1144
|
-
|
|
757
|
+
this.setCoarseDynamicBlocks(self.dynamicBlocks);
|
|
1145
758
|
}
|
|
1146
759
|
}, { delay: 150 }));
|
|
1147
760
|
},
|
|
1148
|
-
})
|
|
1149
|
-
.actions(
|
|
1150
|
-
exportSvg
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
761
|
+
}))
|
|
762
|
+
.actions(self => ({
|
|
763
|
+
async exportSvg(opts = {}) {
|
|
764
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
765
|
+
const html = await (0, LinearGenomeViewSvg_1.renderToSvg)(self, opts);
|
|
766
|
+
const blob = new Blob([html], { type: 'image/svg+xml' });
|
|
767
|
+
(0, file_saver_1.saveAs)(blob, opts.filename || 'image.svg');
|
|
768
|
+
},
|
|
769
|
+
/**
|
|
770
|
+
* offset is the base-pair-offset in the displayed region, index is the index of the
|
|
771
|
+
* displayed region in the linear genome view
|
|
772
|
+
*
|
|
773
|
+
* @param start - object as `{start, end, offset, index}`
|
|
774
|
+
* @param end - object as `{start, end, offset, index}`
|
|
775
|
+
*/
|
|
776
|
+
moveTo(start, end) {
|
|
777
|
+
(0, Base1DUtils_1.moveTo)(self, start, end);
|
|
778
|
+
},
|
|
779
|
+
navToLocString(locString, optAssemblyName) {
|
|
780
|
+
const { assemblyNames } = self;
|
|
781
|
+
const { assemblyManager } = (0, util_1.getSession)(self);
|
|
782
|
+
const { isValidRefName } = assemblyManager;
|
|
783
|
+
const assemblyName = optAssemblyName || assemblyNames[0];
|
|
784
|
+
let parsedLocStrings;
|
|
785
|
+
const inputs = locString
|
|
786
|
+
.split(/(\s+)/)
|
|
787
|
+
.map(f => f.trim())
|
|
788
|
+
.filter(f => !!f);
|
|
789
|
+
// first try interpreting as a whitespace-separated sequence of
|
|
790
|
+
// multiple locstrings
|
|
791
|
+
try {
|
|
792
|
+
parsedLocStrings = inputs.map(l => (0, util_1.parseLocString)(l, ref => isValidRefName(ref, assemblyName)));
|
|
793
|
+
}
|
|
794
|
+
catch (e) {
|
|
795
|
+
// if this fails, try interpreting as a whitespace-separated refname,
|
|
796
|
+
// start, end if start and end are integer inputs
|
|
797
|
+
const [refName, start, end] = inputs;
|
|
798
|
+
if (`${e}`.match(/Unknown reference sequence/) &&
|
|
799
|
+
Number.isInteger(+start) &&
|
|
800
|
+
Number.isInteger(+end)) {
|
|
801
|
+
parsedLocStrings = [
|
|
802
|
+
(0, util_1.parseLocString)(refName + ':' + start + '..' + end, ref => isValidRefName(ref, assemblyName)),
|
|
803
|
+
];
|
|
804
|
+
}
|
|
805
|
+
else {
|
|
806
|
+
throw e;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
const locations = parsedLocStrings === null || parsedLocStrings === void 0 ? void 0 : parsedLocStrings.map(region => {
|
|
810
|
+
const asmName = region.assemblyName || assemblyName;
|
|
811
|
+
const asm = assemblyManager.get(asmName);
|
|
812
|
+
const { refName } = region;
|
|
813
|
+
if (!asm) {
|
|
814
|
+
throw new Error(`assembly ${asmName} not found`);
|
|
815
|
+
}
|
|
816
|
+
const { regions } = asm;
|
|
817
|
+
if (!regions) {
|
|
818
|
+
throw new Error(`regions not loaded yet for ${asmName}`);
|
|
819
|
+
}
|
|
820
|
+
const canonicalRefName = asm.getCanonicalRefName(region.refName);
|
|
821
|
+
if (!canonicalRefName) {
|
|
822
|
+
throw new Error(`Could not find refName ${refName} in ${asm.name}`);
|
|
823
|
+
}
|
|
824
|
+
const parentRegion = regions.find(region => region.refName === canonicalRefName);
|
|
825
|
+
if (!parentRegion) {
|
|
826
|
+
throw new Error(`Could not find refName ${refName} in ${asmName}`);
|
|
827
|
+
}
|
|
828
|
+
return {
|
|
829
|
+
...region,
|
|
830
|
+
assemblyName: asmName,
|
|
831
|
+
parentRegion,
|
|
832
|
+
};
|
|
1164
833
|
});
|
|
834
|
+
if (locations.length === 1) {
|
|
835
|
+
const loc = locations[0];
|
|
836
|
+
self.setDisplayedRegions([
|
|
837
|
+
{ reversed: loc.reversed, ...loc.parentRegion },
|
|
838
|
+
]);
|
|
839
|
+
const { start, end, parentRegion } = loc;
|
|
840
|
+
this.navTo({
|
|
841
|
+
...loc,
|
|
842
|
+
start: (0, util_1.clamp)(start !== null && start !== void 0 ? start : 0, 0, parentRegion.end),
|
|
843
|
+
end: (0, util_1.clamp)(end !== null && end !== void 0 ? end : parentRegion.end, 0, parentRegion.end),
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
else {
|
|
847
|
+
self.setDisplayedRegions(
|
|
848
|
+
// @ts-ignore
|
|
849
|
+
locations.map(r => (r.start === undefined ? r.parentRegion : r)));
|
|
850
|
+
self.showAllRegions();
|
|
851
|
+
}
|
|
1165
852
|
},
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
853
|
+
/**
|
|
854
|
+
* Navigate to a location based on its refName and optionally start, end,
|
|
855
|
+
* and assemblyName. Can handle if there are multiple displayedRegions
|
|
856
|
+
* from same refName. Only navigates to a location if it is entirely
|
|
857
|
+
* within a displayedRegion. Navigates to the first matching location
|
|
858
|
+
* encountered.
|
|
859
|
+
*
|
|
860
|
+
* Throws an error if navigation was unsuccessful
|
|
861
|
+
*
|
|
862
|
+
* @param location - a proposed location to navigate to
|
|
863
|
+
*/
|
|
864
|
+
navTo(query) {
|
|
865
|
+
this.navToMultiple([query]);
|
|
866
|
+
},
|
|
867
|
+
navToMultiple(locations) {
|
|
868
|
+
const firstLocation = locations[0];
|
|
869
|
+
let { refName } = firstLocation;
|
|
870
|
+
const { start, end, assemblyName = self.assemblyNames[0], } = firstLocation;
|
|
871
|
+
if (start !== undefined && end !== undefined && start > end) {
|
|
872
|
+
throw new Error(`start "${start + 1}" is greater than end "${end}"`);
|
|
873
|
+
}
|
|
874
|
+
const session = (0, util_1.getSession)(self);
|
|
875
|
+
const { assemblyManager } = session;
|
|
876
|
+
const assembly = assemblyManager.get(assemblyName);
|
|
877
|
+
if (assembly) {
|
|
878
|
+
const canonicalRefName = assembly.getCanonicalRefName(refName);
|
|
879
|
+
if (canonicalRefName) {
|
|
880
|
+
refName = canonicalRefName;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
let s = start;
|
|
884
|
+
let e = end;
|
|
885
|
+
let refNameMatched = false;
|
|
886
|
+
const predicate = (r) => {
|
|
887
|
+
if (refName === r.refName) {
|
|
888
|
+
refNameMatched = true;
|
|
889
|
+
if (s === undefined) {
|
|
890
|
+
s = r.start;
|
|
891
|
+
}
|
|
892
|
+
if (e === undefined) {
|
|
893
|
+
e = r.end;
|
|
894
|
+
}
|
|
895
|
+
if (s >= r.start && s <= r.end && e <= r.end && e >= r.start) {
|
|
896
|
+
return true;
|
|
897
|
+
}
|
|
898
|
+
s = start;
|
|
899
|
+
e = end;
|
|
900
|
+
}
|
|
901
|
+
return false;
|
|
902
|
+
};
|
|
903
|
+
const lastIndex = (0, util_1.findLastIndex)(self.displayedRegions, predicate);
|
|
904
|
+
let index;
|
|
905
|
+
while (index !== lastIndex) {
|
|
906
|
+
try {
|
|
907
|
+
const previousIndex = index;
|
|
908
|
+
index = self.displayedRegions
|
|
909
|
+
.slice(previousIndex === undefined ? 0 : previousIndex + 1)
|
|
910
|
+
.findIndex(predicate);
|
|
911
|
+
if (previousIndex !== undefined) {
|
|
912
|
+
index += previousIndex + 1;
|
|
913
|
+
}
|
|
914
|
+
if (!refNameMatched) {
|
|
915
|
+
throw new Error(`could not find a region with refName "${refName}"`);
|
|
916
|
+
}
|
|
917
|
+
if (s === undefined) {
|
|
918
|
+
throw new Error(`could not find a region with refName "${refName}" that contained an end position ${e}`);
|
|
919
|
+
}
|
|
920
|
+
if (e === undefined) {
|
|
921
|
+
throw new Error(`could not find a region with refName "${refName}" that contained a start position ${s + 1}`);
|
|
922
|
+
}
|
|
923
|
+
if (index === -1) {
|
|
924
|
+
throw new Error(`could not find a region that completely contained "${(0, util_1.assembleLocString)(firstLocation)}"`);
|
|
925
|
+
}
|
|
926
|
+
if (locations.length === 1) {
|
|
927
|
+
const f = self.displayedRegions[index];
|
|
928
|
+
this.moveTo({ index, offset: f.reversed ? f.end - e : s - f.start }, { index, offset: f.reversed ? f.end - s : e - f.start });
|
|
929
|
+
return;
|
|
930
|
+
}
|
|
931
|
+
let locationIndex = 0;
|
|
932
|
+
let locationStart = 0;
|
|
933
|
+
let locationEnd = 0;
|
|
934
|
+
for (locationIndex; locationIndex < locations.length; locationIndex++) {
|
|
935
|
+
const location = locations[locationIndex];
|
|
936
|
+
const region = self.displayedRegions[index + locationIndex];
|
|
937
|
+
locationStart = location.start || region.start;
|
|
938
|
+
locationEnd = location.end || region.end;
|
|
939
|
+
if (location.refName !== region.refName) {
|
|
940
|
+
throw new Error(`Entered location ${(0, util_1.assembleLocString)(location)} does not match with displayed regions`);
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
locationIndex -= 1;
|
|
944
|
+
const startDisplayedRegion = self.displayedRegions[index];
|
|
945
|
+
const endDisplayedRegion = self.displayedRegions[index + locationIndex];
|
|
946
|
+
this.moveTo({
|
|
947
|
+
index,
|
|
948
|
+
offset: startDisplayedRegion.reversed
|
|
949
|
+
? startDisplayedRegion.end - e
|
|
950
|
+
: s - startDisplayedRegion.start,
|
|
951
|
+
}, {
|
|
952
|
+
index: index + locationIndex,
|
|
953
|
+
offset: endDisplayedRegion.reversed
|
|
954
|
+
? endDisplayedRegion.end - locationStart
|
|
955
|
+
: locationEnd - endDisplayedRegion.start,
|
|
956
|
+
});
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
catch (error) {
|
|
960
|
+
if (index === lastIndex) {
|
|
961
|
+
throw error;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
},
|
|
966
|
+
}))
|
|
967
|
+
.views(self => ({
|
|
968
|
+
rubberBandMenuItems() {
|
|
1169
969
|
return [
|
|
1170
970
|
{
|
|
1171
971
|
label: 'Zoom to region',
|
|
1172
972
|
icon: ZoomIn_1.default,
|
|
1173
|
-
onClick:
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
self.moveTo(leftOffset, rightOffset);
|
|
1177
|
-
}
|
|
973
|
+
onClick: () => {
|
|
974
|
+
const { leftOffset, rightOffset } = self;
|
|
975
|
+
self.moveTo(leftOffset, rightOffset);
|
|
1178
976
|
},
|
|
1179
977
|
},
|
|
1180
978
|
{
|
|
1181
979
|
label: 'Get sequence',
|
|
1182
980
|
icon: MenuOpen_1.default,
|
|
1183
|
-
onClick:
|
|
1184
|
-
self.setSequenceDialogOpen(true);
|
|
1185
|
-
},
|
|
981
|
+
onClick: () => self.setGetSequenceDialogOpen(true),
|
|
1186
982
|
},
|
|
1187
983
|
];
|
|
1188
984
|
},
|
|
1189
|
-
|
|
985
|
+
bpToPx({ refName, coord, regionNumber, }) {
|
|
986
|
+
return (0, Base1DUtils_1.bpToPx)({ refName, coord, regionNumber, self });
|
|
987
|
+
},
|
|
988
|
+
/**
|
|
989
|
+
* scrolls the view to center on the given bp. if that is not in any
|
|
990
|
+
* of the displayed regions, does nothing
|
|
991
|
+
* @param coord - basepair at which you want to center the view
|
|
992
|
+
* @param refName - refName of the displayedRegion you are centering at
|
|
993
|
+
* @param regionNumber - index of the displayedRegion
|
|
994
|
+
*/
|
|
995
|
+
centerAt(coord, refName, regionNumber) {
|
|
996
|
+
const centerPx = this.bpToPx({
|
|
997
|
+
refName,
|
|
998
|
+
coord,
|
|
999
|
+
regionNumber,
|
|
1000
|
+
});
|
|
1001
|
+
if (centerPx) {
|
|
1002
|
+
self.scrollTo(Math.round(centerPx.offsetPx - self.width / 2));
|
|
1003
|
+
}
|
|
1004
|
+
},
|
|
1005
|
+
pxToBp(px) {
|
|
1006
|
+
return (0, Base1DUtils_1.pxToBp)(self, px);
|
|
1007
|
+
},
|
|
1008
|
+
get centerLineInfo() {
|
|
1009
|
+
return self.displayedRegions.length
|
|
1010
|
+
? this.pxToBp(self.width / 2)
|
|
1011
|
+
: undefined;
|
|
1012
|
+
},
|
|
1013
|
+
}));
|
|
1190
1014
|
}
|
|
1191
1015
|
exports.stateModelFactory = stateModelFactory;
|
|
1192
1016
|
var LinearGenomeView_1 = require("./components/LinearGenomeView");
|