From 2d2f2683469c9388d0b210e681d298be633b3b5e Mon Sep 17 00:00:00 2001 From: Matej Trojak Date: Thu, 6 Oct 2022 17:13:29 +0200 Subject: [PATCH] Init files --- .../ts_visjs/config/ts_visjs.xml | 16 + .../visualizations/ts_visjs/package.json | 13 + .../visualizations/ts_visjs/static/style.css | 174 +++++++ .../ts_visjs/templates/ts_visjs.mako | 462 ++++++++++++++++++ 4 files changed, 665 insertions(+) create mode 100644 config/plugins/visualizations/ts_visjs/config/ts_visjs.xml create mode 100644 config/plugins/visualizations/ts_visjs/package.json create mode 100644 config/plugins/visualizations/ts_visjs/static/style.css create mode 100644 config/plugins/visualizations/ts_visjs/templates/ts_visjs.mako diff --git a/config/plugins/visualizations/ts_visjs/config/ts_visjs.xml b/config/plugins/visualizations/ts_visjs/config/ts_visjs.xml new file mode 100644 index 00000000000..697ee498551 --- /dev/null +++ b/config/plugins/visualizations/ts_visjs/config/ts_visjs.xml @@ -0,0 +1,16 @@ + + + + - visjs-based interactive visualization of transition system in graph form. + + + HistoryDatasetAssociation + text.BCSLts + dataset_id + + + + dataset_id + + ts_visjs.mako + diff --git a/config/plugins/visualizations/ts_visjs/package.json b/config/plugins/visualizations/ts_visjs/package.json new file mode 100644 index 00000000000..ada8e3d8b11 --- /dev/null +++ b/config/plugins/visualizations/ts_visjs/package.json @@ -0,0 +1,13 @@ +{ + "name": "ts_visjs", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "plotly.js": "^2.11.1", + "pca-js": "^1.0.2", + "d3": "^7.4.4" + }, + "scripts": { + "build": "mkdir -p static/dist && cp node_modules/pca-js/pca.min.js node_modules/plotly.js/dist/plotly.min.js node_modules/d3/dist/d3.min.js static/dist" + } +} diff --git a/config/plugins/visualizations/ts_visjs/static/style.css b/config/plugins/visualizations/ts_visjs/static/style.css new file mode 100644 index 00000000000..53edbbc8552 --- /dev/null +++ b/config/plugins/visualizations/ts_visjs/static/style.css @@ -0,0 +1,174 @@ +#mynetwork { + width: 94%; + height: 100%; + border: 1px solid #000; + float: left; +} + +#rectangle { + text-align: center; + font-weight: bold; +} + +#loadingBar { + position:absolute; + top:1px; + left:1px; + width: 94%; + height: 93%; + background-color:rgba(200,200,200,0.8); + -webkit-transition: all 0.5s ease; + -moz-transition: all 0.5s ease; + -ms-transition: all 0.5s ease; + -o-transition: all 0.5s ease; + transition: all 0.5s ease; + opacity:1; +} + +#wrapper { + position:relative; + width:900px; + height:900px; +} + +#text { + position:absolute; + top:8px; + left:530px; + width:30px; + height:50px; + margin:auto auto auto auto; + font-size:22px; + color: #000000; +} + +div.outerBorder { + position:relative; + top:400px; + width:600px; + height:44px; + margin:auto auto auto auto; + border:8px solid rgba(0,0,0,0.1); + background: rgb(252,252,252); /* Old browsers */ + background: -moz-linear-gradient(top, rgba(252,252,252,1) 0%, rgba(237,237,237,1) 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(252,252,252,1)), color-stop(100%,rgba(237,237,237,1))); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, rgba(252,252,252,1) 0%,rgba(237,237,237,1) 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, rgba(252,252,252,1) 0%,rgba(237,237,237,1) 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, rgba(252,252,252,1) 0%,rgba(237,237,237,1) 100%); /* IE10+ */ + background: linear-gradient(to bottom, rgba(252,252,252,1) 0%,rgba(237,237,237,1) 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fcfcfc', endColorstr='#ededed',GradientType=0 ); /* IE6-9 */ + border-radius:72px; + box-shadow: 0px 0px 10px rgba(0,0,0,0.2); +} + +#border { + position:absolute; + top:10px; + left:10px; + width:500px; + height:23px; + margin:auto auto auto auto; + box-shadow: 0px 0px 4px rgba(0,0,0,0.2); + border-radius:10px; +} + +#bar { + position:absolute; + top:0px; + left:0px; + width:20px; + height:20px; + margin:auto auto auto auto; + border-radius:11px; + border:2px solid rgba(30,30,30,0.05); + background: rgb(0, 173, 246); /* Old browsers */ + box-shadow: 2px 0px 4px rgba(0,0,0,0.4); +} + +html { + height: 100%; +} + +body { + height: 90%; +} + + /* The switch - the box around the slider */ +.switch { + position: relative; + display: inline-block; + width: 60px; + height: 34px; +} + +/* Hide default HTML checkbox */ +.switch input { + opacity: 0; + width: 0; + height: 0; +} + +/* The slider */ +.slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #ccc; + -webkit-transition: .4s; + transition: .4s; +} + +.slider:before { + position: absolute; + content: ""; + height: 26px; + width: 26px; + left: 4px; + bottom: 4px; + background-color: white; + -webkit-transition: .4s; + transition: .4s; +} + +input:checked + .slider { + background-color: #2196F3; +} + +input:focus + .slider { + box-shadow: 0 0 1px #2196F3; +} + +input:checked + .slider:before { + -webkit-transform: translateX(26px); + -ms-transform: translateX(26px); + transform: translateX(26px); +} + +/* Rounded sliders */ +.slider.round { + border-radius: 34px; +} + +.slider.round:before { + border-radius: 50%; +} + +aside { + float: right; + width: 5%; +} + +table { + border-collapse: collapse; +} + +td.switch_td { + padding-bottom: 6px; +} + +.switch_button { + border-bottom: 2px solid black; +} diff --git a/config/plugins/visualizations/ts_visjs/templates/ts_visjs.mako b/config/plugins/visualizations/ts_visjs/templates/ts_visjs.mako new file mode 100644 index 00000000000..ae6be9d77b8 --- /dev/null +++ b/config/plugins/visualizations/ts_visjs/templates/ts_visjs.mako @@ -0,0 +1,462 @@ +<%! +import collections +import json +import sys +from numpy import inf +%> + +<% +def to_counter(state, ordering): + """ + Transforms given state to Counter using given ordering + + :param state: str representation of state + :param ordering: enumeration of agents + :return: Counter representing the state + """ + state = eval(state) + if state[0] == inf: + return inf + return +collections.Counter({ordering[i]: state[i] for i in range(len(ordering))}) + + +def node_to_string(node): + """ + Creates string representation of Counter of agents. + + :param node: given Counter of agents. + :return: string representation of Counter + """ + if node == inf: + return "inf" + return "
".join([str(int(v)) + " " + str(k) for k, v in node.items()]) + + +def side_to_string(side): + """ + Another string representation of Counter, this time used as side in reaction + :param side: given Counter + :return: string representation of Counter + """ + if side == inf: + return "inf" + return " + ".join([str(int(v)) + " " + str(k) for k, v in side.items()]) + + +def create_sides(lhs, rhs): + """ + From given substrates and products counters creates their mutual differences + + :param lhs: dict of substrates + :param rhs: dict of products + :return: two counters representing differences + """ + if lhs == inf: + return inf, inf + if rhs == inf: + return collections.Counter(), inf + left = lhs - rhs + right = rhs - lhs + return left, right + + +def write_node(ID, label, node_class): + """ + Creates string representation of a node + + :param ID: ID of given node + :param label: enumeration of agents + :return: string representation + """ + if label == "inf": + node_class = "hell" + return "\t\t{{id: {0}, label: '{0}', class: '{2}', shape: 'ellipse', title: '{0}', text: '{1}'}},\n".format( + ID, label, node_class) + + +def write_reaction(edge_id, left_index, right_index, substrates, products, rate, label): + """ + Creates string representation of a reaction + + :param edge_id: ID of given reaction + :param left_index: ID of FROM node + :param right_index: ID of TO node + :param substrates: enumeration of substrates + :param products: enumeration of products + :param rate: rate of the reaction (if any) + :param label: used rule label + :return: string representation + """ + rate = " @ " + str(rate) if rate else "" + label = label + " ~ " if label else "" + return "\t\t{{id: {}, from: {}, to: {}, arrows: 'to', text: '{}{} => {}{}'}},\n".format( + edge_id, left_index, right_index, label, side_to_string(substrates), side_to_string(products), rate) + + +def create_HTML_graph(): #data): + output_file = firstpart + + data = ''.join(list(hda.datatype.dataprovider(hda, 'line', strip_lines=True, strip_newlines=True))) + data = json.loads(data) + + # data = json.load(data) + + ordering = data['ordering'] + nodes = {int(key): to_counter(data['nodes'][key], ordering) for key in data['nodes'].keys()} + + border_nodes = set() + + edges = [] + self_loops = [] + for edge_id, edge in enumerate(data['edges'], 1): + substrates, products = create_sides(nodes[edge['s']], nodes[edge['t']]) + if edge['s'] == edge['t']: + self_loops.append((edge_id, edge['s'], edge['t'], substrates, + products, edge.get('p', None), edge.get('label', None))) + edges.append((edge_id, edge['s'], edge['t'], substrates, products, + edge.get('p', None), edge.get('label', None))) + if products == inf and substrates != inf: + border_nodes.add(edge['s']) + + border_nodes_write = [] + for id, state in nodes.items(): + if id in border_nodes: + node_class = "border" + border_nodes_write.append((id, node_to_string(state), node_class)) + else: + node_class = "default" + output_file += write_node(id, node_to_string(state), node_class) + + output_file += mid_1 + + for node in border_nodes_write: + output_file += write_node(*node) + + output_file += mid_2 + + for edge in edges: + output_file += write_reaction(*edge) + + output_file += mid_3 + + for edge in self_loops: + output_file += write_reaction(*edge) + + initial = data['initial'] + + iterations = (len(nodes)//100+1) * 100 + step = iterations//100 + + output_file += secondpart_1_1 + output_file += stabil_physics.format(iterations, step) + output_file += secondpart_1_2 + + output_file += "\tvar fromNode = " + str(int(initial)) + ";\n" + + output_file += secondpart_2_1 + output_file += stabil_bar.format(iterations, step) + output_file += secondpart_2_2 + return output_file + + +firstpart = \ +''' + + + TS network visualisation + + ${h.javascript_link(app_root + "dist/vis.min.js")} + # da sa to? + ${h.stylesheet_link(app_root + "dist/vis.min.css")} + ${h.stylesheet_link(app_root + "style.css")} + + + + + + + + +
+ + + +
+
+
+
0%
+
+
+
+
+
+ + + + + +''' + +stabil_physics = \ +''' iterations: {}, + updateInterval: {} +''' + +stabil_bar = \ +''' var iterations = {}; + var updateInterval = {}; +''' + +# for testing +# filename = open('bigger_pMC.json', "r") +# graph = create_HTML_graph(filename) + +graph = create_HTML_graph() +%> + +${graph}