Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
2764f1c
Setup basic viz app demo
matekdev Oct 1, 2021
b008dd8
Setup WIP demo picking page
matekdev Oct 1, 2021
80bd96b
Create demo dashboard, generic layout/navbar
matekdev Oct 1, 2021
a7b1d7b
Add WIP demo view
matekdev Oct 1, 2021
7a727ef
Style up pick demo screen
matekdev Oct 1, 2021
05f9a05
Change to dark theme buttons
matekdev Oct 1, 2021
8084dea
Add footer
matekdev Oct 1, 2021
33b352d
Fix merge conflicts
matekdev Oct 1, 2021
7623e62
Fix footer links
matekdev Oct 1, 2021
f8bbb88
Reorganize folder structure, add WIP data table and data metrics
matekdev Oct 1, 2021
3dc82a5
Add WIP slide menu
matekdev Oct 5, 2021
d04a32e
Add yarn file
matekdev Oct 5, 2021
9ca652d
Merge branch 'main' into viz-app-setup
matekdev Oct 7, 2021
9759f9f
Add header underline component
matekdev Oct 7, 2021
d521cd0
Add file selection hooks
matekdev Oct 8, 2021
f48f23a
Add render button, expose hooks into select data and render button
matekdev Oct 12, 2021
d39ca85
Expose data table and data metrics to top layer
matekdev Oct 12, 2021
470909d
Provide some margin to the footer
matekdev Oct 12, 2021
fbed8e3
WIP tab list
matekdev Oct 12, 2021
98d4c10
Expose demo view to top layer, fix up tab css
matekdev Oct 12, 2021
7bd8977
Style up tabs
matekdev Oct 12, 2021
d2d39de
Add in a temp data metrics
matekdev Oct 12, 2021
7047a1c
WIP extended table
matekdev Oct 13, 2021
0788c78
Extract data to outside the table
matekdev Oct 13, 2021
2051e85
Extract data to outside the table
matekdev Oct 13, 2021
9672c22
add box-select to ssr/graph
AjayThorve Oct 14, 2021
17052d1
update toggling box view
AjayThorve Oct 14, 2021
dc9659d
Merge with main
matekdev Oct 14, 2021
3be4355
minor fixes
AjayThorve Oct 14, 2021
b073e27
Merge branch 'viz-app-setup' of https://github.com/mzegar/node-rapids…
AjayThorve Oct 14, 2021
ea849c1
add video ssr to viz-demo
AjayThorve Oct 14, 2021
044c0c3
Add extended table pagination
matekdev Oct 14, 2021
1036c9c
Finish styling select
matekdev Oct 14, 2021
ab57874
Add white text button
matekdev Oct 14, 2021
815dfcd
Add toolbar with no icons
matekdev Oct 14, 2021
dad54e5
Use icons for tool bar
matekdev Oct 14, 2021
e173331
transfer callbacks to makeDeck
AjayThorve Oct 14, 2021
f291149
fix custom window width/height issue
AjayThorve Oct 14, 2021
17cf1eb
Fix up select styling
matekdev Oct 14, 2021
1c3fb6e
Add status to navbar
matekdev Oct 14, 2021
6001add
Add onclick css to table page selector
matekdev Oct 14, 2021
06b65b1
Change export to white file select
matekdev Oct 14, 2021
1d0392c
checkpoint
AjayThorve Oct 14, 2021
2bfe7f9
fixes multiple nodes not being selected issue
AjayThorve Oct 15, 2021
64b0bbe
resolve cudaErrorAlreadyMapped error
AjayThorve Oct 15, 2021
7aff017
add condition to access peer
AjayThorve Oct 15, 2021
1401656
Merge branch 'viz-app-setup' of https://github.com/mzegar/node-rapids…
AjayThorve Oct 15, 2021
fc3884a
Merge branch 'mzegar-viz-app-setup' into demo/ssr/box-select
AjayThorve Oct 15, 2021
1de488b
add toolbar
AjayThorve Oct 15, 2021
ce7a114
added dynamic table updates
AjayThorve Oct 15, 2021
4b72558
temp fix reconnection: true does not coz server fail on repeated refresh
AjayThorve Oct 15, 2021
6464905
add edge selection
AjayThorve Oct 15, 2021
aede537
minor fixes
AjayThorve Oct 15, 2021
013477f
viz app running instructions
AjayThorve Oct 15, 2021
23dfd64
add metrics hooks
AjayThorve Oct 15, 2021
a726aef
Uint8->Uint32
AjayThorve Oct 15, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"modules/demo/ssr/*",
"modules/demo/tfjs/*",
"modules/demo/client-server",
"modules/demo/viz-app",
"modules/demo/sql/*"
]
}
2 changes: 1 addition & 1 deletion modules/deck.gl/src/layers/edges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export class EdgeLayer extends (Layer as typeof DeckLayer) {
this.internalState.selectedSourceNodeId = this.internalState.highlightedSourceNodeId;
this.internalState.selectedTargetNodeId = this.internalState.highlightedTargetNodeId;
}

