9 Commits

Author SHA1 Message Date
Ferrari Martino Giordano b6cd0994ea use monospace everywhere 2024-07-25 17:34:48 +02:00
Ferrari Martino Giordano 3c9b4e3161 examples 2024-07-25 17:29:20 +02:00
Ferrari Martino Giordano 4a9ea7db6d added output flag 2024-07-25 17:29:08 +02:00
Ferrari Martino Giordano 88f9a05fc1 using monospace 2024-07-25 17:28:59 +02:00
Ferrari Martino Giordano 57507598cc feat: added support to samples 2024-04-16 16:54:06 +02:00
Ferrari Martino Giordano 8e3115386b initial test 2024-04-04 16:00:34 +02:00
Ferrari Martino Giordano caa698ffe4 feat: initial work on a simple gui based on xdot.py 2024-04-03 17:17:44 +02:00
Ferrari Martino Giordano cbb37b4303 feat: improved triggered iogam 2024-03-29 16:45:56 +01:00
Ferrari Martino Giordano 47f7147e12 feat: uniform styling elements between simplified and full graph 2024-03-29 14:08:43 +01:00
9 changed files with 654 additions and 6565 deletions
+5 -1
View File
@@ -39,6 +39,7 @@ def __args__():
parser.add_argument(
"-d", "--destination", help="Destination folder", type=str, default="."
)
parser.add_argument("-o", "--output", help="Output name", type=str, default="")
return parser.parse_args()
@@ -73,7 +74,10 @@ def main():
if not config:
logging.error(f"Impossible to load configuration `{args.filename}`")
sys.exit(1)
filename = os.path.splitext(os.path.basename(args.filename))[0]
if args.output:
filename = args.output
else:
filename = os.path.splitext(os.path.basename(args.filename))[0]
autodoc.document(filename, args, config)
+2 -1
View File
@@ -34,8 +34,9 @@ def signal_byte_size(sig):
nod = 1 if "NumberOfDimensions" not in sig else int(sig["NumberOfDimensions"])
nod = nod if nod > 0 else 1
noe = noe if noe > 0 else 1
nos = 1 if "Samples" not in sig else int(sig["Samples"])
bytes = type_bytes_count(sig["Type"])
tot = noe * nod
tot = noe * nod * nos
if "Ranges" in sig:
tot = 0
+128 -90
View File
@@ -1,5 +1,7 @@
import copy
import logging
import os
import re
import common as doc
@@ -10,9 +12,9 @@ def __doc_obj__(label, obj, id):
def __doc_common_gam__(name, obj, edges, thread):
inputs = ""
outputs = ""
if "InputSignals" in obj:
inputs = "<table cellborder='0' border='0'>"
outputs = "<table cellborder='0' border='0'>"
if "InputSignals" in obj and len(obj["InputSignals"]):
for i, (l, sig) in enumerate(obj["InputSignals"].items()):
alias = doc.signal_alias(l, sig)
mtype = doc.signal_type(sig)
@@ -25,9 +27,11 @@ def __doc_common_gam__(name, obj, edges, thread):
)
)
if i != 0:
inputs += " | "
inputs += f"<in_{doc.format_name(l)}> {l}"
if "OutputSignals" in obj:
inputs += "<hr/>"
inputs += f"<tr><td port='in_{doc.format_name(l)}'>{l}</td></tr>"
else:
inputs += "<tr><td></td></tr>"
if "OutputSignals" in obj and len(obj["OutputSignals"]):
for i, (l, sig) in enumerate(obj["OutputSignals"].items()):
alias = doc.signal_alias(l, sig)
mtype = doc.signal_type(sig)
@@ -40,51 +44,41 @@ def __doc_common_gam__(name, obj, edges, thread):
)
)
if i != 0:
outputs += " | "
outputs += f"<out_{doc.format_name(l)}> {l}"
return "{ {" + inputs + " } | { " + outputs + "} }", edges
outputs += "<hr/>"
outputs += f"<tr><td port='out_{doc.format_name(l)}'>{l}</td></tr>"
else:
outputs += "<tr><td></td></tr>"
return (
"<tr><td>" + inputs + "</table></td><vr/><td>" + outputs + "</table></td></tr>",
edges,
)
def __doc_triggered_iogam__(name, obj, edges, thread):
signals = ""
if "InputSignals" in obj:
for i, (l, sig) in enumerate(obj["InputSignals"].items()):
alias = doc.signal_alias(l, sig)
mtype = doc.signal_type(sig)
datasrc = sig["DataSource"]
edges.append(
doc.edge(
doc.signal(datasrc, alias, mtype),
doc.signal(name, l, mtype),
thread,
)
def __doc_triggered_iogam__(id, obj, edges, thread):
node = ""
if len(obj["InputSignals"]) > 0:
name = id[2:]
node = __gam__(id, name, "TriggeredIOGAM")
recl = copy.deepcopy(obj)
trg = list(obj["InputSignals"].keys())[0]
sig = obj["InputSignals"][trg]
alias = doc.signal_alias(trg, sig)
mtype = doc.signal_type(sig)
datasrc = sig["DataSource"]
edges.append(
doc.edge(
doc.signal(datasrc, alias, mtype),
doc.signal(id, trg, mtype),
thread,
)
if i > 1:
signals += " | "
signals += f"<in_{doc.format_name(l)}> "
if i == 0:
signals += "Trigger | { { "
else:
signals += f"{l}"
signals += " } | { "
if "OutputSignals" in obj:
for i, (l, sig) in enumerate(obj["OutputSignals"].items()):
alias = doc.signal_alias(l, sig)
mtype = doc.signal_type(sig)
datasrc = sig["DataSource"]
edges.append(
doc.edge(
doc.signal(name, l, mtype),
doc.signal(datasrc, alias, mtype),
thread,
)
)
if i != 0:
signals += " | "
signals += f"<out_{doc.format_name(l)}> {l} "
signals += " } }"
node = f'{name} [tooltip=" TriggeredIOGAM::{name} ", label="{name}&#92;nTriggeredIOGAM | {signals}", style=filled, fillcolor="#eee"];\n'
)
node += f"<tr><td port='in_{doc.format_name(trg)}' colspan='2'><b>Trigger</b></td></tr><hr/>"
del recl["InputSignals"][trg]
sigs, edges = __doc_common_gam__(id, recl, edges, thread)
node += sigs
node += "</table>>];"
return node, edges
@@ -92,6 +86,7 @@ __set_keys__ = (
"Alias",
"Type",
"DataSource",
"Samples",
"NumberOfElements",
"NumberOfDimensions",
"Ranges",
@@ -159,42 +154,43 @@ def __doc_iogam__(id, obj, edges, thread):
)
)
orows.append(orow)
fill = "#fff"
fill = "#eee"
fcolor = "#000"
total = max(len(orows), len(irows))
if bold or total > 1:
fill = "#333"
fill = "#eee"
bold = True
else:
fill = "#666"
fill = "#eee"
inode = f"{id}_{counter} [shape=plaintext,"
inode += f'tooltip=" IOGAM::{id} ", label=<'
inode += "<table cellspacing='0' cellborder='1'"
inode += f" cellpadding='4' border='0' bgcolor='{fill}'>"
inode += "<table cellspacing='0' cellborder='0' style='rounded'"
inode += f" cellpadding='4' border='1' bgcolor='{fill}'>"
if bold:
for i in range(total):
inode += "<tr>"
if i < len(irows):
inode += f'<td port="in_{i}" bgcolor="{fill}"'
inode += f'<td port="in_{i}"'
if len(orows) > len(irows):
inode += f' rowspan="{len(orows)}"'
inode += ">"
inode += '<font color="#fff">'
inode += f'<font color="{fcolor}">'
inode += irows[i]
inode += "</font></td>"
inode += "</font></td><vr/>"
if i < len(orows):
inode += f'<td port="out_{i}" bgcolor="{fill}"'
inode += f'<td port="out_{i}"'
if len(orows) < len(irows):
inode += f' rowspan="{len(irows)}"'
inode += ">"
inode += '<font color="#fff">'
inode += f'<font color="{fcolor}">'
inode += orows[i]
inode += "</font></td>"
inode += "</tr>"
else:
inode += "<tr><td port='in_0'></td>"
inode += "<td port='out_0'></td></tr>"
if i < total - 1:
inode += "<hr/>"
inode += "</table>>"
inode += "];\n"
if not bold:
@@ -210,7 +206,7 @@ def __doc_iogam__(id, obj, edges, thread):
def __doc_constgam__(id, obj, edges, thread):
node = f" {id} [shape=plaintext, label=<<table cellspacing='0' cellborder='1' cellpadding='4' border='0'>"
node = f" {id} [shape=plaintext, label=<<table cellspacing='0' cellborder='0' cellpadding='4' border='1' style='rounded'>"
node += f"<tr><td colspan='2'><b>{id[2:]}</b><br/>{obj['Class']}</td></tr>"
if "OutputSignals" in obj:
@@ -225,8 +221,9 @@ def __doc_constgam__(id, obj, edges, thread):
thread,
)
)
node += f'<tr><td bgcolor="#eee">{doc.type_to_string(mtype)}<br/><font point-size="8">{l}</font></td>'
node += f'<td port="out_{doc.format_name(l)}">'
node += "<hr/>"
node += f'<tr><td>{doc.type_to_string(mtype)}<br/><font point-size="8">{l}</font></td>'
node += f'<vr/><td port="out_{doc.format_name(l)}">'
node += f'{sig["Default"]}</td></tr>'
node += "</table>>];\n"
return node, edges
@@ -252,7 +249,7 @@ def __doc_message_gam__(id, obj, edges, thread):
inputs += " | "
inputs += f"<in_{doc.format_name(l)}> {l}"
if inputs:
node += inputs + '"];'
node += inputs + '", style=filled, fillcolor=lightyellow];'
else:
node = ""
@@ -264,6 +261,7 @@ def __doc_message_gam__(id, obj, edges, thread):
def __doc_events__(id, obj, edges, thread):
nodes = ""
bgcolor = "lightyellow"
for event_id, event in obj["+Events"].items():
if event_id[0] == "+":
event_id = event_id[1:]
@@ -272,22 +270,20 @@ def __doc_events__(id, obj, edges, thread):
for msg_id in message_ids:
nodes += f" {id}_{event_id}_{msg_id} [shape=plaintext, label=<"
nodes += '<table cellspacing="0" cellborder="1" border="0" cellpadding="4"><tr>'
nodes += (
"<td bgcolor='#ccc' align='left'><b>When</b></td><td balign='left'>"
)
nodes += f"<td bgcolor='{bgcolor}' align='left'><b>When</b></td><td balign='left'>"
for i, (sig, val) in enumerate(trigger.items()):
if i > 0:
nodes += "<br/>"
nodes += f"{sig} == {val}"
nodes += "</td></tr><tr><td bgcolor='#ccc' align='left'><b>Destination</b></td>"
nodes += f"</td></tr><tr><td bgcolor='{bgcolor}' align='left'><b>Destination</b></td>"
msg = event[f"+{msg_id}"]
fn = msg["Function"]
nodes += f"<td align='left'>{msg['Destination']}</td></tr>"
nodes += "<tr><td bgcolor='#ccc' align='left'><b>Function</b></td><td align='left'>"
nodes += f"<tr><td bgcolor='{bgcolor}' align='left'><b>Message</b></td><td align='left'>"
if fn == "SetOutput":
params = msg["+Parameters"]
nodes += f"{params['SignalName']} = {params['SignalValue']}"
nodes += f"<i>set</i> {params['SignalName']} <i>to</i> {params['SignalValue']}"
else:
nodes += f"{fn} "
nodes += "</td></tr></table>>];\n"
@@ -297,18 +293,42 @@ def __doc_events__(id, obj, edges, thread):
def __sanitize__(expression):
expression = expression.strip()
expression = re.sub(" +", " ", expression)
if expression[0] == "\n":
expression = expression[1:]
return expression.replace(">", "&gt;").replace("<", "&lt;").replace("\n", "&#92;n")
if expression[-1] == "\n":
expression = expression[:-1]
expression = (
expression.replace("&", "&amp;")
.replace(">", "&gt;")
.replace("<", "&lt;")
.replace("\n", "<br/>")
)
return expression
def __gam__(id, label, cls):
node = f" {id} [shape=plaintext, label=<<table border='1' cellborder='0' cellpadding='0' style='rounded'>"
node += f"<tr><td colspan='2'><b>{label}</b><br/>{cls}</td></tr><hr/>"
return node
def __doc_mathgam__(id, obj, edges, thread):
label = id[2:]
node = f' {id} [label="{label}&#92;n{obj["Class"]} | '
node += __sanitize__(obj["Expression"]) + " | "
import sys
node = __gam__(id, label, obj["Class"])
node += (
"<tr><td colspan='2' align='left' balign='left' bgcolor='#fef'><font face='mono' point-size='9'>"
+ __sanitize__(obj["Expression"])
+ "</font></td></tr><hr/> "
)
sigs, edges = __doc_common_gam__(id, obj, edges, thread)
if sigs:
node += sigs + '"];'
node += sigs + "</table>>];"
else:
node = ""
return node, edges
@@ -328,10 +348,10 @@ def __doc_gam__(label, obj, edges, thread, classfilter=True):
cls = obj["Class"]
if classfilter and cls in __gams_fns__:
return __gams_fns__[cls](id, obj, edges, thread)
node = f' {id} [label="{label}&#92;n{obj["Class"]} | '
node = __gam__(id, label, cls)
sigs, edges = __doc_common_gam__(id, obj, edges, thread)
if sigs:
node += sigs + '"];'
node += sigs + "</table>>];"
else:
node = ""
return node, edges
@@ -388,10 +408,17 @@ def __process_gamds__(name, cls, signals, edges):
node += " | "
sig_type = signals[sig_name]
node += (
f"<{doc.format_name(sig_name)}> {sig_name} ({doc.type_to_string(sig_type)})"
f'<tr><td port="{doc.format_name(sig_name)}">'
f"{sig_name} ({doc.type_to_string(sig_type)})"
"</td></tr>"
)
if node:
node = f'{name} [label="{name}&#92;n{cls} | {node}", color=blue, style=filled, fillcolor=lightyellow];\n'
label = f"""<table border="0" cellpadding="4" cellborder="1" cellspacing="0" bgcolor="#eee">
<tr><td><b>{name}</b><br/>{cls}</td></tr>
{node}
</table>
"""
node = f'{name} [shape=plaintext, label=<{label}>, color="#0af"];\n'
return node, edges
@@ -430,9 +457,7 @@ def __process_ds__(name, obj, edges):
if sig not in order:
lost.append(sig)
node = f"{name} [shape=plaintext; label=<"
node += (
'<table border="0" cellpadding="4" cellborder="1" cellspacing="0">\n'
)
node += '<table border="0" cellpadding="4" cellborder="1" cellspacing="0" bgcolor="lightblue">\n'
node += f"<tr><td><b>{name}</b><br/>{cls}</td></tr>\n"
for i, sig_name in enumerate(order):
node += f'<tr><td port="{doc.format_name(sig_name)}">'
@@ -445,7 +470,7 @@ def __process_ds__(name, obj, edges):
sig_type = sigs[sig_name]
node += f"{sig_name} ({doc.type_to_string(sig_type)})"
node += "</td></tr>\n"
node += "</table>>, color=blue];\n"
node += '</table>>, color="#0af"];\n'
if not multi_thread and node:
node = f"subgraph cluster_{thread}" + "{\n" + node + "};\n"
return node, edges
@@ -489,8 +514,10 @@ def __state_full_graph__(label, state, app):
graph = f"digraph {label[1:]}" + "{\n"
graph += "ranksep = 2;\n"
graph += "nodesep = 0.05;\n"
graph += 'fontname="monospace";\n'
graph += "rankdir = LR;\n"
graph += "node [shape=Mrecord];\n"
graph += 'edge [fontname="monospace"];\n'
graph += 'node [shape=Mrecord, fontname="monospace"];\n'
graph += f"label=<State: <B>{label[1:]}</B>>;\n"
graph += "fontsize=40;\n"
graph += "\n"
@@ -532,18 +559,18 @@ def __state_full_graph__(label, state, app):
def __simple_gam__(label, obj):
cls = obj["Class"]
id = f"fn{doc.format_name(label)}"
style = ""
style = "style=rounded"
if cls == "IOGAM":
style = ", style=filled, fillcolor=lightgray"
style = 'style="rounded,filled", fillcolor="#eee"'
elif cls == "MessageGAM":
style = ", style=filled, fillcolor=yellow"
style = 'style="rounded,filled", fillcolor=lightyellow'
if "InputSignals" in obj:
for _, signal in obj["InputSignals"].items():
ds = f'ds{doc.format_name(signal["DataSource"])}'
if "OutputSignals" in obj:
for _, signal in obj["OutputSignals"].items():
ds = f'ds{doc.format_name(signal["DataSource"])}'
return f"{id}[label=<<B>{label}</B><BR/>{cls}> {style}]\n"
return f"{id}[label=<<B>{label}</B><BR/>{cls}>, {style}]\n"
def __simple_ds__(label, obj, edges):
@@ -564,7 +591,14 @@ def __simple_ds__(label, obj, edges):
thread = edge[-1]
elif thread != edge[-1]:
multi_thread = True
node = f"{id}[label=<<B>{label}</B><BR/>{cls}>, fillcolor=lightblue]\n"
fillcolor = "lightblue"
bordercolor = "#0af"
style = "penwidth=2"
if cls == "GAMDataSource":
fillcolor = "#eee"
node = f"{id}[label=<<B>{label}</B><BR/>{cls}>, "
node += f'{style}, fillcolor="{fillcolor}", color="{bordercolor}"]\n'
if thread and not multi_thread:
node = f"subgraph cluster_{thread}" + "{\n " + node + "}"
return node
@@ -592,8 +626,12 @@ def __simple_edges__(edges, datasources):
def __state_simple_graph__(label, state, app):
graph = f"digraph {label[1:]}" + "{\n"
graph += "rankdir = LR;\n"
graph += 'node [shape=rect, style="filled", fillcolor=white];\n'
graph += (
'node [shape=rect, style="filled", fillcolor=white, fontname="monospace"];\n'
)
graph += 'edge [fontname="monospace"];\n'
graph += f"label=<State: <B>{label[1:]}</B>>;\n"
graph += 'fontname="monospace";\n'
graph += "fontsize=40;\n"
graph += "\n"
arrows = ""
+3 -1
View File
@@ -13,7 +13,9 @@ def doc_state_machine(name, obj):
graph = f"digraph {name}" + "{\n"
graph += "rankdir = LR;\n"
# graph += "layout = circo;\n"
graph += 'node [shape=egg, style="filled"];\n'
graph += 'fontname="monospace";\n'
graph += 'node [shape=egg, style="filled", fontname="monospace"];\n'
graph += 'edge [fontname="monospace"];\n'
first = True
for key in obj:
if key[0] == "+":
File diff suppressed because it is too large Load Diff
+247 -58
View File
@@ -989,16 +989,16 @@
"GB_GCPS_Amplitude_Max_Delta_Read": {
"Type": "float32"
},
"GA_BPS_Voltage_SP_Read": {
"GA_ABPS_BPS_Voltage_SP_Read": {
"Type": "float32"
},
"GA_APS_Voltage_SP_Read": {
"GA_ABPS_APS_Voltage_SP_Read": {
"Type": "float32"
},
"GB_BPS_Voltage_SP_Read": {
"GB_ABPS_BPS_Voltage_SP_Read": {
"Type": "float32"
},
"GB_APS_Voltage_SP_Read": {
"GB_ABPS_APS_Voltage_SP_Read": {
"Type": "float32"
},
"ACK_GCOM_FCT_ABORT_CMD": {
@@ -1459,16 +1459,16 @@
"GB_GCPS_Amplitude_Max_Delta": {
"Type": "float32"
},
"GA_BPS_Voltage_SP": {
"GA_ABPS_BPS_Voltage_SP": {
"Type": "float32"
},
"GA_APS_Voltage_SP": {
"GA_ABPS_APS_Voltage_SP": {
"Type": "float32"
},
"GB_BPS_Voltage_SP": {
"GB_ABPS_BPS_Voltage_SP": {
"Type": "float32"
},
"GB_APS_Voltage_SP": {
"GB_ABPS_APS_Voltage_SP": {
"Type": "float32"
},
"GCOM_HVPS_Voltage_SP": {
@@ -1875,6 +1875,9 @@
"MHVPS_OC": {
"Type": "uint8"
},
"SDNAbsTime": {
"Type": "uint64"
},
"OSMState": {
"Type": "uint8"
},
@@ -1917,6 +1920,9 @@
"PendingSegChange": {
"Type": "uint32"
},
"LOAD_DONE": {
"Type": "uint8"
},
"GA_CCPS_Config_Status": {
"Type": "uint8"
},
@@ -1952,7 +1958,10 @@
"Type": "uint8",
"NumberOfElements": 6
},
"LOAD_DONE": {
"SimTime": {
"Type": "float32"
},
"ACK_GA_FHPS_CONFIG_SEQ_CMD": {
"Type": "uint8"
},
"GB_CCPS_Operation_Pending": {
@@ -2251,16 +2260,16 @@
"GB_GCPS_Sweep_Rate": {
"Type": "float32"
},
"GA_BPS_Voltage_SP": {
"GA_ABPS_BPS_Voltage_SP": {
"Type": "float32"
},
"GA_APS_Voltage_SP": {
"GA_ABPS_APS_Voltage_SP": {
"Type": "float32"
},
"GB_BPS_Voltage_SP": {
"GB_ABPS_BPS_Voltage_SP": {
"Type": "float32"
},
"GB_APS_Voltage_SP": {
"GB_ABPS_APS_Voltage_SP": {
"Type": "float32"
},
"GCOM_HVPS_Voltage_SP": {
@@ -2368,6 +2377,24 @@
"GA_CCPS_CONFIG_SEQ_STAT": {
"Type": "uint8"
},
"GA_FHPS_CONF_CMD": {
"Type": "uint8"
},
"GA_FHPS_CONF_STAT": {
"Type": "uint8"
},
"GA_FHPS_AC_V_IN": {
"Type": "float32"
},
"GA_FHPS_AC_V_INT": {
"Type": "float32"
},
"GA_FHPS_AC_V_OUT": {
"Type": "float32"
},
"GA_FHPS_ACK": {
"Type": "uint8"
},
"ShotTime": {
"Type": "uint32",
"Ignore": 1
@@ -3481,19 +3508,19 @@
"DataSource": "PLCSDNSub",
"Type": "float32"
},
"GA_BPS_Voltage_SP": {
"GA_ABPS_BPS_Voltage_SP": {
"DataSource": "PLCSDNSub",
"Type": "float32"
},
"GA_APS_Voltage_SP": {
"GA_ABPS_APS_Voltage_SP": {
"DataSource": "PLCSDNSub",
"Type": "float32"
},
"GB_BPS_Voltage_SP": {
"GB_ABPS_BPS_Voltage_SP": {
"DataSource": "PLCSDNSub",
"Type": "float32"
},
"GB_APS_Voltage_SP": {
"GB_ABPS_APS_Voltage_SP": {
"DataSource": "PLCSDNSub",
"Type": "float32"
},
@@ -3831,19 +3858,19 @@
"DataSource": "ConfActualDB",
"Type": "float32"
},
"GA_BPS_Voltage_SP": {
"GA_ABPS_BPS_Voltage_SP": {
"DataSource": "ConfActualDB",
"Type": "float32"
},
"GA_APS_Voltage_SP": {
"GA_ABPS_APS_Voltage_SP": {
"DataSource": "ConfActualDB",
"Type": "float32"
},
"GB_BPS_Voltage_SP": {
"GB_ABPS_BPS_Voltage_SP": {
"DataSource": "ConfActualDB",
"Type": "float32"
},
"GB_APS_Voltage_SP": {
"GB_ABPS_APS_Voltage_SP": {
"DataSource": "ConfActualDB",
"Type": "float32"
},
@@ -4580,44 +4607,44 @@
"Alias": "GB_GCPS_Sweep_Rate",
"Type": "float32"
},
"GA_BPS_Voltage_SP_a": {
"Alias": "GA_BPS_Voltage_SP",
"GA_ABPS_BPS_Voltage_SP_a": {
"Alias": "GA_ABPS_BPS_Voltage_SP",
"DataSource": "PLCSDNSub",
"Type": "float32"
},
"GA_BPS_Voltage_SP_b": {
"GA_ABPS_BPS_Voltage_SP_b": {
"DataSource": "ConfActualDB",
"Alias": "GA_BPS_Voltage_SP",
"Alias": "GA_ABPS_BPS_Voltage_SP",
"Type": "float32"
},
"GA_APS_Voltage_SP_a": {
"Alias": "GA_APS_Voltage_SP",
"GA_ABPS_APS_Voltage_SP_a": {
"Alias": "GA_ABPS_APS_Voltage_SP",
"DataSource": "PLCSDNSub",
"Type": "float32"
},
"GA_APS_Voltage_SP_b": {
"GA_ABPS_APS_Voltage_SP_b": {
"DataSource": "ConfActualDB",
"Alias": "GA_APS_Voltage_SP",
"Alias": "GA_ABPS_APS_Voltage_SP",
"Type": "float32"
},
"GB_BPS_Voltage_SP_a": {
"Alias": "GB_BPS_Voltage_SP",
"GB_ABPS_BPS_Voltage_SP_a": {
"Alias": "GB_ABPS_BPS_Voltage_SP",
"DataSource": "PLCSDNSub",
"Type": "float32"
},
"GB_BPS_Voltage_SP_b": {
"GB_ABPS_BPS_Voltage_SP_b": {
"DataSource": "ConfActualDB",
"Alias": "GB_BPS_Voltage_SP",
"Alias": "GB_ABPS_BPS_Voltage_SP",
"Type": "float32"
},
"GB_APS_Voltage_SP_a": {
"Alias": "GB_APS_Voltage_SP",
"GB_ABPS_APS_Voltage_SP_a": {
"Alias": "GB_ABPS_APS_Voltage_SP",
"DataSource": "PLCSDNSub",
"Type": "float32"
},
"GB_APS_Voltage_SP_b": {
"GB_ABPS_APS_Voltage_SP_b": {
"DataSource": "ConfActualDB",
"Alias": "GB_APS_Voltage_SP",
"Alias": "GB_ABPS_APS_Voltage_SP",
"Type": "float32"
},
"GCOM_HVPS_Voltage_SP_a": {
@@ -5561,7 +5588,7 @@
"Alias": "ACK_GA_FHPS_RAMP_CMD"
},
"ACK_GA_FHPS_CONFIG_SEQ_CMD": {
"DataSource": "PLCSDNPub",
"DataSource": "DDB1",
"Type": "uint8",
"Alias": "ACK_GA_FHPS_CONFIG_SEQ_CMD"
},
@@ -6064,6 +6091,48 @@
}
}
},
"+SDNTimeGAM": {
"Class": "IOGAM",
"InputSignals": {
"Time": {
"NumberOfElements": 48,
"Range": [
[
32,
39
]
],
"DataSource": "PLCSDNSub",
"Type": "uint8",
"Alias": "Header"
}
},
"OutputSignals": {
"Time": {
"DataSource": "DDB1",
"Type": "uint64",
"Alias": "SDNAbsTime"
}
}
},
"+SimTimeGAM": {
"Class": "ConversionGAM",
"InputSignals": {
"Time": {
"DataSource": "DDB1",
"Type": "uint64",
"Alias": "SDNAbsTime"
}
},
"OutputSignals": {
"Time": {
"Gain": 1e-06,
"DataSource": "DDB1",
"Type": "float32",
"Alias": "SimTime"
}
}
},
"+ReferenceGAM": {
"Class": "ConstantGAM",
"OutputSignals": {
@@ -6447,8 +6516,8 @@
"Expression": "cpsA_On = (uint8)((Mode == (uint8)1) || (Mode == (uint8)3));\ncpsB_On = (uint8)((Mode == (uint8)2) || (Mode == (uint8)3));"
},
"+FHPSAOnGAM": {
"Class": "ChaiGAM",
"Code": "fun() {\n\tif (State == 105) { \n\t\tCommand = 3; \n\t} else if (APSSwitch == 3){ \n\t\tCommand = 1; \n\t} else { \n\t\tCommand = 0; \n\t} \n}",
"Class": "LuaGAM",
"Code": "function gam() \n\tif (State == 105) then \n\t\tCommand = 3 \n\telseif (APSSwitch == 3) then \n\t\tCommand = 1 \n\telse \n\t\tCommand = 0 \n\tend \nend",
"InputSignals": {
"State": {
"Type": "uint8",
@@ -6470,8 +6539,8 @@
}
},
"+FHPSBOnGAM": {
"Class": "ChaiGAM",
"Code": "fun() {\n\tif (State == 105) { \n\t\tCommand = 3; \n\t} else if (APSSwitch == 3){ \n\t\tCommand = 1; \n\t} else { \n\t\tCommand = 0; \n\t} \n}",
"Class": "LuaGAM",
"Code": "function gam() \n\tif (State == 105) then \n\t\tCommand = 3 \n\telseif (APSSwitch == 3) then \n\t\tCommand = 1 \n\telse \n\t\tCommand = 0 \n\tend \nend",
"InputSignals": {
"State": {
"Type": "uint8",
@@ -6575,10 +6644,40 @@
"Type": "uint8",
"Alias": "GA_CCPS_Config_Status"
},
"GA_FHPS_CONF_CMD": {
"DataSource": "PLCSDNSub",
"Type": "uint8",
"Alias": "GA_FHPS_CONFIG_SEQ_CMD"
},
"GA_FHPS_V_IN": {
"DataSource": "PLCSDNSub",
"Type": "float32",
"Alias": "GA_FHPS_AC_Voltage"
},
"GA_FHPS_V_INT": {
"DataSource": "ConfActualDB",
"Type": "float32",
"Alias": "GA_FHPS_AC_Voltage"
},
"GA_FHPS_V_OUT": {
"DataSource": "GA_FHPS",
"Type": "float32",
"Alias": "AC_Voltage_Read"
},
"GA_FHPS_ACK": {
"DataSource": "DDB1",
"Type": "uint8",
"Alias": "ACK_GA_FHPS_CONFIG_SEQ_CMD"
},
"ShotTime": {
"DataSource": "ABDB",
"Type": "uint32",
"Alias": "ShotTime"
},
"ACK": {
"DataSource": "DDB1",
"Type": "uint8",
"Alias": "ACK_GA_FHPS_CONFIG_SEQ_CMD"
}
},
"OutputSignals": {
@@ -6662,10 +6761,40 @@
"Type": "uint8",
"Alias": "GA_CCPS_CONFIG_SEQ_STAT"
},
"GA_FHPS_CONF_CMD": {
"DataSource": "Logger",
"Type": "uint8",
"Alias": "GA_FHPS_CONF_CMD"
},
"GA_FHPS_V_IN": {
"DataSource": "Logger",
"Type": "float32",
"Alias": "GA_FHPS_AC_V_IN"
},
"GA_FHPS_V_INT": {
"DataSource": "Logger",
"Type": "float32",
"Alias": "GA_FHPS_AC_V_INT"
},
"GA_FHPS_V_OUT": {
"DataSource": "Logger",
"Type": "float32",
"Alias": "GA_FHPS_AC_V_OUT"
},
"GA_FHPS_ACK": {
"DataSource": "Logger",
"Type": "uint8",
"Alias": "GA_FHPS_ACK"
},
"ShotTime": {
"DataSource": "Logger",
"Type": "uint32",
"Alias": "ShotTime"
},
"ACK": {
"DataSource": "PLCSDNPub",
"Type": "uint8",
"Alias": "ACK_GA_FHPS_CONFIG_SEQ_CMD"
}
}
},
@@ -8374,25 +8503,25 @@
"Type": "float32",
"Alias": "GB_GCPS_Amplitude_Max_Delta"
},
"GA_APS_Voltage_SP": {
"GA_ABPS_APS_Voltage_SP": {
"DataSource": "ConfActualDB",
"Type": "float32",
"Alias": "GA_APS_Voltage_SP"
"Alias": "GA_ABPS_APS_Voltage_SP"
},
"GB_APS_Voltage_SP": {
"GB_ABPS_APS_Voltage_SP": {
"DataSource": "ConfActualDB",
"Type": "float32",
"Alias": "GB_APS_Voltage_SP"
"Alias": "GB_ABPS_APS_Voltage_SP"
},
"GA_BPS_Voltage_SP": {
"GA_ABPS_BPS_Voltage_SP": {
"DataSource": "ConfActualDB",
"Type": "float32",
"Alias": "GA_BPS_Voltage_SP"
"Alias": "GA_ABPS_BPS_Voltage_SP"
},
"GB_BPS_Voltage_SP": {
"GB_ABPS_BPS_Voltage_SP": {
"DataSource": "ConfActualDB",
"Type": "float32",
"Alias": "GB_BPS_Voltage_SP"
"Alias": "GB_ABPS_BPS_Voltage_SP"
}
},
"OutputSignals": {
@@ -8456,25 +8585,25 @@
"Type": "float32",
"Alias": "GB_GCPS_Amplitude_Max_Delta_Read"
},
"GA_APS_Voltage_SP_Read": {
"GA_ABPS_APS_Voltage_SP_Read": {
"DataSource": "PLCSDNPub",
"Type": "float32",
"Alias": "GA_APS_Voltage_SP_Read"
"Alias": "GA_ABPS_APS_Voltage_SP_Read"
},
"GB_APS_Voltage_SP_Read": {
"GB_ABPS_APS_Voltage_SP_Read": {
"DataSource": "PLCSDNPub",
"Type": "float32",
"Alias": "GB_APS_Voltage_SP_Read"
"Alias": "GB_ABPS_APS_Voltage_SP_Read"
},
"GA_BPS_Voltage_SP_Read": {
"GA_ABPS_BPS_Voltage_SP_Read": {
"DataSource": "PLCSDNPub",
"Type": "float32",
"Alias": "GA_BPS_Voltage_SP_Read"
"Alias": "GA_ABPS_BPS_Voltage_SP_Read"
},
"GB_BPS_Voltage_SP_Read": {
"GB_ABPS_BPS_Voltage_SP_Read": {
"DataSource": "PLCSDNPub",
"Type": "float32",
"Alias": "GB_BPS_Voltage_SP_Read"
"Alias": "GB_ABPS_BPS_Voltage_SP_Read"
}
}
},
@@ -8807,6 +8936,54 @@
}
}
},
"+SimMCPS_A_GAM": {
"Class": "LuaGAM",
"Code": "last_time = 0\nfunction gam() \n\tif hold_cmd == 1 then \n\t\tramp_done = 0\n\t\tstate = 0\n\tif ramp_cmd == 1 then\n\t\tlast_time = time\n\t\tramp_done = 0\n\t\tstate = 1\n\telif ramp_cmd == 2 then\n\t\tlast_time = time\n\t\tramp_done = 0 \n\t\tstate = 2\n\tend\n\tif state == 2 then\n\t\tlocal dt = time - last_time -- ms?\n\t\tcurrent = current - (sweep_rate/60000.0) * dt\n\t\tif current_rb <= current_sp then\n\t\t\t-- current = current_sp\n\t\t\tstate = 4\n\t\t\tramp_done = 2\n\t\tend \n\telseif state == 1 then\n\t\tlocal dt = time - last_time -- ms?\n\t\tcurrent = current + (sweep_rate/60000.0) * dt\n\t\tif current >= current_sp then\n\t\t\t-- current_rb = current_sp\n\t\t\tstate = 3\n\t\t\tramp_done = 1\n\t\tend \n\tend\n\tlast_time = time\nend",
"InputSignals": {
"ramp_cmd": {
"Type": "uint8",
"DataSource": "PLCSDNSub",
"Alias": "GA_MCPS_RAMP_CMD"
},
"hold_cmd": {
"Type": "uint8",
"DataSource": "PLCSDNSub",
"Alias": "GA_MCPS_HOLD_CMD"
},
"current_sp": {
"Type": "float32",
"DataSource": "ConfActualDB",
"Alias": "GA_MCPS_Current"
},
"sweep_rate": {
"Type": "float32",
"DataSource": "ConfActualDB",
"Alias": "GA_MCPS_Sweep_Rate"
},
"time_ms": {
"Type": "float32",
"DataSource": "DDB1",
"Alias": "SimTime"
}
},
"OutputSignals": {
"state": {
"Type": "uint8",
"DataSource": "PLCSDNPub",
"Alias": "GA_MCPS_STAT"
},
"ramp_done": {
"Type": "uint8",
"DataSource": "PLCSDNPub",
"Alias": "GA_MCPS_RAMP_DONE"
},
"current": {
"Type": "float32",
"DataSource": "PLCSDNPub",
"Alias": "GA_MCPS_Current"
}
}
},
"+LogWFGAM": {
"Class": "IOGAM",
"InputSignals": {
@@ -9072,6 +9249,9 @@
"StatePublisherGAM",
"SegMessageGAM",
"SegStateGAM",
"SDNTimeGAM",
"SimTimeGAM",
"SimMCPS_A_GAM",
"EpicsLogGAM",
"LoggerGAM"
]
@@ -9157,6 +9337,9 @@
"PLCReadBackPubGAM",
"StatePublisherGAM",
"SegStateGAM",
"SDNTimeGAM",
"SimTimeGAM",
"SimMCPS_A_GAM",
"EpicsLogGAM",
"LoggerGAM"
]
@@ -9267,6 +9450,9 @@
"PLCReadBackPubGAM",
"StatePublisherGAM",
"SegStateGAM",
"SDNTimeGAM",
"SimTimeGAM",
"SimMCPS_A_GAM",
"EpicsLogGAM",
"LoggerGAM"
]
@@ -9374,6 +9560,9 @@
"PLCReadBackPubGAM",
"StatePublisherGAM",
"SegStateGAM",
"SDNTimeGAM",
"SimTimeGAM",
"SimMCPS_A_GAM",
"EpicsLogGAM",
"LoggerGAM"
]
View File
View File
+269
View File
@@ -0,0 +1,269 @@
#!/usr/bin/env python3
#
# Copyright 2008 Jose Fonseca
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import operator
import re
import sys
import gi
gi.require_version("Gtk", "3.0")
import xdot.ui
from gi.repository import Gdk, Gio, GObject, Gtk
class ControlPanel(Gtk.Box):
def __init__(self):
super().__init__(orientation=Gtk.Orientation.VERTICAL, spacing=5)
# Place the control panel in the top right
self.set_halign(Gtk.Align.END)
self.set_valign(Gtk.Align.START)
# Add the .control-panel CSS class to this widget
context = self.get_style_context()
context.add_class("control-panel")
def add_group(self, group):
self.pack_start(group, False, False, 0)
class ControlPanelGroup(Gtk.Expander):
def __init__(self, title: str):
Gtk.Expander.__init__(self, label=title)
self._inner = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
# Set the size request to 200 pixels wide
self.set_size_request(200, -1)
# Add a bit of margin after the header
self._inner.set_margin_top(5)
self.add(self._inner)
def add_row(self, widget):
self._inner.pack_start(widget, False, False, 0)
class MyControlPanel(ControlPanel):
def __init__(self):
super().__init__()
self._first_panel = ControlPanelGroup("Some Buttons")
self._first_panel.add_row(Gtk.Button(label="Button 1"))
self._first_panel.add_row(Gtk.Button(label="Button 2"))
self.add_group(self._first_panel)
self._second_panel = ControlPanelGroup("Extra Settings")
self._second_panel.add_row(Gtk.Button(label="Button 3"))
self._second_panel.add_row(Gtk.Button(label="Button 4"))
self._second_panel.add_row(Gtk.CheckButton.new_with_label("First checkbox"))
self._second_panel.add_row(Gtk.CheckButton.new_with_label("Second checkbox"))
combo = Gtk.ComboBoxText()
combo.append("first", "First Choice")
combo.append("second", "Second Choice")
combo.append("third", "Third Choice")
combo.append("forth", "This one is quite long")
combo.set_active_id("first")
self._second_panel.add_row(combo)
self.add_group(self._second_panel)
def __icon_button__(icon_name: str) -> Gtk.Button:
icon = Gio.ThemedIcon(name=icon_name)
image = Gtk.Image.new_from_gicon(icon, Gtk.IconSize.BUTTON)
button = Gtk.Button()
button.add(image)
return button
def get_handler_id(obj, signal_name):
signal_id, detail = GObject.signal_parse_name(signal_name, obj, True)
return GObject.signal_handler_find(
obj, GObject.SignalMatchType.ID, signal_id, detail, None, None, None
)
class MainView(Gtk.Grid):
def __init__(self):
super().__init__()
self.searchbar = Gtk.SearchBar()
self.dot = xdot.ui.DotWidget()
self.searchentry = Gtk.SearchEntry()
self.searchbar.connect_entry(self.searchentry)
self.searchbar.add(self.searchentry)
self.searchentry.connect("search-changed", self.search)
self.searchentry.connect("stop-search", self.search_close)
# Create the overlay widget
self._overlay = Gtk.Overlay()
# Add our editor and control panel as overlays
self._overlay.add_overlay(self.dot)
self._overlay.add_overlay(MyControlPanel())
self.attach(self.searchbar, 0, 1, 1, 1)
self.attach(self._overlay, 0, 0, 1, 1)
self.dot.set_hexpand(True)
self.dot.set_vexpand(True)
self.dot.grab_focus()
self.dot.connect("clicked", self.on_click)
self.dot.disconnect(get_handler_id(self.dot, "key-press-event"))
self.dot.connect("key-press-event", self.on_key_pressed)
self.dot.connect("button-press-event", self.on_focus)
def open_dotcode(self, path):
fp = open(path, "rb")
self.dot.set_dotcode(fp.read(), path)
def set_dotcode(self, code):
try:
self.dot.set_dotcode(code)
except AssertionError as e:
print("something wrong:", e)
def find_text(self, entry_text):
found_items = []
dot_widget = self.dot
try:
regexp = re.compile(entry_text)
except re.error as err:
sys.stderr.write('warning: re.compile() failed with error "%s"\n' % err)
return []
for element in (
dot_widget.graph.nodes + dot_widget.graph.edges + dot_widget.graph.shapes
):
if element.search_text(regexp):
found_items.append(element)
return sorted(found_items, key=operator.methodcaller("get_text"))
def search(self, _):
txt = self.searchentry.get_text()
if txt:
items = self.find_text(txt)
self.dot.set_highlight(items, search=True)
else:
self.dot.set_highlight(None, search=True)
def search_close(
self,
_,
):
self.dot.grab_focus()
def on_click(self, _, url, event):
print(url, event)
# center element
x, y = int(event.x), int(event.y)
jump = self.dot.get_jump(x, y)
if jump is not None:
self.dot.animate_to(jump.x, jump.y)
def on_focus(self, widget, _):
self.dot.grab_focus()
def on_key_pressed(self, _, event):
if event.keyval in (Gdk.KEY_f, Gdk.KEY_slash):
if self.searchbar.get_search_mode():
self.searchentry.grab_focus()
else:
self.searchbar.set_search_mode(True)
return True
if event.keyval == Gdk.KEY_w:
self.dot.zoom_to_fit()
return True
if event.keyval == Gdk.KEY_plus:
self.dot.zoom_image(self.dot.zoom_ratio * 1.1)
return True
if event.keyval == Gdk.KEY_minus:
self.dot.zoom_image(self.dot.zoom_ratio / 1.1)
return True
if event.keyval == Gdk.KEY_equal:
self.dot.zoom_image(1.0)
return True
if event.keyval == Gdk.KEY_Left:
self.dot.x -= self.dot.POS_INCREMENT / self.dot.zoom_ratio
self.dot.queue_draw()
return True
if event.keyval == Gdk.KEY_Right:
self.dot.x += self.dot.POS_INCREMENT / self.dot.zoom_ratio
self.dot.queue_draw()
return True
if event.keyval == Gdk.KEY_Up:
self.dot.y -= self.dot.POS_INCREMENT / self.dot.zoom_ratio
self.dot.queue_draw()
return True
if event.keyval == Gdk.KEY_Down:
self.dot.y += self.dot.POS_INCREMENT / self.dot.zoom_ratio
self.dot.queue_draw()
return True
class MyDotWindow(Gtk.Window):
def __init__(self):
super().__init__(title="Test")
self.set_default_size(400, 200)
self._main_view = MainView()
box = Gtk.VBox()
paned1 = Gtk.Paned()
paned2 = Gtk.Paned()
button1 = Gtk.Button(label="Button1")
button2 = Gtk.Button(label="Button2")
paned1.add1(button1)
paned1.add2(paned2)
paned2.pack1(self._main_view, True, False)
paned2.pack2(button2, False, True)
box.pack_start(paned1, True, True, 0)
self.add(box)
self.show_all()
def open_dotcode(self, path):
self._main_view.open_dotcode(path)
def install_css():
screen = Gdk.Screen.get_default()
provider = Gtk.CssProvider()
provider.load_from_data(
b"""
.control-panel {
background-color: rgba(255,255,255, 0.8);
padding: 4px;
border-bottom-left-radius: 4px;
}
"""
)
Gtk.StyleContext.add_provider_for_screen(screen, provider, 600)
def main():
install_css()
window = MyDotWindow()
window.open_dotcode("../output/Test.dot")
window.connect("delete-event", Gtk.main_quit)
window.show_all()
Gtk.main()
if __name__ == "__main__":
main()