From f7413b2527b395c3bbf5db06d36c5024030cc2cc Mon Sep 17 00:00:00 2001 From: Colin Diesh Date: Wed, 10 Jul 2024 14:13:03 -0400 Subject: [PATCH] Add ability to use CSI indexes in @jbrowse/img (#4478) --- .../LinearPileupDisplay/configSchema.test.js | 89 ------------------ .../data/volvox/volvox-sorted.bam.csi | 1 + products/jbrowse-img/src/index.test.ts | 15 +++ products/jbrowse-img/src/renderRegion.tsx | 34 +++---- test_data/volvox/volvox-sorted.bam.csi | Bin 146 -> 143 bytes 5 files changed, 30 insertions(+), 109 deletions(-) delete mode 100644 plugins/alignments/src/LinearPileupDisplay/configSchema.test.js create mode 120000 products/jbrowse-img/data/volvox/volvox-sorted.bam.csi diff --git a/plugins/alignments/src/LinearPileupDisplay/configSchema.test.js b/plugins/alignments/src/LinearPileupDisplay/configSchema.test.js deleted file mode 100644 index bdaab7666a..0000000000 --- a/plugins/alignments/src/LinearPileupDisplay/configSchema.test.js +++ /dev/null @@ -1,89 +0,0 @@ -import Plugin from '@jbrowse/core/Plugin' -import PluginManager from '@jbrowse/core/PluginManager' -import BoxRendererType from '@jbrowse/core/pluggableElementTypes/renderers/BoxRendererType' -import { - svgFeatureRendererConfigSchema, - SvgFeatureRendererReactComponent, -} from '@jbrowse/plugin-svg' -import PileupRenderer from '../PileupRenderer' -import configSchemaFactory from './configSchema' -import modelFactory from './model' -import LinearPileupDisplay from '.' - -// mock warnings to avoid unnecessary outputs -beforeEach(() => { - jest.spyOn(console, 'warn').mockImplementation(() => {}) -}) - -afterEach(() => { - console.warn.mockRestore() -}) - -class PileupRendererPlugin extends Plugin { - install(pluginManager) { - PileupRenderer(pluginManager) - } -} - -class LinearPileupDisplayPlugin extends Plugin { - install(pluginManager) { - LinearPileupDisplay(pluginManager) - } -} - -class SvgFeatureRendererPlugin extends Plugin { - install(pluginManager) { - pluginManager.addRendererType( - () => - new BoxRendererType({ - name: 'SvgFeatureRenderer', - ReactComponent: SvgFeatureRendererReactComponent, - configSchema: svgFeatureRendererConfigSchema, - pluginManager, - }), - ) - } -} - -test('has a type attr', () => { - const configSchema = configSchemaFactory( - new PluginManager([ - new PileupRendererPlugin(), - new SvgFeatureRendererPlugin(), - ]) - .createPluggableElements() - .configure(), - ) - const config = configSchema.create({ - type: 'LinearPileupDisplay', - displayId: 'display0', - name: 'Zonker Display', - }) - expect(config.type).toEqual('LinearPileupDisplay') -}) - -test('set custom jexl filters on linear pileup display', () => { - const configSchema = configSchemaFactory( - new PluginManager([ - new PileupRendererPlugin(), - new SvgFeatureRendererPlugin(), - new LinearPileupDisplayPlugin(), - ]) - .createPluggableElements() - .configure(), - ) - - const config = { - type: 'LinearPileupDisplay', - displayId: 'display0', - name: 'Zonker Display', - } - - const model = modelFactory(configSchema) - const nm = model.create(config) - - expect(nm.jexlFilters).toEqual([]) - const filter = [`jexl:get(feature,'end')==${99319638}`] - nm.setJexlFilters(filter) - expect(nm.jexlFilters).toEqual([`jexl:get(feature,'end')==${99319638}`]) -}) diff --git a/products/jbrowse-img/data/volvox/volvox-sorted.bam.csi b/products/jbrowse-img/data/volvox/volvox-sorted.bam.csi new file mode 120000 index 0000000000..70a48d51ae --- /dev/null +++ b/products/jbrowse-img/data/volvox/volvox-sorted.bam.csi @@ -0,0 +1 @@ +../../../../test_data/volvox/volvox-sorted.bam.csi \ No newline at end of file diff --git a/products/jbrowse-img/src/index.test.ts b/products/jbrowse-img/src/index.test.ts index ee7e2fc3f9..f263288567 100644 --- a/products/jbrowse-img/src/index.test.ts +++ b/products/jbrowse-img/src/index.test.ts @@ -57,6 +57,21 @@ test('renders volvox with variety of args', async () => { expect(result).toBeTruthy() }, 40000) +test('renders volvox with csi index', async () => { + const result = await renderRegion({ + fasta: fp('volvox.fa'), + trackList: [ + [ + 'bam', + [fp('volvox-sorted.bam'), 'index:' + fp('volvox-sorted.bam.csi')], + ], + ], + loc: 'ctgA:1000-2000', + }) + fs.writeFileSync(pa('../test/svg_from_volvox_fasta_and_bam_csi.svg'), result) + expect(result).toBeTruthy() +}, 40000) + test('renders volvox alignments as snpcov', async () => { const result = await renderRegion({ fasta: fp('volvox.fa'), diff --git a/products/jbrowse-img/src/renderRegion.tsx b/products/jbrowse-img/src/renderRegion.tsx index ba6eaa8b10..776bc118bd 100644 --- a/products/jbrowse-img/src/renderRegion.tsx +++ b/products/jbrowse-img/src/renderRegion.tsx @@ -1,18 +1,15 @@ -import React from 'react' +import { createRoot } from 'react-dom/client' import { createViewState } from '@jbrowse/react-linear-genome-view' import { LinearGenomeViewModel, renderToSvg, } from '@jbrowse/plugin-linear-genome-view' -import createCache from '@emotion/cache' -import { CacheProvider } from '@emotion/react' import path from 'path' import fs from 'fs' // local import { Entry } from './parseArgv' import { booleanize } from './util' -import { createRoot } from 'react-dom/client' export interface Opts { noRasterize?: boolean @@ -173,7 +170,8 @@ export function readData({ trackList.forEach(track => { const [type, opts] = track - const [file] = opts + const [file, ...rest] = opts + const index = rest.find(r => r.startsWith('index:'))?.replace('index:', '') if (type === 'bam') { configData.tracks = [ @@ -186,7 +184,10 @@ export function readData({ adapter: { type: 'BamAdapter', bamLocation: makeLocation(file), - index: { location: makeLocation(file + '.bai') }, + index: { + location: makeLocation(index || file + '.bai'), + indexType: index?.endsWith('.csi') ? 'CSI' : 'BAI', + }, sequenceAdapter: configData.assembly.sequence.adapter, }, ...(opts.includes('snpcov') @@ -213,7 +214,7 @@ export function readData({ adapter: { type: 'CramAdapter', cramLocation: makeLocation(file), - craiLocation: makeLocation(file + '.crai'), + craiLocation: makeLocation(index || file + '.crai'), sequenceAdapter: configData.assembly.sequence.adapter, }, ...(opts.includes('snpcov') @@ -257,7 +258,8 @@ export function readData({ type: 'VcfTabixAdapter', vcfGzLocation: makeLocation(file), index: { - location: makeLocation(file + '.tbi'), + location: makeLocation(index || file + '.tbi'), + indexType: index?.endsWith('.csi') ? 'CSI' : 'TBI', }, }, }, @@ -276,7 +278,8 @@ export function readData({ type: 'Gff3TabixAdapter', gffGzLocation: makeLocation(file), index: { - location: makeLocation(file + '.tbi'), + location: makeLocation(index || file + '.tbi'), + indexType: index?.endsWith('.csi') ? 'CSI' : 'TBI', }, }, }, @@ -325,7 +328,8 @@ export function readData({ type: 'BedTabixAdapter', bedGzLocation: makeLocation(file), index: { - location: makeLocation(file + '.tbi'), + location: makeLocation(index || file + '.tbi'), + indexType: index?.endsWith('.csi') ? 'CSI' : 'TBI', }, }, }, @@ -347,13 +351,6 @@ export function readData({ return configData } -// without this, the styles can become messed up especially in lgv header -// xref https://github.com/garronej/tss-react/issues/25 -export const muiCache = createCache({ - key: 'mui', - prepend: true, -}) - function process( trackEntry: Entry, view: LinearGenomeViewModel, @@ -474,8 +471,5 @@ export async function renderRegion(opts: Opts) { return renderToSvg(view, { rasterizeLayers: !opts.noRasterize, ...opts, - Wrapper: ({ children }) => ( - {children} - ), }) } diff --git a/test_data/volvox/volvox-sorted.bam.csi b/test_data/volvox/volvox-sorted.bam.csi index c0afbb87154ff01fbc308a1eb8d770e5c03a6275..0e2387d7b6b9e5ea5db6cec667b4dc0fd81baaeb 100644 GIT binary patch literal 143 zcmb2|=3rp}f&Xj_PR>jWMGVD!-%_3=CnO}KG%yI9J;lI$`GAVCz-<#fd)7(OCX!Ci zk7?#Jck27LU&v137H|4us@Hy@$K%(;n+C-*CfvAjCehHzVVW31`}G#xFkA cz_iT4mV?25bIFqrK%3;ztdwS81~~u>0QRdcjsO4v literal 146 zcmb2|=3rp}f&Xj_PR>jWr3}S<-%_3=CnO}KG%yI9J;lJhE@6^nhy2uzxr`?(w>ZD3 zJ$Jsm>B#<{4lmy5|KwGuom<*JZR4S{#jUeBlMkOsbV^D#o-WyWw&SRr9ve%7laYK{ geXkZX*9@kw3Jf`ta>*ZnmdT^pD$T$QaswCu0G~TBBLDyZ