Skip to content

Commit

Permalink
json parsing proof of concept is complete
Browse files Browse the repository at this point in the history
  • Loading branch information
YouGuessedMyName committed Jul 1, 2024
1 parent 6950e78 commit e6c1e9b
Show file tree
Hide file tree
Showing 7 changed files with 234 additions and 112 deletions.
167 changes: 167 additions & 0 deletions notebooks/groups.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
<html>
<head>
<meta charset="utf-8">

<script src="lib/bindings/utils.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/vis-network/9.1.2/dist/dist/vis-network.min.css" integrity="sha512-WgxfT5LWjfszlPHXRmBWHkV2eceiWTOBvrKCNbdgDYTHrT2AeLCGbF4sZlZw3UMN3WtL0tGUoIAKsu8mllg/XA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vis-network/9.1.2/dist/vis-network.min.js" integrity="sha512-LnvoEWDFrqGHlHmDD2101OrLcbsfkrzoSpvtSQtxK3RMnRV0eOkhhBN2dXHKRrUU8p2DGRTk35n4O8nWSVe1mQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>


<center>
<h1></h1>
</center>

<!-- <link rel="stylesheet" href="../node_modules/vis/dist/vis.min.css" type="text/css" />
<script type="text/javascript" src="../node_modules/vis/dist/vis.js"> </script>-->
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6"
crossorigin="anonymous"
/>
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf"
crossorigin="anonymous"
></script>


<center>
<h1></h1>
</center>
<style type="text/css">

#mynetwork {
width: 100%;
height: 600px;
background-color: #ffffff;
border: 1px solid lightgray;
position: relative;
float: left;
}




#config {
float: left;
width: 400px;
height: 600px;
}



</style>
</head>


<body>
<div class="card" style="width: 100%">


<div id="mynetwork" class="card-body"></div>
</div>



<div id="config"></div>


<script type="text/javascript">

// initialize global variables.
var edges;
var nodes;
var allNodes;
var allEdges;
var nodeColors;
var originalNodes;
var network;
var container;
var options, data;
var filter = {
item : '',
property : '',
value : []
};





