diff --git a/src/App.tsx b/src/App.tsx index e76b360a..e307c00a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useRef, useState } from 'react'; +import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'; import { GoslingComponent, GoslingRef, embed } from 'gosling.js'; import { debounce, sample } from 'lodash'; import type { RouteComponentProps } from 'react-router-dom'; @@ -198,110 +198,6 @@ function App(props: RouteComponentProps) { ); }, [filterSampleBy]); - useEffect(() => { - if (!gosRef.current) return; - - gosRef.current.api.subscribe('click', (_, e) => { - // console.log(e); - - let x = +e.data[0].start1; - let xe = +e.data[0].end1; - let x1 = +e.data[0].start2; - let x1e = +e.data[0].end2; - - // safetly swap - if (x > x1) { - x = +e.data[0].start2; - xe = +e.data[0].end2; - x1 = +e.data[0].start1; - x1e = +e.data[0].end1; - } - - let zoomStart = x; - let zoomEnd = x1e; - let padding = (zoomEnd - zoomStart) / 4.0; - if (e.data[0].svclass === 'Translocation') { - zoomStart = x; - zoomEnd = xe; - padding = 10000; - } - - gosRef.current.api.zoomTo( - `${demo.id}-mid-ideogram`, - `chr1:${zoomStart}-${zoomEnd}`, - padding, - ZOOM_DURATION - ); - - // we will show the bam files, so set the initial positions - setBreakpoints([+x - ZOOM_PADDING, +xe + ZOOM_PADDING, +x1 - ZOOM_PADDING, +x1e + ZOOM_PADDING]); - setBpIntervals([x, xe, x1, x1e]); - setSelectedSvId(e.data[0].sv_id + ''); - - // move to the bottom - setTimeout( - () => document.getElementById('gosling-panel')?.scrollTo({ top: 1000000, behavior: 'smooth' }), - 2000 - ); - - leftReads.current = []; - rightReads.current = []; - }); - - gosRef.current.api.subscribe('mouseOver', (_, e) => { - const sanitizedChr = (c: string | number) => { - return `${c}`.replace('chr', ''); - }; - const calDir = (c1: string | number, c2: string | number) => { - c1 = sanitizedChr(c1); - c2 = sanitizedChr(c2); - if (+c1 && +c1 <= 9) { - c1 = '0' + c1; - } - if (+c2 && +c2 <= 9) { - c2 = '0' + c2; - } - return c1 < c2 ? 'rightward' : 'leftward'; - }; - if (e.id.includes('-mid-sv') && e.data[0].svclass === 'Translocation') { - const { chromosome: c, position: p } = e.genomicPosition; - const padding = 100000; - if (sanitizedChr(c) === sanitizedChr(e.data[0].chrom1)) { - const direction = calDir(c, e.data[0].chrom2); - const id = e.data[0].sv_id + '-' + direction; - if (id === prevJumpId.current) return; - const { start2, end2 } = e.data[0]; - setJumpButtonInfo({ - id, - x: mousePos.current.x, - y: mousePos.current.y, - direction, - zoomTo: () => gosRef.current.api.zoomTo(e.id, `chr1:${start2}-${end2}`, padding, ZOOM_DURATION) - }); - } else { - const direction = calDir(c, e.data[0].chrom1); - const id = e.data[0].sv_id + '-' + direction; - if (id === prevJumpId.current) return; - const { start1, end1 } = e.data[0]; - setJumpButtonInfo({ - id, - x: mousePos.current.x, - y: mousePos.current.y, - direction, - zoomTo: () => gosRef.current.api.zoomTo(e.id, `chr1:${start1}-${end1}`, padding, ZOOM_DURATION) - }); - } - } else { - setJumpButtonInfo(undefined); - } - }); - - return () => { - gosRef.current.api.unsubscribe('click'); - gosRef.current.api.unsubscribe('mouseOver'); - }; - }, [gosRef, drivers]); // !! instead of `[demo]`, we use drivers which are updated as a side effect of a demo - useEffect(() => { if (!gosRef.current || !demo.bai || !demo.bam) return; @@ -609,6 +505,110 @@ function App(props: RouteComponentProps) { // !! Removed `demo` not to update twice since `drivers` are updated right after a demo update. }, [ready, xDomain, visPanelWidth, drivers, showOverview, showPutativeDriver, selectedSvId, breakpoints, svReads]); + useLayoutEffect(() => { + if (!gosRef.current) return; + + gosRef.current.api.subscribe('click', (_, e) => { + // console.log(e); + + let x = +e.data[0].start1; + let xe = +e.data[0].end1; + let x1 = +e.data[0].start2; + let x1e = +e.data[0].end2; + + // safetly swap + if (x > x1) { + x = +e.data[0].start2; + xe = +e.data[0].end2; + x1 = +e.data[0].start1; + x1e = +e.data[0].end1; + } + + let zoomStart = x; + let zoomEnd = x1e; + let padding = (zoomEnd - zoomStart) / 4.0; + if (e.data[0].svclass === 'Translocation') { + zoomStart = x; + zoomEnd = xe; + padding = 10000; + } + + gosRef.current.api.zoomTo( + `${demo.id}-mid-ideogram`, + `chr1:${zoomStart}-${zoomEnd}`, + padding, + ZOOM_DURATION + ); + + // we will show the bam files, so set the initial positions + setBreakpoints([+x - ZOOM_PADDING, +xe + ZOOM_PADDING, +x1 - ZOOM_PADDING, +x1e + ZOOM_PADDING]); + setBpIntervals([x, xe, x1, x1e]); + setSelectedSvId(e.data[0].sv_id + ''); + + // move to the bottom + setTimeout( + () => document.getElementById('gosling-panel')?.scrollTo({ top: 1000000, behavior: 'smooth' }), + 2000 + ); + + leftReads.current = []; + rightReads.current = []; + }); + + gosRef.current.api.subscribe('mouseOver', (_, e) => { + const sanitizedChr = (c: string | number) => { + return `${c}`.replace('chr', ''); + }; + const calDir = (c1: string | number, c2: string | number) => { + c1 = sanitizedChr(c1); + c2 = sanitizedChr(c2); + if (+c1 && +c1 <= 9) { + c1 = '0' + c1; + } + if (+c2 && +c2 <= 9) { + c2 = '0' + c2; + } + return c1 < c2 ? 'rightward' : 'leftward'; + }; + if (e.id.includes('-mid-sv') && e.data[0].svclass === 'Translocation') { + const { chromosome: c, position: p } = e.genomicPosition; + const padding = 100000; + if (sanitizedChr(c) === sanitizedChr(e.data[0].chrom1)) { + const direction = calDir(c, e.data[0].chrom2); + const id = e.data[0].sv_id + '-' + direction; + if (id === prevJumpId.current) return; + const { start2, end2 } = e.data[0]; + setJumpButtonInfo({ + id, + x: mousePos.current.x, + y: mousePos.current.y, + direction, + zoomTo: () => gosRef.current.api.zoomTo(e.id, `chr1:${start2}-${end2}`, padding, ZOOM_DURATION) + }); + } else { + const direction = calDir(c, e.data[0].chrom1); + const id = e.data[0].sv_id + '-' + direction; + if (id === prevJumpId.current) return; + const { start1, end1 } = e.data[0]; + setJumpButtonInfo({ + id, + x: mousePos.current.x, + y: mousePos.current.y, + direction, + zoomTo: () => gosRef.current.api.zoomTo(e.id, `chr1:${start1}-${end1}`, padding, ZOOM_DURATION) + }); + } + } else { + setJumpButtonInfo(undefined); + } + }); + + return () => { + gosRef.current?.api.unsubscribe('click'); + gosRef.current?.api.unsubscribe('mouseOver'); + }; + }); + return (
{ diff --git a/src/track/driver.ts b/src/track/driver.ts index 8b5d1837..0b54673c 100644 --- a/src/track/driver.ts +++ b/src/track/driver.ts @@ -1,4 +1,4 @@ -import { SingleTrack } from 'gosling.js/dist/src/core/gosling.schema'; +import { SingleTrack } from 'gosling.js/dist/src/gosling-schema'; import { TrackMode } from './index'; export default function driver( diff --git a/src/track/gain.ts b/src/track/gain.ts index 33eb6a0f..79c3974e 100644 --- a/src/track/gain.ts +++ b/src/track/gain.ts @@ -1,4 +1,4 @@ -import { SingleTrack } from 'gosling.js/dist/src/core/gosling.schema'; +import { SingleTrack } from 'gosling.js/dist/src/gosling-schema'; import { TrackMode } from './index'; export default function gain( diff --git a/src/track/indel.ts b/src/track/indel.ts index fb88a190..6550521d 100644 --- a/src/track/indel.ts +++ b/src/track/indel.ts @@ -1,4 +1,4 @@ -import { OverlaidTracks } from 'gosling.js/dist/src/core/gosling.schema'; +import { OverlaidTracks } from 'gosling.js/dist/src/gosling-schema'; import { TrackMode } from './index'; export default function indel( diff --git a/src/track/loh.ts b/src/track/loh.ts index 5a01986b..da678df4 100644 --- a/src/track/loh.ts +++ b/src/track/loh.ts @@ -1,4 +1,4 @@ -import { SingleTrack } from 'gosling.js/dist/src/core/gosling.schema'; +import { SingleTrack } from 'gosling.js/dist/src/gosling-schema'; import { TrackMode } from './index'; export default function loh( diff --git a/src/track/mutation.ts b/src/track/mutation.ts index bf37b9a7..5f753776 100644 --- a/src/track/mutation.ts +++ b/src/track/mutation.ts @@ -1,4 +1,4 @@ -import { SingleTrack } from 'gosling.js/dist/src/core/gosling.schema'; +import { SingleTrack } from 'gosling.js/dist/src/gosling-schema'; import { TrackMode } from './index'; export default function mutation( diff --git a/src/track/sv.ts b/src/track/sv.ts index 84d5c7f9..93e71ff5 100644 --- a/src/track/sv.ts +++ b/src/track/sv.ts @@ -4,7 +4,7 @@ import { SingleTrack, StrReplaceTransform, SvTypeTransform -} from 'gosling.js/dist/src/core/gosling.schema'; +} from 'gosling.js/dist/src/gosling-schema'; import { consistentSv } from '../constants'; import defaults from '../default-encoding'; import { TrackMode } from '.';