@jbrowse/plugin-variants 3.0.4 → 3.1.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.
@@ -14,7 +14,7 @@ const useStyles = (0, mui_1.makeStyles)()({
14
14
  },
15
15
  cursor: {
16
16
  pointerEvents: 'none',
17
- zIndex: 1000,
17
+ zIndex: 800,
18
18
  position: 'absolute',
19
19
  },
20
20
  color: {
@@ -11,7 +11,7 @@ const MultiVariantTooltip_1 = __importDefault(require("../../shared/components/M
11
11
  const useStyles = (0, mui_1.makeStyles)()({
12
12
  cursor: {
13
13
  pointerEvents: 'none',
14
- zIndex: 1000,
14
+ zIndex: 800,
15
15
  position: 'relative',
16
16
  },
17
17
  });
@@ -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
  }>;
@@ -12,6 +12,6 @@ export declare class MultiVariantGetGenotypeMatrix extends RpcMethodTypeWithFilt
12
12
  bpPerPx: number;
13
13
  }, rpcDriverClassName: string): Promise<Record<string, {
14
14
  name: string;
15
- genotypes: number[];
15
+ genotypes: string[];
16
16
  }>>;
17
17
  }
@@ -19,21 +19,19 @@ class MultiVariantGetGenotypeMatrix extends RpcMethodTypeWithFiltersAndRenameReg
19
19
  const { sources, minorAlleleFrequencyFilter, regions, adapterConfig, sessionId, } = deserializedArgs;
20
20
  const adapter = await (0, dataAdapterCache_1.getAdapter)(pm, sessionId, adapterConfig);
21
21
  const dataAdapter = adapter.dataAdapter;
22
- const region = regions[0];
23
- const feats = await (0, rxjs_1.firstValueFrom)(dataAdapter.getFeatures(region, deserializedArgs).pipe((0, rxjs_1.toArray)()));
22
+ const feats = await (0, rxjs_1.firstValueFrom)(dataAdapter
23
+ .getFeaturesInMultipleRegions(regions, deserializedArgs)
24
+ .pipe((0, rxjs_1.toArray)()));
24
25
  const genotypeFactor = new Set();
25
26
  const mafs = (0, minorAlleleFrequencyUtils_1.getFeaturesThatPassMinorAlleleFrequencyFilter)(feats, minorAlleleFrequencyFilter);
26
- for (const feat of feats) {
27
- const samp = feat.get('genotypes');
28
- for (const { name } of sources) {
29
- const s = samp[name];
30
- genotypeFactor.add(s);
27
+ for (const { alleleCounts } of mafs) {
28
+ for (const alt of alleleCounts.keys()) {
29
+ genotypeFactor.add(alt);
31
30
  }
32
31
  }
33
- const genotypeFactorMap = Object.fromEntries([...genotypeFactor].map((type, idx) => [type, idx]));
34
32
  const rows = {};
35
33
  for (const { feature } of mafs) {
36
- const samp = feature.get('genotypes');
34
+ const genotypes = feature.get('genotypes');
37
35
  for (const { name } of sources) {
38
36
  if (!rows[name]) {
39
37
  rows[name] = {
@@ -41,7 +39,32 @@ class MultiVariantGetGenotypeMatrix extends RpcMethodTypeWithFiltersAndRenameReg
41
39
  genotypes: [],
42
40
  };
43
41
  }
44
- rows[name].genotypes.push(genotypeFactorMap[samp[name]]);
42
+ const val = genotypes[name];
43
+ const alleles = val.split(/[/|]/);
44
+ let genotypeStatus = '0';
45
+ let nonRefCount = 0;
46
+ let uncalledCount = 0;
47
+ for (const l of alleles) {
48
+ if (l === '.') {
49
+ uncalledCount++;
50
+ }
51
+ else if (l !== '0') {
52
+ nonRefCount++;
53
+ }
54
+ }
55
+ if (uncalledCount === alleles.length) {
56
+ genotypeStatus = '-1';
57
+ }
58
+ else if (nonRefCount === 0) {
59
+ genotypeStatus = '0';
60
+ }
61
+ else if (nonRefCount === alleles.length) {
62
+ genotypeStatus = '2';
63
+ }
64
+ else {
65
+ genotypeStatus = '1';
66
+ }
67
+ rows[name].genotypes.push(genotypeStatus);
45
68
  }
46
69
  }
47
70
  return rows;
@@ -18,5 +18,18 @@ const VcfAdapter = (0, configuration_1.ConfigurationSchema)('VcfAdapter', {
18
18
  locationType: 'UriLocation',
19
19
  },
20
20
  },
21
- }, { explicitlyTyped: true });
21
+ }, {
22
+ explicitlyTyped: true,
23
+ preProcessSnapshot: snap => {
24
+ return snap.uri
25
+ ? {
26
+ ...snap,
27
+ vcfLocation: {
28
+ uri: snap.uri,
29
+ baseUri: snap.baseUri,
30
+ },
31
+ }
32
+ : snap;
33
+ },
34
+ });
22
35
  exports.default = VcfAdapter;
