Skip to content

Commit

Permalink
feat: mirror gene tree horizontally
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-aksamentov committed Jan 17, 2023
1 parent 4b745ee commit d25bdf7
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 10 deletions.
5 changes: 4 additions & 1 deletion src/components/Tree/GeneTree.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import React, { memo, useMemo } from 'react'
import { useRecoilValue } from 'recoil'
import { useResizeDetector } from 'react-resize-detector'
import { useGeneClusterData } from 'src/hooks/useDataIndexQuery'
import type { GeneCluster, SpeciesDesc } from 'src/hooks/useDataIndexQuery'
import { convertPhyloTreeToGraph } from 'src/components/Tree/PhyloGraph/convertPhyloTreeToGraph'
import { PhyloGraph } from 'src/components/Tree/PhyloGraph/PhyloGraph'
import { geneTreeOptionsAtom } from 'src/state/tree.state'

export interface GeneTreeProps {
species: SpeciesDesc
gene: GeneCluster
}

function GeneTreeUnmemo({ species, gene }: GeneTreeProps) {
const geneTreeOptions = useRecoilValue(geneTreeOptionsAtom)
const { tree, meta } = useGeneClusterData(species, gene)
const graph = useMemo(() => {
if (!tree || !meta) {
Expand All @@ -34,7 +37,7 @@ function GeneTreeUnmemo({ species, gene }: GeneTreeProps) {

return (
<div className="w-100 h-100" ref={containerRef}>
<PhyloGraph width={width} height={height} graph={graph} />
<PhyloGraph width={width} height={height} graph={graph} options={geneTreeOptions} />
</div>
)
}
Expand Down
9 changes: 5 additions & 4 deletions src/components/Tree/PhyloGraph/PhyloGraph.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
import React, { memo, useMemo } from 'react'
import { Stage, Layer } from 'react-konva'
import { verifyGraph } from 'src/components/Tree/PhyloGraph/verifyGraph'
import { calculateGraphLayout, GraphRaw } from './graph'
import { calculateGraphLayout, GraphLayoutOptions, GraphRaw } from './graph'
import { Node } from './Node'
import { Edge } from './Edge'

export interface PhyloGraphProps {
width?: number
height?: number
graph: GraphRaw
options?: GraphLayoutOptions
}

export const PhyloGraph = memo(PhyloGraphUnmemo)

function PhyloGraphUnmemo({ width, height, graph: graphRaw }: PhyloGraphProps) {
function PhyloGraphUnmemo({ width, height, graph: graphRaw, options }: PhyloGraphProps) {
const { nodeComponents, edgeComponents } = useMemo(() => {
if (!width || !height) {
return { nodeComponents: [], edgeComponents: [] }
}
verifyGraph(graphRaw)
const graph = calculateGraphLayout(graphRaw, width, height)
const graph = calculateGraphLayout(graphRaw, width, height, options)
const nodeComponents = graph.nodes.map((node) => <Node key={node.id} graph={graph} node={node} />)
const edgeComponents = graph.edges.map((edge) => <Edge key={edge.id} graph={graph} edge={edge} />)
return { nodeComponents, edgeComponents }
}, [graphRaw, height, width])
}, [graphRaw, height, options, width])

return (
<Stage width={width} height={height}>
Expand Down
22 changes: 18 additions & 4 deletions src/components/Tree/PhyloGraph/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,16 @@ export interface GraphEdge {
target: string
}

export function calculateGraphLayout(graphRaw: GraphRaw, width: number, height: number): Graph {
export interface GraphLayoutOptions {
mirrored?: boolean
}

export function calculateGraphLayout(
graphRaw: GraphRaw,
width: number,
height: number,
options?: GraphLayoutOptions,
): Graph {
const graph: Graph = { ...cloneDeep(graphRaw), nodes: graphRaw.nodes.map(convertNode) }

let rank = 0
Expand Down Expand Up @@ -118,12 +127,17 @@ export function calculateGraphLayout(graphRaw: GraphRaw, width: number, height:
const ySpacing = (height - PHYLO_GRAPH_NODE_RADIUS * 2) / rank

graph.nodes.forEach((node) => {
node.x = node.layout.meanDepth * xSpacing + PHYLO_GRAPH_NODE_RADIUS
const x = node.layout.meanDepth * xSpacing + PHYLO_GRAPH_NODE_RADIUS
node.x = options?.mirrored ? width - x : x
node.y = node.layout.meanRank * ySpacing + PHYLO_GRAPH_NODE_RADIUS
if (!isLeafNode(graph, node.id)) {
node.layout.xTBarStart = node.layout.meanDepth * xSpacing + PHYLO_GRAPH_NODE_RADIUS
const xTBarStart = node.layout.meanDepth * xSpacing + PHYLO_GRAPH_NODE_RADIUS
const xTBarEnd = node.layout.meanDepth * xSpacing + PHYLO_GRAPH_NODE_RADIUS

node.layout.xTBarStart = options?.mirrored ? width - xTBarStart : xTBarStart
node.layout.xTBarEnd = options?.mirrored ? width - xTBarEnd : xTBarEnd

node.layout.yTBarStart = node.layout.minRank * ySpacing + PHYLO_GRAPH_NODE_RADIUS
node.layout.xTBarEnd = node.layout.meanDepth * xSpacing + PHYLO_GRAPH_NODE_RADIUS
node.layout.yTBarEnd = node.layout.maxRank * ySpacing + PHYLO_GRAPH_NODE_RADIUS
}
})
Expand Down
10 changes: 9 additions & 1 deletion src/state/tree.state.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { atomFamily } from 'recoil'
import { atom, atomFamily } from 'recoil'
import { GraphLayoutOptions } from 'src/components/Tree/PhyloGraph/graph'

export const highlightedNodeAtom = atomFamily<boolean, string>({
key: 'highlightedNodeAtom',
default: false,
})

export const geneTreeOptionsAtom = atom<GraphLayoutOptions>({
key: 'geneTreeOptionsAtom',
default: {
mirrored: true,
},
})

1 comment on commit d25bdf7

@vercel
Copy link

@vercel vercel bot commented on d25bdf7 Jan 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

pangenome – ./

pangenome-git-react-app-neherlab.vercel.app
pangenome-neherlab.vercel.app

Please sign in to comment.