@jbrowse/plugin-variants 3.1.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/MultiLinearVariantDisplay/model.d.ts +19 -0
- package/dist/MultiLinearVariantMatrixDisplay/model.d.ts +20 -0
- package/dist/MultiLinearVariantMatrixDisplay/model.js +4 -1
- package/dist/MultiLinearVariantMatrixRenderer/makeImageData.js +9 -1
- package/dist/MultiLinearVariantRenderer/makeImageData.js +9 -1
- package/dist/VariantRPC/MultiVariantClusterGenotypeMatrix.d.ts +28 -0
- package/dist/VariantRPC/MultiVariantClusterGenotypeMatrix.js +33 -0
- package/dist/VariantRPC/MultiVariantGetGenotypeMatrix.d.ts +13 -11
- package/dist/VariantRPC/MultiVariantGetGenotypeMatrix.js +5 -57
- package/dist/VariantRPC/MultiVariantGetSimplifiedFeatures.d.ts +11 -8
- package/dist/VariantRPC/MultiVariantGetSimplifiedFeatures.js +1 -2
- package/dist/VariantRPC/cluster.d.ts +17 -0
- package/dist/VariantRPC/cluster.js +84 -0
- package/dist/VariantRPC/getGenotypeMatrix.d.ts +6 -0
- package/dist/VariantRPC/getGenotypeMatrix.js +55 -0
- package/dist/VariantRPC/types.d.ts +13 -0
- package/dist/VariantRPC/types.js +2 -0
- package/dist/VcfAdapter/VcfAdapter.js +6 -3
- package/dist/VcfFeature/util.js +2 -2
- package/dist/VcfTabixAdapter/VcfTabixAdapter.js +11 -6
- package/dist/index.js +2 -0
- package/dist/shared/MultiVariantBaseModel.d.ts +19 -0
- package/dist/shared/MultiVariantBaseModel.js +27 -35
- package/dist/shared/components/ClusterDialog/ClusterDialog.d.ts +6 -0
- package/dist/shared/components/ClusterDialog/ClusterDialog.js +29 -0
- package/dist/shared/components/ClusterDialog/ClusterDialogAuto.d.ts +7 -0
- package/dist/shared/components/ClusterDialog/ClusterDialogAuto.js +69 -0
- package/dist/shared/components/ClusterDialog/ClusterDialogManual.d.ts +7 -0
- package/dist/shared/components/ClusterDialog/ClusterDialogManual.js +144 -0
- package/dist/shared/components/ClusterDialog/types.d.ts +9 -0
- package/dist/shared/components/ClusterDialog/types.js +2 -0
- package/dist/shared/components/SourcesDataGrid.js +47 -40
- package/dist/shared/components/SourcesGridHeader.js +2 -2
- package/dist/shared/getSources.d.ts +15 -0
- package/dist/shared/getSources.js +34 -0
- package/esm/MultiLinearVariantDisplay/model.d.ts +19 -0
- package/esm/MultiLinearVariantMatrixDisplay/model.d.ts +20 -0
- package/esm/MultiLinearVariantMatrixDisplay/model.js +4 -1
- package/esm/MultiLinearVariantMatrixRenderer/makeImageData.js +9 -1
- package/esm/MultiLinearVariantRenderer/makeImageData.js +9 -1
- package/esm/VariantRPC/MultiVariantClusterGenotypeMatrix.d.ts +28 -0
- package/esm/VariantRPC/MultiVariantClusterGenotypeMatrix.js +26 -0
- package/esm/VariantRPC/MultiVariantGetGenotypeMatrix.d.ts +13 -11
- package/esm/VariantRPC/MultiVariantGetGenotypeMatrix.js +5 -57
- package/esm/VariantRPC/MultiVariantGetSimplifiedFeatures.d.ts +11 -8
- package/esm/VariantRPC/MultiVariantGetSimplifiedFeatures.js +1 -2
- package/esm/VariantRPC/cluster.d.ts +17 -0
- package/esm/VariantRPC/cluster.js +79 -0
- package/esm/VariantRPC/getGenotypeMatrix.d.ts +6 -0
- package/esm/VariantRPC/getGenotypeMatrix.js +52 -0
- package/esm/VariantRPC/types.d.ts +13 -0
- package/esm/VariantRPC/types.js +1 -0
- package/esm/VcfAdapter/VcfAdapter.js +7 -4
- package/esm/VcfFeature/util.js +2 -2
- package/esm/VcfTabixAdapter/VcfTabixAdapter.js +11 -6
- package/esm/index.js +2 -0
- package/esm/shared/MultiVariantBaseModel.d.ts +19 -0
- package/esm/shared/MultiVariantBaseModel.js +27 -35
- package/esm/shared/components/ClusterDialog/ClusterDialog.d.ts +6 -0
- package/esm/shared/components/ClusterDialog/ClusterDialog.js +24 -0
- package/esm/shared/components/ClusterDialog/ClusterDialogAuto.d.ts +7 -0
- package/esm/shared/components/ClusterDialog/ClusterDialogAuto.js +67 -0
- package/esm/shared/components/ClusterDialog/ClusterDialogManual.d.ts +7 -0
- package/esm/shared/components/ClusterDialog/ClusterDialogManual.js +139 -0
- package/esm/shared/components/ClusterDialog/types.d.ts +9 -0
- package/esm/shared/components/ClusterDialog/types.js +1 -0
- package/esm/shared/components/SourcesDataGrid.js +47 -40
- package/esm/shared/components/SourcesGridHeader.js +2 -2
- package/esm/shared/getSources.d.ts +15 -0
- package/esm/shared/getSources.js +31 -0
- package/package.json +6 -6
- package/dist/shared/components/ClusterDialog.d.ts +0 -11
- package/dist/shared/components/ClusterDialog.js +0 -113
- package/esm/shared/components/ClusterDialog.d.ts +0 -11
- package/esm/shared/components/ClusterDialog.js +0 -107
|
@@ -258,6 +258,15 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
|
|
|
258
258
|
setSampleInfo(arg: Record<string, import("../shared/types").SampleInfo>): void;
|
|
259
259
|
} & {
|
|
260
260
|
readonly preSources: import("../shared/types").Source[] | undefined;
|
|
261
|
+
readonly sourcesWithoutLayout: {
|
|
262
|
+
label: string;
|
|
263
|
+
id: string;
|
|
264
|
+
baseUri?: string;
|
|
265
|
+
name: string;
|
|
266
|
+
color?: string;
|
|
267
|
+
group?: string;
|
|
268
|
+
HP?: number;
|
|
269
|
+
}[] | undefined;
|
|
261
270
|
readonly sources: {
|
|
262
271
|
label: string;
|
|
263
272
|
id: string;
|
|
@@ -333,10 +342,20 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
|
|
|
333
342
|
type?: undefined;
|
|
334
343
|
checked?: undefined;
|
|
335
344
|
onClick?: undefined;
|
|
345
|
+
} | {
|
|
346
|
+
label: string;
|
|
347
|
+
icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
|
|
348
|
+
muiName: string;
|
|
349
|
+
};
|
|
350
|
+
onClick: () => void;
|
|
351
|
+
type?: undefined;
|
|
352
|
+
checked?: undefined;
|
|
353
|
+
subMenu?: undefined;
|
|
336
354
|
})[];
|
|
337
355
|
} & {
|
|
338
356
|
readonly canDisplayLabels: boolean;
|
|
339
357
|
readonly totalHeight: number;
|
|
358
|
+
readonly featuresReady: boolean;
|
|
340
359
|
} & {
|
|
341
360
|
renderProps(): any;
|
|
342
361
|
} & {
|
|
@@ -344,6 +363,7 @@ export default function stateModelFactory(configSchema: AnyConfigurationSchemaTy
|
|
|
344
363
|
readonly blockType: string;
|
|
345
364
|
readonly totalHeight: number;
|
|
346
365
|
readonly rowHeight: number;
|
|
366
|
+
readonly featuresReady: boolean;
|
|
347
367
|
} & {
|
|
348
368
|
renderProps(): any;
|
|
349
369
|
readonly canDisplayLabels: boolean;
|
|
@@ -26,13 +26,16 @@ export default function stateModelFactory(configSchema) {
|
|
|
26
26
|
? self.totalHeight / this.nrow
|
|
27
27
|
: self.rowHeightSetting;
|
|
28
28
|
},
|
|
29
|
+
get featuresReady() {
|
|
30
|
+
return !!self.featuresVolatile;
|
|
31
|
+
},
|
|
29
32
|
}))
|
|
30
33
|
.views(self => ({
|
|
31
34
|
renderProps() {
|
|
32
35
|
const superProps = self.adapterProps();
|
|
33
36
|
return {
|
|
34
37
|
...superProps,
|
|
35
|
-
notReady: superProps.notReady || !self.sources || !self.
|
|
38
|
+
notReady: superProps.notReady || !self.sources || !self.featuresReady,
|
|
36
39
|
renderingMode: self.renderingMode,
|
|
37
40
|
minorAlleleFrequencyFilter: self.minorAlleleFrequencyFilter,
|
|
38
41
|
height: self.totalHeight,
|
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
import { updateStatus } from '@jbrowse/core/util';
|
|
2
|
+
import { checkStopToken } from '@jbrowse/core/util/stopToken';
|
|
2
3
|
import { f2 } from '../shared/constants';
|
|
3
4
|
import { drawColorAlleleCount } from '../shared/drawAlleleCount';
|
|
4
5
|
import { drawPhased } from '../shared/drawPhased';
|
|
5
6
|
import { getFeaturesThatPassMinorAlleleFrequencyFilter } from '../shared/minorAlleleFrequencyUtils';
|
|
6
7
|
export async function makeImageData({ ctx, canvasWidth, canvasHeight, renderArgs, }) {
|
|
7
|
-
const { renderingMode: renderingMode, minorAlleleFrequencyFilter, sources, features, } = renderArgs;
|
|
8
|
+
const { renderingMode: renderingMode, minorAlleleFrequencyFilter, sources, features, stopToken, } = renderArgs;
|
|
8
9
|
const { statusCallback = () => { } } = renderArgs;
|
|
9
10
|
const h = canvasHeight / sources.length;
|
|
11
|
+
checkStopToken(stopToken);
|
|
10
12
|
const mafs = getFeaturesThatPassMinorAlleleFrequencyFilter(features.values(), minorAlleleFrequencyFilter);
|
|
13
|
+
checkStopToken(stopToken);
|
|
11
14
|
const arr = [];
|
|
12
15
|
const m = mafs.length;
|
|
13
16
|
const w = canvasWidth / m;
|
|
14
17
|
await updateStatus('Drawing variant matrix', statusCallback, () => {
|
|
15
18
|
var _a, _b, _c;
|
|
19
|
+
let start = performance.now();
|
|
16
20
|
for (let i = 0; i < m; i++) {
|
|
21
|
+
if (performance.now() - start > 400) {
|
|
22
|
+
checkStopToken(stopToken);
|
|
23
|
+
start = performance.now();
|
|
24
|
+
}
|
|
17
25
|
const arr2 = [];
|
|
18
26
|
const { feature, mostFrequentAlt } = mafs[i];
|
|
19
27
|
const hasPhaseSet = (_a = feature.get('FORMAT')) === null || _a === void 0 ? void 0 : _a.includes('PS');
|
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import { featureSpanPx } from '@jbrowse/core/util';
|
|
2
|
+
import { checkStopToken } from '@jbrowse/core/util/stopToken';
|
|
2
3
|
import RBush from 'rbush';
|
|
3
4
|
import { f2 } from '../shared/constants';
|
|
4
5
|
import { drawColorAlleleCount } from '../shared/drawAlleleCount';
|
|
5
6
|
import { drawPhased } from '../shared/drawPhased';
|
|
6
7
|
import { getFeaturesThatPassMinorAlleleFrequencyFilter } from '../shared/minorAlleleFrequencyUtils';
|
|
7
8
|
export async function makeImageData(ctx, props) {
|
|
8
|
-
const { scrollTop, minorAlleleFrequencyFilter, sources, rowHeight, features, regions, bpPerPx, renderingMode, } = props;
|
|
9
|
+
const { scrollTop, minorAlleleFrequencyFilter, sources, rowHeight, features, regions, bpPerPx, renderingMode, stopToken, } = props;
|
|
9
10
|
const region = regions[0];
|
|
11
|
+
checkStopToken(stopToken);
|
|
10
12
|
const mafs = getFeaturesThatPassMinorAlleleFrequencyFilter(features.values(), minorAlleleFrequencyFilter);
|
|
13
|
+
checkStopToken(stopToken);
|
|
11
14
|
const rbush = new RBush();
|
|
15
|
+
let start = performance.now();
|
|
12
16
|
for (const { mostFrequentAlt, feature } of mafs) {
|
|
17
|
+
if (performance.now() - start > 400) {
|
|
18
|
+
checkStopToken(stopToken);
|
|
19
|
+
start = performance.now();
|
|
20
|
+
}
|
|
13
21
|
const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx);
|
|
14
22
|
const w = Math.max(Math.round(rightPx - leftPx), 2);
|
|
15
23
|
const samp = feature.get('genotypes');
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import RpcMethodTypeWithFiltersAndRenameRegions from '@jbrowse/core/pluggableElementTypes/RpcMethodTypeWithFiltersAndRenameRegions';
|
|
2
|
+
import type { Source } from '../shared/types';
|
|
3
|
+
import type { AnyConfigurationModel } from '@jbrowse/core/configuration';
|
|
4
|
+
import type { Region } from '@jbrowse/core/util';
|
|
5
|
+
interface Args {
|
|
6
|
+
adapterConfig: AnyConfigurationModel;
|
|
7
|
+
stopToken?: string;
|
|
8
|
+
statusCallback: (arg: string) => void;
|
|
9
|
+
sessionId: string;
|
|
10
|
+
headers?: Record<string, string>;
|
|
11
|
+
regions: Region[];
|
|
12
|
+
bpPerPx: number;
|
|
13
|
+
sources: Source[];
|
|
14
|
+
minorAlleleFrequencyFilter: number;
|
|
15
|
+
}
|
|
16
|
+
export declare class MultiVariantClusterGenotypeMatrix extends RpcMethodTypeWithFiltersAndRenameRegions {
|
|
17
|
+
name: string;
|
|
18
|
+
execute(args: Args, rpcDriverClassName: string): Promise<{
|
|
19
|
+
clusters: {
|
|
20
|
+
height: number;
|
|
21
|
+
indexes: number[];
|
|
22
|
+
} | undefined;
|
|
23
|
+
distances: number[][];
|
|
24
|
+
order: number[];
|
|
25
|
+
clustersGivenK: number[][][];
|
|
26
|
+
}>;
|
|
27
|
+
}
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import RpcMethodTypeWithFiltersAndRenameRegions from '@jbrowse/core/pluggableElementTypes/RpcMethodTypeWithFiltersAndRenameRegions';
|
|
2
|
+
import { clusterData } from './cluster';
|
|
3
|
+
import { getGenotypeMatrix } from './getGenotypeMatrix';
|
|
4
|
+
export class MultiVariantClusterGenotypeMatrix extends RpcMethodTypeWithFiltersAndRenameRegions {
|
|
5
|
+
constructor() {
|
|
6
|
+
super(...arguments);
|
|
7
|
+
this.name = 'MultiVariantClusterGenotypeMatrix';
|
|
8
|
+
}
|
|
9
|
+
async execute(args, rpcDriverClassName) {
|
|
10
|
+
const deserializedArgs = await this.deserializeArguments(args, rpcDriverClassName);
|
|
11
|
+
const matrix = await getGenotypeMatrix({
|
|
12
|
+
pluginManager: this.pluginManager,
|
|
13
|
+
args: deserializedArgs,
|
|
14
|
+
});
|
|
15
|
+
return clusterData({
|
|
16
|
+
data: Object.values(matrix),
|
|
17
|
+
onProgress: a => {
|
|
18
|
+
deserializedArgs.statusCallback(`${toP(a * 100)}%`);
|
|
19
|
+
},
|
|
20
|
+
stopToken: deserializedArgs.stopToken,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function toP(n) {
|
|
25
|
+
return Number.parseFloat(n.toPrecision(3));
|
|
26
|
+
}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import RpcMethodTypeWithFiltersAndRenameRegions from '@jbrowse/core/pluggableElementTypes/RpcMethodTypeWithFiltersAndRenameRegions';
|
|
2
|
+
import type { Source } from '../shared/types';
|
|
2
3
|
import type { AnyConfigurationModel } from '@jbrowse/core/configuration';
|
|
3
4
|
import type { Region } from '@jbrowse/core/util';
|
|
5
|
+
interface Args {
|
|
6
|
+
adapterConfig: AnyConfigurationModel;
|
|
7
|
+
stopToken?: string;
|
|
8
|
+
sessionId: string;
|
|
9
|
+
headers?: Record<string, string>;
|
|
10
|
+
regions: Region[];
|
|
11
|
+
bpPerPx: number;
|
|
12
|
+
sources: Source[];
|
|
13
|
+
minorAlleleFrequencyFilter: number;
|
|
14
|
+
}
|
|
4
15
|
export declare class MultiVariantGetGenotypeMatrix extends RpcMethodTypeWithFiltersAndRenameRegions {
|
|
5
16
|
name: string;
|
|
6
|
-
execute(args:
|
|
7
|
-
adapterConfig: AnyConfigurationModel;
|
|
8
|
-
stopToken?: string;
|
|
9
|
-
sessionId: string;
|
|
10
|
-
headers?: Record<string, string>;
|
|
11
|
-
regions: Region[];
|
|
12
|
-
bpPerPx: number;
|
|
13
|
-
}, rpcDriverClassName: string): Promise<Record<string, {
|
|
14
|
-
name: string;
|
|
15
|
-
genotypes: string[];
|
|
16
|
-
}>>;
|
|
17
|
+
execute(args: Args, rpcDriverClassName: string): Promise<Record<string, number[]>>;
|
|
17
18
|
}
|
|
19
|
+
export {};
|
|
@@ -1,66 +1,14 @@
|
|
|
1
|
-
import { getAdapter } from '@jbrowse/core/data_adapters/dataAdapterCache';
|
|
2
1
|
import RpcMethodTypeWithFiltersAndRenameRegions from '@jbrowse/core/pluggableElementTypes/RpcMethodTypeWithFiltersAndRenameRegions';
|
|
3
|
-
import {
|
|
4
|
-
import { getFeaturesThatPassMinorAlleleFrequencyFilter } from '../shared/minorAlleleFrequencyUtils';
|
|
2
|
+
import { getGenotypeMatrix } from './getGenotypeMatrix';
|
|
5
3
|
export class MultiVariantGetGenotypeMatrix extends RpcMethodTypeWithFiltersAndRenameRegions {
|
|
6
4
|
constructor() {
|
|
7
5
|
super(...arguments);
|
|
8
6
|
this.name = 'MultiVariantGetGenotypeMatrix';
|
|
9
7
|
}
|
|
10
8
|
async execute(args, rpcDriverClassName) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const dataAdapter = adapter.dataAdapter;
|
|
16
|
-
const feats = await firstValueFrom(dataAdapter
|
|
17
|
-
.getFeaturesInMultipleRegions(regions, deserializedArgs)
|
|
18
|
-
.pipe(toArray()));
|
|
19
|
-
const genotypeFactor = new Set();
|
|
20
|
-
const mafs = getFeaturesThatPassMinorAlleleFrequencyFilter(feats, minorAlleleFrequencyFilter);
|
|
21
|
-
for (const { alleleCounts } of mafs) {
|
|
22
|
-
for (const alt of alleleCounts.keys()) {
|
|
23
|
-
genotypeFactor.add(alt);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
const rows = {};
|
|
27
|
-
for (const { feature } of mafs) {
|
|
28
|
-
const genotypes = feature.get('genotypes');
|
|
29
|
-
for (const { name } of sources) {
|
|
30
|
-
if (!rows[name]) {
|
|
31
|
-
rows[name] = {
|
|
32
|
-
name,
|
|
33
|
-
genotypes: [],
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
const val = genotypes[name];
|
|
37
|
-
const alleles = val.split(/[/|]/);
|
|
38
|
-
let genotypeStatus = '0';
|
|
39
|
-
let nonRefCount = 0;
|
|
40
|
-
let uncalledCount = 0;
|
|
41
|
-
for (const l of alleles) {
|
|
42
|
-
if (l === '.') {
|
|
43
|
-
uncalledCount++;
|
|
44
|
-
}
|
|
45
|
-
else if (l !== '0') {
|
|
46
|
-
nonRefCount++;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
if (uncalledCount === alleles.length) {
|
|
50
|
-
genotypeStatus = '-1';
|
|
51
|
-
}
|
|
52
|
-
else if (nonRefCount === 0) {
|
|
53
|
-
genotypeStatus = '0';
|
|
54
|
-
}
|
|
55
|
-
else if (nonRefCount === alleles.length) {
|
|
56
|
-
genotypeStatus = '2';
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
genotypeStatus = '1';
|
|
60
|
-
}
|
|
61
|
-
rows[name].genotypes.push(genotypeStatus);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
return rows;
|
|
9
|
+
return getGenotypeMatrix({
|
|
10
|
+
pluginManager: this.pluginManager,
|
|
11
|
+
args: await this.deserializeArguments(args, rpcDriverClassName),
|
|
12
|
+
});
|
|
65
13
|
}
|
|
66
14
|
}
|
|
@@ -2,16 +2,18 @@ import RpcMethodTypeWithFiltersAndRenameRegions from '@jbrowse/core/pluggableEle
|
|
|
2
2
|
import type { SampleInfo } from '../shared/types';
|
|
3
3
|
import type { AnyConfigurationModel } from '@jbrowse/core/configuration';
|
|
4
4
|
import type { Region } from '@jbrowse/core/util';
|
|
5
|
+
interface Args {
|
|
6
|
+
adapterConfig: AnyConfigurationModel;
|
|
7
|
+
stopToken?: string;
|
|
8
|
+
sessionId: string;
|
|
9
|
+
headers?: Record<string, string>;
|
|
10
|
+
regions: Region[];
|
|
11
|
+
bpPerPx: number;
|
|
12
|
+
minorAlleleFrequencyFilter: number;
|
|
13
|
+
}
|
|
5
14
|
export declare class MultiVariantGetSimplifiedFeatures extends RpcMethodTypeWithFiltersAndRenameRegions {
|
|
6
15
|
name: string;
|
|
7
|
-
execute(args: {
|
|
8
|
-
adapterConfig: AnyConfigurationModel;
|
|
9
|
-
stopToken?: string;
|
|
10
|
-
sessionId: string;
|
|
11
|
-
headers?: Record<string, string>;
|
|
12
|
-
regions: Region[];
|
|
13
|
-
bpPerPx: number;
|
|
14
|
-
}, rpcDriverClassName: string): Promise<{
|
|
16
|
+
execute(args: Args, rpcDriverClassName: string): Promise<{
|
|
15
17
|
hasPhased: boolean;
|
|
16
18
|
sampleInfo: Record<string, SampleInfo>;
|
|
17
19
|
features: {
|
|
@@ -24,3 +26,4 @@ export declare class MultiVariantGetSimplifiedFeatures extends RpcMethodTypeWith
|
|
|
24
26
|
}[];
|
|
25
27
|
}>;
|
|
26
28
|
}
|
|
29
|
+
export {};
|
|
@@ -9,10 +9,9 @@ export class MultiVariantGetSimplifiedFeatures extends RpcMethodTypeWithFiltersA
|
|
|
9
9
|
}
|
|
10
10
|
async execute(args, rpcDriverClassName) {
|
|
11
11
|
var _a, _b;
|
|
12
|
-
const pm = this.pluginManager;
|
|
13
12
|
const deserializedArgs = await this.deserializeArguments(args, rpcDriverClassName);
|
|
14
13
|
const { minorAlleleFrequencyFilter, regions, adapterConfig, sessionId } = deserializedArgs;
|
|
15
|
-
const { dataAdapter } = await getAdapter(
|
|
14
|
+
const { dataAdapter } = await getAdapter(this.pluginManager, sessionId, adapterConfig);
|
|
16
15
|
const feats = await firstValueFrom(dataAdapter
|
|
17
16
|
.getFeaturesInMultipleRegions(regions, deserializedArgs)
|
|
18
17
|
.pipe(toArray()));
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare function euclideanDistance(a: number[], b: number[]): number;
|
|
2
|
+
export declare function averageDistance(setA: number[], setB: number[], distances: number[][]): number;
|
|
3
|
+
export declare function clusterData({ data, distance, linkage, onProgress, stopToken, }: {
|
|
4
|
+
data: number[][];
|
|
5
|
+
distance?: (a: number[], b: number[]) => number;
|
|
6
|
+
linkage?: (a: number[], b: number[], distances: number[][]) => number;
|
|
7
|
+
onProgress?: (a: number) => void;
|
|
8
|
+
stopToken?: string;
|
|
9
|
+
}): {
|
|
10
|
+
clusters: {
|
|
11
|
+
height: number;
|
|
12
|
+
indexes: number[];
|
|
13
|
+
} | undefined;
|
|
14
|
+
distances: number[][];
|
|
15
|
+
order: number[];
|
|
16
|
+
clustersGivenK: number[][][];
|
|
17
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { checkStopToken } from '@jbrowse/core/util/stopToken';
|
|
2
|
+
export function euclideanDistance(a, b) {
|
|
3
|
+
const size = Math.min(a.length, b.length);
|
|
4
|
+
let sum = 0;
|
|
5
|
+
for (let index = 0; index < size; index++) {
|
|
6
|
+
sum += (a[index] - b[index]) * (a[index] - b[index]);
|
|
7
|
+
}
|
|
8
|
+
return Math.sqrt(sum);
|
|
9
|
+
}
|
|
10
|
+
export function averageDistance(setA, setB, distances) {
|
|
11
|
+
let distance = 0;
|
|
12
|
+
for (const a of setA) {
|
|
13
|
+
for (const b of setB) {
|
|
14
|
+
distance += distances[a][b];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return distance / setA.length / setB.length;
|
|
18
|
+
}
|
|
19
|
+
function updateProgress(stepNumber, stepProgress, onProgress) {
|
|
20
|
+
onProgress(stepNumber / 2 + stepProgress / 2);
|
|
21
|
+
}
|
|
22
|
+
export function clusterData({ data, distance = euclideanDistance, linkage = averageDistance, onProgress, stopToken, }) {
|
|
23
|
+
const distances = data.map((datum, index) => {
|
|
24
|
+
if (onProgress) {
|
|
25
|
+
updateProgress(0, index / (data.length - 1), onProgress);
|
|
26
|
+
}
|
|
27
|
+
return data.map(otherDatum => distance(datum, otherDatum));
|
|
28
|
+
});
|
|
29
|
+
const clusters = data.map((_datum, index) => ({
|
|
30
|
+
height: 0,
|
|
31
|
+
indexes: [Number(index)],
|
|
32
|
+
}));
|
|
33
|
+
let clustersGivenK = [];
|
|
34
|
+
let start = performance.now();
|
|
35
|
+
for (let iteration = 0; iteration < data.length; iteration++) {
|
|
36
|
+
if (performance.now() - start > 2000) {
|
|
37
|
+
checkStopToken(stopToken);
|
|
38
|
+
start = performance.now();
|
|
39
|
+
}
|
|
40
|
+
if (onProgress) {
|
|
41
|
+
updateProgress(1, (iteration + 1) / data.length, onProgress);
|
|
42
|
+
}
|
|
43
|
+
clustersGivenK.push(clusters.map(cluster => cluster.indexes));
|
|
44
|
+
if (iteration >= data.length - 1) {
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
let nearestDistance = Infinity;
|
|
48
|
+
let nearestRow = 0;
|
|
49
|
+
let nearestCol = 0;
|
|
50
|
+
for (let row = 0; row < clusters.length; row++) {
|
|
51
|
+
for (let col = row + 1; col < clusters.length; col++) {
|
|
52
|
+
const distance = linkage(clusters[row].indexes, clusters[col].indexes, distances);
|
|
53
|
+
if (distance < nearestDistance) {
|
|
54
|
+
nearestDistance = distance;
|
|
55
|
+
nearestRow = row;
|
|
56
|
+
nearestCol = col;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const newCluster = {
|
|
61
|
+
indexes: [
|
|
62
|
+
...clusters[nearestRow].indexes,
|
|
63
|
+
...clusters[nearestCol].indexes,
|
|
64
|
+
],
|
|
65
|
+
height: nearestDistance,
|
|
66
|
+
children: [clusters[nearestRow], clusters[nearestCol]],
|
|
67
|
+
};
|
|
68
|
+
clusters.splice(Math.max(nearestRow, nearestCol), 1);
|
|
69
|
+
clusters.splice(Math.min(nearestRow, nearestCol), 1);
|
|
70
|
+
clusters.push(newCluster);
|
|
71
|
+
}
|
|
72
|
+
clustersGivenK = [[], ...clustersGivenK.reverse()];
|
|
73
|
+
return {
|
|
74
|
+
clusters: clusters[0],
|
|
75
|
+
distances: distances,
|
|
76
|
+
order: clusters[0].indexes,
|
|
77
|
+
clustersGivenK: clustersGivenK,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { GetGenotypeMatrixArgs } from './types';
|
|
2
|
+
import type PluginManager from '@jbrowse/core/PluginManager';
|
|
3
|
+
export declare function getGenotypeMatrix({ pluginManager, args, }: {
|
|
4
|
+
pluginManager: PluginManager;
|
|
5
|
+
args: GetGenotypeMatrixArgs;
|
|
6
|
+
}): Promise<Record<string, number[]>>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { getAdapter } from '@jbrowse/core/data_adapters/dataAdapterCache';
|
|
2
|
+
import { firstValueFrom, toArray } from 'rxjs';
|
|
3
|
+
import { getFeaturesThatPassMinorAlleleFrequencyFilter } from '../shared/minorAlleleFrequencyUtils';
|
|
4
|
+
export async function getGenotypeMatrix({ pluginManager, args, }) {
|
|
5
|
+
const { sources, minorAlleleFrequencyFilter, regions, adapterConfig, sessionId, } = args;
|
|
6
|
+
const adapter = await getAdapter(pluginManager, sessionId, adapterConfig);
|
|
7
|
+
const dataAdapter = adapter.dataAdapter;
|
|
8
|
+
const feats = await firstValueFrom(dataAdapter.getFeaturesInMultipleRegions(regions, args).pipe(toArray()));
|
|
9
|
+
const genotypeFactor = new Set();
|
|
10
|
+
const mafs = getFeaturesThatPassMinorAlleleFrequencyFilter(feats, minorAlleleFrequencyFilter);
|
|
11
|
+
for (const { alleleCounts } of mafs) {
|
|
12
|
+
for (const alt of alleleCounts.keys()) {
|
|
13
|
+
genotypeFactor.add(alt);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
const rows = {};
|
|
17
|
+
for (const { feature } of mafs) {
|
|
18
|
+
const genotypes = feature.get('genotypes');
|
|
19
|
+
for (const { name } of sources) {
|
|
20
|
+
if (!rows[name]) {
|
|
21
|
+
rows[name] = [];
|
|
22
|
+
}
|
|
23
|
+
const val = genotypes[name];
|
|
24
|
+
const alleles = val.split(/[/|]/);
|
|
25
|
+
let genotypeStatus = 0;
|
|
26
|
+
let nonRefCount = 0;
|
|
27
|
+
let uncalledCount = 0;
|
|
28
|
+
for (const l of alleles) {
|
|
29
|
+
if (l === '.') {
|
|
30
|
+
uncalledCount++;
|
|
31
|
+
}
|
|
32
|
+
else if (l !== '0') {
|
|
33
|
+
nonRefCount++;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (uncalledCount === alleles.length) {
|
|
37
|
+
genotypeStatus = -1;
|
|
38
|
+
}
|
|
39
|
+
else if (nonRefCount === 0) {
|
|
40
|
+
genotypeStatus = 0;
|
|
41
|
+
}
|
|
42
|
+
else if (nonRefCount === alleles.length) {
|
|
43
|
+
genotypeStatus = 2;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
genotypeStatus = 1;
|
|
47
|
+
}
|
|
48
|
+
rows[name].push(genotypeStatus);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return rows;
|
|
52
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Source } from '../shared/types';
|
|
2
|
+
import type { AnyConfigurationModel } from '@jbrowse/core/configuration';
|
|
3
|
+
import type { Region } from '@jbrowse/core/util';
|
|
4
|
+
export interface GetGenotypeMatrixArgs {
|
|
5
|
+
sources: Source[];
|
|
6
|
+
minorAlleleFrequencyFilter: number;
|
|
7
|
+
adapterConfig: AnyConfigurationModel;
|
|
8
|
+
stopToken?: string;
|
|
9
|
+
sessionId: string;
|
|
10
|
+
headers?: Record<string, string>;
|
|
11
|
+
regions: Region[];
|
|
12
|
+
bpPerPx: number;
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import IntervalTree from '@flatten-js/interval-tree';
|
|
2
2
|
import VcfParser from '@gmod/vcf';
|
|
3
3
|
import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter';
|
|
4
|
-
import { fetchAndMaybeUnzip } from '@jbrowse/core/util';
|
|
4
|
+
import { fetchAndMaybeUnzip, getProgressDisplayStr } from '@jbrowse/core/util';
|
|
5
5
|
import { openLocation } from '@jbrowse/core/util/io';
|
|
6
6
|
import { ObservableCreate } from '@jbrowse/core/util/rxjs';
|
|
7
7
|
import VcfFeature from '../VcfFeature';
|
|
@@ -45,7 +45,7 @@ class VcfAdapter extends BaseFeatureDataAdapter {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
if (i++ % 10000 === 0) {
|
|
48
|
-
statusCallback(`Loading ${
|
|
48
|
+
statusCallback(`Loading ${getProgressDisplayStr(blockStart, buffer.length)}`);
|
|
49
49
|
}
|
|
50
50
|
blockStart = n + 1;
|
|
51
51
|
}
|
|
@@ -96,9 +96,12 @@ class VcfAdapter extends BaseFeatureDataAdapter {
|
|
|
96
96
|
try {
|
|
97
97
|
const { start, end, refName } = region;
|
|
98
98
|
const { intervalTreeMap } = await this.setup();
|
|
99
|
-
(_a = intervalTreeMap[refName]) === null || _a === void 0 ? void 0 : _a.call(intervalTreeMap, opts.statusCallback).search([
|
|
99
|
+
for (const f of ((_a = intervalTreeMap[refName]) === null || _a === void 0 ? void 0 : _a.call(intervalTreeMap, opts.statusCallback).search([
|
|
100
|
+
start,
|
|
101
|
+
end,
|
|
102
|
+
])) || []) {
|
|
100
103
|
observer.next(f);
|
|
101
|
-
}
|
|
104
|
+
}
|
|
102
105
|
observer.complete();
|
|
103
106
|
}
|
|
104
107
|
catch (e) {
|
package/esm/VcfFeature/util.js
CHANGED
|
@@ -17,7 +17,7 @@ export function getSOTermAndDescription(ref, alt, parser) {
|
|
|
17
17
|
}
|
|
18
18
|
const soTerms = new Set();
|
|
19
19
|
let descriptions = new Set();
|
|
20
|
-
|
|
20
|
+
for (const a of alt) {
|
|
21
21
|
let [soTerm, description] = getSOAndDescFromAltDefs(a, parser);
|
|
22
22
|
if (!soTerm) {
|
|
23
23
|
;
|
|
@@ -27,7 +27,7 @@ export function getSOTermAndDescription(ref, alt, parser) {
|
|
|
27
27
|
soTerms.add(soTerm);
|
|
28
28
|
descriptions.add(description);
|
|
29
29
|
}
|
|
30
|
-
}
|
|
30
|
+
}
|
|
31
31
|
if (descriptions.size > 1) {
|
|
32
32
|
const descs = [...descriptions];
|
|
33
33
|
const prefixes = new Set(descs
|
|
@@ -86,16 +86,21 @@ export default class VcfTabixAdapter extends BaseFeatureDataAdapter {
|
|
|
86
86
|
const header = lines[0].split('\t');
|
|
87
87
|
const { parser } = await this.configure();
|
|
88
88
|
const s = new Set(parser.samples);
|
|
89
|
-
|
|
89
|
+
const ret = lines
|
|
90
90
|
.slice(1)
|
|
91
|
+
.filter(f => !!f)
|
|
91
92
|
.map(line => {
|
|
92
|
-
const
|
|
93
|
+
const [name, ...rest] = line.split('\t');
|
|
93
94
|
return {
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
...Object.fromEntries(rest.map((c, idx) => [header[idx + 1], c])),
|
|
96
|
+
name: name,
|
|
96
97
|
};
|
|
97
|
-
})
|
|
98
|
-
|
|
98
|
+
});
|
|
99
|
+
const missing = ret.filter(f => !s.has(f.name));
|
|
100
|
+
if (missing.length) {
|
|
101
|
+
console.warn('Samples in metadata file not in VCF:', ret.filter(f => !s.has(f.name)));
|
|
102
|
+
}
|
|
103
|
+
return ret.filter(f => s.has(f.name));
|
|
99
104
|
}
|
|
100
105
|
}
|
|
101
106
|
freeResources() { }
|
package/esm/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import MultiVariantRendererF from './MultiLinearVariantRenderer';
|
|
|
8
8
|
import SplitVcfTabixAdapterF from './SplitVcfTabixAdapter';
|
|
9
9
|
import StructuralVariantChordRendererF from './StructuralVariantChordRenderer';
|
|
10
10
|
import VariantFeatureWidgetF from './VariantFeatureWidget';
|
|
11
|
+
import { MultiVariantClusterGenotypeMatrix } from './VariantRPC/MultiVariantClusterGenotypeMatrix';
|
|
11
12
|
import { MultiVariantGetGenotypeMatrix } from './VariantRPC/MultiVariantGetGenotypeMatrix';
|
|
12
13
|
import { MultiVariantGetSimplifiedFeatures } from './VariantRPC/MultiVariantGetSimplifiedFeatures';
|
|
13
14
|
import { MultiVariantGetSources } from './VariantRPC/MultiVariantGetSources';
|
|
@@ -36,6 +37,7 @@ export default class VariantsPlugin extends Plugin {
|
|
|
36
37
|
ChordVariantDisplayF(pluginManager);
|
|
37
38
|
pluginManager.addRpcMethod(() => new MultiVariantGetSources(pluginManager));
|
|
38
39
|
pluginManager.addRpcMethod(() => new MultiVariantGetGenotypeMatrix(pluginManager));
|
|
40
|
+
pluginManager.addRpcMethod(() => new MultiVariantClusterGenotypeMatrix(pluginManager));
|
|
39
41
|
pluginManager.addRpcMethod(() => new MultiVariantGetSimplifiedFeatures(pluginManager));
|
|
40
42
|
}
|
|
41
43
|
}
|
|
@@ -255,6 +255,15 @@ export default function MultiVariantBaseModelF(configSchema: AnyConfigurationSch
|
|
|
255
255
|
setSampleInfo(arg: Record<string, SampleInfo>): void;
|
|
256
256
|
} & {
|
|
257
257
|
readonly preSources: Source[] | undefined;
|
|
258
|
+
readonly sourcesWithoutLayout: {
|
|
259
|
+
label: string;
|
|
260
|
+
id: string;
|
|
261
|
+
baseUri?: string;
|
|
262
|
+
name: string;
|
|
263
|
+
color?: string;
|
|
264
|
+
group?: string;
|
|
265
|
+
HP?: number;
|
|
266
|
+
}[] | undefined;
|
|
258
267
|
readonly sources: {
|
|
259
268
|
label: string;
|
|
260
269
|
id: string;
|
|
@@ -330,10 +339,20 @@ export default function MultiVariantBaseModelF(configSchema: AnyConfigurationSch
|
|
|
330
339
|
type?: undefined;
|
|
331
340
|
checked?: undefined;
|
|
332
341
|
onClick?: undefined;
|
|
342
|
+
} | {
|
|
343
|
+
label: string;
|
|
344
|
+
icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
|
|
345
|
+
muiName: string;
|
|
346
|
+
};
|
|
347
|
+
onClick: () => void;
|
|
348
|
+
type?: undefined;
|
|
349
|
+
checked?: undefined;
|
|
350
|
+
subMenu?: undefined;
|
|
333
351
|
})[];
|
|
334
352
|
} & {
|
|
335
353
|
readonly canDisplayLabels: boolean;
|
|
336
354
|
readonly totalHeight: number;
|
|
355
|
+
readonly featuresReady: boolean;
|
|
337
356
|
} & {
|
|
338
357
|
renderProps(): any;
|
|
339
358
|
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
|