Skip to content

Commit

Permalink
VT-23. Add functionality to expand nodes in the ontology
Browse files Browse the repository at this point in the history
  • Loading branch information
romina1601 committed Aug 22, 2024
1 parent 5a9a61a commit d2f9d6a
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 39 deletions.
67 changes: 40 additions & 27 deletions src/components/GaphView.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react';
import ForceGraph2D from 'react-force-graph-2d';
import { fetchNodeByLabel, fetchNodeConnections } from '../handler';
import { fetchNodeByLabel, fetchNodeChildren } from '../handler';
import { ISelectedNodeType } from './interfaces/InfoBoxInterfaces';
import { ILinkType, INodeType } from './interfaces/GraphViewInterfaces';
import { ITreeNode } from './interfaces/TreeViewInterfaces';
Expand Down Expand Up @@ -33,7 +33,7 @@ export const GraphViewComponent: React.FC<IGraphViewProps> = ({
}, [searchLabel]);

const buildTree = (currentNode: INodeType): ITreeNode => {
const nodeMap = new Map<number, ITreeNode>();
const nodeMap = new Map<string, ITreeNode>();

// Initialize parents and children for all nodes in graph
data.nodes.forEach(node => {
Expand All @@ -45,17 +45,13 @@ export const GraphViewComponent: React.FC<IGraphViewProps> = ({
parents: []
});
});
console.log(nodeMap);

const currentTreeNode = nodeMap.get(currentNode.id)!;

// Get parents and children
data.links.forEach(link => {
console.log('Link: ', link);
const sourceNode = nodeMap.get(link.source);
const targetNode = nodeMap.get(link.target);
console.log('Source Node: ', sourceNode);
console.log('Target Node: ', targetNode);

if (sourceNode && targetNode) {
if (link.target === currentNode.id) {
Expand All @@ -81,38 +77,55 @@ export const GraphViewComponent: React.FC<IGraphViewProps> = ({
type: node.type,
definition: node.definition,
iri: node.iri,
childNodes: node.childNodes,
childLinks: node.childLinks,
collapsed: false
});
console.log('Node clicked');
console.log('Node clicked: ', node);
node.collapsed = !node.collapsed;

// Build the tree view for the clicked node
const tree = buildTree(node);
setTreeData(tree);

const connections = await fetchNodeConnections(node.label);

const nodesById = Object.fromEntries(
data.nodes.map(node => [node.id, node])
);

// link parent/children
data.nodes.forEach(n => {
n.collapsed = n.id !== node.id;
n.childLinks = [];
});
const connections = await fetchNodeChildren(node.label, node.id);
console.log('GraphView connections: ', connections);
node.childNodes = connections.nodes;
node.childLinks = connections.links;
console.log(node.childNodes);
console.log(node.childLinks);

const visibleNodes: INodeType[] = [];
const visibleLinks: ILinkType[] = [];
let newNodes: INodeType[] = [];
let newLinks: ILinkType[] = [];
const visitedIds: string[] = [];

for (const n of data.nodes) {
visitedIds.push(n.id);
}

connections!.links.forEach(link => {
const sourceNode = nodesById[link.source];
if (sourceNode) {
sourceNode.childLinks!.push(link);
const processNode = (n: INodeType) => {
console.log('PROCESSING NODE: ', n);
if (!visitedIds.includes(n.id)) {
visitedIds.push(n.id);
visibleNodes.push(n);
}
if (!n.collapsed) {
visibleLinks.push(...n.childLinks!);
for (const childNode of n.childNodes!) {
processNode(childNode);
}
} else {
console.error(
`Node with id ${link.source} does not exist in nodesById`
);
return;
}
});
data.nodes = Object.values(nodesById);
};

processNode(node);
newNodes = [...data.nodes, ...visibleNodes];
newLinks = [...data.links, ...visibleLinks];
console.log(newNodes);
setData({ nodes: newNodes, links: newLinks });
};

// Handle search
Expand Down
1 change: 1 addition & 0 deletions src/components/InfoBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const InfoBoxComponent: React.FC<IInfoBoxProps> = ({

return (
<div className="info-box">
<h3>Concept Details</h3>
{selectedNode ? (
<div>
<h3>Node Information</h3>
Expand Down
7 changes: 4 additions & 3 deletions src/components/interfaces/GraphViewInterfaces.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
export interface INodeType {
id: number;
id: string;
label: string;
type: string;
definition: string;
iri: string;
x?: number;
y?: number;
collapsed?: boolean;
childNodes?: INodeType[];
childLinks?: ILinkType[];
}

export interface ILinkType {
source: number;
target: number;
source: string;
target: string;
type: string;
}
5 changes: 3 additions & 2 deletions src/components/interfaces/InfoBoxInterfaces.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { ILinkType } from './GraphViewInterfaces';
import { ILinkType, INodeType } from './GraphViewInterfaces';

export interface ISelectedNodeType {
label: string;
type: string;
definition: string;
iri: string;
childLinks?: ILinkType[],
childNodes?: INodeType[];
childLinks?: ILinkType[];
collapsed?: boolean;
}
2 changes: 1 addition & 1 deletion src/components/interfaces/TreeViewInterfaces.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export interface ITreeNode {
id: number;
id: string;
label: string;
type: string;
children: ITreeNode[];
Expand Down
17 changes: 14 additions & 3 deletions src/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,32 @@ export async function requestAPI<T>(
return data;
}

export async function fetchNodeByLabel(label: string): Promise<any> {
export async function fetchNodeByLabel(label: string): Promise<{ nodes: INodeType[]; links: ILinkType[] }> {
try {
const response = await requestAPI<any>(`node?label=${label}`);
return response;
} catch (error) {
console.error(`Error fetching node data: ${error}`);
return { nodes: [], links: []};
}
}

export async function fetchNodeConnections(label: string): Promise<{ nodes: INodeType[]; links: ILinkType[] } | null> {
export async function fetchNodeConnections(label: string): Promise<{ nodes: INodeType[]; links: ILinkType[] }> {
try {
const response = await requestAPI<{ nodes: INodeType[]; links: ILinkType[] }>(`node-connections?label=${label}`);
return response;
} catch (error) {
console.error(`Error fetching node data: ${error}`);
return null;
return { nodes: [], links: [] };
}
}

export async function fetchNodeChildren(label: string, id: string): Promise<{ nodes: INodeType[]; links: ILinkType[] }> {
try {
const response = await requestAPI<{ nodes: INodeType[]; links: ILinkType[] }>(`node-children-connections?label=${label}&id=${id}`);
return response;
} catch (error) {
console.error(`Error fetching node data: ${error}`);
return { nodes: [], links: [] };
}
}
34 changes: 31 additions & 3 deletions tvb_ext_ontology/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ def get(self):
return

node_data = onto_api.get_node_by_label(label)
print(f'Links: {node_data["links"]}')
if not node_data:
self.set_status(404)
self.finish(json.dumps({"error": f"No data found for label: {label}"}))
Expand All @@ -52,7 +51,34 @@ def get(self):
nodes = onto_api.nodes
links = onto_api.edges
node_data = {'nodes': nodes, 'links': links}
print(f'Connections links: {node_data["links"]}')
if not node_data:
self.set_status(404)
self.finish(json.dumps({"error": f"No data found for label: {label}"}))
return

self.set_header("Content-Type", "application/json")
self.finish(json.dumps(node_data))


class NodeChildrenConnectionsHandler(APIHandler):
@tornado.web.authenticated
def get(self):
label = self.get_argument('label', None)
id = self.get_argument('id', None)
if not label:
self.set_status(400)
self.finish(json.dumps({"error": "Missing 'label' parameter"}))
return
if not id:
self.set_status(400)
self.finish(json.dumps({"error": "Missing 'ID' parameter"}))
return
print(f'Label: {label}')
print(f'ID: {id}')
onto_api.expand_node_relationships(label)
# print(onto_api.nodes)
node_data = onto_api.get_child_connections(id)
print(f'node_data: {node_data}')
if not node_data:
self.set_status(404)
self.finish(json.dumps({"error": f"No data found for label: {label}"}))
Expand All @@ -69,10 +95,12 @@ def setup_handlers(web_app):
route_pattern = url_path_join(base_url, "tvb-ext-ontology", "get-example")
node_pattern = url_path_join(base_url, "tvb-ext-ontology", "node")
node_connections_pattern = url_path_join(base_url, "tvb-ext-ontology", "node-connections")
node_children_connections_pattern = url_path_join(base_url, "tvb-ext-ontology", "node-children-connections")

handlers = [
(route_pattern, RouteHandler),
(node_pattern, NodeHandler),
(node_connections_pattern, NodeConnectionsHandler)
(node_connections_pattern, NodeConnectionsHandler),
(node_children_connections_pattern, NodeChildrenConnectionsHandler)
]
web_app.add_handlers(host_pattern, handlers)

0 comments on commit d2f9d6a

Please sign in to comment.