@jbrowse/plugin-variants 3.0.5 → 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.
Files changed (89) hide show
  1. package/dist/MultiLinearVariantDisplay/components/Crosshair.js +1 -1
  2. package/dist/MultiLinearVariantDisplay/model.d.ts +19 -0
  3. package/dist/MultiLinearVariantMatrixDisplay/components/Crosshair.js +1 -1
  4. package/dist/MultiLinearVariantMatrixDisplay/model.d.ts +20 -0
  5. package/dist/MultiLinearVariantMatrixDisplay/model.js +4 -1
  6. package/dist/MultiLinearVariantMatrixRenderer/makeImageData.d.ts +1 -0
  7. package/dist/MultiLinearVariantMatrixRenderer/makeImageData.js +9 -1
  8. package/dist/MultiLinearVariantRenderer/makeImageData.js +9 -1
  9. package/dist/VariantRPC/MultiVariantClusterGenotypeMatrix.d.ts +28 -0
  10. package/dist/VariantRPC/MultiVariantClusterGenotypeMatrix.js +33 -0
  11. package/dist/VariantRPC/MultiVariantGetGenotypeMatrix.d.ts +13 -11
  12. package/dist/VariantRPC/MultiVariantGetGenotypeMatrix.js +5 -34
  13. package/dist/VariantRPC/MultiVariantGetSimplifiedFeatures.d.ts +11 -8
  14. package/dist/VariantRPC/MultiVariantGetSimplifiedFeatures.js +1 -2
  15. package/dist/VariantRPC/cluster.d.ts +17 -0
  16. package/dist/VariantRPC/cluster.js +84 -0
  17. package/dist/VariantRPC/getGenotypeMatrix.d.ts +6 -0
  18. package/dist/VariantRPC/getGenotypeMatrix.js +55 -0
  19. package/dist/VariantRPC/types.d.ts +13 -0
  20. package/dist/VariantRPC/types.js +2 -0
  21. package/dist/VcfAdapter/VcfAdapter.js +6 -3
  22. package/dist/VcfAdapter/configSchema.js +14 -1
  23. package/dist/VcfFeature/util.js +2 -2
  24. package/dist/VcfTabixAdapter/VcfTabixAdapter.js +11 -6
  25. package/dist/VcfTabixAdapter/configSchema.js +24 -2
  26. package/dist/index.js +2 -0
  27. package/dist/shared/MultiVariantBaseModel.d.ts +19 -0
  28. package/dist/shared/MultiVariantBaseModel.js +27 -35
  29. package/dist/shared/components/ClusterDialog/ClusterDialog.d.ts +6 -0
  30. package/dist/shared/components/ClusterDialog/ClusterDialog.js +29 -0
  31. package/dist/shared/components/ClusterDialog/ClusterDialogAuto.d.ts +7 -0
  32. package/dist/shared/components/ClusterDialog/ClusterDialogAuto.js +69 -0
  33. package/dist/shared/components/ClusterDialog/ClusterDialogManual.d.ts +7 -0
  34. package/dist/shared/components/ClusterDialog/ClusterDialogManual.js +144 -0
  35. package/dist/shared/components/ClusterDialog/types.d.ts +9 -0
  36. package/dist/shared/components/ClusterDialog/types.js +2 -0
  37. package/dist/shared/components/SourcesDataGrid.js +47 -40
  38. package/dist/shared/components/SourcesGridHeader.js +2 -2
  39. package/dist/shared/getSources.d.ts +15 -0
  40. package/dist/shared/getSources.js +34 -0
  41. package/dist/shared/minorAlleleFrequencyUtils.d.ts +3 -5
  42. package/dist/shared/minorAlleleFrequencyUtils.js +13 -8
  43. package/esm/MultiLinearVariantDisplay/components/Crosshair.js +1 -1
  44. package/esm/MultiLinearVariantDisplay/model.d.ts +19 -0
  45. package/esm/MultiLinearVariantMatrixDisplay/components/Crosshair.js +1 -1
  46. package/esm/MultiLinearVariantMatrixDisplay/model.d.ts +20 -0
  47. package/esm/MultiLinearVariantMatrixDisplay/model.js +4 -1
  48. package/esm/MultiLinearVariantMatrixRenderer/makeImageData.d.ts +1 -0
  49. package/esm/MultiLinearVariantMatrixRenderer/makeImageData.js +9 -1
  50. package/esm/MultiLinearVariantRenderer/makeImageData.js +9 -1
  51. package/esm/VariantRPC/MultiVariantClusterGenotypeMatrix.d.ts +28 -0
  52. package/esm/VariantRPC/MultiVariantClusterGenotypeMatrix.js +26 -0
  53. package/esm/VariantRPC/MultiVariantGetGenotypeMatrix.d.ts +13 -11
  54. package/esm/VariantRPC/MultiVariantGetGenotypeMatrix.js +5 -34
  55. package/esm/VariantRPC/MultiVariantGetSimplifiedFeatures.d.ts +11 -8
  56. package/esm/VariantRPC/MultiVariantGetSimplifiedFeatures.js +1 -2
  57. package/esm/VariantRPC/cluster.d.ts +17 -0
  58. package/esm/VariantRPC/cluster.js +79 -0
  59. package/esm/VariantRPC/getGenotypeMatrix.d.ts +6 -0
  60. package/esm/VariantRPC/getGenotypeMatrix.js +52 -0
  61. package/esm/VariantRPC/types.d.ts +13 -0
  62. package/esm/VariantRPC/types.js +1 -0
  63. package/esm/VcfAdapter/VcfAdapter.js +7 -4
  64. package/esm/VcfAdapter/configSchema.js +14 -1
  65. package/esm/VcfFeature/util.js +2 -2
  66. package/esm/VcfTabixAdapter/VcfTabixAdapter.js +11 -6
  67. package/esm/VcfTabixAdapter/configSchema.js +24 -2
  68. package/esm/index.js +2 -0
  69. package/esm/shared/MultiVariantBaseModel.d.ts +19 -0
  70. package/esm/shared/MultiVariantBaseModel.js +27 -35
  71. package/esm/shared/components/ClusterDialog/ClusterDialog.d.ts +6 -0
  72. package/esm/shared/components/ClusterDialog/ClusterDialog.js +24 -0
  73. package/esm/shared/components/ClusterDialog/ClusterDialogAuto.d.ts +7 -0
  74. package/esm/shared/components/ClusterDialog/ClusterDialogAuto.js +67 -0
  75. package/esm/shared/components/ClusterDialog/ClusterDialogManual.d.ts +7 -0
  76. package/esm/shared/components/ClusterDialog/ClusterDialogManual.js +139 -0
  77. package/esm/shared/components/ClusterDialog/types.d.ts +9 -0
  78. package/esm/shared/components/ClusterDialog/types.js +1 -0
  79. package/esm/shared/components/SourcesDataGrid.js +47 -40
  80. package/esm/shared/components/SourcesGridHeader.js +2 -2
  81. package/esm/shared/getSources.d.ts +15 -0
  82. package/esm/shared/getSources.js +31 -0
  83. package/esm/shared/minorAlleleFrequencyUtils.d.ts +3 -5
  84. package/esm/shared/minorAlleleFrequencyUtils.js +13 -8
  85. package/package.json +6 -6
  86. package/dist/shared/components/ClusterDialog.d.ts +0 -11
  87. package/dist/shared/components/ClusterDialog.js +0 -109
  88. package/esm/shared/components/ClusterDialog.d.ts +0 -11
  89. package/esm/shared/components/ClusterDialog.js +0 -103
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSources = getSources;
4
+ function getSources({ sources, layout = sources, renderingMode, sampleInfo, }) {
5
+ const rows = [];
6
+ const sourceMap = Object.fromEntries(sources.map(s => [s.name, s]));
7
+ for (const row of layout) {
8
+ if (renderingMode === 'phased') {
9
+ const info = sampleInfo === null || sampleInfo === void 0 ? void 0 : sampleInfo[row.name];
10
+ if (info === null || info === void 0 ? void 0 : info.isPhased) {
11
+ const ploidy = info.maxPloidy;
12
+ for (let i = 0; i < ploidy; i++) {
13
+ const id = `${row.name} HP${i}`;
14
+ rows.push({
15
+ ...sourceMap[row.name],
16
+ ...row,
17
+ label: id,
18
+ HP: i,
19
+ id: id,
20
+ });
21
+ }
22
+ }
23
+ }
24
+ else {
25
+ rows.push({
26
+ ...sourceMap[row.name],
27
+ ...row,
28
+ label: row.name,
29
+ id: row.name,
30
+ });
31
+ }
32
+ }
33
+ return rows;
34
+ }
@@ -1,11 +1,9 @@
1
1
  import type { Feature } from '@jbrowse/core/util';