@@ -6,7 +6,10 @@ function x() { }
6
6
  const VcfTabixAdapter = (0, configuration_1.ConfigurationSchema)('VcfTabixAdapter', {
7
7
  vcfGzLocation: {
8
8
  type: 'fileLocation',
9
- defaultValue: { uri: '/path/to/my.vcf.gz', locationType: 'UriLocation' },
9
+ defaultValue: {
10
+ uri: '/path/to/my.vcf.gz',
11
+ locationType: 'UriLocation',
12
+ },
10
13
  },
11
14
  index: (0, configuration_1.ConfigurationSchema)('VcfIndex', {
12
15
  indexType: {
@@ -30,5 +33,24 @@ const VcfTabixAdapter = (0, configuration_1.ConfigurationSchema)('VcfTabixAdapte
30
33
  locationType: 'UriLocation',
31
34
  },
32
35
  },
33
- }, { explicitlyTyped: true });
36
+ }, {
37
+ explicitlyTyped: true,
38
+ preProcessSnapshot: snap => {
39
+ return snap.uri
40
+ ? {
41
+ ...snap,
42
+ vcfGzLocation: {
43
+ uri: snap.uri,
44
+ baseUri: snap.baseUri,
45
+ },
46
+ index: {
47
+ location: {
48
+ uri: `${snap.uri}.tbi`,
49
+ baseUri: snap.baseUri,
50
+ },
51
+ },
52
+ }
53
+ : snap;
54
+ },
55
+ });
34
56
  exports.default = VcfTabixAdapter;
