From 00124b336e2edb6a26662c8a4c14afb9afddf56a Mon Sep 17 00:00:00 2001 From: evac-tcxr Date: Tue, 18 Jun 2024 13:18:54 -0400 Subject: [PATCH] centered cCRE graphs and other fixes --- example/data.json | 5 +- example/data2.json | 11 + example/data3.json | 607 +++++++++++++++++++++++++++ src/components/AppBar/AppBar.tsx | 129 +++--- src/components/Graph/Graph.tsx | 203 ++++++--- src/components/Graph/GraphButton.tsx | 29 +- src/components/Graph/Legend.tsx | 8 +- src/components/Graph/ScaleLegend.tsx | 2 +- src/components/Graph/types.ts | 2 +- stories/Graph.stories.tsx | 20 +- 10 files changed, 877 insertions(+), 139 deletions(-) create mode 100644 example/data3.json diff --git a/example/data.json b/example/data.json index af67074..e94bd7a 100644 --- a/example/data.json +++ b/example/data.json @@ -602,6 +602,9 @@ "category": "pELS", "simple": "Proximal Enhancer" } - ] + ], + "centered": { + "cCRE": "EH38E4193211" + } } } \ No newline at end of file diff --git a/example/data2.json b/example/data2.json index b94a07b..a38b226 100644 --- a/example/data2.json +++ b/example/data2.json @@ -6,6 +6,12 @@ "target": "node_2", "effectSize": 0.1134, "expressionImpact": "lower-expression" + }, + { + "perturbed": "node_3", + "target": "node_2", + "effectSize": 0.5, + "expressionImpact": "higher-expression" } ], "node": [ @@ -18,6 +24,11 @@ "cCRE": "node_2", "category": "CA-CTCF", "simple": "Chromatin Accessible + CTCF" + }, + { + "cCRE": "node_3", + "category": "CA-TF", + "simple": "Transcription Factor" } ] } diff --git a/example/data3.json b/example/data3.json new file mode 100644 index 0000000..af67074 --- /dev/null +++ b/example/data3.json @@ -0,0 +1,607 @@ +{ + "data": { + "edge": [ + { + "perturbed": "EH38E3291096", + "target": "EH38E1939823", + "effectSize": 0.1134, + "expressionImpact": "lower-expression" + }, + { + "perturbed": "EH38E1939823", + "target": "EH38E1939823", + "effectSize": 0.1933, + "expressionImpact": "lower-expression" + }, + { + "perturbed": "EH38E3291121", + "target": "EH38E1939823", + "effectSize": 0.0545, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291122", + "target": "EH38E1939823", + "effectSize": 0.0665, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291358", + "target": "EH38E1939823", + "effectSize": 0.0674, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291271", + "target": "EH38E3291279", + "effectSize": 0.0381, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291279", + "target": "EH38E3291279", + "effectSize": 0.1667, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291358", + "target": "EH38E3291279", + "effectSize": 0.0478, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291174", + "target": "EH38E3291410", + "effectSize": 0.0504, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E4193273", + "target": "EH38E3291410", + "effectSize": 0.0507, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291358", + "target": "EH38E3291410", + "effectSize": 0.0895, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291392", + "target": "EH38E3291410", + "effectSize": 0.0352, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291410", + "target": "EH38E3291410", + "effectSize": 0.2538, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291174", + "target": "EH38E4193228", + "effectSize": 0.0211, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291218", + "target": "EH38E4193228", + "effectSize": 0.0477, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291222", + "target": "EH38E4193228", + "effectSize": 0.0627, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291226", + "target": "EH38E4193228", + "effectSize": 0.0448, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E4193211", + "target": "EH38E4193228", + "effectSize": 0.0454, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291232", + "target": "EH38E4193228", + "effectSize": 0.0311, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291249", + "target": "EH38E4193228", + "effectSize": 0.0593, + "expressionImpact": "higher-expression" + + }, + { + "perturbed": "EH38E3291263", + "target": "EH38E4193228", + "effectSize": 0.1136, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291271", + "target": "EH38E4193228", + "effectSize": 0.4097, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291279", + "target": "EH38E4193228", + "effectSize": 0.1077, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E4193243", + "target": "EH38E4193228", + "effectSize": 0.026, + "expressionImpact": "higher-expression" + + }, + { + "perturbed": "EH38E3291318", + "target": "EH38E4193228", + "effectSize": 0.0297, + "expressionImpact": "higher-expression" + + }, + { + "perturbed": "EH38E4193273", + "target": "EH38E4193228", + "effectSize": 0.0405, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291358", + "target": "EH38E4193228", + "effectSize": 0.0918, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291779", + "target": "EH38E4193228", + "effectSize": 0.0263, + "expressionImpact": "higher-expression" + + }, + { + "perturbed": "EH38E4193467", + "target": "EH38E4193228", + "effectSize": 0.0374, + "expressionImpact": "higher-expression" + + }, + { + "perturbed": "EH38E1960374", + "target": "EH38E1960374", + "effectSize": 0.1853, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3312736", + "target": "EH38E1960374", + "effectSize": 0.0698, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E1960377", + "target": "EH38E1960374", + "effectSize": 0.1479, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E4201343", + "target": "EH38E1960374", + "effectSize": 0.1042, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E1960374", + "target": "EH38E3312774", + "effectSize": 0.143, + "expressionImpact": "higher-expression" + + }, + { + "perturbed": "EH38E3312736", + "target": "EH38E3312774", + "effectSize": 0.0864, + "expressionImpact": "higher-expression" + + }, + { + "perturbed": "EH38E1960377", + "target": "EH38E3312774", + "effectSize": 0.1641, + "expressionImpact": "higher-expression" + + }, + { + "perturbed": "EH38E4201343", + "target": "EH38E3312774", + "effectSize": 0.0652, + "expressionImpact": "higher-expression" + + }, + { + "perturbed": "EH38E3312746", + "target": "EH38E3312774", + "effectSize": 0.0835, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3312765", + "target": "EH38E3312774", + "effectSize": 0.0386, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3312774", + "target": "EH38E3312774", + "effectSize": 0.3507, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3312787", + "target": "EH38E3312774", + "effectSize": 0.0959, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E1940335", + "target": "EH38E3291664", + "effectSize": 0.0701, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291664", + "target": "EH38E3291664", + "effectSize": 0.3563, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291668", + "target": "EH38E3291664", + "effectSize": 0.1181, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291318", + "target": "EH38E3291358", + "effectSize": 0.0369, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291346", + "target": "EH38E3291358", + "effectSize": 0.108, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E4193273", + "target": "EH38E3291358", + "effectSize": 0.2005, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291358", + "target": "EH38E3291358", + "effectSize": 0.441, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291364", + "target": "EH38E3291358", + "effectSize": 0.0862, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291374", + "target": "EH38E3291358", + "effectSize": 0.0278, + "expressionImpact": "higher-expression" + + }, + { + "perturbed": "EH38E3291664", + "target": "EH38E3291358", + "effectSize": 0.0291, + "expressionImpact": "higher-expression" + + }, + { + "perturbed": "EH38E1939855", + "target": "EH38E3291249", + "effectSize": 0.0684, + "expressionImpact": "higher-expression" + + }, + { + "perturbed": "EH38E4193211", + "target": "EH38E3291249", + "effectSize": 0.0354, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291232", + "target": "EH38E3291249", + "effectSize": 0.0767, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291244", + "target": "EH38E3291249", + "effectSize": 0.0883, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291249", + "target": "EH38E3291249", + "effectSize": 0.1514, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291358", + "target": "EH38E3291249", + "effectSize": 0.0378, + "expressionImpact": "lower-expression" + + }, + { + "perturbed": "EH38E3291664", + "target": "EH38E3291249", + "effectSize": 0.0276, + "expressionImpact": "higher-expression" + + } + ], + "node": [ + { + "cCRE": "EH38E1939823", + "category": "PLS", + "simple": "Promoter" + }, + { + "cCRE": "EH38E1939855", + "category": "CA-CTCF", + "simple": "Chromatin Accessible + CTCF" + }, + { + "cCRE": "EH38E1940335", + "category": "dELS", + "simple": "Distal Enhancer" + }, + { + "cCRE": "EH38E1960374", + "category": "PLS", + "simple": "Promoter" + }, + { + "cCRE": "EH38E1960377", + "category": "pELS", + "simple": "Proximal Enhancer" + }, + { + "cCRE": "EH38E3291096", + "category": "PLS", + "simple": "Promoter" + }, + { + "cCRE": "EH38E3291121", + "category": "PLS", + "simple": "Promoter" + }, + { + "cCRE": "EH38E3291122", + "category": "PLS", + "simple": "Promoter" + }, + { + "cCRE": "EH38E3291174", + "category": "PLS", + "simple": "Promoter" + }, + { + "cCRE": "EH38E3291218", + "category": "PLS", + "simple": "Promoter" + }, + { + "cCRE": "EH38E3291222", + "category": "dELS", + "simple": "Distal Enhancer" + }, + { + "cCRE": "EH38E3291226", + "category": "dELS", + "simple": "Distal Enhancer" + }, + { + "cCRE": "EH38E3291232", + "category": "pELS", + "simple": "Proximal Enhancer" + }, + { + "cCRE": "EH38E3291244", + "category": "pELS", + "simple": "Proximal Enhancer" + }, + { + "cCRE": "EH38E3291249", + "category": "PLS", + "simple": "Promoter" + }, + { + "cCRE": "EH38E3291263", + "category": "pELS", + "simple": "Proximal Enhancer" + }, + { + "cCRE": "EH38E3291271", + "category": "PLS", + "simple": "Promoter" + }, + { + "cCRE": "EH38E3291279", + "category": "PLS", + "simple": "Promoter" + }, + { + "cCRE": "EH38E3291318", + "category": "CA-CTCF", + "simple": "Chromatin Accessible + CTCF" + }, + { + "cCRE": "EH38E3291346", + "category": "PLS", + "simple": "Promoter" + }, + { + "cCRE": "EH38E3291358", + "category": "PLS", + "simple": "Promoter" + }, + { + "cCRE": "EH38E3291364", + "category": "PLS", + "simple": "Promoter" + }, + { + "cCRE": "EH38E3291374", + "category": "CA-TF", + "simple": "Chromatin Accessible + Transcription Factor" + }, + { + "cCRE": "EH38E3291392", + "category": "PLS", + "simple": "Promoter" + }, + { + "cCRE": "EH38E3291410", + "category": "PLS", + "simple": "Promoter" + }, + { + "cCRE": "EH38E3291664", + "category": "PLS", + "simple": "Promoter" + }, + { + "cCRE": "EH38E3291668", + "category": "pELS", + "simple": "Proximal Enhancer" + }, + { + "cCRE": "EH38E3291779", + "category": "CA-CTCF", + "simple": "Chromatin Accessible + CTCF" + }, + { + "cCRE": "EH38E3312736", + "category": "pELS", + "simple": "Proximal Enhancer" + }, + { + "cCRE": "EH38E3312746", + "category": "dELS", + "simple": "Distal Enhancer" + }, + { + "cCRE": "EH38E3312765", + "category": "CA-TF", + "simple": "Chromatin Accessible + Transcription Factor" + }, + { + "cCRE": "EH38E3312774", + "category": "PLS", + "simple": "Promoter" + }, + { + "cCRE": "EH38E3312787", + "category": "CA-TF", + "simple": "Chromatin Accessible + Transcription Factor" + }, + { + "cCRE": "EH38E4193211", + "category": "pELS", + "simple": "Proximal Enhancer" + }, + { + "cCRE": "EH38E4193228", + "category": "PLS", + "simple": "Promoter" + }, + { + "cCRE": "EH38E4193243", + "category": "CA-H3K4me3", + "simple": "Chromatin Accessible + H3K4me3" + }, + { + "cCRE": "EH38E4193273", + "category": "pELS", + "simple": "Proximal Enhancer" + }, + { + "cCRE": "EH38E4193467", + "category": "CA-CTCF", + "simple": "Chromatin Accessible + CTCF" + }, + { + "cCRE": "EH38E4201343", + "category": "pELS", + "simple": "Proximal Enhancer" + } + ] + } +} \ No newline at end of file diff --git a/src/components/AppBar/AppBar.tsx b/src/components/AppBar/AppBar.tsx index 0bfd715..d699aa3 100644 --- a/src/components/AppBar/AppBar.tsx +++ b/src/components/AppBar/AppBar.tsx @@ -3,8 +3,13 @@ */ import React from 'react'; -import { AppBar as MUIAppBar, AppBarProps as MUIAppBarProps, Box, Toolbar } from '@mui/material'; -import { styled } from "@mui/material/styles" +import { + AppBar as MUIAppBar, + AppBarProps as MUIAppBarProps, + Box, + Toolbar, +} from '@mui/material'; +import { styled } from '@mui/material/styles'; import MenuItem from './MenuItem'; import DropDownMenuItem from './DropDownMenuItem'; @@ -17,71 +22,77 @@ import DropDownMenuItem from './DropDownMenuItem'; * @member onDownloadsClicked event handler for when the downloads link is clicked. */ export type AppBarProps = MUIAppBarProps & { - onHomepageClicked?: () => void; - onAboutClicked?: () => void; - onPortalClicked?: (index: number) => void; - onDownloadsClicked?: () => void; - centered?: boolean; + onHomepageClicked?: () => void; + onAboutClicked?: () => void; + onPortalClicked?: (index: number) => void; + onDownloadsClicked?: () => void; + centered?: boolean; }; export const StyledAppBar = styled(MUIAppBar)((props) => ({ - backgroundColor: "#ffffff", - color: "#000000", - alignItems: props.centered===true ? "center" : "left" - + backgroundColor: '#ffffff', + color: '#000000', + alignItems: props.centered === true ? 'center' : 'left', })); -export const PortalsMenuItem: React.FC<{ children?: React.ReactNode, onClick?: () => void }> = ({ children, onClick }) => ( - - {children} - +export const PortalsMenuItem: React.FC<{ + children?: React.ReactNode; + onClick?: () => void; +}> = ({ children, onClick }) => ( + + {children} + ); -const PortalsMenu: React.FC<{ onPortalClicked?: (index: number) => void }> = ({ onPortalClicked }) => ( - <> - onPortalClicked && onPortalClicked(0)}>Disease/Trait - onPortalClicked && onPortalClicked(1)}>Gene/b-cCRE - onPortalClicked && onPortalClicked(2)}>SNP/QTL - onPortalClicked && onPortalClicked(3)}>Single-Cell - +const PortalsMenu: React.FC<{ onPortalClicked?: (index: number) => void }> = ({ + onPortalClicked, +}) => ( + <> + onPortalClicked && onPortalClicked(0)}> + Disease/Trait + + onPortalClicked && onPortalClicked(1)}> + Gene/b-cCRE + + onPortalClicked && onPortalClicked(2)}> + SNP/QTL + + onPortalClicked && onPortalClicked(3)}> + Single-Cell + + ); -const AppBar: React.FC = props => ( - - - - - psych
 screen -
- } - > - Portals - - - About Us - - - Downloads - -
-
-
+const AppBar: React.FC = (props) => ( + + + + + psych +
+  screen +
+ } + > + Portals + + About Us + Downloads +
+
+
); export default AppBar; diff --git a/src/components/Graph/Graph.tsx b/src/components/Graph/Graph.tsx index 846250c..4bcb69c 100644 --- a/src/components/Graph/Graph.tsx +++ b/src/components/Graph/Graph.tsx @@ -4,7 +4,6 @@ import coseBilkent from 'cytoscape-cose-bilkent'; import { useTooltip, useTooltipInPortal, defaultStyles } from '@visx/tooltip'; import { useScreenshot } from 'use-react-screenshot'; import { cCREConstants, cCREClass, buttonStyle } from './constants'; -// import './Graph.css'; import { GraphProps, Node, Edge } from './types'; import Legend from './Legend'; import ScaleLegend from './ScaleLegend'; @@ -17,6 +16,12 @@ cytoscape.use(coseBilkent); interface ToolTipData { cCRE?: string; type: string; + centered?: string; +} + +function shortHand(str: string): string { + const simple = str as cCREClass; + return cCREConstants[simple]?.label || 'n/a'; } const download = (image: string, { name = 'img', extension = 'jpg' } = {}) => { @@ -41,6 +46,7 @@ const Graph: React.FC = ({ const [scales, setScales] = useState([]); const [expressionType, setExpressions] = useState([]); const [edges, setEdges] = useState([]); + const [showLabels, setShowLabels] = useState(true); // State for label visibility const [toggles, setToggles] = useState<{ [key: string]: boolean }>({ Promoter: true, 'Distal Enhancer': true, @@ -52,6 +58,7 @@ const Graph: React.FC = ({ 'Lower-Expression': true, 'Higher-Expression': true, }); + const [degree, setDegree] = useState(3); const toggleControls = () => { setShowControls(!showControls); @@ -83,7 +90,7 @@ const Graph: React.FC = ({ scroll: true, }); - const handleMouseOver = (event: cytoscape.EventObject, datum: any) => { + const handleMouseMove = (event: cytoscape.EventObject, datum: any) => { if (!containerRef.current) { console.error('Container ref is not set'); return; @@ -104,18 +111,77 @@ const Graph: React.FC = ({ // each graph needs a unique id let k = 'cy-' + id; - useEffect(() => { - setElements(data.node); - setEdges(data.edge); - setScales(data.edge.map((e: Edge) => e.effectSize)); - setExpressions( - data.edge.map((e: Edge) => - e.expressionImpact === 'higher-expression' - ? 'Higher-Expression' - : 'Lower-Expression' - ) - ); - }, [data]); + if (data.centered) { + // function to filter nodes and edges based on degree - do some check here for if centered even exists in data + const filterNodesAndEdges = (degree: number) => { + const centeredNode = data.centered.cCRE; + let nodesToInclude = new Set([centeredNode]); + let edgesToInclude: Edge[] = []; + let visited = new Set([centeredNode]); + + // queue to manage BFS traversal + let queue: { node: string; depth: number }[] = [ + { node: centeredNode, depth: 0 }, + ]; + + while (queue.length > 0) { + const { node, depth } = queue.shift()!; + + // if the curr depth = to the degree, skip further expansion + if (depth >= degree) continue; + + // find edges involving the current node + data.edge.forEach((edge) => { + const neighbors = [ + { target: edge.target, perturbed: edge.perturbed }, + { target: edge.perturbed, perturbed: edge.target }, + ]; + + neighbors.forEach(({ target, perturbed }) => { + if (perturbed === node && !visited.has(target)) { + visited.add(target); + nodesToInclude.add(target); + edgesToInclude.push(edge); + queue.push({ node: target, depth: depth + 1 }); + } + }); + }); + } + + // filter nodes to include only those found within the specified degrees of separation + const filteredNodes = data.node.filter((node) => + nodesToInclude.has(node.cCRE) + ); + return { nodes: filteredNodes, edges: edgesToInclude }; + }; + + useEffect(() => { + const filteredData = filterNodesAndEdges(degree); + setElements(filteredData.nodes); + setEdges(filteredData.edges); + setScales(filteredData.edges.map((e) => e.effectSize)); + setExpressions( + filteredData.edges.map((e) => + e.expressionImpact === 'higher-expression' + ? 'Higher-Expression' + : 'Lower-Expression' + ) + ); + }, [data, degree]); + } else { + useEffect(() => { + setElements(data.node); + setEdges(data.edge); + setScales(data.edge.map((e: Edge) => e.effectSize)); + setExpressions( + data.edge.map((e: Edge) => + e.expressionImpact === 'higher-expression' + ? 'Higher-Expression' + : 'Lower-Expression' + ) + ); + }, [data]); + } useEffect(() => { if ( @@ -148,18 +214,13 @@ const Graph: React.FC = ({ return cCREConstants[simple]?.color || 'grey'; } - function shortHand(str: string): string { - const simple = str as cCREClass; - return cCREConstants[simple]?.label || 'n/a'; - } - const cy = cytoscape({ container: document.getElementById(k), style: [ { selector: 'node', style: { - label: 'data(id)', + label: '', 'font-size': 15, }, }, @@ -206,7 +267,7 @@ const Graph: React.FC = ({ style: { // find color based on CRE 'background-color': chooseColor(i), - label: shortHand(elements[i].simple), + label: showLabels ? shortHand(elements[i].simple) : '', }, }); } @@ -246,19 +307,29 @@ const Graph: React.FC = ({ cy.nodes().forEach((node: NodeSingular) => { let cre = allcCREs[idx].toString(); let simple = elements[idx].simple.toString(); - node.on('mousemove', (event) => - handleMouseOver(event, { - cCRE: cre, - type: simple, - }) - ); + if (data.centered && cre === data.centered.cCRE) { + node.on('mousemove', (event) => + handleMouseMove(event, { + cCRE: cre, + type: simple, + centered: 'Centered Node', + }) + ); + } else { + node.on('mousemove', (event) => + handleMouseMove(event, { + cCRE: cre, + type: simple, + }) + ); + } idx++; node.on('mouseout', hideTooltip); }); cy.edges().forEach((edge: EdgeSingular) => { edge.on('mousemove', (event) => - handleMouseOver(event, { + handleMouseMove(event, { type: edge.style('line-color').toString() === 'rgb(0,0,0)' ? 'Lower-Expression' @@ -267,6 +338,7 @@ const Graph: React.FC = ({ ); edge.on('mouseout', hideTooltip); }); + organize(); return () => { cy.destroy(); @@ -281,6 +353,19 @@ const Graph: React.FC = ({ hideTooltip, ]); + useEffect(() => { + const allSIMPLE: string[] = elements.map((e) => e.simple); + + if (!cyRef.current) return; + let ind = 0; + cyRef.current.nodes().forEach((node) => { + node.style({ + label: showLabels ? shortHand(allSIMPLE[ind]) : '', // Update label based on `showLabels` + }); + ind++; + }); + }, [showLabels]); + // RANDOMIZE const randomize = () => { const cy = cyRef.current; @@ -318,39 +403,38 @@ const Graph: React.FC = ({ })); }; - // organize on any toggle change - useEffect(() => { - if (cyRef.current) { - organize(); - } - }, [toggles]); - const downloadStyle = { ...buttonStyle, - top: '5px', + top: '0px', right: '5px', }; const randomizeStyle = { ...buttonStyle, - top: '50px', + top: '45px', right: '5px', }; const organizeStyle = { ...buttonStyle, - top: '95px', + top: '90px', right: '5px', }; const toggleControlsStyle = { ...buttonStyle, - top: '5px', + top: '0px', padding: '3px', backgroundColor: 'white', color: '#0095ff', }; + const labelStyle = { + ...buttonStyle, + top: '135px', + right: '5px', + }; + const r = { collapsed: { right: '175px', @@ -359,6 +443,7 @@ const Graph: React.FC = ({ right: '2px', }, }; + console.log(showLabels); return (
= ({ fontFamily: 'helvetica', }} > +
+

