import * as React from 'react'; import { getCumulativePValue } from '../../../shared/lib/FisherExactTestCalculator'; import { MutualExclusivity } from '../../../shared/model/MutualExclusivity'; import { calculateQValues } from '../../../shared/lib/calculation/BenjaminiHochbergFDRCalculator'; import Combinatorics from 'js-combinatorics'; import Dictionary = _.Dictionary; import _ from 'lodash'; import { SampleAlteredMap } from '../ResultsViewPageStoreUtils'; export enum AlteredStatus { UNPROFILED = 'unprofiled', ALTERED = 'altered', UNALTERED = 'unaltered', } export function calculateAssociation(logOddsRatio: number): string { return logOddsRatio > 0 ? 'Co-occurrence' : 'Mutual exclusivity'; } export function countOccurences( valuesA: AlteredStatus[], valuesB: AlteredStatus[] ): [number, number, number, number] { let neither = 0; let bNotA = 0; let aNotB = 0; let both = 0; valuesA.forEach((valueA, index) => { // jump over this comparison if there is a unprofiled value if ( valueA === AlteredStatus.UNPROFILED || valuesB[index] === AlteredStatus.UNPROFILED ) { return true; } const valueB = valuesB[index]; if ( valueA === AlteredStatus.UNALTERED && valueB === AlteredStatus.UNALTERED ) { neither++; } else if ( valueA === AlteredStatus.UNALTERED && valueB === AlteredStatus.ALTERED ) { bNotA++; } else if ( valueA === AlteredStatus.ALTERED && valueB === AlteredStatus.UNALTERED ) { aNotB++; } else { both++; } }); return [neither, bNotA, aNotB, both]; } export function calculatePValue( a: number, b: number, c: number, d: number ): number { return getCumulativePValue(a, b, c, d); } export function calculateAdjustedPValue(pValue: number, count: number): number { let value = pValue * count; return value > 1 ? 1 : value; } export function calculateLogOddsRatio( a: number, b: number, c: number, d: number ): number { if (a * d === 0 && b * c === 0) { return Infinity; } return Math.log2((a * d) / (b * c)); } export function getMutuallyExclusiveCounts( data: MutualExclusivity[], exclusive: (n: number) => boolean ): [JSX.Element | null, JSX.Element | null] { let exclusiveCount = null; let significantCount = null; const exclusiveData = data.filter(mutualExclusivity => exclusive(mutualExclusivity.logOddsRatio) ); const significantData = exclusiveData.filter( mutualExclusivity => mutualExclusivity.qValue < 0.05 ); const exclusiveLength = exclusiveData.length; const significantLength = significantData.length; if (exclusiveLength === 0) { exclusiveCount = ( no track pair ); } else if (exclusiveLength === 1) { exclusiveCount = ( 1 track pair ); } else { exclusiveCount = ( {exclusiveLength} track pairs ); } if (exclusiveLength > 0) { if (significantLength === 0) { significantCount = (none significant); } else { significantCount = ( {' '} ({significantLength} significant) ); } } return [exclusiveCount, significantCount]; } export function getTrackPairsCountText( data: MutualExclusivity[], trackCount: number ): JSX.Element { const trackPairsCount = _.size(data); const pairText = trackPairsCount > 1 ? 'pairs' : 'pair'; return (
The analysis tested {trackPairsCount} {pairText} between the{' '} {trackCount} tracks in the OncoPrint.
); } export function getCountsText(data: MutualExclusivity[]): JSX.Element { const mutuallyExclusiveCounts = getMutuallyExclusiveCounts( data, n => n <= 0 ); const coOccurentCounts = getMutuallyExclusiveCounts(data, n => n > 0); return (The query contains {mutuallyExclusiveCounts[0]} with mutually exclusive alterations{mutuallyExclusiveCounts[1]}, and{' '} {coOccurentCounts[0]} with co-occurrent alterations {coOccurentCounts[1]}.
); } export function getData( isSampleAlteredMap: Dictionary