2
2
  export declare function findSecondLargestNumber(arr: Iterable<number>): number;
3
- export declare function calculateAlleleCounts(feat: Feature): {
4
- alleleCounts: Map<any, any>;
5
- mostFrequentAlt: any;
6
- };
3
+ export declare function calculateAlleleCounts(feat: Feature): Map<any, any>;
7
4
  export declare function calculateMinorAlleleFrequency(alleleCounts: Map<string, number>): number;
8
- export declare function getFeaturesThatPassMinorAlleleFrequencyFilter(feats: Iterable<Feature>, minorAlleleFrequencyFilter: number): {
5
+ export declare function getFeaturesThatPassMinorAlleleFrequencyFilter(feats: Iterable<Feature>, minorAlleleFrequencyFilter: number, lengthCutoffFilter?: number): {
9
6
  feature: Feature;
10
7
  mostFrequentAlt: string;
8
+ alleleCounts: Map<string, number>;
11
9
  }[];
@@ -28,6 +28,13 @@ function calculateAlleleCounts(feat) {
28
28
  alleleCounts.set(allele, (alleleCounts.get(allele) || 0) + 1);
29
29
  }
30
30
  }
31
+ return alleleCounts;
32
+ }
33
+ function calculateMinorAlleleFrequency(alleleCounts) {
34
+ return (findSecondLargestNumber(alleleCounts.values()) /
35
+ ((0, util_1.sum)(alleleCounts.values()) || 1));
36
+ }
37
+ function getMostFrequentAlt(alleleCounts) {
31
38
  let mostFrequentAlt;
32
39
  let max = 0;
33
40
  for (const [alt, altCount] of alleleCounts.entries()) {
@@ -38,22 +45,20 @@ function calculateAlleleCounts(feat) {
38
45
  }
39
46
  }
40
47
  }
