UNPKG

oncoprintjs

Version:

A data visualization for cancer genomic data.

145 lines (130 loc) 3.91 kB
import { ComputedShapeParams } from './oncoprintshape'; import { RGBAColor } from './oncoprintruleset'; export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>; export function cloneShallow<T extends Object>(obj: T) { const ret: Partial<T> = {}; for (const key of Object.keys(obj) as (keyof T)[]) { ret[key] = obj[key]; } return ret as T; } export function extendArray(target: any[], source: any[]) { for (let i = 0; i < source.length; i++) { target.push(source[i]); } } export function doesCellIntersectPixel( cellHitzone: [number, number], pixelX: number ) { // checks intersection with the half-open interval [pixelX, pixelX+1) const lower = cellHitzone[0], upper = cellHitzone[1]; if (upper < pixelX) { return false; } else if (lower < pixelX + 1) { return true; } else { return false; } } export function ifndef<T>(x: T | undefined, val: T): T { return typeof x === 'undefined' ? val : x; } export function shallowExtend<T extends Object, S extends Object>( target: T, source: S ): T & S { const ret: Partial<T & S> = {}; for (const key of Object.keys(target) as (keyof T & S)[]) { ret[key] = target[key as keyof T] as any; } for (const key of Object.keys(source) as (keyof T & S)[]) { ret[key] = source[key as keyof S] as any; } return ret as T & S; } export function objectValues<T extends Object>(obj: T): T[keyof T][] { return Object.keys(obj).map(function(key: string & keyof T) { return obj[key]; }); } export function arrayFindIndex<T>( arr: T[], predicate: (t: T) => boolean, start_index?: number ) { start_index = start_index || 0; for (let i = start_index; i < arr.length; i++) { if (predicate(arr[i])) { return i; } } return -1; } export function sgndiff(a: number, b: number) { if (a < b) { return -1; } else if (a > b) { return 1; } else { return 0; } } export function clamp(x: number, lower: number, upper: number) { return Math.max(lower, Math.min(upper, x)); } export function z_comparator( shapeA: ComputedShapeParams, shapeB: ComputedShapeParams ) { const zA = shapeA.z; const zB = shapeB.z; if (zA < zB) { return -1; } else if (zA > zB) { return 1; } else { return 0; } } export function fastParseInt10( x: string, substringStart?: number, substringEnd?: number ) { // simple, fast parseInt when you know its a base-10 int and // you don't need any error handling. // Performance testing shows this is 85% faster than built-in parseInt substringStart = substringStart || 0; substringEnd = substringEnd || x.length; let ret = 0; for (let i = substringStart; i < substringEnd; i++) { ret *= 10; ret += x.charCodeAt(i) - 48; // the integer character codes from 0 to 9 are 48, 49, ..., 58 } return ret; } export function fastParseInt16(x: string) { // simple, fast parseInt when you know its a base-16 int and // you don't need any error handling. // Performance testing shows this is 43% faster than parseInt(x,16) let ret = 0; let nextCharCode: number; for (let i = 0; i < x.length; i++) { ret *= 16; nextCharCode = x.charCodeAt(i); if (nextCharCode > 96) { ret += nextCharCode - 87; // lower case letters start at 97. a is 97, should be 10 } else if (nextCharCode > 64) { ret += nextCharCode - 55; // capital letters start at 65. A is 65, should be 10 } else { // otherwise, its an integer ret += nextCharCode - 48; } } return ret; } export function rgbString(color: RGBAColor) { return `rgb(${color[0]},${color[1]},${color[2]})`; }