{title}

+
+ {data.centered ? ( +
+ + setDegree(parseInt(e.target.value))} + /> +
+ ) : null} + {showControls && (
= ({ styles={organizeStyle} func={organize} > + setShowLabels(!showLabels)} + > @@ -420,21 +533,12 @@ const Graph: React.FC = ({ position: 'relative', }} > -
-

{title}

-
@@ -456,6 +560,7 @@ const Graph: React.FC = ({
cCRE: {tooltipData.cCRE}
Type: {tooltipData.type} + {tooltipData.centered ?
Centered Node
: null}
) : (
diff --git a/src/components/Graph/GraphButton.tsx b/src/components/Graph/GraphButton.tsx index 30de53b..60e9543 100644 --- a/src/components/Graph/GraphButton.tsx +++ b/src/components/Graph/GraphButton.tsx @@ -1,38 +1,25 @@ -import React from 'react'; +import React, { CSSProperties } from 'react'; interface buttonProps { text: string; - styles: any; + styles: CSSProperties; func: any; } const GraphButton: React.FC = ({ text, styles, func }) => { const randID = Math.random() * 1000000; const r = randID + ''; - - function mouseover(): null | undefined | void { - const c = document.getElementById(r); - if (c === null) { - return null; - } - c.style.backgroundColor = '#07c'; - } - - function mouseout(): null | undefined | void { - const c = document.getElementById(r); - if (c === null) { - return null; - } - c.style.backgroundColor = '#0095ff'; - } - return ( <>
diff --git a/src/components/Graph/ScaleLegend.tsx b/src/components/Graph/ScaleLegend.tsx index b44cbf2..f630e6c 100644 --- a/src/components/Graph/ScaleLegend.tsx +++ b/src/components/Graph/ScaleLegend.tsx @@ -40,7 +40,7 @@ const ScaleLegend: React.FC = ({ scales }) => { const divStyle: CSSProperties = { position: 'absolute', - top: '150px', + top: '200px', right: '10px', zIndex: 1000, backgroundColor: 'white', diff --git a/src/components/Graph/types.ts b/src/components/Graph/types.ts index e437e46..35ecc60 100644 --- a/src/components/Graph/types.ts +++ b/src/components/Graph/types.ts @@ -13,7 +13,7 @@ export interface Edge { export interface GraphProps { data: { - edge: Edge[], node: Node[] + edge: Edge[], node: Node[], centered: {cCRE: string} }, title?: string, id: number | string, diff --git a/stories/Graph.stories.tsx b/stories/Graph.stories.tsx index 4d4e7fe..c2f04dd 100644 --- a/stories/Graph.stories.tsx +++ b/stories/Graph.stories.tsx @@ -3,6 +3,7 @@ import { Meta, Story } from '@storybook/react'; import { Graph } from '../src'; import { GraphProps } from '../src'; import data2 from '../example/data2.json'; +import data3 from '../example/data3.json'; import data from '../example/data.json'; import '../src/App.css'; @@ -15,11 +16,15 @@ export default meta; const Template: Story = (args) => ; export const SampleGraph = Template.bind({}); -SampleGraph.args = { data: data2.data, title: 'Sample Graph', id: 1 }; -export const GraphWithPilotData = Template.bind({}); -GraphWithPilotData.args = { +SampleGraph.args = { + data: data2.data, + title: 'Sample Graph With No Centered cCRE', + id: 1, +}; +export const PilotDataWithCentered = Template.bind({}); +PilotDataWithCentered.args = { data: data.data, - title: 'cCRE Impact With Pilot Data', + title: 'cCRE Impact With Pilot Data With Centered cCRE', id: 'hello', }; @@ -31,3 +36,10 @@ FiftyPercent.args = { width: '50%', height: '50%', }; + +export const PilotDataWithoutCentered = Template.bind({}); +PilotDataWithoutCentered.args = { + data: data3.data, + title: 'cCRE Impact With Pilot Data Without Centered cCRE', + id: 'hi', +};