Skip to content

Commit

Permalink
v0.4.1 changes include new edge animations features and updated deps
Browse files Browse the repository at this point in the history
  • Loading branch information
itsMando committed Nov 20, 2024
1 parent afe33fa commit 9b56c39
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 68 deletions.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,21 @@ asar: true
files:
- from: ./
filter:
- "!data${/*}"
- "!socket_testing${/*}"
- "!node_modules${/*}"
- "!local-server${/*}"
- "!renderer/src${/*}"
- "!themes${/*}"
- "!config${/*}"
- "!data${/*}"
- "!out${/*}"
extraResources:
- ./GLIMPSE-Event-API.pdf
- ./socket_testing/**
- ./local-server/server/**
- ./themes/**
- ./data/**
- ./config/**
- ./local-server/**
- ./data/**
win:
target:
- target: msi
Expand Down
35 changes: 23 additions & 12 deletions glimpse/local-server/server.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from flask import Flask, request as req
from flask_socketio import SocketIO
# from engineio.async_drivers import gevent
import networkx as nx
import glm
import json
Expand All @@ -8,19 +9,19 @@
GRAPH = nx.MultiGraph()

#Convert glm file to python dictionary
def glm_to_dict( file_paths: list ):
def glm_to_dict( file_paths: list ) -> dict:
glm_dicts = {}
for glm_path in file_paths:
glm_dicts[ path.basename(glm_path).split(".")[0] + ".json" ] = glm.load(glm_path)

return glm_dicts

#Converts glm dict to json
def dict2json( glm_dict: dict ):
def dict2json( glm_dict: dict ) -> str:
glm_json = json.dumps( glm_dict, indent= 3 )
return glm_json

def create_graph(data: dict, set_communities=False):
def create_graph(data: dict, set_communities: bool=False) -> dict:
GRAPH.clear()

for obj in data["objects"]:
Expand All @@ -37,12 +38,12 @@ def create_graph(data: dict, set_communities=False):
nx.set_node_attributes(GRAPH, community_ids, "glimpse_community_id")
return nx.get_node_attributes(G=GRAPH, name="glimpse_community_id")

def get_modularity():
def get_modularity() -> float:
modularity = nx.community.modularity(GRAPH, nx.community.label_propagation_communities(GRAPH))
return modularity

# long computation with larger graphs
def get_avg_betweenness_centrality():
def get_avg_betweenness_centrality() -> float:
my_k = int(GRAPH.number_of_nodes()*0.68)
betweenness_centrality_dict = nx.betweenness_centrality(GRAPH, k=my_k)

Expand All @@ -65,33 +66,43 @@ def get_avg_betweenness_centrality():
def hello():
return {"api": "GLIMPSE flask backend"}

'''
This endpoint gets the paths of the uploaded glm files to be converted to JSON
'''
@app.route("/glm2json", methods=["POST"])
def glm_to_json():
paths = req.get_json()
glm_dict = glm_to_dict(paths)

return dict2json(glm_dict)

'''
This endpoint will create a networkx GRAPH object in this server. If the graph data is a list
then most likely there is a true value where this end point needs to return a dict of community IDs
'''
@app.route("/create-nx-graph", methods=["POST"])
def create_nx_graph():
graphData = req.get_json()

if isinstance(graphData, dict):
create_graph(graphData)
return '', 204
return "", 204
elif isinstance(graphData, list):
#index 0 contains the data and index 1 contains a bool value whether to set the community IDs as well
community_ids = create_graph(data=graphData[0], set_communities=graphData[1])
return community_ids


'''
This endpoint gathers some summary statistics using networkx and the already existing GRAPH object.
'''
@app.route("/get-stats", methods=["GET"])
def get_stats():
summary_stats = {
'#Nodes': GRAPH.number_of_nodes(),
'#Edges': GRAPH.number_of_edges(),
'#ConnectedComponets': nx.number_connected_components(GRAPH),
'modularity': get_modularity(),
'avgBetweennessCentrality': get_avg_betweenness_centrality()
"#Nodes": GRAPH.number_of_nodes(),
"#Edges": GRAPH.number_of_edges(),
"#ConnectedComponets": nx.number_connected_components(GRAPH),
"modularity": get_modularity(),
"avgBetweennessCentrality": get_avg_betweenness_centrality()
}

return summary_stats
Expand Down
10 changes: 4 additions & 6 deletions glimpse/local-server/server.spec
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
# -*- mode: python ; coding: utf-8 -*-

from PyInstaller.utils.hooks import collect_data_files
from PyInstaller.utils.hooks import collect_submodules
import sys

sys.setrecursionlimit(sys.getrecursionlimit() * 5)

datas = []

datas += collect_data_files("engineio")
hiddenimports = collect_submodules('engineio.async_drivers') + collect_submodules('gevent')

a = Analysis(
['server.py'],
pathex=[],
binaries=[],
datas=datas,
hiddenimports=[],
datas=[],
hiddenimports=hiddenimports,
hookspath=[],
hooksconfig={},
runtime_hooks=[],
Expand Down
10 changes: 6 additions & 4 deletions glimpse/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,9 @@ const json2glmFunc = async (jsonData) => {

const parsedData = JSON.parse(jsonData);
const json2glmArg =
process.platform == "darwin" ? ".\\tools\\json2glm" : ".\\tools\\json2glm.exe";
process.platform == "darwin"
? path.join(__dirname, "tools", "json2glm")
: path.join(__dirname, "tools", "json2glm.exe");

// for each json file data, make a json file and turn it to a glm file
for (const file of Object.keys(parsedData)) {
Expand Down Expand Up @@ -373,10 +375,10 @@ const makeSplashWindow = () => {
resizable: false,
movable: true,
roundedCorners: true,
icon: "./assets/GLIMPSE_color_icon.ico",
icon: path.join(__dirname, "assets", "GLIMPSE_color_icon.ico"),
});

splashWindow.loadFile("./splash_window/splash-window.html");
splashWindow.loadFile(path.join(__dirname, "splash_window", "splash-window.html"));
splashWindow.center();
};

Expand All @@ -394,7 +396,7 @@ const initiateServer = () => {
return;
}
} else {
const python = spawn("python", ["./local-server/server.py"]);
const python = spawn("python", [path.join(__dirname, "local-server", "server.py")]);
python.stdout.on("data", function (data) {
console.log("data: ", data.toString("utf8"));
});
Expand Down
26 changes: 12 additions & 14 deletions glimpse/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"productName": "GLIMPSE",
"version": "0.4.0",
"version": "0.4.1",
"main": "main.js",
"description": "A lightweight graph-based power grid model visualization tool",
"author": "Armando Mendoza Sanchez",
Expand All @@ -20,32 +20,30 @@
"@emotion/styled": "^11.13.0",
"@mui/icons-material": "^6.1.7",
"@mui/material": "^6.1.7",
"ajv": "^8.12.0",
"ajv": "^8.17.1",
"axios": "^1.7.7",
"mui-color-input": "^5.0.1",
"react": "^18.3.1",
"react-dom": "^18.2.0",
"react-dom": "^18.3.1",
"react-draggable": "^4.4.6",
"socket.io-client": "^4.7.4",
"socket.io-client": "^4.8.1",
"tree-kill": "^1.2.2",
"vis-data": "^7.1.7",
"vis-data": "^7.1.9",
"vis-network": "^9.1.9"
},
"devDependencies": {
"@babel/core": "^7.23.0",
"@babel/core": "^7.26.0",
"@babel/preset-env": "^7.22.20",
"@babel/preset-react": "^7.22.15",
"@electron-forge/cli": "^7.3.0",
"babel-loader": "^9.1.3",
"css-loader": "^6.8.1",
"@electron-forge/cli": "^7.5.0",
"babel-loader": "^9.2.1",
"css-loader": "^7.1.2",
"electron": "^26.4.0",
"electron-builder": "^25.1.8",
"electron-reload": "^2.0.0-alpha.1",
"eslint": "^9.5.0",
"sass": "^1.68.0",
"sass-loader": "^13.3.2",
"style-loader": "^3.3.3",
"webpack": "^5.95.0",
"eslint": "^9.15.0",
"style-loader": "^4.0.0",
"webpack": "^5.96.1",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^5.1.0"
},
Expand Down
12 changes: 11 additions & 1 deletion glimpse/renderer/src/components/About.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const About = ({ show, close }) => {
</div>
<DialogContent sx={{ maxWidth: "72rem", padding: "0 2rem" }}>
<div className="about-title">
<h1>GLIMPSE v0.4.0</h1>
<h1>GLIMPSE v0.4.1</h1>
<h3>(Grid Layout Interface for Model Preview and System Exploration)</h3>
</div>
<div className="description">
Expand Down Expand Up @@ -106,6 +106,16 @@ const About = ({ show, close }) => {
an empty space will now show the option to create a new edge which can be
used to create connections between multiple models being visualized.
</li>
<li>
If there are multiple models you can right click on a node that belongs to a
model and cluster that model.
</li>
<li>
Right clicking on an edge will now give you the option to animate that edge.
This animated edge will persist when clustering and de-clustering if the
edge is between models. Right clicking on an animated edge and clicking the
animate edge context menu item will remove the animation.
</li>
<li>
{`Using GLIMPSE's local WebSocket API a key value pair such as {animation: true} can be supplied to an existing edge to show an animation of a small red circle following the edge's path.`}
</li>
Expand Down
2 changes: 1 addition & 1 deletion glimpse/renderer/src/components/Graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,7 @@ const Graph = ({ dataToVis, theme, isGlm }) => {
for (let i = 0; i < replacedEdgeIDs.length; i++) {
if (!edgesToAnimate.includes(replacedEdgeIDs[i])) continue;

// remove the replaced ID from the edges to animate list
// remove the replaced/base edge ID from the edges to animate list
edgesToAnimate.splice(edgesToAnimate.indexOf(replacedEdgeIDs[i]), 1);
delete positions[replacedEdgeIDs[i]];
}
Expand Down
File renamed without changes
2 changes: 1 addition & 1 deletion glimpse/splash_window/splash-window.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
</head>
<body>
<div class="img-wrapper">
<img src="NSD_2294_BRAND_HAGEN-GLIMPSE_final_color.png" alt="GLIMPSE-LOGO">
<img src="GLIMPSE_color.png" alt="GLIMPSE-LOGO">
</div>
</body>
</html>
54 changes: 28 additions & 26 deletions glimpse/webpack.common.js
Original file line number Diff line number Diff line change
@@ -1,46 +1,48 @@
const path = require('path');
const path = require("path");

module.exports = {
mode: 'development',
entry: './renderer/src/index.js',
devtool: 'inline-source-map',
target: 'electron-renderer',
mode: "development",
entry: "./renderer/src/index.js",
devtool: "inline-source-map",
target: "electron-renderer",
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
loader: "babel-loader",
options: {
presets: [[
'@babel/preset-env', {
targets: {
esmodules: true
}
}],
'@babel/preset-react']
}
}
presets: [
[
"@babel/preset-env",
{
targets: {
esmodules: true,
},
},
],
"@babel/preset-react",
],
},
},
},
{
test: [/\.s[ac]ss$/i, /\.css$/i],
test: [/\.css$/i],
use: [
// Creates `style` nodes from JS strings
'style-loader',
"style-loader",
// Translates CSS into CommonJS
'css-loader',
// Compiles Sass to CSS
'sass-loader',
"css-loader",
],
}
]
},
],
},
resolve: {
extensions: ['.js'],
extensions: [".js"],
},
output: {
filename: 'renderer.js',
path: path.resolve(__dirname, 'renderer', 'build'),
filename: "renderer.js",
path: path.resolve(__dirname, "renderer", "build"),
},
};
};

0 comments on commit 9b56c39

Please sign in to comment.