@jbrowse/plugin-variants 4.0.3 → 4.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/ChordVariantDisplay/models/stateModelFactory.d.ts +9 -0
- package/esm/LDDisplay/SharedLDConfigSchema.d.ts +102 -0
- package/esm/LDDisplay/SharedLDConfigSchema.js +83 -0
- package/esm/LDDisplay/afterAttach.d.ts +2 -0
- package/esm/LDDisplay/afterAttach.js +123 -0
- package/esm/LDDisplay/components/BaseDisplayComponent.d.ts +15 -0
- package/esm/LDDisplay/components/BaseDisplayComponent.js +39 -0
- package/esm/LDDisplay/components/LDColorLegend.d.ts +15 -0
- package/esm/LDDisplay/components/LDColorLegend.js +75 -0
- package/esm/LDDisplay/components/LDDisplayComponent.d.ts +5 -0
- package/esm/LDDisplay/components/LDDisplayComponent.js +203 -0
- package/esm/LDDisplay/components/LinesConnectingMatrixToGenomicPosition.d.ts +16 -0
- package/esm/LDDisplay/components/LinesConnectingMatrixToGenomicPosition.js +109 -0
- package/esm/LDDisplay/configSchema1.d.ts +115 -0
- package/esm/LDDisplay/configSchema1.js +16 -0
- package/esm/LDDisplay/configSchema2.d.ts +115 -0
- package/esm/LDDisplay/configSchema2.js +16 -0
- package/esm/LDDisplay/index.d.ts +2 -0
- package/esm/LDDisplay/index.js +35 -0
- package/esm/LDDisplay/renderSvg.d.ts +3 -0
- package/esm/LDDisplay/renderSvg.js +36 -0
- package/esm/LDDisplay/shared.d.ts +367 -0
- package/esm/LDDisplay/shared.js +467 -0
- package/esm/LDDisplay/stateModel1.d.ts +365 -0
- package/esm/LDDisplay/stateModel1.js +10 -0
- package/esm/LDDisplay/stateModel2.d.ts +365 -0
- package/esm/LDDisplay/stateModel2.js +10 -0
- package/esm/LDRenderer/LDRenderer.d.ts +30 -0
- package/esm/LDRenderer/LDRenderer.js +109 -0
- package/esm/LDRenderer/components/LDRendering.d.ts +2 -0
- package/esm/LDRenderer/components/LDRendering.js +4 -0
- package/esm/LDRenderer/configSchema.d.ts +8 -0
- package/esm/LDRenderer/configSchema.js +10 -0
- package/esm/LDRenderer/index.d.ts +2 -0
- package/esm/LDRenderer/index.js +11 -0
- package/esm/LDRenderer/makeImageData.d.ts +20 -0
- package/esm/LDRenderer/makeImageData.js +158 -0
- package/esm/LDRenderer/types.d.ts +8 -0
- package/esm/LDRenderer/types.js +1 -0
- package/esm/LDTrack/configSchema.d.ts +85 -0
- package/esm/LDTrack/configSchema.js +7 -0
- package/esm/LDTrack/index.d.ts +2 -0
- package/esm/LDTrack/index.js +14 -0
- package/esm/LinearVariantDisplay/model.d.ts +139 -42
- package/esm/LinearVariantDisplay/model.js +46 -8
- package/esm/MultiLinearVariantDisplay/configSchema.d.ts +27 -1
- package/esm/MultiLinearVariantDisplay/model.d.ts +2647 -58
- package/esm/MultiLinearVariantDisplay/model.js +6 -0
- package/esm/MultiLinearVariantDisplay/renderSvg.d.ts +10 -2
- package/esm/MultiLinearVariantMatrixDisplay/configSchema.d.ts +25 -0
- package/esm/MultiLinearVariantMatrixDisplay/configSchema.js +26 -0
- package/esm/MultiLinearVariantMatrixDisplay/model.d.ts +2648 -59
- package/esm/MultiLinearVariantMatrixDisplay/model.js +6 -0
- package/esm/MultiLinearVariantMatrixRenderer/MultiLinearVariantMatrixRenderer.d.ts +2 -2
- package/esm/MultiLinearVariantMatrixRenderer/MultiLinearVariantMatrixRenderer.js +11 -9
- package/esm/MultiLinearVariantMatrixRenderer/components/MultiLinearVariantMatrixRendering.d.ts +8 -0
- package/esm/MultiLinearVariantMatrixRenderer/components/MultiLinearVariantMatrixRendering.js +14 -2
- package/esm/MultiLinearVariantMatrixRenderer/makeImageData.js +14 -8
- package/esm/MultiLinearVariantRenderer/MultiVariantRenderer.d.ts +2 -2
- package/esm/MultiLinearVariantRenderer/MultiVariantRenderer.js +4 -3
- package/esm/MultiLinearVariantRenderer/components/MultiLinearVariantRendering.d.ts +4 -0
- package/esm/MultiLinearVariantRenderer/components/MultiLinearVariantRendering.js +23 -2
- package/esm/MultiLinearVariantRenderer/makeImageData.js +8 -3
- package/esm/PlinkLDAdapter/PlinkLDAdapter.d.ts +25 -0
- package/esm/PlinkLDAdapter/PlinkLDAdapter.js +147 -0
- package/esm/PlinkLDAdapter/PlinkLDTabixAdapter.d.ts +24 -0
- package/esm/PlinkLDAdapter/PlinkLDTabixAdapter.js +156 -0
- package/esm/PlinkLDAdapter/configSchema.d.ts +10 -0
- package/esm/PlinkLDAdapter/configSchema.js +25 -0
- package/esm/PlinkLDAdapter/configSchemaTabix.d.ts +24 -0
- package/esm/PlinkLDAdapter/configSchemaTabix.js +46 -0
- package/esm/PlinkLDAdapter/index.d.ts +2 -0
- package/esm/PlinkLDAdapter/index.js +25 -0
- package/esm/PlinkLDAdapter/types.d.ts +29 -0
- package/esm/PlinkLDAdapter/types.js +1 -0
- package/esm/VariantFeatureWidget/VariantSampleGrid/VariantSampleGrid.js +1 -1
- package/esm/VariantRPC/MultiVariantGetFeatureDetails.d.ts +14 -0
- package/esm/VariantRPC/MultiVariantGetFeatureDetails.js +15 -0
- package/esm/VariantRPC/executeClusterGenotypeMatrix.d.ts +3 -1
- package/esm/VariantRPC/executeClusterGenotypeMatrix.js +8 -4
- package/esm/VariantRPC/getLDMatrix.d.ts +48 -0
- package/esm/VariantRPC/getLDMatrix.js +388 -0
- package/esm/VariantRPC/getLDMatrixFromPlink.d.ts +16 -0
- package/esm/VariantRPC/getLDMatrixFromPlink.js +105 -0
- package/esm/VariantRPC/getPhasedGenotypeMatrix.d.ts +20 -0
- package/esm/VariantRPC/getPhasedGenotypeMatrix.js +50 -0
- package/esm/VariantRPC/types.d.ts +3 -0
- package/esm/VcfAdapter/VcfAdapter.d.ts +1 -1
- package/esm/VcfAdapter/VcfAdapter.js +1 -2
- package/esm/VcfExtensionPoints/index.js +29 -3
- package/esm/VcfFeature/index.d.ts +2 -1
- package/esm/VcfFeature/index.js +4 -2
- package/esm/index.d.ts +1 -0
- package/esm/index.js +23 -0
- package/esm/shared/MultiVariantBaseModel.d.ts +2638 -53
- package/esm/shared/MultiVariantBaseModel.js +100 -47
- package/esm/shared/SharedVariantConfigSchema.d.ts +27 -1
- package/esm/shared/SharedVariantConfigSchema.js +28 -1
- package/esm/shared/VariantFeatureCache.d.ts +27 -0
- package/esm/shared/VariantFeatureCache.js +48 -0
- package/esm/shared/VariantRendererType.d.ts +23 -0
- package/esm/shared/VariantRendererType.js +15 -0
- package/esm/shared/applyColorPalette.d.ts +9 -0
- package/esm/shared/applyColorPalette.js +23 -0
- package/esm/shared/colorByAutorun.d.ts +10 -0
- package/esm/shared/colorByAutorun.js +39 -0
- package/esm/shared/components/AddFiltersDialog.d.ts +3 -3
- package/esm/shared/components/AddFiltersDialog.js +29 -22
- package/esm/shared/components/LDFilterDialog.d.ts +13 -0
- package/esm/shared/components/LDFilterDialog.js +102 -0
- package/esm/shared/components/MAFFilterDialog.js +23 -16
- package/esm/shared/components/MultiVariantClusterDialog/ClusterDialogAuto.js +19 -6
- package/esm/shared/components/MultiVariantClusterDialog/types.d.ts +4 -1
- package/esm/shared/components/MultiVariantColorLegend.js +4 -4
- package/esm/shared/components/MultiVariantLegendBar.js +1 -1
- package/esm/shared/components/MultiVariantTooltip.d.ts +1 -0
- package/esm/shared/components/MultiVariantTooltip.js +2 -2
- package/esm/shared/components/RecombinationTrack.d.ts +21 -0
- package/esm/shared/components/RecombinationTrack.js +54 -0
- package/esm/shared/components/RecombinationYScaleBar.d.ts +7 -0
- package/esm/shared/components/RecombinationYScaleBar.js +34 -0
- package/esm/shared/components/RectBg.js +1 -1
- package/esm/shared/components/SetColorDialogRowPalettizer.d.ts +3 -8
- package/esm/shared/components/SetColorDialogRowPalettizer.js +2 -14
- package/esm/shared/components/SourcesDataGrid.js +4 -4
- package/esm/shared/components/TreeSidebar.js +11 -1
- package/esm/shared/drawAlleleCount.js +9 -0
- package/esm/shared/drawPhased.d.ts +1 -1
- package/esm/shared/drawPhased.js +31 -2
- package/esm/shared/getMultiVariantFeaturesAutorun.d.ts +1 -0
- package/esm/shared/getMultiVariantFeaturesAutorun.js +3 -0
- package/esm/shared/getMultiVariantSourcesAutorun.d.ts +1 -0
- package/esm/shared/getMultiVariantSourcesAutorun.js +3 -0
- package/esm/shared/getSources.d.ts +5 -9
- package/esm/shared/getSources.js +30 -25
- package/esm/shared/mafFilterUtils.d.ts +5 -0
- package/esm/shared/mafFilterUtils.js +17 -0
- package/esm/shared/minorAlleleFrequencyUtils.d.ts +2 -0
- package/esm/shared/minorAlleleFrequencyUtils.js +259 -17
- package/esm/shared/setupMultiVariantAutoruns.js +2 -0
- package/esm/shared/treeDrawingAutorun.d.ts +1 -0
- package/esm/shared/treeDrawingAutorun.js +7 -1
- package/esm/shared/types.d.ts +1 -2
- package/package.json +12 -11
|
@@ -3,12 +3,13 @@ import { fromNewick } from '@gmod/hclust';
|
|
|
3
3
|
import { ConfigurationReference, getConf } from '@jbrowse/core/configuration';
|
|
4
4
|
import SerializableFilterChain from '@jbrowse/core/pluggableElementTypes/renderers/util/serializableFilterChain';
|
|
5
5
|
import { set1 } from '@jbrowse/core/ui/colors';
|
|
6
|
-
import { getSession } from '@jbrowse/core/util';
|
|
6
|
+
import { SimpleFeature, getContainingTrack, getSession, } from '@jbrowse/core/util';
|
|
7
7
|
import { stopStopToken } from '@jbrowse/core/util/stopToken';
|
|
8
|
+
import { getRpcSessionId } from '@jbrowse/core/util/tracks';
|
|
8
9
|
import { cast, isAlive, types } from '@jbrowse/mobx-state-tree';
|
|
9
10
|
import { linearBareDisplayStateModelFactory } from '@jbrowse/plugin-linear-genome-view';
|
|
10
11
|
import CategoryIcon from '@mui/icons-material/Category';
|
|
11
|
-
import
|
|
12
|
+
import ClearAllIcon from '@mui/icons-material/ClearAll';
|
|
12
13
|
import HeightIcon from '@mui/icons-material/Height';
|
|
13
14
|
import SplitscreenIcon from '@mui/icons-material/Splitscreen';
|
|
14
15
|
import VisibilityIcon from '@mui/icons-material/Visibility';
|
|
@@ -16,10 +17,10 @@ import { ascending } from '@mui/x-charts-vendor/d3-array';
|
|
|
16
17
|
import deepEqual from 'fast-deep-equal';
|
|
17
18
|
import { NO_CALL_COLOR, OTHER_ALT_COLOR, REFERENCE_COLOR, UNPHASED_COLOR, getAltColorForDosage, } from "./constants.js";
|
|
18
19
|
import { getSources } from "./getSources.js";
|
|
20
|
+
import { createMAFFilterMenuItem } from "./mafFilterUtils.js";
|
|
19
21
|
import { cluster, hierarchy } from "../d3-hierarchy2/index.js";
|
|
20
|
-
const SetColorDialog = lazy(() => import("./components/SetColorDialog.js"));
|
|
21
|
-
const MAFFilterDialog = lazy(() => import("./components/MAFFilterDialog.js"));
|
|
22
22
|
const AddFiltersDialog = lazy(() => import("./components/AddFiltersDialog.js"));
|
|
23
|
+
const SetColorDialog = lazy(() => import("./components/SetColorDialog.js"));
|
|
23
24
|
const ClusterDialog = lazy(() => import("./components/MultiVariantClusterDialog/ClusterDialog.js"));
|
|
24
25
|
const SetRowHeightDialog = lazy(() => import("./components/SetRowHeightDialog.js"));
|
|
25
26
|
export default function MultiVariantBaseModelF(configSchema) {
|
|
@@ -28,14 +29,14 @@ export default function MultiVariantBaseModelF(configSchema) {
|
|
|
28
29
|
type: types.literal('LinearVariantMatrixDisplay'),
|
|
29
30
|
layout: types.optional(types.frozen(), []),
|
|
30
31
|
configuration: ConfigurationReference(configSchema),
|
|
31
|
-
|
|
32
|
-
showSidebarLabelsSetting: types.
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
minorAlleleFrequencyFilterSetting: types.maybe(types.number),
|
|
33
|
+
showSidebarLabelsSetting: types.maybe(types.boolean),
|
|
34
|
+
showTreeSetting: types.maybe(types.boolean),
|
|
35
|
+
renderingModeSetting: types.maybe(types.string),
|
|
35
36
|
rowHeightMode: types.optional(types.union(types.literal('auto'), types.number), 'auto'),
|
|
36
37
|
lengthCutoffFilter: types.optional(types.number, Number.MAX_SAFE_INTEGER),
|
|
37
38
|
jexlFilters: types.maybe(types.array(types.string)),
|
|
38
|
-
|
|
39
|
+
referenceDrawingModeSetting: types.maybe(types.string),
|
|
39
40
|
clusterTree: types.maybe(types.string),
|
|
40
41
|
treeAreaWidth: types.optional(types.number, 80),
|
|
41
42
|
lineZoneHeight: types.optional(types.number, 0),
|
|
@@ -45,6 +46,7 @@ export default function MultiVariantBaseModelF(configSchema) {
|
|
|
45
46
|
simplifiedFeaturesStopToken: undefined,
|
|
46
47
|
featureUnderMouseVolatile: undefined,
|
|
47
48
|
sourcesVolatile: undefined,
|
|
49
|
+
colorByApplied: false,
|
|
48
50
|
featuresVolatile: undefined,
|
|
49
51
|
hasPhased: false,
|
|
50
52
|
sampleInfo: undefined,
|
|
@@ -52,6 +54,11 @@ export default function MultiVariantBaseModelF(configSchema) {
|
|
|
52
54
|
hoveredTreeNode: undefined,
|
|
53
55
|
treeCanvas: undefined,
|
|
54
56
|
mouseoverCanvas: undefined,
|
|
57
|
+
}))
|
|
58
|
+
.views(self => ({
|
|
59
|
+
get renderingMode() {
|
|
60
|
+
return (self.renderingModeSetting ?? getConf(self, 'renderingMode'));
|
|
61
|
+
},
|
|
55
62
|
}))
|
|
56
63
|
.actions(self => ({
|
|
57
64
|
setJexlFilters(f) {
|
|
@@ -78,6 +85,9 @@ export default function MultiVariantBaseModelF(configSchema) {
|
|
|
78
85
|
setFeatures(f) {
|
|
79
86
|
self.featuresVolatile = f;
|
|
80
87
|
},
|
|
88
|
+
setColorByApplied(value) {
|
|
89
|
+
self.colorByApplied = value;
|
|
90
|
+
},
|
|
81
91
|
setLayout(layout, clearTree = true) {
|
|
82
92
|
const orderChanged = clearTree &&
|
|
83
93
|
self.clusterTree &&
|
|
@@ -113,16 +123,21 @@ export default function MultiVariantBaseModelF(configSchema) {
|
|
|
113
123
|
}
|
|
114
124
|
},
|
|
115
125
|
setMafFilter(arg) {
|
|
116
|
-
self.
|
|
126
|
+
self.minorAlleleFrequencyFilterSetting = arg;
|
|
117
127
|
},
|
|
118
128
|
setShowSidebarLabels(arg) {
|
|
119
129
|
self.showSidebarLabelsSetting = arg;
|
|
120
130
|
},
|
|
121
131
|
setShowTree(arg) {
|
|
122
|
-
self.
|
|
132
|
+
self.showTreeSetting = arg;
|
|
123
133
|
},
|
|
124
134
|
setPhasedMode(arg) {
|
|
125
|
-
self.
|
|
135
|
+
const currentMode = self.renderingModeSetting ?? getConf(self, 'renderingMode');
|
|
136
|
+
if (currentMode !== arg) {
|
|
137
|
+
self.layout = [];
|
|
138
|
+
self.clusterTree = undefined;
|
|
139
|
+
}
|
|
140
|
+
self.renderingModeSetting = arg;
|
|
126
141
|
},
|
|
127
142
|
setAutoHeight(auto) {
|
|
128
143
|
self.rowHeightMode = auto ? 'auto' : 10;
|
|
@@ -136,14 +151,31 @@ export default function MultiVariantBaseModelF(configSchema) {
|
|
|
136
151
|
}
|
|
137
152
|
},
|
|
138
153
|
setReferenceDrawingMode(arg) {
|
|
139
|
-
self.
|
|
154
|
+
self.referenceDrawingModeSetting = arg;
|
|
140
155
|
},
|
|
141
156
|
}))
|
|
142
157
|
.views(self => ({
|
|
143
158
|
get autoHeight() {
|
|
144
159
|
return self.rowHeightMode === 'auto';
|
|
145
160
|
},
|
|
146
|
-
get
|
|
161
|
+
get minorAlleleFrequencyFilter() {
|
|
162
|
+
return (self.minorAlleleFrequencyFilterSetting ??
|
|
163
|
+
getConf(self, 'minorAlleleFrequencyFilter'));
|
|
164
|
+
},
|
|
165
|
+
get showSidebarLabels() {
|
|
166
|
+
return (self.showSidebarLabelsSetting ?? getConf(self, 'showSidebarLabels'));
|
|
167
|
+
},
|
|
168
|
+
get showTree() {
|
|
169
|
+
return self.showTreeSetting ?? getConf(self, 'showTree');
|
|
170
|
+
},
|
|
171
|
+
get referenceDrawingMode() {
|
|
172
|
+
if (self.referenceDrawingModeSetting !== undefined) {
|
|
173
|
+
return self.referenceDrawingModeSetting;
|
|
174
|
+
}
|
|
175
|
+
const showRef = getConf(self, 'showReferenceAlleles');
|
|
176
|
+
return showRef ? 'draw' : 'skip';
|
|
177
|
+
},
|
|
178
|
+
activeFilters() {
|
|
147
179
|
return (self.jexlFilters ??
|
|
148
180
|
getConf(self, 'jexlFilters').map((r) => `jexl:${r}`));
|
|
149
181
|
},
|
|
@@ -157,12 +189,10 @@ export default function MultiVariantBaseModelF(configSchema) {
|
|
|
157
189
|
: undefined;
|
|
158
190
|
},
|
|
159
191
|
get sources() {
|
|
160
|
-
|
|
161
|
-
? self.layout
|
|
162
|
-
: self.sourcesVolatile;
|
|
163
|
-
return sourcesWithLayout
|
|
192
|
+
return self.sourcesVolatile
|
|
164
193
|
? getSources({
|
|
165
|
-
sources:
|
|
194
|
+
sources: self.sourcesVolatile,
|
|
195
|
+
layout: self.layout.length ? self.layout : undefined,
|
|
166
196
|
renderingMode: self.renderingMode,
|
|
167
197
|
sampleInfo: self.sampleInfo,
|
|
168
198
|
})
|
|
@@ -184,7 +214,7 @@ export default function MultiVariantBaseModelF(configSchema) {
|
|
|
184
214
|
return {
|
|
185
215
|
get sourceMap() {
|
|
186
216
|
return self.sources
|
|
187
|
-
? Object.fromEntries(self.sources.map(source => [source.name, source]))
|
|
217
|
+
? Object.fromEntries(self.sources.map((source) => [source.name, source]))
|
|
188
218
|
: undefined;
|
|
189
219
|
},
|
|
190
220
|
get availableHeight() {
|
|
@@ -231,13 +261,13 @@ export default function MultiVariantBaseModelF(configSchema) {
|
|
|
231
261
|
{
|
|
232
262
|
label: 'Show sidebar labels',
|
|
233
263
|
type: 'checkbox',
|
|
234
|
-
checked: self.
|
|
264
|
+
checked: self.showSidebarLabels,
|
|
235
265
|
onClick: () => {
|
|
236
|
-
self.setShowSidebarLabels(!self.
|
|
266
|
+
self.setShowSidebarLabels(!self.showSidebarLabels);
|
|
237
267
|
},
|
|
238
268
|
},
|
|
239
269
|
{
|
|
240
|
-
label:
|
|
270
|
+
label: `Show tree${!self.clusterTree ? ' (run clustering first)' : ''}`,
|
|
241
271
|
type: 'checkbox',
|
|
242
272
|
checked: self.showTree,
|
|
243
273
|
disabled: !self.clusterTree,
|
|
@@ -305,9 +335,11 @@ export default function MultiVariantBaseModelF(configSchema) {
|
|
|
305
335
|
},
|
|
306
336
|
},
|
|
307
337
|
{
|
|
308
|
-
label: `Phased${
|
|
309
|
-
? '
|
|
310
|
-
:
|
|
338
|
+
label: `Phased${self.hasPhased
|
|
339
|
+
? ''
|
|
340
|
+
: !self.featuresVolatile
|
|
341
|
+
? ' (checking for phased variants...)'
|
|
342
|
+
: ' (disabled, no phased variants found)'}`,
|
|
311
343
|
helpText: 'Phased mode splits each sample into multiple rows representing each haplotype, and the phasing of the variants is used to color the variant in the individual haplotype rows. For example, a diploid sample SAMPLE1 will generate two rows SAMPLE1-HP0 and SAMPLE1 HP1 and a variant 1|0 will draw a box in the top row but not the bottom row',
|
|
312
344
|
disabled: !self.hasPhased,
|
|
313
345
|
checked: self.renderingMode === 'phased',
|
|
@@ -320,20 +352,9 @@ export default function MultiVariantBaseModelF(configSchema) {
|
|
|
320
352
|
},
|
|
321
353
|
{
|
|
322
354
|
label: 'Filter by',
|
|
323
|
-
icon:
|
|
355
|
+
icon: ClearAllIcon,
|
|
324
356
|
subMenu: [
|
|
325
|
-
|
|
326
|
-
label: 'Minor allele frequency',
|
|
327
|
-
onClick: () => {
|
|
328
|
-
getSession(self).queueDialog(handleClose => [
|
|
329
|
-
MAFFilterDialog,
|
|
330
|
-
{
|
|
331
|
-
model: self,
|
|
332
|
-
handleClose,
|
|
333
|
-
},
|
|
334
|
-
]);
|
|
335
|
-
},
|
|
336
|
-
},
|
|
357
|
+
createMAFFilterMenuItem(self),
|
|
337
358
|
{
|
|
338
359
|
label: 'Edit filters',
|
|
339
360
|
onClick: () => {
|
|
@@ -379,7 +400,7 @@ export default function MultiVariantBaseModelF(configSchema) {
|
|
|
379
400
|
})
|
|
380
401
|
.views(self => ({
|
|
381
402
|
get canDisplayLabels() {
|
|
382
|
-
return self.rowHeight >= 6 && self.
|
|
403
|
+
return self.rowHeight >= 6 && self.showSidebarLabels;
|
|
383
404
|
},
|
|
384
405
|
get totalHeight() {
|
|
385
406
|
return self.rowHeight * (self.sources?.length || 1);
|
|
@@ -419,10 +440,36 @@ export default function MultiVariantBaseModelF(configSchema) {
|
|
|
419
440
|
scrollTop: self.scrollTop,
|
|
420
441
|
referenceDrawingMode: self.referenceDrawingMode,
|
|
421
442
|
filters: new SerializableFilterChain({
|
|
422
|
-
filters: self.activeFilters,
|
|
443
|
+
filters: self.activeFilters(),
|
|
423
444
|
}),
|
|
424
445
|
};
|
|
425
446
|
},
|
|
447
|
+
renderingProps() {
|
|
448
|
+
return {
|
|
449
|
+
displayModel: self,
|
|
450
|
+
async onFeatureClick(_, featureId) {
|
|
451
|
+
const session = getSession(self);
|
|
452
|
+
const { rpcManager } = session;
|
|
453
|
+
try {
|
|
454
|
+
const sessionId = getRpcSessionId(self);
|
|
455
|
+
const track = getContainingTrack(self);
|
|
456
|
+
const { feature } = (await rpcManager.call(sessionId, 'MultiVariantGetFeatureDetails', {
|
|
457
|
+
featureId,
|
|
458
|
+
sessionId,
|
|
459
|
+
trackInstanceId: track.id,
|
|
460
|
+
rendererType: self.rendererTypeName,
|
|
461
|
+
}));
|
|
462
|
+
if (isAlive(self) && feature) {
|
|
463
|
+
self.selectFeature(new SimpleFeature(feature));
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
catch (e) {
|
|
467
|
+
console.error(e);
|
|
468
|
+
session.notifyError(`${e}`, e);
|
|
469
|
+
}
|
|
470
|
+
},
|
|
471
|
+
};
|
|
472
|
+
},
|
|
426
473
|
legendItems() {
|
|
427
474
|
if (self.renderingMode === 'phased') {
|
|
428
475
|
let maxAltAlleles = 1;
|
|
@@ -478,20 +525,26 @@ export default function MultiVariantBaseModelF(configSchema) {
|
|
|
478
525
|
if (!snap) {
|
|
479
526
|
return snap;
|
|
480
527
|
}
|
|
481
|
-
const { layout,
|
|
528
|
+
const { layout, minorAlleleFrequencyFilterSetting, showSidebarLabelsSetting, showTreeSetting, renderingModeSetting, rowHeightMode, lengthCutoffFilter, jexlFilters, referenceDrawingModeSetting, clusterTree, treeAreaWidth, lineZoneHeight, ...rest } = snap;
|
|
482
529
|
return {
|
|
483
530
|
...rest,
|
|
484
531
|
...(layout.length ? { layout } : {}),
|
|
485
|
-
...(
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
...(
|
|
532
|
+
...(minorAlleleFrequencyFilterSetting !== undefined
|
|
533
|
+
? { minorAlleleFrequencyFilterSetting }
|
|
534
|
+
: {}),
|
|
535
|
+
...(showSidebarLabelsSetting !== undefined
|
|
536
|
+
? { showSidebarLabelsSetting }
|
|
537
|
+
: {}),
|
|
538
|
+
...(showTreeSetting !== undefined ? { showTreeSetting } : {}),
|
|
539
|
+
...(renderingModeSetting !== undefined ? { renderingModeSetting } : {}),
|
|
489
540
|
...(rowHeightMode !== 'auto' ? { rowHeightMode } : {}),
|
|
490
541
|
...(lengthCutoffFilter !== Number.MAX_SAFE_INTEGER
|
|
491
542
|
? { lengthCutoffFilter }
|
|
492
543
|
: {}),
|
|
493
544
|
...(jexlFilters?.length ? { jexlFilters } : {}),
|
|
494
|
-
...(
|
|
545
|
+
...(referenceDrawingModeSetting !== undefined
|
|
546
|
+
? { referenceDrawingModeSetting }
|
|
547
|
+
: {}),
|
|
495
548
|
...(clusterTree !== undefined ? { clusterTree } : {}),
|
|
496
549
|
...(treeAreaWidth !== 80 ? { treeAreaWidth } : {}),
|
|
497
550
|
...(lineZoneHeight ? { lineZoneHeight } : {}),
|
|
@@ -1,4 +1,30 @@
|
|
|
1
|
-
export default function sharedVariantConfigFactory(): import("node_modules/@jbrowse/core/src/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
1
|
+
export default function sharedVariantConfigFactory(): import("node_modules/@jbrowse/core/src/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
2
|
+
showReferenceAlleles: {
|
|
3
|
+
type: string;
|
|
4
|
+
defaultValue: boolean;
|
|
5
|
+
};
|
|
6
|
+
showSidebarLabels: {
|
|
7
|
+
type: string;
|
|
8
|
+
defaultValue: boolean;
|
|
9
|
+
};
|
|
10
|
+
showTree: {
|
|
11
|
+
type: string;
|
|
12
|
+
defaultValue: boolean;
|
|
13
|
+
};
|
|
14
|
+
renderingMode: {
|
|
15
|
+
type: string;
|
|
16
|
+
model: import("@jbrowse/mobx-state-tree").ISimpleType<string>;
|
|
17
|
+
defaultValue: string;
|
|
18
|
+
};
|
|
19
|
+
minorAlleleFrequencyFilter: {
|
|
20
|
+
type: string;
|
|
21
|
+
defaultValue: number;
|
|
22
|
+
};
|
|
23
|
+
colorBy: {
|
|
24
|
+
type: string;
|
|
25
|
+
defaultValue: string;
|
|
26
|
+
};
|
|
27
|
+
}, import("node_modules/@jbrowse/core/src/configuration/configurationSchema").ConfigurationSchemaOptions<import("node_modules/@jbrowse/core/src/configuration/configurationSchema").ConfigurationSchemaType<{
|
|
2
28
|
maxFeatureScreenDensity: {
|
|
3
29
|
type: string;
|
|
4
30
|
description: string;
|
|
@@ -1,7 +1,34 @@
|
|
|
1
1
|
import { ConfigurationSchema } from '@jbrowse/core/configuration';
|
|
2
|
+
import { types } from '@jbrowse/mobx-state-tree';
|
|
2
3
|
import { baseLinearDisplayConfigSchema } from '@jbrowse/plugin-linear-genome-view';
|
|
3
4
|
export default function sharedVariantConfigFactory() {
|
|
4
|
-
return ConfigurationSchema('SharedVariantDisplay', {
|
|
5
|
+
return ConfigurationSchema('SharedVariantDisplay', {
|
|
6
|
+
showReferenceAlleles: {
|
|
7
|
+
type: 'boolean',
|
|
8
|
+
defaultValue: false,
|
|
9
|
+
},
|
|
10
|
+
showSidebarLabels: {
|
|
11
|
+
type: 'boolean',
|
|
12
|
+
defaultValue: true,
|
|
13
|
+
},
|
|
14
|
+
showTree: {
|
|
15
|
+
type: 'boolean',
|
|
16
|
+
defaultValue: true,
|
|
17
|
+
},
|
|
18
|
+
renderingMode: {
|
|
19
|
+
type: 'stringEnum',
|
|
20
|
+
model: types.enumeration('RenderingMode', ['alleleCount', 'phased']),
|
|
21
|
+
defaultValue: 'alleleCount',
|
|
22
|
+
},
|
|
23
|
+
minorAlleleFrequencyFilter: {
|
|
24
|
+
type: 'number',
|
|
25
|
+
defaultValue: 0,
|
|
26
|
+
},
|
|
27
|
+
colorBy: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
defaultValue: '',
|
|
30
|
+
},
|
|
31
|
+
}, {
|
|
5
32
|
baseConfiguration: baseLinearDisplayConfigSchema,
|
|
6
33
|
explicitlyTyped: true,
|
|
7
34
|
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Feature } from '@jbrowse/core/util';
|
|
2
|
+
export declare class VariantFeatureSession {
|
|
3
|
+
private features;
|
|
4
|
+
addFeatures(refName: string, features: Map<string, Feature>): void;
|
|
5
|
+
getDataByID(id: string): Feature | undefined;
|
|
6
|
+
discardRange(refName: string, start: number, end: number): void;
|
|
7
|
+
}
|
|
8
|
+
export declare class VariantFeatureCacheManager {
|
|
9
|
+
private sessions;
|
|
10
|
+
getSession(args: {
|
|
11
|
+
sessionId: string;
|
|
12
|
+
trackInstanceId: string;
|
|
13
|
+
}): VariantFeatureSession;
|
|
14
|
+
freeResources(args: {
|
|
15
|
+
sessionId: string;
|
|
16
|
+
trackInstanceId: string;
|
|
17
|
+
regions: {
|
|
18
|
+
refName: string;
|
|
19
|
+
start: number;
|
|
20
|
+
end: number;
|
|
21
|
+
}[];
|
|
22
|
+
}): void;
|
|
23
|
+
deleteSession(args: {
|
|
24
|
+
sessionId: string;
|
|
25
|
+
trackInstanceId: string;
|
|
26
|
+
}): void;
|
|
27
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export class VariantFeatureSession {
|
|
2
|
+
features = new Map();
|
|
3
|
+
addFeatures(refName, features) {
|
|
4
|
+
for (const [id, feature] of features) {
|
|
5
|
+
this.features.set(id, feature);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
getDataByID(id) {
|
|
9
|
+
return this.features.get(id);
|
|
10
|
+
}
|
|
11
|
+
discardRange(refName, start, end) {
|
|
12
|
+
for (const [id, feature] of this.features) {
|
|
13
|
+
const fRefName = feature.get('refName');
|
|
14
|
+
const fStart = feature.get('start');
|
|
15
|
+
const fEnd = feature.get('end');
|
|
16
|
+
if (fRefName === refName && fStart < end && fEnd > start) {
|
|
17
|
+
this.features.delete(id);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function getLayoutId(args) {
|
|
23
|
+
return `${args.sessionId}-${args.trackInstanceId}`;
|
|
24
|
+
}
|
|
25
|
+
export class VariantFeatureCacheManager {
|
|
26
|
+
sessions = {};
|
|
27
|
+
getSession(args) {
|
|
28
|
+
const key = getLayoutId(args);
|
|
29
|
+
if (!this.sessions[key]) {
|
|
30
|
+
this.sessions[key] = new VariantFeatureSession();
|
|
31
|
+
}
|
|
32
|
+
return this.sessions[key];
|
|
33
|
+
}
|
|
34
|
+
freeResources(args) {
|
|
35
|
+
const key = getLayoutId(args);
|
|
36
|
+
const session = this.sessions[key];
|
|
37
|
+
if (session) {
|
|
38
|
+
const region = args.regions[0];
|
|
39
|
+
if (region) {
|
|
40
|
+
session.discardRange(region.refName, region.start, region.end);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
deleteSession(args) {
|
|
45
|
+
const key = getLayoutId(args);
|
|
46
|
+
delete this.sessions[key];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import FeatureRendererType from '@jbrowse/core/pluggableElementTypes/renderers/FeatureRendererType';
|
|
2
|
+
import { VariantFeatureCacheManager } from './VariantFeatureCache.ts';
|
|
3
|
+
import type { Feature } from '@jbrowse/core/util';
|
|
4
|
+
export default class VariantRendererType extends FeatureRendererType {
|
|
5
|
+
featureCacheManager: VariantFeatureCacheManager;
|
|
6
|
+
getFeatureById(featureId: string, args: {
|
|
7
|
+
sessionId: string;
|
|
8
|
+
trackInstanceId: string;
|
|
9
|
+
}): Feature | undefined;
|
|
10
|
+
freeResources(args: {
|
|
11
|
+
sessionId: string;
|
|
12
|
+
trackInstanceId: string;
|
|
13
|
+
regions: {
|
|
14
|
+
refName: string;
|
|
15
|
+
start: number;
|
|
16
|
+
end: number;
|
|
17
|
+
}[];
|
|
18
|
+
}): void;
|
|
19
|
+
protected cacheFeatures(args: {
|
|
20
|
+
sessionId: string;
|
|
21
|
+
trackInstanceId: string;
|
|
22
|
+
}, refName: string, features: Map<string, Feature>): void;
|
|
23
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import FeatureRendererType from '@jbrowse/core/pluggableElementTypes/renderers/FeatureRendererType';
|
|
2
|
+
import { VariantFeatureCacheManager } from "./VariantFeatureCache.js";
|
|
3
|
+
export default class VariantRendererType extends FeatureRendererType {
|
|
4
|
+
featureCacheManager = new VariantFeatureCacheManager();
|
|
5
|
+
getFeatureById(featureId, args) {
|
|
6
|
+
return this.featureCacheManager.getSession(args).getDataByID(featureId);
|
|
7
|
+
}
|
|
8
|
+
freeResources(args) {
|
|
9
|
+
this.featureCacheManager.freeResources(args);
|
|
10
|
+
}
|
|
11
|
+
cacheFeatures(args, refName, features) {
|
|
12
|
+
const session = this.featureCacheManager.getSession(args);
|
|
13
|
+
session.addFeatures(refName, features);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { set1 } from '@jbrowse/core/ui/colors';
|
|
2
|
+
import { randomColor } from '@jbrowse/core/util/color';
|
|
3
|
+
export function applyColorPalette(sources, attribute) {
|
|
4
|
+
if (!attribute || sources.length === 0) {
|
|
5
|
+
return sources;
|
|
6
|
+
}
|
|
7
|
+
const hasAttribute = sources.some(source => attribute in source);
|
|
8
|
+
if (!hasAttribute) {
|
|
9
|
+
return sources;
|
|
10
|
+
}
|
|
11
|
+
const counts = new Map();
|
|
12
|
+
for (const source of sources) {
|
|
13
|
+
const key = String(source[attribute] ?? '');
|
|
14
|
+
counts.set(key, (counts.get(key) || 0) + 1);
|
|
15
|
+
}
|
|
16
|
+
const colorMap = Object.fromEntries([...counts.entries()]
|
|
17
|
+
.sort((a, b) => a[1] - b[1])
|
|
18
|
+
.map(([key], idx) => [key, set1[idx] || randomColor(key)]));
|
|
19
|
+
return sources.map(source => ({
|
|
20
|
+
...source,
|
|
21
|
+
color: colorMap[String(source[attribute] ?? '')],
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Source } from './types.ts';
|
|
2
|
+
import type { AnyConfigurationModel } from '@jbrowse/core/configuration';
|
|
3
|
+
export declare function setupColorByAutorun(self: {
|
|
4
|
+
configuration: AnyConfigurationModel;
|
|
5
|
+
sourcesVolatile: Source[] | undefined;
|
|
6
|
+
layout: Source[];
|
|
7
|
+
colorByApplied: boolean;
|
|
8
|
+
setLayout: (layout: Source[], clearTree?: boolean) => void;
|
|
9
|
+
setColorByApplied: (value: boolean) => void;
|
|
10
|
+
}): void;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { getConf } from '@jbrowse/core/configuration';
|
|
2
|
+
import { addDisposer, isAlive } from '@jbrowse/mobx-state-tree';
|
|
3
|
+
import { autorun } from 'mobx';
|
|
4
|
+
import { applyColorPalette } from "./applyColorPalette.js";
|
|
5
|
+
export function setupColorByAutorun(self) {
|
|
6
|
+
addDisposer(self, autorun(() => {
|
|
7
|
+
if (!isAlive(self)) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (self.colorByApplied) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const sources = self.sourcesVolatile;
|
|
14
|
+
if (!sources || sources.length === 0) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (self.layout.length > 0) {
|
|
18
|
+
self.setColorByApplied(true);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const colorBy = getConf(self, 'colorBy');
|
|
22
|
+
if (!colorBy) {
|
|
23
|
+
self.setColorByApplied(true);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const hasAttribute = sources.some(source => colorBy in source);
|
|
27
|
+
if (!hasAttribute) {
|
|
28
|
+
console.warn(`colorBy attribute "${colorBy}" not found in sample metadata. ` +
|
|
29
|
+
`Available attributes: ${Object.keys(sources[0] || {}).join(', ')}`);
|
|
30
|
+
self.setColorByApplied(true);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const coloredSources = applyColorPalette(sources, colorBy);
|
|
34
|
+
self.setLayout(coloredSources, false);
|
|
35
|
+
self.setColorByApplied(true);
|
|
36
|
+
}, {
|
|
37
|
+
name: 'ColorByAutorun',
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
declare const AddFiltersDialog: ({ model, handleClose, }: {
|
|
2
2
|
model: {
|
|
3
3
|
jexlFilters?: string[];
|
|
4
|
-
activeFilters: string[];
|
|
5
4
|
setJexlFilters: (arg?: string[]) => void;
|
|
6
5
|
};
|
|
7
6
|
handleClose: () => void;
|
|
8
|
-
})
|
|
7
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export default AddFiltersDialog;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
3
|
import { Dialog } from '@jbrowse/core/ui';
|
|
4
4
|
import { stringToJexlExpression } from '@jbrowse/core/util/jexlStrings';
|
|
5
5
|
import { makeStyles } from '@jbrowse/core/util/tss-react';
|
|
6
6
|
import { Button, DialogActions, DialogContent, TextField } from '@mui/material';
|
|
7
|
+
import { observer } from 'mobx-react';
|
|
7
8
|
const useStyles = makeStyles()({
|
|
8
9
|
dialogContent: {
|
|
9
10
|
width: '80em',
|
|
@@ -16,27 +17,30 @@ const useStyles = makeStyles()({
|
|
|
16
17
|
fontSize: '0.8em',
|
|
17
18
|
},
|
|
18
19
|
});
|
|
19
|
-
function
|
|
20
|
-
|
|
21
|
-
for (const line of data
|
|
22
|
-
.split('\n')
|
|
23
|
-
.map(l => l.trim())
|
|
24
|
-
.filter(Boolean)) {
|
|
25
|
-
stringToJexlExpression(line);
|
|
26
|
-
}
|
|
27
|
-
return undefined;
|
|
28
|
-
}
|
|
29
|
-
catch (e) {
|
|
30
|
-
console.error(e);
|
|
31
|
-
return e;
|
|
32
|
-
}
|
|
20
|
+
function checkJexl(code) {
|
|
21
|
+
stringToJexlExpression(code);
|
|
33
22
|
}
|
|
34
|
-
|
|
23
|
+
const AddFiltersDialog = observer(function AddFiltersDialog({ model, handleClose, }) {
|
|
35
24
|
const { classes } = useStyles();
|
|
36
|
-
const {
|
|
37
|
-
const [data, setData] = useState(
|
|
38
|
-
const error =
|
|
39
|
-
|
|
25
|
+
const { jexlFilters } = model;
|
|
26
|
+
const [data, setData] = useState((jexlFilters ?? []).join('\n'));
|
|
27
|
+
const [error, setError] = useState();
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
try {
|
|
30
|
+
for (const line of data
|
|
31
|
+
.split('\n')
|
|
32
|
+
.map(line => line.trim())
|
|
33
|
+
.filter(line => !!line)) {
|
|
34
|
+
checkJexl(line);
|
|
35
|
+
}
|
|
36
|
+
setError(undefined);
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
console.error(e);
|
|
40
|
+
setError(e);
|
|
41
|
+
}
|
|
42
|
+
}, [data]);
|
|
43
|
+
return (_jsxs(Dialog, { maxWidth: "xl", open: true, onClose: handleClose, title: "Add track filters", children: [_jsxs(DialogContent, { children: [_jsxs("div", { children: ["Add filters, in jexl format, one per line, starting with the string jexl:. Examples:", ' ', _jsxs("ul", { children: [_jsxs("li", { children: [_jsx("code", { children: "jexl:get(feature,'name')=='BRCA1'" }), " - show only feature where the name attribute is BRCA1"] }), _jsxs("li", { children: [_jsx("code", { children: "jexl:startsWith(get(feature,'name'),'PREFIX')" }), " - show only feature where the string 'PREFIX' is the prefix of feature name. endsWith also works"] }), _jsxs("li", { children: [_jsx("code", { children: "jexl:includes(get(feature,'name'),'PREFIX')" }), " - show only feature where the string 'PREFIX' is the prefix of feature name"] }), _jsxs("li", { children: [_jsx("code", { children: "jexl:get(feature,'type')=='gene'" }), " - show only gene type features in a GFF that has many other feature types"] }), _jsxs("li", { children: [_jsx("code", { children: "jexl:get(feature,'score') > 400" }), " - show only features that have a score greater than 400"] }), _jsxs("li", { children: [_jsx("code", { children: "jexl:get(feature,'end') - get(feature,'start') < 1000000" }), ' ', "- show only features with length less than 1Mbp"] })] }), _jsxs("p", { children: ["Please see", ' ', _jsx("a", { href: "https://jbrowse.org/jb2/docs/config_guides/jexl/", children: "Jexl" }), ' ', "documentation for more information"] })] }), error ? _jsx("p", { className: classes.error, children: `${error}` }) : null, _jsx(TextField, { variant: "outlined", multiline: true, minRows: 5, maxRows: 10, className: classes.dialogContent, fullWidth: true, value: data, onChange: event => {
|
|
40
44
|
setData(event.target.value);
|
|
41
45
|
}, slotProps: {
|
|
42
46
|
input: {
|
|
@@ -47,5 +51,8 @@ export default function AddFiltersDialog({ model, handleClose, }) {
|
|
|
47
51
|
} })] }), _jsxs(DialogActions, { children: [_jsx(Button, { variant: "contained", color: "primary", type: "submit", autoFocus: true, disabled: !!error, onClick: () => {
|
|
48
52
|
model.setJexlFilters(data.split('\n'));
|
|
49
53
|
handleClose();
|
|
50
|
-
}, children: "Submit" }), _jsx(Button, { variant: "contained", color: "secondary", onClick:
|
|
51
|
-
|
|
54
|
+
}, children: "Submit" }), _jsx(Button, { variant: "contained", color: "secondary", onClick: () => {
|
|
55
|
+
handleClose();
|
|
56
|
+
}, children: "Cancel" })] })] }));
|
|
57
|
+
});
|
|
58
|
+
export default AddFiltersDialog;
|