// This method is responsible for drawing the graph, returns the drawn network
function drawGraph() {
var container = document.getElementById('mynetwork');



// parsing and collecting nodes and edges from the python
nodes = new vis.DataSet([{"group": 0, "id": 0, "label": 0, "shape": "dot"}, {"group": 0, "id": 1, "label": 1, "shape": "dot"}, {"group": 1, "id": 2, "label": 2, "shape": "dot"}, {"group": 1, "id": 3, "label": 3, "shape": "dot"}, {"group": 2, "id": 4, "label": 4, "shape": "dot"}, {"group": 2, "id": 5, "label": 5, "shape": "dot"}]);
edges = new vis.DataSet([]);

nodeColors = {};
allNodes = nodes.get({ returnType: "Object" });
for (nodeId in allNodes) {
nodeColors[nodeId] = allNodes[nodeId].color;
}
allEdges = edges.get({ returnType: "Object" });
// adding nodes and edges to the graph
data = {nodes: nodes, edges: edges};

var options = {
"configure": {
"enabled": true
},
"edges": {
"color": {
"inherit": true
},
"smooth": {
"enabled": true,
"type": "dynamic"
}
},
"interaction": {
"dragNodes": true,
"hideEdgesOnDrag": false,
"hideNodesOnDrag": false
},
"physics": {
"enabled": true,
"stabilization": {
"enabled": true,
"fit": true,
"iterations": 1000,
"onlyDynamicEdges": false,
"updateInterval": 50
}
}
};





// if this network requires displaying the configure window,
// put it in its div
options.configure["container"] = document.getElementById("config");


network = new vis.Network(container, data, options);










return network;

}
drawGraph();
</script>
</body>
</html>
31 changes: 4 additions & 27 deletions notebooks/layouts.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -13,38 +13,15 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 3,
"id": "8c98f637-ed9c-430b-b414-09c665b307f8",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'color': 'red'}\n",
"{'color': 'red'}\n",
"{'color': 'blue'}\n",
"{'color': 'blue'}\n"
]
}
],
"outputs": [],
"source": [
"# Import custom layout\n",
"l1 = stormvogel.layout.Layout(custom=True, custom_path=\"custom_layout.json\")\n",
"l2 = stormvogel.layout.Layout(custom=True, custom_path=\"/home/ivo/git/stormvogel/notebooks/custom_layout.json\", custom_path_relative=False)\n",
"# Import template layout\n",
"l3 = stormvogel.layout.Layout(custom=False, template_path=\"layouts/default.json\")\n",
"l4 = stormvogel.layout.Layout(custom=False, template_path=DEFAULT)\n",
"l5 = "
"l1 = stormvogel.layout.Layout(\"custom_layout.json\")\n",
"l2 = stormvogel.layout.Layout(path=\"/home/ivo/git/stormvogel/notebooks/custom_layout.json\", path_relative=False)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9198a4b4-12cd-47a4-8950-278c18023192",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
Expand Down
4 changes: 2 additions & 2 deletions notebooks/model.html
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ <h1></h1>


// parsing and collecting nodes and edges from the python
nodes = new vis.DataSet([{"borderWidth": 3, "color": null, "id": 0, "label": "init", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 1, "label": "studied", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 2, "label": "didn\u0027t study", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 3, "label": "pass test", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 4, "label": "fail test", "shape": "dot"}, {"color": null, "id": 100000000, "label": "study", "shape": "box"}, {"color": null, "id": 100000001, "label": "don\u0027t study", "shape": "box"}]);
nodes = new vis.DataSet([{"borderWidth": 10, "color": null, "id": 0, "label": "init", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 1, "label": "studied", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 2, "label": "didn\u0027t study", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 3, "label": "pass test", "shape": "dot"}, {"borderWidth": 1, "color": null, "id": 4, "label": "fail test", "shape": "dot"}, {"color": null, "id": 100000000, "label": "study", "shape": "box"}, {"color": null, "id": 100000001, "label": "don\u0027t study", "shape": "box"}]);
edges = new vis.DataSet([{"arrows": "to", "color": "red", "from": 0, "to": 100000000}, {"arrows": "to", "color": "red", "from": 100000000, "label": "1", "to": 1}, {"arrows": "to", "color": "red", "from": 0, "to": 100000001}, {"arrows": "to", "color": "red", "from": 100000001, "label": "1", "to": 2}, {"arrows": "to", "color": "red", "from": 1, "label": "9/10", "to": 3}, {"arrows": "to", "color": "red", "from": 1, "label": "1/10", "to": 4}, {"arrows": "to", "color": "red", "from": 2, "label": "2/5", "to": 3}, {"arrows": "to", "color": "red", "from": 2, "label": "3/5", "to": 4}, {"arrows": "to", "color": "red", "from": 3, "label": "1", "to": 3}, {"arrows": "to", "color": "red", "from": 4, "label": "1", "to": 4}]);

nodeColors = {};
Expand All @@ -294,7 +294,7 @@ <h1></h1>
// adding nodes and edges to the graph
data = {nodes: nodes, edges: edges};

var options = {"nodes": {"color": {"background": "blue", "border": "black"}}};
var options = {"nodes": {"color": {"background": "white", "border": "black"}}, "init": {"borderWidth": 10, "color": "green"}};



Expand Down
45 changes: 11 additions & 34 deletions notebooks/study.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,18 @@
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"var options = {\n",
" \"nodes\": {\n",
" \"color\": {\n",
" \"background\": \"blue\",\n",
" \"border\": \"black\"\n",
" }\n",
" }\n",
"}\n",
"model.html\n"
"ename": "AttributeError",
"evalue": "'Visualization' object has no attribute 'layout'",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn[1], line 33\u001b[0m\n\u001b[1;32m 27\u001b[0m \u001b[38;5;66;03m# If you did not study, then there is only a 40% chance that you pass the test.\u001b[39;00m\n\u001b[1;32m 28\u001b[0m not_studied\u001b[38;5;241m.\u001b[39mset_transitions([\n\u001b[1;32m 29\u001b[0m (\u001b[38;5;241m4\u001b[39m\u001b[38;5;241m/\u001b[39m\u001b[38;5;241m10\u001b[39m, pass_test),\n\u001b[1;32m 30\u001b[0m (\u001b[38;5;241m6\u001b[39m\u001b[38;5;241m/\u001b[39m\u001b[38;5;241m10\u001b[39m, fail_test)\n\u001b[1;32m 31\u001b[0m ])\n\u001b[0;32m---> 33\u001b[0m \u001b[43mstormvogel\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mvisualization\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mshow\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmdp\u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[0;32m~/git/stormvogel/.venv/lib/python3.11/site-packages/stormvogel/visualization.py:119\u001b[0m, in \u001b[0;36mshow\u001b[0;34m(model, name, notebook)\u001b[0m\n\u001b[1;32m 111\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mshow\u001b[39m(model: Model, name: \u001b[38;5;28mstr\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmodel\u001b[39m\u001b[38;5;124m\"\u001b[39m, notebook: \u001b[38;5;28mbool\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m):\n\u001b[1;32m 112\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"Create and show a visualization of a Model using a pyvis Network\u001b[39;00m\n\u001b[1;32m 113\u001b[0m \n\u001b[1;32m 114\u001b[0m \u001b[38;5;124;03m Args:\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 117\u001b[0m \u001b[38;5;124;03m notebook (bool, optional): Leave to true if you are using in a notebook. Defaults to True.\u001b[39;00m\n\u001b[1;32m 118\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m--> 119\u001b[0m vis \u001b[38;5;241m=\u001b[39m \u001b[43mVisualization\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmodel\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mname\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mnotebook\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 120\u001b[0m vis\u001b[38;5;241m.\u001b[39mshow()\n",
"File \u001b[0;32m~/git/stormvogel/.venv/lib/python3.11/site-packages/stormvogel/visualization.py:43\u001b[0m, in \u001b[0;36mVisualization.__init__\u001b[0;34m(self, model, name, notebook, cdn_resources, layout)\u001b[0m\n\u001b[1;32m 41\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mname \u001b[38;5;241m=\u001b[39m name\n\u001b[1;32m 42\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mg \u001b[38;5;241m=\u001b[39m Network(notebook\u001b[38;5;241m=\u001b[39mnotebook, directed\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m, cdn_resources\u001b[38;5;241m=\u001b[39mcdn_resources)\n\u001b[0;32m---> 43\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m__add_states\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 44\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m__add_transitions()\n\u001b[1;32m 45\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m layout \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n",
"File \u001b[0;32m~/git/stormvogel/.venv/lib/python3.11/site-packages/stormvogel/visualization.py:57\u001b[0m, in \u001b[0;36mVisualization.__add_states\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 55\u001b[0m borderWidth \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[1;32m 56\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m state \u001b[38;5;241m==\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mmodel\u001b[38;5;241m.\u001b[39mget_initial_state():\n\u001b[0;32m---> 57\u001b[0m borderWidth \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlayout\u001b[49m[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124minit\u001b[39m\u001b[38;5;124m\"\u001b[39m][\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mborderWidth\u001b[39m\u001b[38;5;124m\"\u001b[39m]\n\u001b[1;32m 58\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mg\u001b[38;5;241m.\u001b[39madd_node(\n\u001b[1;32m 59\u001b[0m state\u001b[38;5;241m.\u001b[39mid,\n\u001b[1;32m 60\u001b[0m label\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m,\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;241m.\u001b[39mjoin(state\u001b[38;5;241m.\u001b[39mlabels),\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 63\u001b[0m shape\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdot\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 64\u001b[0m )\n",
"\u001b[0;31mAttributeError\u001b[0m: 'Visualization' object has no attribute 'layout'"
]
},
{
"data": {
"text/html": [
"\n",
" <iframe\n",
" width=\"100%\"\n",
" height=\"600px\"\n",
" src=\"model.html\"\n",
" frameborder=\"0\"\n",
" allowfullscreen\n",
" \n",
" ></iframe>\n",
" "
],
"text/plain": [
"<IPython.lib.display.IFrame at 0x7f9fbf8dcc10>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
Expand Down
76 changes: 34 additions & 42 deletions stormvogel/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,62 +4,40 @@
import os
import json

DEFAULT = "layouts/default.json"


class Layout:
layout: dict
layout: dict[str, str]

def __init__(
self,
custom: bool,
path: str | None = None,
path_relative: bool = True,
template_path: str = DEFAULT,
) -> None:
def __init__(self, path: str, path_relative: bool = True) -> None:
"""Load a new Layout from a json file. Use either a custom or a template file.
Args:
custom (bool, optional): If set to true, stormvogel will look for your custom layout.json file. Otherwise a template will be used.
path (str, optional): Relavant if custom is true. Path to your custom layout file, relative to the current working directory. Defaults to None.
path_relative (bool): Relavant if custom is true. If set to true, then stormvogel will look for a custom layout file relative to the current working directory.
template_path (str, optional): Relavant if custom is false. Path to a template layout files.
These are stored in the folder layouts. For simplicity, we recommed using the constants DEFAULT, etc.
Defaults to DEFAULT (="layouts/default.json").
"""
if custom:
if path is None:
raise Exception(
"If custom is set to true, then the path needs to be set."
)
cwd = os.getcwd()
if path_relative:
complete_path = os.path.join(cwd, path)
else:
complete_path = path
with open(complete_path) as f:
json_string = f.read()
self.layout = json.loads(json_string)
if path_relative:
complete_path = os.path.join(os.getcwd(), path)
else:
package_root_dir = os.path.dirname(os.path.realpath(__file__))
with open(os.path.join(package_root_dir, template_path)) as f:
json_string = f.read()
self.layout = json.loads(json_string)
complete_path = path
with open(complete_path) as f:
json_string = f.read()
self.layout = json.loads(json_string)

def set_nt_layout(self, nt: Network) -> None:
"""Set the layout of the network passed as the arugment."""
# We here use <> instead of {} because the f-string formatting already uses them.
option_string = f"""
var options = <
"nodes": <
"color": <
"background": "{self.layout["color"]}",
"border": "black"
>
>
>""".replace("<", "{").replace(">", "}")
print(option_string)
nt.set_options(option_string)
# option_string = f"""
# var options = <
# "nodes": <
# "color": <
# "background": "{self.layout["color"]}",
# "border": "black"
# >
# >
# >""".replace("<", "{").replace(">", "}")
options = "var options = " + str(self.layout).replace("'", '"')
print(options)
nt.set_options(options)

def save(self) -> None:
raise NotImplementedError()
Expand All @@ -69,3 +47,17 @@ def show_buttons(self) -> None:

def __str__(self) -> str:
raise NotImplementedError()

def __getitem__(self, key: str) -> str | None:
try:
return self.layout[key]
except KeyError:
return None


package_root_dir = os.path.dirname(os.path.realpath(__file__))

# Define template layouts.
DEFAULT = Layout(
os.path.join(package_root_dir, "layouts/default.json"), path_relative=False
)
11 changes: 10 additions & 1 deletion stormvogel/layouts/default.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
{
"color": "blue"
"nodes": {
"color": {
"background": "white",
"border": "black"
}
},
"init": {
"borderWidth": 10,
"color": "green"
}
}
Loading

0 comments on commit e6c1e9b

Please sign in to comment.