import React, { useRef, useMemo, useContext, useEffect } from 'react'; import { v1 as uuidv1 } from 'uuid'; import { xtransform } from '../../../utils/coordinates'; import { ClipPath } from '../../clippath'; import { LDTrackProps, SNP } from './types'; import { renderLD, renderSNPs } from './utils'; import { TooltipContext } from "../../tooltip/tooltipcontext"; import { svgPoint } from '../../../utils/svg'; const LDTrack: React.FC = props => { const tooltipContext = useContext(TooltipContext); const mouseOver = (event: React.MouseEvent, snp: SNP) => { if(props.svgRef) { let mousePosition = svgPoint(props.svgRef.current!, event); tooltipContext.setTooltip({ show: true, x: mousePosition[0] > props.width - 120 ? (mousePosition[0] - 120) + 15: mousePosition[0] + 15, y: mousePosition[1] + 10, width: 120, height: 50, content: {snp.id} }); } props.onVariantMouseOver && props.onVariantMouseOver(snp) }; const mouseOut = () => { tooltipContext.setTooltip({ show: false, x: 0, y: 0, content: undefined, width: 0, height: 0 }); }; const uuid = useRef(uuidv1()); const x = xtransform(props.domain, props.width); const color = props.color || "#000000"; const ldThreshold = props.ldThreshold || 0.7; const highlightColor = props.highlightColor || "#ff0000"; const highlighted = props.highlighted || new Set(); const renderedSNPs = useMemo( () => renderSNPs(props.data!.snps, highlighted, x, highlightColor, color), [ props.domain, props.width, props.data!.snps, props.highlighted, highlightColor, color ] ); const renderedLD = props.data!.ld && useMemo( () => renderLD(renderedSNPs.coords, props.anchor || "", props.data!.ld!.filter(l=>l.coordinates), x, ldThreshold, props.height), [ renderedSNPs, props.height, props.anchor, props.data!.ld, props.domain, props.ldThreshold ] ); useEffect( () => { props.onHeightChanged && props.onHeightChanged(props.height); }, [ props.height ]); const isAnchor = props.anchor && renderedSNPs.snps.find(r=>r.id===props.anchor) const anchorSnp = renderedSNPs.snps.find(r=>r.id===props.anchor) return React.useMemo(() => { return ( {isAnchor && renderedLD?.length===0 && r.id===props.anchor)?.domain.start} y={20} style={{ pointerEvents: 'none', WebkitTouchCallout: 'none', WebkitUserSelect: 'none', MozUserSelect: 'none', msUserSelect: 'none', userSelect: 'none'}} > {`There are no SNPs in LD (r-squared > ${ldThreshold}) with ${props.anchor} in ${props.id} track`} } {isAnchor && } { renderedSNPs.snps.map( (snp, i) => { const height = props.height * (snp.taller ? 1.0 : 0.6) * (props.anchor ? 0.25 : 0.6); return ( )=> mouseOver(e, snp)} onMouseOut={() => { mouseOut(); props.onVariantMouseOut && props.onVariantMouseOut(snp)}} onClick={() => props.onVariantClick && props.onVariantClick(snp)} /> ); })} { renderedLD && renderedLD.map( (path, i) => ( ))} ) },[ color, props.data?.snps, props.ldThreshold , props.highlighted, props.highlightColor, props.data?.ld, props.domain, props.height, props.width, props.id]) } export default LDTrack;