41
- return { alleleCounts, mostFrequentAlt };
42
- }
43
- function calculateMinorAlleleFrequency(alleleCounts) {
44
- return (findSecondLargestNumber(alleleCounts.values()) /
45
- ((0, util_1.sum)(alleleCounts.values()) || 1));
48
+ return mostFrequentAlt;
46
49
  }
47
- function getFeaturesThatPassMinorAlleleFrequencyFilter(feats, minorAlleleFrequencyFilter) {
50
+ function getFeaturesThatPassMinorAlleleFrequencyFilter(feats, minorAlleleFrequencyFilter, lengthCutoffFilter = 10) {
48
51
  const results = [];
49
52
  for (const feature of feats) {
50
- if (feature.get('end') - feature.get('start') <= 10) {
51
- const { mostFrequentAlt, alleleCounts } = calculateAlleleCounts(feature);
53
+ if (feature.get('end') - feature.get('start') <= lengthCutoffFilter) {
54
+ const alleleCounts = calculateAlleleCounts(feature);
52
55
  if (calculateMinorAlleleFrequency(alleleCounts) >=
53
56
  minorAlleleFrequencyFilter) {
57
+ const mostFrequentAlt = getMostFrequentAlt(alleleCounts);
54
58
  results.push({
55
59
  feature,
56
60
  mostFrequentAlt,
61
+ alleleCounts,
57
62
  });
58
63
  }
59
64
  }
@@ -9,7 +9,7 @@ const useStyles = makeStyles()({
9
9
  },
10
10
  cursor: {
11
11
  pointerEvents: 'none',
12
- zIndex: 1000,
12
+ zIndex: 800,
13
13
  position: 'absolute',
14
14
  },
15
15
  color: {
@@ -259,6 +259,15 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
259
259
  setSampleInfo(arg: Record<string, import("../shared/types").SampleInfo>): void;
260
260
  } & {
261
261
  readonly preSources: import("../shared/types").Source[] | undefined;
262
+ readonly sourcesWithoutLayout: {
263
+ label: string;
264
+ id: string;
265
+ baseUri?: string;
266
+ name: string;
267
+ color?: string;
268
+ group?: string;
269
+ HP?: number;
270
+ }[] | undefined;
262
271
  readonly sources: {
263
272
  label: string;
264
273
  id: string;
@@ -334,10 +343,20 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
334
343
  type?: undefined;
335
344
  checked?: undefined;
336
345
  onClick?: undefined;
346
+ } | {
347
+ label: string;
348
+ icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
349
+ muiName: string;
350
+ };
351
+ onClick: () => void;
352
+ type?: undefined;
353
+ checked?: undefined;
354
+ subMenu?: undefined;
337
355
  })[];
338
356
  } & {
339
357
  readonly canDisplayLabels: boolean;
340
358
  readonly totalHeight: number;
359
+ readonly featuresReady: boolean;
341
360
  } & {
342
361
  renderProps(): any;
343
362
  } & {
@@ -6,7 +6,7 @@ import MultiVariantTooltip from '../../shared/components/MultiVariantTooltip';
6
6
  const useStyles = makeStyles()({
7
7
  cursor: {
8
8
  pointerEvents: 'none',
9
- zIndex: 1000,
9
+ zIndex: 800,
10
10
  position: 'relative',
11
11
  },
12
12
  });
@@ -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.featuresVolatile,
38
+ notReady: superProps.notReady || !self.sources || !self.featuresReady,
36
39
  renderingMode: self.renderingMode,
37
40
  minorAlleleFrequencyFilter: self.minorAlleleFrequencyFilter,
38
41
  height: self.totalHeight,
@@ -8,6 +8,7 @@ export declare function makeImageData({ ctx, canvasWidth, canvasHeight, renderAr
8
8
  mafs: {
9
9
  feature: import("@jbrowse/core/util").Feature;
10
10
  mostFrequentAlt: string;
11
+ alleleCounts: Map<string, number>;
11
12
  }[];
12
13
  arr: string[][];
13
14
  }>;
@@ -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: number[];
16
- }>>;
17
+ execute(args: Args, rpcDriverClassName: string): Promise<Record<string, number[]>>;
17
18
  }
19
+ export {};
@@ -1,43 +1,14 @@
1
- import { getAdapter } from '@jbrowse/core/data_adapters/dataAdapterCache';
2
1
  import RpcMethodTypeWithFiltersAndRenameRegions from '@jbrowse/core/pluggableElementTypes/RpcMethodTypeWithFiltersAndRenameRegions';
3
- import { firstValueFrom, toArray } from 'rxjs';
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
- const pm = this.pluginManager;
12
- const deserializedArgs = await this.deserializeArguments(args, rpcDriverClassName);
13
- const { sources, minorAlleleFrequencyFilter, regions, adapterConfig, sessionId, } = deserializedArgs;
14
- const adapter = await getAdapter(pm, sessionId, adapterConfig);
15
- const dataAdapter = adapter.dataAdapter;
16
- const region = regions[0];
17
- const feats = await firstValueFrom(dataAdapter.getFeatures(region, deserializedArgs).pipe(toArray()));
18
- const genotypeFactor = new Set();
19
- const mafs = getFeaturesThatPassMinorAlleleFrequencyFilter(feats, minorAlleleFrequencyFilter);
20
- for (const feat of feats) {
21
- const samp = feat.get('genotypes');
22
- for (const { name } of sources) {
23
- const s = samp[name];
24
- genotypeFactor.add(s);
25
- }
26
- }
27
- const genotypeFactorMap = Object.fromEntries([...genotypeFactor].map((type, idx) => [type, idx]));
28
- const rows = {};
29
- for (const { feature } of mafs) {
30
- const samp = feature.get('genotypes');
31
- for (const { name } of sources) {
32
- if (!rows[name]) {
33
- rows[name] = {
34
- name,
35
- genotypes: [],
36
- };
37
- }
38
- rows[name].genotypes.push(genotypeFactorMap[samp[name]]);
39
- }
40
- }
41
- return rows;
9
+ return getGenotypeMatrix({
10
+ pluginManager: this.pluginManager,
11
+ args: await this.deserializeArguments(args, rpcDriverClassName),
12
+ });
42
13
  }
43
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(pm, sessionId, adapterConfig);
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 {};