view2dot = function(view, stamp) {
const rt = view._runtime,
ops = rt.nodes,
keys = Object.keys(ops);
const signals = Object.keys(rt.signals).reduce((lut, name) => {
lut[rt.signals[name].id] = name;
return lut;
}, {});
const scales = Object.keys(rt.scales).reduce((lut, name) => {
lut[rt.scales[name].id] = name;
return lut;
}, {});
const data = Object.keys(rt.data).reduce((lut, name) => {
const sets = rt.data[name];
if (sets.input) lut[sets.input.id] = name;
if (sets.output) lut[sets.output.id] = name;
return lut;
}, {});
const nodes = keys.map(key => {
const op = ops[key];
const node = {
id: op.id,
type: op.constructor.name.toLowerCase(),
stamp: op.stamp,
value: op
};
if (markTypes[getType(node.type)]) node.isMark = true;
if (signals[op.id]) node.signal = signals[op.id];
if (scales[op.id]) node.scale = scales[op.id];
if (data[op.id]) node.data = data[op.id];
if (rt.root === op) node.root = true;
return node;
});
const ids = nodes.reduce((lut, node) => {
lut[node.id] = node;
return lut;
}, {});
const edges = [];
keys.forEach(key => {
const op = ops[key];
if (op._targets) op._targets.forEach(t => {
if (!ids[t.id]) return;
edges.push({
nodes: [op.id, t.id],
param: t.source === op ? 'pulse' : argop(t, op)
});
if (t.source === op && ids[op.id].isMark) {
let node = ids[t.id];
if (getType(node.type) === 'collect') {
node.isMark = true;
}
}
});
});
return `digraph {
rankdir = LR;
node [style=filled];
${nodes.map(node => {
return node.id
+ ' [label="' + nodeLabel(node) + '"]'
+ ' [color="' + nodeColor(node, stamp) + '"]'
+ ' [fillcolor="' + nodeFillColor(node, stamp) + '"]'
+ ' [fontcolor="' + nodeFontColor(node, stamp) + '"]';
})
.join(';\n ')};
${edges.map(e => {
return e.nodes.join(' -> ')
+ ' [label="' + (e.param === 'pulse' ? '' : e.param) + '"]'
+ ' [color="' + edgeColor(e, ids, stamp) + '"]'
+ ' [fontcolor="' + edgeLabelColor(e, ids, stamp) + '"]'
+ ' [weight="' + edgeWeight(e, ids) + '"]';
}).join(';\n ')};
}`;
}