Flip regions
Reverse-complement the whole view, or mix orientations across multiple displayed regions.
Horizontally flip the view
Regions can render reversed (3’→5’), which is what you want for a gene on the negative strand or a synteny-style layout. Two ways in:
- imperatively,
view.horizontallyFlip()— for your own toolbar button or keyboard shortcut; - declaratively,
[rev]appended to a locstring (init: { loc: 'ctgA:1,000..5,000[rev]' }), so the view opens flipped.
The button takes the engine as a plain prop rather than a ref to one, which is
what useCreateViewState buys: the engine exists before the first render, so
there is no RefObject to thread down and no ?. at the call.
To flip only some regions of a multi-region view, see mixing orientations.
View source — 76 lines
import { useState } from 'react'
import { ErrorBanner } from '@jbrowse/core/ui'
import {
JBrowseLinearGenomeView,
useCreateViewState,
} from '@jbrowse/react-linear-genome-view2'
import type { ViewModel } from '@jbrowse/react-linear-genome-view2'
const assembly = {
name: 'volvox',
uri: 'https://jbrowse.org/genomes/volvox/volvox.2bit',
}
const tracks = [
{
type: 'FeatureTrack',
trackId: 'volvox_gff3',
name: 'Volvox genes',
assemblyNames: ['volvox'],
adapter: {
type: 'Gff3TabixAdapter',
uri: 'https://jbrowse.org/code/jb2/main/test_data/volvox/volvox.sort.gff3.gz',
},
},
]
// imperative toggle via the view's horizontallyFlip() action. The engine is
// built by the hook and passed down as a plain value, so this takes a
// ViewModel rather than a ref to one: `<LinearGenomeView ref>` would hand it
// over a render later, which is a RefObject to thread through and a `?.` at
// every use for a value that is never actually absent here.
function FlipButton({ viewState }: { viewState: ViewModel }) {
const [error, setError] = useState<unknown>()
return (
<div>
<button
onClick={() => {
try {
viewState.session.view.horizontallyFlip()
} catch (e) {
setError(e)
}
}}
>
Horizontally flip
</button>
{error ? <ErrorBanner error={error} /> : null}
</div>
)
}
export default function HorizontallyFlip() {
const state = useCreateViewState({
assembly,
tracks,
init: { loc: 'ctgA:1-50000' },
})
const flipped = useCreateViewState({
assembly,
tracks,
// the same view, opened already reversed: [rev] is part of the locstring,
// so it travels through a saved session or a shared URL like any other
init: { loc: 'ctgA:1-50000[rev]' },
})
return (
<div>
<h3>Flip imperatively from a button</h3>
<FlipButton viewState={state} />
<JBrowseLinearGenomeView viewState={state} />
<h3>Open already flipped via a [rev] locstring</h3>
<JBrowseLinearGenomeView viewState={flipped} />
</div>
)
}Multiple displayed regions, some flipped
A space-separated multi-region locstring in init.loc shows several regions at
once.
Orientation is per region — a [rev] suffix reverse-complements just that one,
so the regions on screen can differ. view.horizontallyFlip() reverses the
whole arrangement: the regions swap order and each flips its own reversed,
which is why there is no single “is it flipped” flag to read back — on these two
regions displayedRegions[0].reversed is false before the click and false
after it. Watch the scalebar instead. Multi-region views are the building block
for gene-centric layouts and synteny ribbons.
See horizontally flip for the single-region cases.
View source — 60 lines
import {
JBrowseLinearGenomeView,
useCreateViewState,
} from '@jbrowse/react-linear-genome-view2'
export default function WithMultipleDisplayedRegionsFlipped() {
const state = useCreateViewState({
assembly: {
name: 'GRCh38',
uri: 'https://s3.amazonaws.com/jbrowse.org/genomes/GRCh38/fasta/GRCh38.fa.gz',
aliases: ['hg38'],
refNameAliases: {
uri: 'https://s3.amazonaws.com/jbrowse.org/genomes/GRCh38/hg38_aliases.txt',
},
},
tracks: [
{
type: 'FeatureTrack',
trackId: 'ncbi-refseq-genes',
name: 'NCBI RefSeq Genes',
category: ['Genes'],
assemblyNames: ['GRCh38'],
adapter: {
type: 'Gff3TabixAdapter',
uri: 'https://s3.amazonaws.com/jbrowse.org/genomes/GRCh38/ncbi_refseq/GCA_000001405.15_GRCh38_full_analysis_set.refseq_annotation.sorted.gff.gz',
},
},
],
defaultSession: {
name: 'Multi-region flipped example',
view: {
type: 'LinearGenomeView',
init: {
// two displayed regions, the second reverse-complemented via its own
// [rev] suffix — orientation is per-region, so they can differ
loc: 'chr1:113073119..113073695 chr1:113091267..113091433[rev]',
assembly: 'GRCh38',
tracks: ['ncbi-refseq-genes'],
},
},
},
})
return (
<div>
{/* horizontallyFlip() reverses the *arrangement*: the regions swap
places and each one's own `reversed` flips with them. So there is no
"is the view flipped" bit to read back — with these two regions,
region 0 is forward-facing both before and after. The scalebar is
what shows it */}
<button
onClick={() => {
state.session.view.horizontallyFlip()
}}
>
Flip horizontally
</button>
<JBrowseLinearGenomeView viewState={state} />
</div>
)
}