@@ -29,6 +29,7 @@ function ClusterDialog({ model, handleClose, }) {
29
29
  const [results, setResults] = (0, react_1.useState)();
30
30
  const [error, setError] = (0, react_1.useState)();
31
31
  const [paste, setPaste] = (0, react_1.useState)('');
32
+ const [useCompleteMethod, setUseCompleteMethod] = (0, react_1.useState)(false);
32
33
  (0, react_1.useEffect)(() => {
33
34
  ;
34
35
  (async () => {
@@ -50,11 +51,12 @@ function ClusterDialog({ model, handleClose, }) {
50
51
  }));
51
52
  const entries = Object.values(ret);
52
53
  const keys = Object.keys(ret);
54
+ const clusterMethod = useCompleteMethod ? 'complete' : 'single';
53
55
  const text = `try(library(fastcluster), silent=TRUE)
54
56
  inputMatrix<-matrix(c(${entries.map(val => val.genotypes.join(',')).join(',\n')}
55
57
  ),nrow=${entries.length},byrow=TRUE)
56
58
  rownames(inputMatrix)<-c(${keys.map(key => `'${key}'`).join(',')})
57
- resultClusters<-hclust(dist(inputMatrix), method='single')
59
+ resultClusters<-hclust(dist(inputMatrix), method='${clusterMethod}')
58
60
  cat(resultClusters$order,sep='\\n')`;
59
61
  setResults(text);
60
62
  }
@@ -65,14 +67,16 @@ cat(resultClusters$order,sep='\\n')`;
65
67
  }
66
68
  }
67
69
  })();
68
- }, [model]);
70
+ }, [model, useCompleteMethod]);
69
71
  return ((0, jsx_runtime_1.jsxs)(ui_1.Dialog, { open: true, title: "Cluster by genotype", onClose: handleClose, children: [(0, jsx_runtime_1.jsx)(material_1.DialogContent, { children: (0, jsx_runtime_1.jsxs)("div", { className: classes.mgap, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { children: "This page will produce an R script that will perform hierarchical clustering on the visible genotype data using `hclust`." }), (0, jsx_runtime_1.jsx)(material_1.Typography, { children: "You can then paste the results in this form to specify the row ordering." }), results ? ((0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsxs)("div", { children: ["Step 1:", ' ', (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", onClick: () => {
70
72
  (0, file_saver_1.saveAs)(new Blob([results || ''], {
71
73
  type: 'text/plain;charset=utf-8',
72
74
  }), 'cluster.R');
73
75
  }, children: "Download Rscript" }), ' ', "or", ' ', (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", onClick: () => {
74
76
  (0, copy_to_clipboard_1.default)(results || '');
75
- }, children: "Copy Rscript to clipboard" }), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(material_1.TextField, { multiline: true, fullWidth: true, variant: "outlined", placeholder: "Step 2. Paste results from Rscript here (sequence of numbers, one per line, specifying the new ordering)", rows: 10, value: paste, onChange: event => {
77
+ }, children: "Copy Rscript to clipboard" }), (0, jsx_runtime_1.jsx)(material_1.FormControlLabel, { control: (0, jsx_runtime_1.jsx)(material_1.Checkbox, { checked: useCompleteMethod, onChange: e => {
78
+ setUseCompleteMethod(e.target.checked);
79
+ } }), label: "Use 'complete' linkage method instead of 'single'" }), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(material_1.TextField, { multiline: true, fullWidth: true, variant: "outlined", placeholder: "Step 2. Paste results from Rscript here (sequence of numbers, one per line, specifying the new ordering)", rows: 10, value: paste, onChange: event => {
76
80
  setPaste(event.target.value);
77
81
  }, slotProps: {
78
82
  input: {
@@ -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: {
@@ -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
  });
@@ -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
  }>;
@@ -12,6 +12,6 @@ export declare class MultiVariantGetGenotypeMatrix extends RpcMethodTypeWithFilt
12
12
  bpPerPx: number;
13
13
  }, rpcDriverClassName: string): Promise<Record<string, {
14
14
  name: string;
15
- genotypes: number[];
15
+ genotypes: string[];
16
16
  }>>;
17
17
  }
@@ -13,21 +13,19 @@ export class MultiVariantGetGenotypeMatrix extends RpcMethodTypeWithFiltersAndRe
13
13
  const { sources, minorAlleleFrequencyFilter, regions, adapterConfig, sessionId, } = deserializedArgs;
14
14
  const adapter = await getAdapter(pm, sessionId, adapterConfig);
15
15
  const dataAdapter = adapter.dataAdapter;
16
- const region = regions[0];
17
- const feats = await firstValueFrom(dataAdapter.getFeatures(region, deserializedArgs).pipe(toArray()));
16
+ const feats = await firstValueFrom(dataAdapter
17
+ .getFeaturesInMultipleRegions(regions, deserializedArgs)
18
+ .pipe(toArray()));
18
19
  const genotypeFactor = new Set();
19
20
  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);
21
+ for (const { alleleCounts } of mafs) {
22
+ for (const alt of alleleCounts.keys()) {
23
+ genotypeFactor.add(alt);
25
24
  }
26
25
  }
27
- const genotypeFactorMap = Object.fromEntries([...genotypeFactor].map((type, idx) => [type, idx]));
28
26
  const rows = {};
29
27
  for (const { feature } of mafs) {
30
- const samp = feature.get('genotypes');
28
+ const genotypes = feature.get('genotypes');
31
29
  for (const { name } of sources) {
32
30
  if (!rows[name]) {
33
31
  rows[name] = {
@@ -35,7 +33,32 @@ export class MultiVariantGetGenotypeMatrix extends RpcMethodTypeWithFiltersAndRe
35
33
  genotypes: [],
36
34
  };
37
35
  }
38
- rows[name].genotypes.push(genotypeFactorMap[samp[name]]);
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);
39
62
  }
40
63
  }
41
64
  return rows;
@@ -16,5 +16,18 @@ const VcfAdapter = ConfigurationSchema('VcfAdapter', {
16
16
  locationType: 'UriLocation',
17
17
  },
18
18
  },
19
- }, { explicitlyTyped: true });
19
+ }, {
20
+ explicitlyTyped: true,
21
+ preProcessSnapshot: snap => {
22
+ return snap.uri
23
+ ? {
24
+ ...snap,
25
+ vcfLocation: {
26
+ uri: snap.uri,
27
+ baseUri: snap.baseUri,
28
+ },
29
+ }
30
+ : snap;
31
+ },
32
+ });
20
33
  export default VcfAdapter;
@@ -4,7 +4,10 @@ function x() { }
4
4
  const VcfTabixAdapter = ConfigurationSchema('VcfTabixAdapter', {
5
5
  vcfGzLocation: {
6
6
  type: 'fileLocation',
7
- defaultValue: { uri: '/path/to/my.vcf.gz', locationType: 'UriLocation' },
7
+ defaultValue: {
8
+ uri: '/path/to/my.vcf.gz',
9
+ locationType: 'UriLocation',
10
+ },
8
11
  },
9
12
  index: ConfigurationSchema('VcfIndex', {
10
13
  indexType: {
@@ -28,5 +31,24 @@ const VcfTabixAdapter = ConfigurationSchema('VcfTabixAdapter', {
28
31
  locationType: 'UriLocation',
29
32
  },
30
33
  },
31
- }, { explicitlyTyped: true });
34
+ }, {
35
+ explicitlyTyped: true,
36
+ preProcessSnapshot: snap => {
37
+ return snap.uri
38
+ ? {
39
+ ...snap,
40
+ vcfGzLocation: {
41
+ uri: snap.uri,
42
+ baseUri: snap.baseUri,
43
+ },
44
+ index: {
45
+ location: {
46
+ uri: `${snap.uri}.tbi`,
47
+ baseUri: snap.baseUri,
48
+ },
49
+ },
50
+ }
51
+ : snap;
52
+ },
53
+ });
32
54
  export default VcfTabixAdapter;
@@ -3,7 +3,7 @@ import { useEffect, useState } from 'react';
3
3
  import { Dialog, ErrorMessage, LoadingEllipses } from '@jbrowse/core/ui';
4
4
  import { getContainingView, getSession, isAbortException, } from '@jbrowse/core/util';
5
5
  import { getRpcSessionId } from '@jbrowse/core/util/tracks';
6
- import { Button, DialogActions, DialogContent, TextField, Typography, } from '@mui/material';
6
+ import { Button, Checkbox, DialogActions, DialogContent, FormControlLabel, TextField, Typography, } from '@mui/material';
7
7
  import copy from 'copy-to-clipboard';
8
8
  import { saveAs } from 'file-saver';
9
9
  import { isAlive } from 'mobx-state-tree';
@@ -23,6 +23,7 @@ export default function ClusterDialog({ model, handleClose, }) {
23
23
  const [results, setResults] = useState();
24
24
  const [error, setError] = useState();
25
25
  const [paste, setPaste] = useState('');
26
+ const [useCompleteMethod, setUseCompleteMethod] = useState(false);
26
27
  useEffect(() => {
27
28
  ;
28
29
  (async () => {
@@ -44,11 +45,12 @@ export default function ClusterDialog({ model, handleClose, }) {
44
45
  }));
45
46
  const entries = Object.values(ret);
46
47
  const keys = Object.keys(ret);
48
+ const clusterMethod = useCompleteMethod ? 'complete' : 'single';
47
49
  const text = `try(library(fastcluster), silent=TRUE)
48
50
  inputMatrix<-matrix(c(${entries.map(val => val.genotypes.join(',')).join(',\n')}
49
51
  ),nrow=${entries.length},byrow=TRUE)
50
52
  rownames(inputMatrix)<-c(${keys.map(key => `'${key}'`).join(',')})
51
- resultClusters<-hclust(dist(inputMatrix), method='single')
53
+ resultClusters<-hclust(dist(inputMatrix), method='${clusterMethod}')
52
54
  cat(resultClusters$order,sep='\\n')`;
53
55
  setResults(text);
54
56
  }
@@ -59,14 +61,16 @@ cat(resultClusters$order,sep='\\n')`;
59
61
  }
60
62
  }