info.object = info.index; // deck.gl uses info.object to check if item has already been added
return info;
}
_getModel({gl, shaderCache}: DeckContext) {
Expand Down
1 change: 1 addition & 0 deletions modules/deck.gl/src/layers/nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ export class NodeLayer extends (Layer as typeof DeckLayer) {
this.internalState.selectedNodeId = this.internalState.highlightedNodeId;
this.internalState.selectedNodeIndex = this.internalState.highlightedNodeIndex;
}
info.object = info.index; // deck.gl uses info.object to check if item has already been added
return info;
}
_getModel({gl, shaderCache}: DeckContext) {
Expand Down
2 changes: 1 addition & 1 deletion modules/demo/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@
"command": "shellCommand.execute",
"args": {
"description": "Select a demo to debug",
"command": "echo client-server luma graph spatial xterm $(find modules/demo/deck modules/demo/tfjs modules/demo/ipc modules/demo/ssr modules/demo/sql -maxdepth 2 -type f -name 'package.json' -print0 | grep -z -v node_modules | tr -d '\\0' | sed -r 's@modules/demo/@@g' | sed -r 's@/package.json@ @g') | sort -Vr | sed -r 's@\\s@\\n@g'",
"command": "echo client-server viz-app luma graph spatial xterm $(find modules/demo/deck modules/demo/tfjs modules/demo/ipc modules/demo/ssr modules/demo/sql -maxdepth 2 -type f -name 'package.json' -print0 | grep -z -v node_modules | tr -d '\\0' | sed -r 's@modules/demo/@@g' | sed -r 's@/package.json@ @g') | sort -Vr | sed -r 's@\\s@\\n@g'",
}
},
]
Expand Down
167 changes: 123 additions & 44 deletions modules/demo/ssr/graph/plugins/graph/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const wrtc = require('wrtc');
const {MemoryView} = require('@nvidia/cuda');
const {Float32Buffer} = require('@nvidia/cuda');
const {GraphCOO} = require('@rapidsai/cugraph');
const {Series, Int32} = require('@rapidsai/cudf');

const {loadNodes, loadEdges} = require('./loader');
const {RenderCluster} = require('../../render/cluster');
Expand Down Expand Up @@ -54,12 +55,32 @@ function graphSSRClients(fastify) {

clients[stream.id] = {
video: source,
state: {},
state: {
pickingMode: 'click', // 'click', 'boxSelect'
selectedInfo: {},
boxSelectCoordinates: {rectdata: [{polygon: [[]], show: false}], startPos: null},
clearSelections: false
},
event: {},
props: {width, height, layout},
graph: await loadGraph(graphId),
frame: shmCreate(width * height * 3 / 2),
peer: peer,
};
if (clients[stream.id].graph.dataframes[0]) {
const res = getPaginatedRows(clients[stream.id].graph.dataframes[0]);
peer.send(JSON.stringify({
type: 'data',
data: {nodes: {data: res, length: clients[stream.id].graph.dataframes[0].numRows}}
}));
}
if (clients[stream.id].graph.dataframes[1]) {
const res = getPaginatedRows(clients[stream.id].graph.dataframes[1]);
peer.send(JSON.stringify({
type: 'data',
data: {edges: {data: res, length: clients[stream.id].graph.dataframes[1].numRows}}
}));
}

stream.addTrack(source.createTrack());
peer.streams.push(stream);
Expand All @@ -79,6 +100,18 @@ function graphSSRClients(fastify) {
clients[stream.id].event[data.type] = data;
break;
}
case 'pickingMode': {
clients[stream.id].state.pickingMode = data;
break;
}
case 'clearSelections': {
clients[stream.id].state.clearSelections = JSON.parse(data);
break;
}
case 'layout': {
clients[stream.id].props.layout = JSON.parse(data);
break;
}
}
}
}
Expand All @@ -95,22 +128,24 @@ function graphSSRClients(fastify) {
}

