Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,495 changes: 1,458 additions & 1,037 deletions jbrowse/package-lock.json

Large diffs are not rendered by default.

53 changes: 27 additions & 26 deletions jbrowse/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,44 +14,45 @@
"jb-pkg": "npm run prepareCli && npx pkg --outdir=./resources/external/jb-cli ./buildCli/node_modules/@jbrowse/cli && rimraf ./buildCli"
},
"dependencies": {
"@gmod/vcf": "^5.0.10",
"@jbrowse/core": "^2.15.0",
"@jbrowse/plugin-linear-genome-view": "^2.15.0",
"@jbrowse/plugin-svg": "^2.15.0",
"@jbrowse/plugin-variants": "^2.15.0",
"@jbrowse/react-linear-genome-view": "^2.15.0",
"@labkey/api": "^1.35.0",
"@labkey/components": "^5.0.0",
"@mui/x-data-grid": "^7.0.0",
"@yao-pkg/pkg": "^5.12.0",
"assert": "^2.0.0",
"@gmod/vcf": "^6.0.9",
"@jbrowse/core": "^3.2.0",
"@jbrowse/product-core": "^3.2.0",
"@jbrowse/plugin-linear-genome-view": "^3.2.0",
"@jbrowse/plugin-svg": "^3.2.0",
"@jbrowse/plugin-variants": "^3.2.0",
"@jbrowse/react-linear-genome-view2": "^3.2.0",
"@labkey/api": "^1.39.0",
"@labkey/components": "^6.32.2",
"@mui/x-data-grid": "^7.28.1",
"@yao-pkg/pkg": "^6.3.2",
"assert": "^2.1.0",
"browserify-zlib": "^0.2.0",
"buffer": "^6.0.3",
"child_process": "^1.0.2",
"fs": "^0.0.1-security",
"jquery": "^3.7.0",
"jspdf": "^2.5.1",
"jspdf-autotable": "^3.5.31",
"node-polyfill-webpack-plugin": "2.0.1",
"jquery": "^3.7.1",
"jspdf": "^3.0.0",
"jspdf-autotable": "^5.0.2",
"node-polyfill-webpack-plugin": "4.1.0",
"path-browserify": "^1.0.1",
"react": "^18.0.0",
"react": "^18.3.0",
"react-data-grid": "7.0.0-beta.46",
"react-dom": "^18.0.0",
"react-google-charts": "^4.0.1",
"react-select": "^5.8.0",
"regenerator-runtime": "^0.13.11",
"react-dom": "^18.3.0",
"react-google-charts": "^5.2.1",
"react-select": "^5.10.1",
"regenerator-runtime": "^0.14.1",
"stream-browserify": "^3.0.0",
"util": "^0.12.5",
"uuid": "^9.0.0",
"uuid": "^11.1.0",
"vm-browserify": "^1.1.2"
},
"devDependencies": {
"@labkey/build": "^8.3.0",
"@types/jexl": "^2.3.1",
"@types/jquery": "^3.0.0",
"@labkey/build": "^8.4.0",
"@types/jexl": "^2.3.4",
"@types/jquery": "^3.5.32",
"@types/node": "^20.14.11",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"@types/react": "^18.3.0",
"@types/react-dom": "^18.3.0",
"rimraf": "^6.0.1",
"typescript": "^5.1.6"
}
Expand Down
2 changes: 1 addition & 1 deletion jbrowse/src/client/JBrowse/Browser/Browser.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react';

import { JBrowseLinearGenomeView, ViewModel } from '@jbrowse/react-linear-genome-view';
import { JBrowseLinearGenomeView, ViewModel } from '@jbrowse/react-linear-genome-view2'
import { createTheme } from '@mui/material/styles';
import LogSession from './plugins/LogSession/index';
import ExtendedVariantPlugin from './plugins/ExtendedVariantPlugin/index';
Expand Down
8 changes: 3 additions & 5 deletions jbrowse/src/client/JBrowse/Browser/app.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';

import View from './Browser';
import { createRoot } from 'react-dom/client';
import React from 'react';

// Need to wait for container element to be available in labkey wrapper before render
window.addEventListener('DOMContentLoaded', (event) => {
ReactDOM.render(<View />, document.getElementById('app'))
createRoot(document.getElementById('app')).render(<View />)
});
13 changes: 5 additions & 8 deletions jbrowse/src/client/JBrowse/Browser/dev.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';

import View from './Browser';
import { createRoot } from 'react-dom/client';
import React from 'react';