61
63
  })();
62
- }, [model]);
64
+ }, [model, useCompleteMethod]);
63
65
  return (_jsxs(Dialog, { open: true, title: "Cluster by genotype", onClose: handleClose, children: [_jsx(DialogContent, { children: _jsxs("div", { className: classes.mgap, children: [_jsx(Typography, { children: "This page will produce an R script that will perform hierarchical clustering on the visible genotype data using `hclust`." }), _jsx(Typography, { children: "You can then paste the results in this form to specify the row ordering." }), results ? (_jsx("div", { children: _jsxs("div", { children: ["Step 1:", ' ', _jsx(Button, { variant: "contained", onClick: () => {
64
66
  saveAs(new Blob([results || ''], {
65
67
  type: 'text/plain;charset=utf-8',
66
68
  }), 'cluster.R');
67
69
  }, children: "Download Rscript" }), ' ', "or", ' ', _jsx(Button, { variant: "contained", onClick: () => {
68
70
  copy(results || '');
69
- }, children: "Copy Rscript to clipboard" }), _jsx("div", { children: _jsx(TextField, { multiline: true, fullWidth: true, variant: "outlined", placeholder: "Step 2. Paste results from Rscript here (sequence of numbers, one per line, specifying the new ordering)", rows: 10, value: paste, onChange: event => {
71
+ }, children: "Copy Rscript to clipboard" }), _jsx(FormControlLabel, { control: _jsx(Checkbox, { checked: useCompleteMethod, onChange: e => {
72
+ setUseCompleteMethod(e.target.checked);
73
+ } }), label: "Use 'complete' linkage method instead of 'single'" }), _jsx("div", { children: _jsx(TextField, { multiline: true, fullWidth: true, variant: "outlined", placeholder: "Step 2. Paste results from Rscript here (sequence of numbers, one per line, specifying the new ordering)", rows: 10, value: paste, onChange: event => {
70
74
  setPaste(event.target.value);
71
75
  }, slotProps: {
72
76
  input: {
@@ -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
  }[];
@@ -22,6 +22,13 @@ export function calculateAlleleCounts(feat) {
22
22
  alleleCounts.set(allele, (alleleCounts.get(allele) || 0) + 1);
23
23
  }
24
24
  }
25
+ return alleleCounts;
26
+ }
27
+ export function calculateMinorAlleleFrequency(alleleCounts) {
28
+ return (findSecondLargestNumber(alleleCounts.values()) /
29
+ (sum(alleleCounts.values()) || 1));
30
+ }
31
+ function getMostFrequentAlt(alleleCounts) {
25
32
  let mostFrequentAlt;
26
33
  let max = 0;
27
34
  for (const [alt, altCount] of alleleCounts.entries()) {
@@ -32,22 +39,20 @@ export function calculateAlleleCounts(feat) {
32
39
  }
33
40
  }
34
41
  }
35
- return { alleleCounts, mostFrequentAlt };
36
- }
37
- export function calculateMinorAlleleFrequency(alleleCounts) {
38
- return (findSecondLargestNumber(alleleCounts.values()) /
39
- (sum(alleleCounts.values()) || 1));
42
+ return mostFrequentAlt;
40
43
  }
41
- export function getFeaturesThatPassMinorAlleleFrequencyFilter(feats, minorAlleleFrequencyFilter) {
44
+ export function getFeaturesThatPassMinorAlleleFrequencyFilter(feats, minorAlleleFrequencyFilter, lengthCutoffFilter = 10) {
42
45
  const results = [];
43
46
  for (const feature of feats) {
44
- if (feature.get('end') - feature.get('start') <= 10) {
45
- const { mostFrequentAlt, alleleCounts } = calculateAlleleCounts(feature);
47
+ if (feature.get('end') - feature.get('start') <= lengthCutoffFilter) {
48
+ const alleleCounts = calculateAlleleCounts(feature);
46
49
  if (calculateMinorAlleleFrequency(alleleCounts) >=
47
50
  minorAlleleFrequencyFilter) {
51
+ const mostFrequentAlt = getMostFrequentAlt(alleleCounts);
48
52
  results.push({
49
53
  feature,
50
54
  mostFrequentAlt,
55
+ alleleCounts,
51
56
  });
52
57
  }
53
58
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-variants",
3
- "version": "3.0.4",
3
+ "version": "3.1.0",
4
4
  "description": "JBrowse 2 variant adapters, tracks, etc.",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -40,10 +40,10 @@
40
40
  "@gmod/bgzf-filehandle": "^2.0.1",
41
41
  "@gmod/tabix": "^2.0.0",
42
42
  "@gmod/vcf": "^6.0.8",
43
- "@jbrowse/core": "^3.0.4",
44
- "@jbrowse/plugin-circular-view": "^3.0.4",
45
- "@jbrowse/plugin-linear-genome-view": "^3.0.4",
46
- "@jbrowse/sv-core": "^3.0.4",
43
+ "@jbrowse/core": "^3.1.0",
44
+ "@jbrowse/plugin-circular-view": "^3.1.0",
45
+ "@jbrowse/plugin-linear-genome-view": "^3.1.0",
46
+ "@jbrowse/sv-core": "^3.1.0",
47
47
  "@mui/icons-material": "^6.0.0",
48
48
  "@mui/material": "^6.0.0",
49
49
  "@mui/x-data-grid": "^7.0.0",
@@ -62,5 +62,5 @@
62
62
  "distModule": "esm/index.js",
63
63
  "srcModule": "src/index.ts",
64
64
  "module": "esm/index.js",
65
- "gitHead": "61e6d26f83acbf58a946c2add3415bc46b878df9"
65
+ "gitHead": "91492049ddea0aed90eb24d3c066c2d9f5a6b189"
66
66
  }