async function loadGraph(id) {
let dataframes = [];

if (!(id in graphs)) {
const asDeviceMemory = (buf) => new (buf[Symbol.species])(buf);
const [nodes, edges] = await Promise.all([loadNodes(id), loadEdges(id)]);
const src = edges.get('src');
const dst = edges.get('dst');
dataframes = await Promise.all([loadNodes(id), loadEdges(id)]);
const src = dataframes[1].get('src');
const dst = dataframes[1].get('dst');
graphs[id] = {
refCount: 0,
nodes: {
nodeRadius: asDeviceMemory(nodes.get('size').data),
nodeFillColors: asDeviceMemory(nodes.get('color').data),
nodeElementIndices: asDeviceMemory(nodes.get('id').data),
nodeRadius: asDeviceMemory(dataframes[0].get('size').data),
nodeFillColors: asDeviceMemory(dataframes[0].get('color').data),
nodeElementIndices: asDeviceMemory(dataframes[0].get('id').data),
},
edges: {
edgeList: asDeviceMemory(edges.get('edge').data),
edgeColors: asDeviceMemory(edges.get('color').data),
edgeBundles: asDeviceMemory(edges.get('bundle').data),
edgeList: asDeviceMemory(dataframes[1].get('edge').data),
edgeColors: asDeviceMemory(dataframes[1].get('color').data),
edgeBundles: asDeviceMemory(dataframes[1].get('bundle').data),
},
graph: new GraphCOO(src._col, dst._col, {directedEdges: true}),
};
Expand All @@ -124,24 +159,25 @@ function graphSSRClients(fastify) {
));

return {
gravity: 1.0,
gravity: 0.0,
linLogMode: false,
scalingRatio: 5.0,
barnesHutTheta: 0.0,
jitterTolerance: 0.05,
strongGravityMode: false,
outboundAttraction: false,
graph: graphs[id].graph,
edges: {
...graphs[id].edges,
length: graphs[id].graph.numEdges(),
},
nodes: {
...graphs[id].nodes,
length: graphs[id].graph.numNodes(),
nodeXPositions: pos.subarray(0, pos.length / 2),
nodeYPositions: pos.subarray(pos.length / 2),
},
edges: {
...graphs[id].edges,
length: graphs[id].graph.numEdges(),
},
dataframes: dataframes
};
}
}
Expand All @@ -152,8 +188,17 @@ function layoutAndRenderGraphs(clients) {
return () => {
for (const id in clients) {
const client = clients[id];
const sendToClient =
([nodes, edges]) => {
client.peer.send(JSON.stringify(
{type: 'data', data: {nodes: {data: getPaginatedRows(nodes), length: nodes.numRows}}}));
client.peer.send(JSON.stringify(
{type: 'data', data: {edges: {data: getPaginatedRows(edges), length: edges.numRows}}}));
}

if (client.isRendering) { continue; }
if (client.isRendering) {
continue;
}

const state = {...client.state};
const props = {...client.props};
Expand All @@ -170,55 +215,89 @@ function layoutAndRenderGraphs(clients) {
'mouseup',
'mouseleave',
'wheel',
'beforeunload'
'beforeunload',
'shiftKey',
'dragStart',
'dragOver'
].map((x) => client.event[x])
.filter(Boolean);

if (event.length === 0 && !props.layout) { continue; }
if (event.length !== 0) { client.event = Object.create(null); }
if (props.layout) { client.graph = forceAtlas2(client.graph); }
if (props.layout == true) { client.graph = forceAtlas2(client.graph); }

const {
width = client.props.width ?? 800,
height = client.props.height ?? 600,
} = client.state;

state.window = {width: width, height: height, ...client.state.window};

if (client.frame?.byteLength !== (width * height * 3 / 2)) {
shmDetach(client.frame.key, true);
client.frame = shmCreate(width * height * 3 / 2);
}

client.isRendering = true;

renderer.render(id,
{
state,
props,
event,
frame: client.frame.key,
graph: {
...client.graph,
graph: undefined,
edges: getIpcHandles(client.graph.edges),
nodes: getIpcHandles(client.graph.nodes),
},
},
(error, result) => {
client.isRendering = false;
if (id in clients) {
if (error) { throw error; }
result?.state && Object.assign(client.state, result.state);
// console.log(state?.deck?.props?.initialViewState);
// if (state?.deck?.props) {
// client.props.initialViewState = state.deck.props.initialViewState;
// }
client.video.onFrame({...result.frame, data: client.frame.buffer});
}
});
renderer.render(
id,
{
state,
props,
event,
frame: client.frame.key,
graph: {
...client.graph,
graph: undefined,
edges: getIpcHandles(client.graph.edges),
nodes: getIpcHandles(client.graph.nodes),
},
},
(error, result) => {
client.isRendering = false;
if (id in clients) {
if (error) { throw error; }
if (client.state.clearSelections == true) {
// clear selection is called once
result.state.clearSelections = false;

// reset selected state
result.state.selectedInfo.selectedNodes = [];
result.state.selectedInfo.selectedEdges = [];
result.state.selectedInfo.selectedCoordinates = {};
result.state.boxSelectCoordinates.rectdata = [{polygon: [[]], show: false}];

// send to client
if (client.graph.dataframes) { sendToClient(client.graph.dataframes); }
} else if (JSON.stringify(client.state.selectedInfo.selectedCoordinates) !==
JSON.stringify(result.state.selectedInfo.selectedCoordinates)) {
// selections updated
const nodes =
Series.new({type: new Int32, data: result.state.selectedInfo.selectedNodes});
const edges =
Series.new({type: new Int32, data: result.state.selectedInfo.selectedEdges});
if (client.graph.dataframes) {
sendToClient([
client.graph.dataframes[0].gather(nodes),
client.graph.dataframes[1].gather(edges)
]);
}
}
// copy result state to client's current state
result?.state && Object.assign(client.state, result.state);

client.video.onFrame({...result.frame, data: client.frame.buffer});
}
});
}
}
}