const render = () => {
ReactDOM.render(<View />, document.getElementById('app'));
};

render();
window.addEventListener('DOMContentLoaded', (event) => {
createRoot(document.getElementById('app')).render(<View />)
}, true);
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default class extends VcfTabixAdapter {
observer.next(v)
})
observer.complete()
}, opts.signal)
}, opts.stopToken)
}

private async getFeaturesAsArray(query: NoAssemblyRegion, opts: BaseOptions = {}) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,14 @@
import { VcfFeature } from '@jbrowse/plugin-variants'
import VcfParser from '@gmod/vcf'
import VcfParser, { Variant } from '@gmod/vcf';

export default class ExtendedVcfFeature extends VcfFeature {
private readonly vcfParser: VcfParser

constructor(args: { variant: any; parser: VcfParser; id: string }) {
constructor(args: { variant: Variant; parser: VcfParser; id: string }) {
args.variant = ExtendedVcfFeature.extractImpact(args.variant)
//args.variant = ExtendedVcfFeature.calculateVariableSamples(args.variant)

super(args)

this.vcfParser = args.parser
}

public getInfoFieldMeta(propKey: string): VcfParser {
const map = this.vcfParser.getMetadata("INFO")

return map ? map[propKey] : null
}

static extractImpact(variant: {
REF: string
POS: number
ALT: string[]
CHROM: string
INFO: any
ID: string[]
}) {
static extractImpact(variant: Variant) {
// Only append if not present:
if (variant.INFO["IMPACT"]) {
return(variant);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,86 +1,158 @@
import { TabixIndexedFile } from '@gmod/tabix'
import VcfParser from '@gmod/vcf'
import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter'
import {
BaseFeatureDataAdapter,
BaseOptions,
} from '@jbrowse/core/data_adapters/BaseAdapter'
import { NoAssemblyRegion } from '@jbrowse/core/util/types'
fetchAndMaybeUnzipText,
updateStatus,
} from '@jbrowse/core/util'
import { openLocation } from '@jbrowse/core/util/io'
import { ObservableCreate } from '@jbrowse/core/util/rxjs'
import { Feature } from '@jbrowse/core/util'
import { TabixIndexedFile } from '@gmod/tabix'
import VcfParser from '@gmod/vcf'

import type { BaseOptions } from '@jbrowse/core/data_adapters/BaseAdapter'
import type { Feature } from '@jbrowse/core/util'
import type { NoAssemblyRegion } from '@jbrowse/core/util/types'
import { VcfFeature } from '@jbrowse/plugin-variants';

function shorten2(name: string, max = 70) {
return name.length > max ? `${name.slice(0, max)}...` : name
}

export default class VcfTabixAdapter extends BaseFeatureDataAdapter {
private configured?: Promise<{
vcf: TabixIndexedFile
parser: VcfParser
}>

private async configurePre() {
const pm = this.pluginManager
private async configurePre(_opts?: BaseOptions) {
const vcfGzLocation = this.getConf('vcfGzLocation')
const location = this.getConf(['index', 'location'])
const indexType = this.getConf(['index', 'indexType'])

const filehandle = openLocation(vcfGzLocation, pm)
const filehandle = openLocation(vcfGzLocation, this.pluginManager)
const isCSI = indexType === 'CSI'
const vcf = new TabixIndexedFile({
filehandle,
csiFilehandle: isCSI ? openLocation(location, pm) : undefined,
tbiFilehandle: !isCSI ? openLocation(location, pm) : undefined,
chunkCacheSize: 50 * 2 ** 20
csiFilehandle: isCSI
? openLocation(location, this.pluginManager)
: undefined,
tbiFilehandle: !isCSI
? openLocation(location, this.pluginManager)
: undefined,
chunkCacheSize: 50 * 2 ** 20,
})

const header = await vcf.getHeader()
return {
vcf,
parser: new VcfParser({ header }),
parser: new VcfParser({
header: await vcf.getHeader(),
}),
}
}

protected async configure() {
protected async configurePre2() {
if (!this.configured) {
this.configured = this.configurePre().catch(e => {
this.configured = this.configurePre().catch((e: unknown) => {
this.configured = undefined
throw e
})
}
return this.configured
}

async configure(opts?: BaseOptions) {
const { statusCallback = () => {} } = opts || {}
return updateStatus('Downloading index', statusCallback, () =>
this.configurePre2(),
)
}
public async getRefNames(opts: BaseOptions = {}) {
const { vcf } = await this.configure()
const { vcf } = await this.configure(opts)
return vcf.getReferenceSequenceNames(opts)
}

async getHeader() {
const { vcf } = await this.configure()
async getHeader(opts?: BaseOptions) {
const { vcf } = await this.configure(opts)
return vcf.getHeader()
}

async getMetadata() {
const { parser } = await this.configure()
async getMetadata(opts?: BaseOptions) {
const { parser } = await this.configure(opts)
return parser.getMetadata()
}

public getFeatures(query: NoAssemblyRegion, opts: BaseOptions = {}) {
return ObservableCreate<Feature>(async observer => {
const { refName, start, end } = query
const { vcf, parser } = await this.configure()
await vcf.getLines(refName, start, end, {
lineCallback: (line, fileOffset) => {
observer.next(
new VcfFeature({
variant: parser.parseLine(line),
parser,
id: `${this.id}-vcf-${fileOffset}`,
}),
)
},
...opts,
})
const { statusCallback = () => {} } = opts
const { vcf, parser } = await this.configure(opts)

await updateStatus('Downloading variants', statusCallback, () =>
vcf.getLines(refName, start, end, {
lineCallback: (line, fileOffset) => {
observer.next(
new VcfFeature({
variant: parser.parseLine(line),
parser,
id: `${this.id}-vcf-${fileOffset}`,
}),
)
},
...opts,
}),
)
observer.complete()
}, opts.signal)
}, opts.stopToken)
}

async getSources() {
const conf = this.getConf('samplesTsvLocation')
if (conf.uri === '' || conf.uri === '/path/to/samples.tsv') {
const { parser } = await this.configure()
return parser.samples.map(name => ({
name,
}))
} else {
const txt = await fetchAndMaybeUnzipText(
openLocation(conf, this.pluginManager),
)
const lines = txt.split(/\n|\r\n|\r/)
const header = lines[0]!.split('\t')
const { parser } = await this.configure()
const metadataLines = lines
.slice(1)
.filter(f => !!f)
.map(line => {
const [name, ...rest] = line.split('\t')
return {
...Object.fromEntries(
// force col 0 to be called name
rest.map((c, idx) => [header[idx + 1]!, c] as const),
),
name: name!,
}
})
const vcfSampleSet = new Set(parser.samples)
const metadataSet = new Set(metadataLines.map(r => r.name))
const metadataNotInVcfSamples = [...metadataSet].filter(
f => !vcfSampleSet.has(f),
)
const vcfSamplesNotInMetadata = [...vcfSampleSet].filter(
f => !metadataSet.has(f),
)
if (metadataNotInVcfSamples.length) {
console.warn(
`There are ${metadataNotInVcfSamples.length} samples in metadata file (${metadataLines.length} lines) not in VCF (${parser.samples.length} samples):`,
shorten2(metadataNotInVcfSamples.join(',')),
)
}
if (vcfSamplesNotInMetadata.length) {
console.warn(
`There are ${vcfSamplesNotInMetadata.length} samples in VCF file (${parser.samples.length} samples) not in metadata file (${metadataLines.length} lines):`,
shorten2(vcfSamplesNotInMetadata.map(m => m).join(',')),
)
}
return metadataLines.filter(f => vcfSampleSet.has(f.name))
}
}

public freeResources(/* { region } */): void {}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import jexl from 'jexl';
import { SvgFeatureRendererReactComponent } from '@jbrowse/plugin-svg';
import { observer } from 'mobx-react';
import React from 'react';
import { deserializeFilters } from '../../InfoFilterWidget/filterUtil';
import Diamond from './Diamond';
import { passesInfoFilters, passesSampleFilters } from '../../../../../utils';
import { VcfFeature } from '@jbrowse/plugin-variants';

export function ExtendedVariantRendering(props) {
const { features, rendererConfig } = props
Expand All @@ -17,11 +17,11 @@ export function ExtendedVariantRendering(props) {

const sampleFilters = activeSamples.value ? activeSamples.value.split(',') : null

function diamondValidator(feature) {
function diamondValidator(feature: VcfFeature) {
return feature.get('type') === "SNV";
}

function isFeatureDisplayed(feature) {
function isFeatureDisplayed(feature: VcfFeature) {
return passesInfoFilters(feature, expandedFilters) && passesSampleFilters(feature, sampleFilters)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ export default jbrowse => {
feat["INFO"] = null

return (
<Paper data-testid="extended-variant-widget" style={{height: '100vh', overflowY: 'scroll'}}>
<Paper data-testid="extended-variant-widget">
{message}
<FeatureDetails
feature={feat}
Expand Down
Loading