import { trackXTransform } from '../../../utils/coordinates'; import { Domain, ValuedPoint, YRange } from '../../../utils/types'; import { BigWigData, BigZoomData } from 'bigwig-reader'; import { RenderedBigWigData } from './types'; export function isBigWigData(value: BigWigData | BigZoomData): value is BigWigData { return (value as BigWigData).value !== undefined; } export const renderDense = (data: ValuedPoint[] )=> { let domain = { start: data[0].x, end: data[data.length - 1].x }; let x = trackXTransform(domain, data.map(d=>{ return {start: d.x,end: d.x+1} }), 100.0); let initialvalues: ValuedPoint[] = []; for (let i = 0; i <= 100; ++i) { initialvalues.push({ x: i, max: -Infinity, min: Infinity, }); } return data.reduce( (c, point) => { let cxs = Math.floor(x(point.x)), cxe = Math.floor(x(point.x)); if (point.min < c.renderPoints[cxs].min) c.renderPoints[cxs].min = point.min; if (point.max > c.renderPoints[cxs].max) c.renderPoints[cxs].max = point.max; for (let i = cxs + 1; i <= cxe; ++i) { c.renderPoints[i].min = point.min; c.renderPoints[i].max = point.max; } if (point.min < c.range.min) c.range.min = point.min; if (point.max > c.range.max) c.range.max = point.max; return c; }, { renderPoints: initialvalues, range: { max: -Infinity, min: Infinity } } ); }; export function renderBigWig(data: BigWigData[] | BigZoomData[] | undefined | null, width: number): RenderedBigWigData { if (!data) return { renderPoints: [], range: { max: 1, min: 0 } }; // get domain and create x transform mapping const domain = (data as Domain[]).reduce( (domain: Domain, v: Domain): Domain => ({ start: v.start < domain.start ? v.start : domain.start, end: v.end > domain.end ? v.end : domain.end }), { start: Infinity, end: -Infinity }); const x = trackXTransform(domain, data, width); // create array of placeholder values for each x coordinate const initialValues: ValuedPoint[] = []; const cbounds = { start: Math.floor(x(data[0].start)), end: Math.floor(x(data[data.length - 1].end)) }; for (let i = cbounds.start; i < cbounds.end; ++i) initialValues.push({ x: i, max: -Infinity, min: Infinity }); // iterate over passed values, computing ranges for individual points and getting the overall range const result: RenderedBigWigData = { renderPoints: initialValues, range: { max: -Infinity, min: Infinity }}; data.forEach( (point: BigWigData | BigZoomData) => { const cxs = Math.floor(x(point.start)), cxe = Math.floor(x(point.end)); const pmin = (isBigWigData(point) ? point.value : point.minVal); const pmax = (isBigWigData(point) ? point.value : point.maxVal); if (pmin < result.renderPoints[cxs].min) result.renderPoints[cxs].min = pmin; if (pmax > result.renderPoints[cxs].max) result.renderPoints[cxs].max = pmax; for (let i = cxs + 1; i < cxe; ++i) { result.renderPoints[i].min = pmin; result.renderPoints[i].max = pmax; } if (pmin < result.range.min) result.range.min = pmin; if (pmax > result.range.max) result.range.max = pmax; }); return result; }; export const datarange = (data: ValuedPoint[]) => { let range: YRange = { max: -Infinity, min: Infinity, }; data.forEach(d => { if (d.min!==null && (d.min < range.min)) range.min = d.min; if (d.max!==null && (d.max > range.max)) range.max = d.max; }); return range; }; export const wigdatarange = (data: BigWigData[]) => { let range: YRange = { max: -Infinity, min: Infinity, }; data.forEach(d => { if (d.value!==null && (d.value < range.min)) range.min = d.value; if (d.value!==null && (d.value > range.max)) range.max = d.value; }); return range; };