SVGHelper.cpp
Go to the documentation of this file.
1 
18 #include "SVGHelper.hpp"
19 #include <fstream>
20 #include <iostream>
21 #include <string>
22 #include <sstream>
23 
24 #include <boost/version.hpp>
25 
26 namespace ISM
27 {
28 
29  void SVGHelper::processHistory(std::vector<std::vector<std::pair<TopologyPtr, unsigned int>>>& history,
30  CostFunctionPtr<TopologyPtr> globalCostFunction, const std::string& patternName)
31  {
32  double minAverageRecognitionRuntime = std::numeric_limits<double>::max();
33  double maxAverageRecognitionRuntime = std::numeric_limits<double>::min();
34 
35  double minCost = std::numeric_limits<double>::max();
36  double maxCost = std::numeric_limits<double>::min();
37 
38  OptimizationRun optRun;
39  optRun.lastSelectedIndex = 0;
40 
41  for (unsigned int i = 0; i < history.size(); ++i)
42  {
43  OptimizationRound optRound;
44  for (unsigned int j = 0; j < history[i].size(); ++j)
45  {
46  if (history[i][j].second != 0)
47  {
48  optRound.selectedTopologyIndex = j;
49  optRound.selectedTopologyType = history[i][j].second;
50 
51  optRun.lastSelectedIndex = i;
52  }
53 
54  TopologyPtr topology = history[i][j].first;
55 
57  tc.er = topology->evaluationResult;
58  tc.index = topology->index;
59  tc.identifier = topology->identifier;
60 
61  double cost = globalCostFunction->calculateCost(topology);
62  cost = cost == std::numeric_limits<double>::max() ? -1 : cost;
63  tc.cost = cost;
64 
65  minCost = std::min(minCost, cost);
66  maxCost = std::max(maxCost, cost == std::numeric_limits<double>::infinity() ? 0 : cost);
67 
68  optRound.evaluatedTopologies.push_back(tc);
69 
70  minAverageRecognitionRuntime = std::min(minAverageRecognitionRuntime, tc.er.averageRecognitionRuntime);
71  maxAverageRecognitionRuntime = std::max(maxAverageRecognitionRuntime, tc.er.averageRecognitionRuntime);
72  }
73  optRun.allRounds.push_back(optRound);
74  }
75 
76  optRun.minAverageRecognitionRuntime = minAverageRecognitionRuntime;
77  optRun.maxAverageRecognitionRuntime = maxAverageRecognitionRuntime;
78 
79  optRun.minCost = minCost;
80  optRun.maxCost = maxCost;
81 
83  }
84 
86  {
87  #if (BOOST_VERSION >= 105600)
88  boost::property_tree::xml_writer_settings<std::string> settings('\t', 1);
89  #else
90  boost::property_tree::xml_writer_settings<char> settings('\t', 1);
91  #endif
92 
93  for (std::map<std::string, std::vector<OptimizationRun>>::iterator it = mPatternNameToOptimizationRuns.begin();
95  ++it)
96  {
97  std::vector<ptree> roots = createSVG(it->second);
98  for (unsigned int i = 0; i < roots.size(); ++i)
99  {
100  std::string svgFileName = mOutputPath.string() + "/visulisation- "
101  + it->first + "_" + std::to_string(i);
102  boost::property_tree::write_xml(svgFileName + ".svg", roots[i], std::locale(), settings);
103  }
104  }
105  }
106 
107  std::vector<int> SVGHelper::calculateXValues(unsigned int numTopologies, unsigned int imageWidth)
108  {
109  std::vector<int> xValues;
110  unsigned int center = imageWidth / 2;
111 
112  for (unsigned int i = 0; i < numTopologies;)
113  {
114  unsigned int numCirclesThisLine = std::min(MAX_TOPOLOGIES_PER_LINE, numTopologies - i);
115  unsigned int half;
116  int x;
117 
118  if (numCirclesThisLine % 2 == 0)
119  {
120  half = numCirclesThisLine / 2;
121  x = center - (PADDING / 2 + MAX_CIRCLE_RADIUS + (half - 1)
122  * (PADDING + 2 * MAX_CIRCLE_RADIUS));
123  }
124  else
125  {
126  half = (numCirclesThisLine - 1) / 2;
127  x = center - half * (PADDING + 2 * MAX_CIRCLE_RADIUS);
128  }
129 
130  for (unsigned int j = 0; j < numCirclesThisLine; j++)
131  {
132  xValues.push_back(x);
133  x += PADDING + 2 * MAX_CIRCLE_RADIUS;
134  }
135  i += numCirclesThisLine;
136  }
137 
138  return xValues;
139  }
140 
141  void SVGHelper::calculatePositions(std::vector<OptimizationRun>& optimizationRuns,
142  std::vector<std::vector<int>>& seperatorLinePositions,
143  unsigned int& imgWidth, unsigned int& imgHeight)
144  {
145  unsigned int numStartingTopologies = 0;
146  unsigned int maxRoundSize = 0;
147 
148  for (unsigned int i = 0; i < optimizationRuns.size(); ++i)
149  {
150  OptimizationRun optRun = optimizationRuns[i];
151  numStartingTopologies += optRun.allRounds[0].evaluatedTopologies.size();
152  for (unsigned int j = 0; j < optRun.allRounds.size(); ++j)
153  {
154  maxRoundSize = std::max(maxRoundSize,
155  (unsigned int) optRun.allRounds[j].evaluatedTopologies.size());
156  }
157  }
158 
159  unsigned int maxNumTopologiesPerLine = std::min(MAX_TOPOLOGIES_PER_LINE,
160  std::max(maxRoundSize, numStartingTopologies));
161 
162  imgWidth = maxNumTopologiesPerLine * 2 * MAX_CIRCLE_RADIUS + (maxNumTopologiesPerLine + 2)
163  * PADDING;
164 
165  std::vector<int> startingXValues = calculateXValues(numStartingTopologies, imgWidth);
166  unsigned int startingXValuesIndex = 0;
167 
168  unsigned int x;
169  unsigned int y;
170  unsigned int maxY = 0;
171 
172  for (unsigned int i = 0; i < optimizationRuns.size(); ++i)
173  {
174  OptimizationRun & optRun = optimizationRuns[i];
175  seperatorLinePositions.push_back(std::vector<int>());
177  unsigned int index = 0;
178 
179  for (unsigned int j = 0; j < optRun.allRounds.size(); ++j)
180  {
181  index = 0;
182  std::vector<int> xValues;
183  if (j != 0)
184  {
185  xValues = calculateXValues(optRun.allRounds[j].evaluatedTopologies.size(),
186  imgWidth);
187  }
188 
189  for (unsigned int k = 0; k < optRun.allRounds[j].evaluatedTopologies.size(); ++k)
190  {
191  if (index == MAX_TOPOLOGIES_PER_LINE)
192  {
193  y += PADDING + MAX_CIRCLE_RADIUS * 2;
194  index = 0;
195  }
196 
197  if (j == 0)
198  {
199  x = startingXValues[startingXValuesIndex];
200  startingXValuesIndex++;
201  }
202  else
203  {
204  x = xValues[k];
205  }
206 
207  TopologyContainer & tc = optRun.allRounds[j].evaluatedTopologies[k];
208  tc.x = x;
209  tc.y = y;
210  index++;
211  }
212 
213  if (j != optimizationRuns[i].allRounds.size() - 1)
214  {
215  seperatorLinePositions[i].push_back(y + MAX_CIRCLE_RADIUS + 2 * PADDING);
216  y += (2 * PADDING + MAX_CIRCLE_RADIUS) * 2;
217  }
218  else
219  {
220  y += PADDING + MAX_CIRCLE_RADIUS * 2;
221  }
222  }
223  maxY = std::max(y, maxY);
224  }
225 
226  imgHeight = maxY - MAX_CIRCLE_RADIUS;
227  }
228 
229  std::vector<ptree> SVGHelper::createSVG(std::vector<OptimizationRun> optimizationRuns)
230  {
231  std::vector<ptree> roots;
232 
233  std::vector<std::vector<int>> seperatorLinePositions;
234  unsigned int imgWidth, imgHeight;
235  calculatePositions(optimizationRuns, seperatorLinePositions, imgWidth, imgHeight);
236 
237  double maxAverageRecognitionRuntime = std::numeric_limits<double>::min();
238  double minAverageRecognitionRuntime = std::numeric_limits<double>::max();
239 
240  for (unsigned int i = 0; i < optimizationRuns.size(); ++i)
241  {
242  OptimizationRun optRun = optimizationRuns[i];
243 
244  maxAverageRecognitionRuntime = std::max(maxAverageRecognitionRuntime, optRun.maxAverageRecognitionRuntime);
245  minAverageRecognitionRuntime = std::min(minAverageRecognitionRuntime, optRun.minAverageRecognitionRuntime);
246  }
247 
248  for (unsigned int i = 0; i < optimizationRuns.size(); ++i)
249  {
250  OptimizationRun optRun = optimizationRuns[i];
251  std::vector<std::string> linePoints;
252  std::vector<ptree> circleNodes;
253  std::vector<ptree> textNodes;
254  unsigned int index = 0;
255 
256  for (unsigned int j = 0; j < optRun.allRounds.size(); ++j)
257  {
258  OptimizationRound optRound = optRun.allRounds[j];
259 
260  for (unsigned int k = 0; k < optRound.evaluatedTopologies.size(); ++k) {
261  TopologyContainer tc = optRound.evaluatedTopologies[k];
262  int x = tc.x;
263  int y = imgHeight - tc.y;
264  std::string highlightColor = "";
265 
266  bool foundChosen = (int) k == optRound.selectedTopologyIndex;
267  if (foundChosen)
268  {
269  linePoints.push_back(std::to_string(x) + "," + std::to_string(y));
270  if (j == 0)
271  {
272  highlightColor = COLOR_FIRST_HIGHLIGHT;
273  }
274  else if ((int) j == optRun.lastSelectedIndex)
275  {
276  highlightColor = COLOR_LAST_HIGHLIGHT;
277  }
278  else
279  {
280  switch (optRound.selectedTopologyType) {
281  case 1:
282  highlightColor = COLOR_HIGHLIGHT;
283  break;
284  case 2:
285  highlightColor = COLOR_RANDOM_RESTART_HIGHLIGHT;
286  break;
287  case 3:
288  highlightColor = COLOR_RANDOM_WALK_HIGHLIGHT;
289  break;
290  case 4:
291  highlightColor = COLOR_BEST;
292  break;
293  default:
294  highlightColor = COLOR_HIGHLIGHT;
295  break;
296  }
297  }
298  }
299 
300  circleNodes.push_back(genCircleSVG(
302  minAverageRecognitionRuntime,
303  maxAverageRecognitionRuntime),
304  x, y, genRGBString(tc.cost, optRun.minCost, optRun.maxCost),
305  foundChosen, highlightColor));
306 
307  std::ostringstream lineTwo;
308  std::ostringstream lineThree;
309  lineTwo << std::fixed << std::setprecision(3) << tc.cost;
310  lineThree << std::fixed << std::setprecision(3)
311  << tc.er.falsePositives << "/" << tc.er.averageRecognitionRuntime;
312 
313  textNodes.push_back(genTextSVG(std::to_string(tc.index),
314  lineTwo.str(), lineThree.str(),
315  x, y));
316 
317  index++;
318  }
319  }
320 
321  ptree root;
322  ptree svg;
323 
324  svg.put("<xmlattr>.xmlns", "http://www.w3.org/2000/svg") ;
325  svg.put("<xmlattr>.width", std::to_string(imgWidth)) ;
326  svg.put("<xmlattr>.height", std::to_string(imgHeight)) ;
327  svg.put("<xmlattr>.background", "white") ;
328 
329  svg.add_child("rect", genRectSVG(0, 0, imgWidth, imgHeight, "white"));
330  svg.add_child("polyline", genPolylineSVG(linePoints));
331 
332  for (unsigned int j = 0; j < circleNodes.size(); ++j)
333  {
334  svg.add_child("circle", circleNodes[j]);
335  }
336 
337  for (unsigned int j = 0; j < textNodes.size(); ++j)
338  {
339  svg.add_child("text", textNodes[j]);
340  }
341 
342  for (unsigned int j = 0; j < seperatorLinePositions[i].size(); ++j)
343  {
344  svg.add_child("line", genSeparatorLineSVG(imgHeight - seperatorLinePositions[i][j],
345  PADDING, imgWidth - PADDING));
346  }
347 
348  root.add_child("svg", svg);
349  roots.push_back(root);
350  }
351 
352  return roots;
353  }
354 
355  ptree SVGHelper::genCircleSVG(double radius, int x, int y, const std::string& circleColor,
356  bool highlight, const std::string& highlightColor)
357  {
358  ptree circleNode;
359  circleNode.put("<xmlattr>.cx", std::to_string(x));
360  circleNode.put("<xmlattr>.cy", std::to_string(y));
361  circleNode.put("<xmlattr>.r", std::to_string(radius));
362  circleNode.put("<xmlattr>.fill", circleColor);
363  if (highlight)
364  {
365  circleNode.put("<xmlattr>.stroke", highlightColor);
366  circleNode.put("<xmlattr>.stroke-width", std::to_string(HIGHLIGHT_WIDTH));
367  }
368  return circleNode;
369  }
370 
371  ptree SVGHelper::genTextSVG(const std::string& lineOne, const std::string& lineTwo,
372  const std::string& lineThree, int x, int y)
373  {
374  ptree textNode;
375  textNode.put("<xmlattr>.y", std::to_string(y));
376  textNode.put("<xmlattr>.x", std::to_string(x));
377  textNode.put("<xmlattr>.fill", "black");
378  textNode.put("<xmlattr>.font-family", "Courier New");
379  textNode.put("<xmlattr>.text-anchor", "middle");
380  textNode.put("<xmlattr>.font-weight", "bold");
381  textNode.put("<xmlattr>.font-size", std::to_string(FONT_SIZE) + "px") ;
382 
383  ptree lOne;
384  lOne.put("", lineOne);
385  lOne.put("<xmlattr>.x", std::to_string(x + FONT_SIZE / 4));
386  lOne.put("<xmlattr>.dy", - (int) FONT_SIZE * 1.25);
387  lOne.put("<xmlattr>.font-style", "italic");
388 
389  ptree lTwo;
390  lTwo.put("", lineTwo);
391  lTwo.put("<xmlattr>.x", std::to_string(x + FONT_SIZE / 4));
392  lTwo.put("<xmlattr>.dy", FONT_SIZE * 1.25);
393 
394  ptree lThree;
395  lThree.put("", lineThree);
396  lThree.put("<xmlattr>.x", std::to_string(x));
397  lThree.put("<xmlattr>.dy", FONT_SIZE * 1.25);
398 
399  textNode.add_child("tspan", lOne);
400  textNode.add_child("tspan", lTwo);
401  textNode.add_child("tspan", lThree);
402 
403  return textNode;
404  }
405 
406  ptree SVGHelper::genSeparatorLineSVG(int y, int x1, int x2)
407  {
408  ptree sepeartorLineNode;
409  sepeartorLineNode.put("<xmlattr>.stroke-dasharray", "5, 5");
410  sepeartorLineNode.put("<xmlattr>.y1", std::to_string(y));
411  sepeartorLineNode.put("<xmlattr>.y2", std::to_string(y));
412  sepeartorLineNode.put("<xmlattr>.x1", std::to_string(x1));
413  sepeartorLineNode.put("<xmlattr>.x2", std::to_string(x2));
414  sepeartorLineNode.put("<xmlattr>.stroke", "black");
415  sepeartorLineNode.put("<xmlattr>.stroke-width", "3");
416 
417  return sepeartorLineNode;
418  }
419 
420  ptree SVGHelper::genPolylineSVG(std::vector<std::string> linePoints)
421  {
422  std::string linePointsString = "";
423  if (linePoints.size() != 0)
424  {
425  linePointsString += linePoints[0];
426  for (unsigned int i = 1; i < linePoints.size(); ++i)
427  {
428  linePointsString += " " + linePoints[i];
429  }
430  }
431 
432  ptree lineNode;
433  lineNode.put("<xmlattr>.points", linePointsString);
434  lineNode.put("<xmlattr>.style", "fill:none;stroke:"
435  + COLOR_HIGHLIGHT + ";stroke-linejoin:round;stroke-width:"
436  + std::to_string(LINE_WIDTH));
437 
438  return lineNode;
439  }
440 
441  ptree SVGHelper::genRectSVG(int x, int y, unsigned int width,
442  unsigned int height, const std::string& colorString)
443  {
444  ptree rectNode;
445  rectNode.put("<xmlattr>.x", std::to_string(x));
446  rectNode.put("<xmlattr>.y", std::to_string(y));
447  rectNode.put("<xmlattr>.width", std::to_string(width));
448  rectNode.put("<xmlattr>.height", std::to_string(height));
449  rectNode.put("<xmlattr>.style", "fill:" + colorString);
450 
451  return rectNode;
452  }
453 
454 
455  ptree SVGHelper::createXML(const std::string& patternName)
456  {
457  ptree root;
458  ptree optimizationRun;
459  optimizationRun.put("<xmlattr>." + ATR_PATTERN_NAME, patternName) ;
460  for (unsigned int i = 0; i < mAllEvaluationRounds.size(); ++i)
461  {
463  ptree erNode = genEvaluationRoundXML(i, optRound.selectedTopologyIndex);
464 
465  for (unsigned int j = 0; j < optRound.evaluatedTopologies.size(); ++j)
466  {
467  ptree tcNode = genTopologyContainerXML(optRound.evaluatedTopologies[j]);
468  erNode.add_child(NAME_TOPOLOGY, tcNode);
469  }
470  optimizationRun.add_child(NAME_ROUND, erNode);
471  }
472  root.add_child(NAME_OPTIMIZATION_RUN, optimizationRun);
473  return root;
474  }
475 
477  {
478  ptree tcNode;
479  tcNode.put("<xmlattr>." + ATR_EVALUATION_RESULT, std::to_string(tc.cost)) ;
480  tcNode.put("<xmlattr>." + ATR_RELATION_IDS, tc.identifier);
481  return tcNode;
482  }
483 
484  ptree SVGHelper::genEvaluationRoundXML(unsigned int roundNumber, unsigned int chosenIndex)
485  {
486  ptree erNode;
487  erNode.put("<xmlattr>." + ATR_ROUND_NUMBER, std::to_string(roundNumber)) ;
488  erNode.put("<xmlattr>." + ATR_CHOSEN_INDEX, std::to_string(chosenIndex)) ;
489  return erNode;
490  }
491 
492 
493  std::string SVGHelper::genRGBString(double cost, double minCost, double maxCost)
494  {
495  if (cost == std::numeric_limits<double>::infinity())
496  return "rgb(255, 0, 0)";
497 
498  double diff = maxCost - minCost;
499  double halfWay = diff / 2;
500  double ratio = 255 / halfWay;
501  double normedCost= cost - minCost;
502  double redValue, greenValue, blueValue = 0;
503  if (normedCost < halfWay)
504  {
505  redValue = normedCost * ratio;
506  greenValue = 255;
507  }
508  else
509  {
510  redValue = 255;
511  greenValue = (2 * halfWay - normedCost) * ratio;
512  }
513 
514  return "rgb(" + std::to_string((int) redValue) + ","
515  + std::to_string((int) greenValue) + ","
516  + std::to_string((int) blueValue) + ")";
517  }
518 
519  double SVGHelper::calculateCircleRadius(double averageRecognitionRuntime,
520  double minAverageRecognitionRuntime,
521  double maxAverageRecognitionRuntime)
522  {
523  double diff = maxAverageRecognitionRuntime - minAverageRecognitionRuntime;
524  double ratio = (averageRecognitionRuntime - minAverageRecognitionRuntime) / diff;
526  }
527 }
const std::string ATR_CHOSEN_INDEX
Definition: SVGHelper.hpp:79
const unsigned int MIN_CIRCLE_RADIUS
Definition: SVGHelper.hpp:97
double calculateCircleRadius(double evaluationDuration, double minEvaluationDuration, double maxEvaluationDuration)
Definition: SVGHelper.cpp:519
const std::string ATR_PATTERN_NAME
Definition: SVGHelper.hpp:82
boost::shared_ptr< CostFunction< InstanceType >> CostFunctionPtr
const unsigned int MAX_CIRCLE_RADIUS
Definition: SVGHelper.hpp:98
std::map< std::string, std::vector< OptimizationRun > > mPatternNameToOptimizationRuns
Definition: SVGHelper.hpp:112
void calculatePositions(std::vector< OptimizationRun > &optimizationRuns, std::vector< std::vector< int >> &seperatorLinePositions, unsigned int &imgWidth, unsigned int &imgHeight)
Definition: SVGHelper.cpp:141
ptree createXML(const std::string &patternName)
Definition: SVGHelper.cpp:455
ptree genCircleSVG(double radius, int x, int y, const std::string &circleColor, bool highlight, const std::string &highlightColor)
Definition: SVGHelper.cpp:355
std::vector< TopologyContainer > evaluatedTopologies
Definition: SVGHelper.hpp:62
const unsigned int LINE_WIDTH
Definition: SVGHelper.hpp:102
std::string patternName
const std::string ATR_EVALUATION_RESULT
Definition: SVGHelper.hpp:81
const unsigned int FONT_SIZE
Definition: SVGHelper.hpp:100
const std::string NAME_OPTIMIZATION_RUN
Definition: SVGHelper.hpp:87
boost::shared_ptr< Topology > TopologyPtr
Definition: Topology.hpp:51
const unsigned int MAX_TOPOLOGIES_PER_LINE
Definition: SVGHelper.hpp:104
const std::string ATR_ROUND_NUMBER
Definition: SVGHelper.hpp:80
void writeResult()
Definition: SVGHelper.cpp:85
const std::string COLOR_BEST
Definition: SVGHelper.hpp:92
ptree genTextSVG(const std::string &lineOne, const std::string &lineTwo, const std::string &lineThree, int x, int y)
Definition: SVGHelper.cpp:371
ptree genTopologyContainerXML(TopologyContainer tc)
Definition: SVGHelper.cpp:476
const std::string COLOR_RANDOM_WALK_HIGHLIGHT
Definition: SVGHelper.hpp:94
const std::string COLOR_HIGHLIGHT
Definition: SVGHelper.hpp:91
std::vector< OptimizationRound > mAllEvaluationRounds
Definition: SVGHelper.hpp:111
std::vector< int > calculateXValues(unsigned int numTopologies, unsigned int imageWidth)
Definition: SVGHelper.cpp:107
const std::string ATR_RELATION_IDS
Definition: SVGHelper.hpp:83
ptree genRectSVG(int x, int y, unsigned int width, unsigned int height, const std::string &colorString)
Definition: SVGHelper.cpp:441
const std::string COLOR_FIRST_HIGHLIGHT
Definition: SVGHelper.hpp:89
const std::string COLOR_RANDOM_RESTART_HIGHLIGHT
Definition: SVGHelper.hpp:95
std::vector< ptree > createSVG(std::vector< OptimizationRun > optimizationRuns)
Definition: SVGHelper.cpp:229
ptree genSeparatorLineSVG(int y, int x1, int x2)
Definition: SVGHelper.cpp:406
const unsigned int HIGHLIGHT_WIDTH
Definition: SVGHelper.hpp:101
ptree genPolylineSVG(std::vector< std::string > linePoints)
Definition: SVGHelper.cpp:420
ptree genEvaluationRoundXML(unsigned int roundNumber, unsigned int chosenIndex)
Definition: SVGHelper.cpp:484
this namespace contains all generally usable classes.
const std::string NAME_ROUND
Definition: SVGHelper.hpp:86
void processHistory(std::vector< std::vector< std::pair< TopologyPtr, unsigned int >>> &history, CostFunctionPtr< TopologyPtr > globalCostFunction, const std::string &patternName)
Definition: SVGHelper.cpp:29
const std::string NAME_TOPOLOGY
Definition: SVGHelper.hpp:85
std::string genRGBString(double cost, double minCost, double maxCost)
Definition: SVGHelper.cpp:493
std::vector< OptimizationRound > allRounds
Definition: SVGHelper.hpp:68
const unsigned int PADDING
Definition: SVGHelper.hpp:99
const std::string COLOR_LAST_HIGHLIGHT
Definition: SVGHelper.hpp:90


asr_lib_ism
Author(s): Hanselmann Fabian, Heller Florian, Heizmann Heinrich, Kübler Marcel, Mehlhaus Jonas, Meißner Pascal, Qattan Mohamad, Reckling Reno, Stroh Daniel
autogenerated on Wed Jan 8 2020 04:02:41