function getPaginatedRows(df, page = 1, rowsPerPage = 400) {
if (!df) { return {}; }
return df.head(page * rowsPerPage).tail(rowsPerPage).toArrow().toArray();
}

function forceAtlas2({graph, nodes, edges, ...params}) {
graph.forceAtlas2({...params, positions: nodes.nodeXPositions.buffer});
return {
Expand Down
8 changes: 1 addition & 7 deletions modules/demo/ssr/graph/plugins/graph/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,7 @@ function getDefaultNodes() {
'ustr::c',
'ustr::d'
])),
id: Series.new({
type: new Uint32,
data: [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39
]
}),
id: Series.sequence({type: new Uint32, init: 0, step: 1, size: 40}),
color: Series.new({
type: new Uint32,
data: [
Expand Down
25 changes: 24 additions & 1 deletion modules/demo/ssr/graph/public/video.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,21 @@
</head>

<body style="background:#2e2e2e; margin:0;">

<video autoplay muted width="800" height="600"></video>
<div>
<input type="checkbox" id="box-select" onchange="updatePan()">
<label for="box-select">box-select</label>
</div>

<div>
<button onclick="updateClearSelections()">clear selections</button>
</div>

<script src="https://cdn.jsdelivr.net/npm/simple-peer@9.11.0/simplepeer.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.1.3/socket.io.js"></script>
<script>
const sock = io({ transports: ['websocket'], reconnection: false });
const sock = io({ transports: ['websocket'], reconnection: true });
const video = document.querySelector('video');
const peer = new SimplePeer({
trickle: true,
Expand All @@ -31,6 +41,11 @@
// Negotiate handshake
sock.on('signal', (data) => peer.signal(data));
peer.on('signal', (data) => sock.emit('signal', data));
peer.on('data', (data) => {
var decoded = new TextDecoder().decode(data);
var decodedjson = JSON.parse(decoded);
console.log("got data from peer: ", decodedjson.data);
});

// Server video stream
peer.on('stream', (stream) => {
Expand Down Expand Up @@ -64,6 +79,14 @@
});
}

function updatePan(){
let value = document.getElementById("box-select").checked;
peer.send(JSON.stringify({type: 'pickingMode', data: value? "boxSelect" : "click"}));
}
function updateClearSelections(){
peer.send(JSON.stringify({ type: 'clearSelections', data: true}));
}

function serializeEvent(original) {
return Object
.getOwnPropertyNames(Object.getPrototypeOf(original))
Expand Down
Loading