import React from 'react'; import { xtransform } from '../../../utils/coordinates'; import { RulerTrackProps } from './types'; /** * Formats the length of the scale marker at the top of the track into a human-readable * unit of basepairs, kb, Mb, or Gb. * @param length the length to format, in basepairs. */ function lengthFormat(length: number): string { if (length >= 1e9) return Math.round(length / 1e9) + " Gb"; if (length >= 1e6) return Math.round(length / 1e6) + " Mb"; if (length >= 1e3) return Math.round(length / 1e3) + " kb"; return length + " bp"; } /** * Renders the ruler track at the top of the genome browser to provide a readout of coordinates and scale. * This component is chromosome agnostic; chromosome information should be provided elsewhere, such as by * wrapping this component in a WrappedTrack with an appropriate title and shortLabel. */ const RulerTrack: React.FC = props => { /* make linear transform to map coordinates and compute optimal number of ticks */ const x = xtransform(props.domain, props.width); const nticks = Math.ceil(props.width / 100.0); const step = Math.pow(10.0, Math.floor(Math.log10(Math.ceil( (props.domain.end - props.domain.start) / nticks )))) * 6; const gscale = (Math.ceil(props.domain.end / step) - Math.ceil(props.domain.start / step)) * step / 2; const gdomain = { start: props.domain.start + gscale / 2, end: props.domain.end - gscale / 2 }; /* create the ticks and labels */ const gelems = []; for (let i = Math.ceil(props.domain.start / step); i < Math.ceil(props.domain.end / step); ++i) { gelems.push( {i >= Math.ceil(props.domain.start / step) && {i * step}} ); } /* render the scale bar then the ticks and labels */ return ( {lengthFormat(gdomain.end - gdomain.start)} {gelems} ); }; export default RulerTrack;