JBrowse 2 · Linear Genome View examples

Multiple views

Companion panels that follow the view, and two views on one page.

Observe the visible view

Key a fetch off coarseDynamicBlocks, the debounced twin of dynamicBlocks, or a drag fires one per frame. Two fetches can resolve out of order; the generation counter keeps the older one from landing last.

View source — 126 lines
import { useEffect, useState } from 'react'

import { getConf } from '@jbrowse/core/configuration'
import { getRpcSessionId } from '@jbrowse/core/util/tracks'
import {
  JBrowseLinearGenomeView,
  useCreateViewState,
} from '@jbrowse/react-linear-genome-view2'
import { autorun } from 'mobx'
import { observer } from 'mobx-react'

import type { Feature } from '@jbrowse/core/util'
import type { ViewModel } from '@jbrowse/react-linear-genome-view2'

const VisibleRegions = observer(function VisibleRegions({
  viewState,
}: {
  viewState: ViewModel
}) {
  const view = viewState.session.view
  return view.initialized ? (
    <p>Visible region {view.coarseVisibleLocStrings}</p>
  ) : null
})

const VisibleFeatures = observer(function VisibleFeatures({
  viewState,
}: {
  viewState: ViewModel
}) {
  const [features, setFeatures] = useState<Feature[]>()
  const [error, setError] = useState<unknown>()
  const { rpcManager, view } = viewState.session

  useEffect(() => {
    let latest = 0
    return autorun(() => {
      if (view.initialized) {
        const track = view.tracks[0]
        if (track) {
          const adapterConfig = getConf(track, 'adapter')
          const sessionId = getRpcSessionId(track)
          const generation = ++latest
          void rpcManager
            // eslint-disable-next-line no-restricted-syntax
            .call(sessionId, 'CoreGetFeatures', {
              adapterConfig,
              regions: view.coarseDynamicBlocks,
            })
            .then(feats => {
              if (generation === latest) {
                setFeatures(feats)
              }
            })
            .catch((e: unknown) => {
              if (generation === latest) {
                setError(e)
              }
            })
        }
      }
    })
  }, [rpcManager, view])

  return error ? (
    <div>Error: {String(error)}</div>
  ) : !features ? (
    <div>Loading...</div>
  ) : (
    <table>
      <thead>
        <tr>
          <th>Name</th>
          <th>Location</th>
        </tr>
      </thead>
      <tbody>
        {features.map(f => (
          <tr key={f.id()}>
            <td>{f.get('name')}</td>
            <td>
              {f.get('refName')}:{f.get('start')}-{f.get('end')}
            </td>
          </tr>
        ))}
      </tbody>
    </table>
  )
})

export default function ObserveVisible() {
  const state = useCreateViewState({
    assembly: {
      name: 'volvox',
      uri: 'https://jbrowse.org/genomes/volvox/volvox.2bit',
    },
    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',
        },
      },
    ],
    defaultSession: {
      name: 'Observe visible',
      view: {
        type: 'LinearGenomeView',
        assembly: 'volvox',
        loc: 'ctgA:1105..1221',
        tracks: ['volvox_gff3'],
      },
    },
  })
  return state ? (
    <div>
      <JBrowseLinearGenomeView viewState={state} />
      <VisibleRegions viewState={state} />
      <VisibleFeatures viewState={state} />
    </div>
  ) : null
}

Observe the selected feature

View source — 60 lines
import { isFeature } from '@jbrowse/core/util'
import {
  JBrowseLinearGenomeView,
  useCreateViewState,
} from '@jbrowse/react-linear-genome-view2'
import { observer } from 'mobx-react'

import type { ViewModel } from '@jbrowse/react-linear-genome-view2'

const SelectedFeature = observer(function SelectedFeature({
  viewState,
}: {
  viewState: ViewModel
}) {
  const { selection } = viewState.session
  return isFeature(selection) ? (
    <p>
      Selected <b>{selection.get('name') || selection.id()}</b> at{' '}
      {selection.get('refName')}:{selection.get('start')}-{selection.get('end')}
    </p>
  ) : (
    <p>Click a feature to select it.</p>
  )
})

export default function ObserveSelection() {
  const state = useCreateViewState({
    assembly: {
      name: 'volvox',
      uri: 'https://jbrowse.org/genomes/volvox/volvox.2bit',
    },
    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',
        },
      },
    ],
    defaultSession: {
      name: 'Observe selection',
      view: {
        type: 'LinearGenomeView',
        assembly: 'volvox',
        loc: 'ctgA:1..50,000',
        tracks: ['volvox_gff3'],
      },
    },
  })
  return state ? (
    <div>
      <JBrowseLinearGenomeView viewState={state} />
      <SelectedFeature viewState={state} />
    </div>
  ) : null
}

Two linear genome views

View source — 41 lines
import {
  JBrowseLinearGenomeView,
  useCreateViewState,
} 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',
    },
  },
]

export default function WithTwoLinearGenomeViews() {
  const state1 = useCreateViewState({
    assembly,
    tracks,
    location: 'ctgA:1105..1221',
  })
  const state2 = useCreateViewState({
    assembly,
    tracks,
    location: 'ctgA:5560..30589',
  })
  return (
    <div>
      {state1 ? <JBrowseLinearGenomeView viewState={state1} /> : null}
      {state2 ? <JBrowseLinearGenomeView viewState={state2} /> : null}
    </div>
  )
}