iMSTK
Interactive Medical Simulation Toolkit
imstkTaskGraphVizWriter.cpp
1 /*
2 ** This file is part of the Interactive Medical Simulation Toolkit (iMSTK)
3 ** iMSTK is distributed under the Apache License, Version 2.0.
4 ** See accompanying NOTICE for details.
5 */
6 
7 #include "imstkTaskGraphVizWriter.h"
8 #include "imstkLogger.h"
9 #include "imstkTaskGraph.h"
10 #include "imstkColor.h"
11 
12 #include <fstream>
13 
14 namespace imstk
15 {
16 void
18 {
19  if (m_inputGraph == nullptr)
20  {
21  LOG(WARNING) << "No input set, unable to write ComputeGraph";
22  return;
23  }
24 
25  // Compute range of compute times for color function
26  double maxTime = std::numeric_limits<double>::min();
27  if (m_writeNodeComputeTimesColor)
28  {
29  for (auto node : m_inputGraph->getNodes())
30  {
31  if (node->m_computeTime > maxTime)
32  {
33  maxTime = node->m_computeTime;
34  }
35  }
36  }
37 
38  // Hardcoded color function
39  std::vector<Color> colorFunc = std::vector<Color>(3);
40  colorFunc[0] = Color::Blue;
41  colorFunc[1] = Color::Green;
42  colorFunc[2] = Color::Red;
43  const int colorFuncExtent = static_cast<int>(colorFunc.size() - 1);
44 
45  // Compute the critical path (ie: longest path in duration)
46  TaskNodeList critPath;
47  if (m_highlightCriticalPath)
48  {
49  critPath = TaskGraph::getCriticalPath(m_inputGraph);
50  }
51  // Test if edge exists in critical path by linear searching
52  auto edgeExists = [&](const std::shared_ptr<TaskNode>& a, const std::shared_ptr<TaskNode>& b)
53  {
54  TaskNodeList::iterator srcNode = std::find(critPath.begin(), critPath.end(), a);
55  // If srcNode was found and the next node is b
56  return (srcNode != critPath.end() && *std::next(srcNode) == b);
57  };
58 
59  // Write the file
60  {
61  std::ofstream file;
62  file.open(m_fileName);
63 
64  if (!file.is_open() || file.fail())
65  {
66  return;
67  }
68 
69  file <<
70  "digraph imstkTaskGraph\n"
71  "{\n"
72  "style=filled;\n"
73  "color=lightgrey;\n"
74  "edge[arrowhead=vee, arrowtail=inv, arrowsize=.7, color=grey20];\n";
75 
76  // Write the node section
77  const TaskNodeVector& nodes = m_inputGraph->getNodes();
78  TaskNodeNameMap nodeIds;
79  for (size_t i = 0; i < nodes.size(); i++)
80  {
81  const std::string nodeUniqueName = "node" + std::to_string(i);
82  nodeIds[nodes[i]] = nodeUniqueName;
83 
84  file << "\"" << nodeUniqueName << "\" [";
85 
86  // Write label property
87  if (m_writeNodeComputeTimesText)
88  {
89  file << " label=\"" << nodes[i]->m_name << " (" << nodes[i]->m_computeTime << "ms)" << "\"";
90  }
91  else
92  {
93  file << " label=\"" << nodes[i]->m_name << '\"';
94  }
95 
96  // Write style property
97  file << " style=filled";
98 
99  // Write color property
100  if (m_writeNodeComputeTimesColor)
101  {
102  const double t = nodes[i]->m_computeTime / maxTime;
103  const int i1 = static_cast<int>(t * colorFuncExtent);
104  const int i2 = std::min(colorFuncExtent, i1 + 1);
105  Color color = Color::lerpRgb(colorFunc[i1], colorFunc[i2], t);
106  file << " color=\"#" << color.rgbHex() << "\"";
107  }
108  else
109  {
110  if (nodes[i]->m_isCritical)
111  {
112  file << " color=\"#8B2610\"";
113  }
114  else
115  {
116  file << " color=cornflowerblue";
117  }
118  }
119  file << "];" << std::endl;
120  }
121 
122  // Write out all the edges
123  const TaskNodeAdjList& adjList = m_inputGraph->getAdjList();
124  for (TaskNodeAdjList::const_iterator it = adjList.begin(); it != adjList.end(); it++)
125  {
126  std::shared_ptr<TaskNode> srcNode = it->first;
127  const TaskNodeSet& outputNodes = it->second;
128  for (TaskNodeSet::const_iterator jt = outputNodes.begin(); jt != outputNodes.end(); jt++)
129  {
130  std::shared_ptr<TaskNode> destNode = *jt;
131  file << '\"' << nodeIds[srcNode] << '\"' << " -> " << '\"' << nodeIds[destNode] << '\"';
132 
133  if (m_highlightCriticalPath && edgeExists(srcNode, destNode))
134  {
135  file << "[color=red]";
136  }
137  file << std::endl;
138  }
139  }
140  file << "}\n";
141  file.close();
142  }
143 }
144 } // namespace imstk
Compound Geometry.
void write()
Writes the graph to a file given the filename.
static TaskNodeList getCriticalPath(std::shared_ptr< TaskGraph > graph)
Computes the critical path.
std::string rgbHex()
Definition: imstkColor.cpp:165
Color in RGB space.
Definition: imstkColor.h:24