iMSTK
Interactive Medical Simulation Toolkit
imstkDataTracker.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 #pragma once
8 
9 #include "imstkDataTracker.h"
10 #include <cmath>
11 
12 namespace imstk
13 {
14 DataTracker::DataTracker()
15 {
16  m_nextIndex = 0;
17  m_filename = "";
18  useCommaDelimiter();
19 }
20 
21 DataTracker::~DataTracker()
22 {
23  m_elements.clear();
24  m_file.close();
25 }
26 
27 int
28 DataTracker::configureProbe(const std::string& name, std::streamsize precision, eDecimalFormat_Type notation)
29 {
30  auto& e = getElement(name);
31  e.precision = precision;
32  e.notation = notation;
33  return e.index;
34 }
35 
36 int
37 DataTracker::configureProbe(const std::string& name, int index, std::streamsize precision, eDecimalFormat_Type notation)
38 {
39  auto& e = getElement(index);
40  e.name = name;
41  e.precision = precision;
42  e.notation = notation;
43  return e.index;
44 }
45 
46 int
47 DataTracker::probe(const std::string& name, double value)
48 {
49  auto& e = getElement(name);
50  e.value = value;
51  return e.index;
52 }
53 
54 void
55 DataTracker::probe(int index, double value)
56 {
57  auto& e = getElement(index);
58  e.value = value;
59 }
60 
61 void
63 {
64  auto& e = getElement(index);
65  auto& sw = getStopWatch(index);
66  e.value = sw.getTimeElapsed();
67 }
68 
69 double
70 DataTracker::getValue(int idx)
71 {
72  return getElement(idx).value;
73 }
74 
75 double
76 DataTracker::getValue(const std::string& name)
77 {
78  return getElement(name).value;
79 }
80 
81 std::string
82 DataTracker::getName(int idx)
83 {
84  return getElement(idx).name;
85 }
86 
88 DataTracker::getElement(std::string const& name)
89 {
90  for (Element& e : m_elements)
91  {
92  if (e.name == name)
93  {
94  return e;
95  }
96  }
97  Element e;
98  e.name = name;
99  e.index = m_nextIndex++;
100  m_elements.push_back(e);
101  return m_elements.back();
102 }
103 
105 DataTracker::getElement(int idx)
106 {
107  for (Element& e : m_elements)
108  {
109  if (e.index == idx)
110  {
111  return e;
112  }
113  }
114  Element e;
115  e.name = "Unknown";
116  e.index = idx;
117  m_elements.push_back(e);
118  return m_elements.back();
119 }
120 
121 StopWatch&
123 {
124  return m_timers[idx];
125 }
126 
127 void
128 DataTracker::createFile()
129 {
130  if (m_file.is_open())
131  {
132  m_file.close();
133  }
134 
135  int idx = 0;
136  m_file.open(m_filename, std::ofstream::out | std::ofstream::trunc);
137  // Write our headers
138  m_file << "Time(s)" << m_delimiter;
139  for (Element& e : m_elements)
140  {
141  m_file << e.name;
142  if ((++idx) < (m_elements.size()))
143  {
144  m_file << m_delimiter;
145  }
146  }
147  m_file << std::endl;
148  m_file.flush();
149 }
150 
151 void
153 {
154  if (!m_file.is_open())
155  {
156  if (!m_filename.empty())
157  {
158  createFile();
159  }
160  else
161  {
162  return;
163  }
164  }
165 
166  double d;
167  int idx = 0;
168  // Write out probe values in heading order
169  m_file << std::fixed << std::setprecision(3) << time << m_delimiter;
170  for (Element& e : m_elements)
171  {
172  d = e.value;
173  if (d == 0)
174  {
175  m_file << std::fixed << std::setprecision(0);
176  m_file << 0;
177  }
178  else if (d - ((int)d) == 0)
179  {
180  m_file << std::fixed << std::setprecision(0);
181  m_file << d;
182  }
183  else if (std::isnan(d))
184  {
185  m_file << "-0.$";
186  }
187  else
188  {
189  switch (e.notation)
190  {
191  case eDecimalFormat_Type::SystemFormatting:
192  m_file << std::fixed << std::setprecision(e.precision);
193  break;
194  case eDecimalFormat_Type::DefaultFloat:
195  m_file << std::defaultfloat << std::setprecision(e.precision);
196  break;
197  case eDecimalFormat_Type::FixedMantissa:
198  m_file << std::fixed << std::setprecision(e.precision);
199  break;
200  case eDecimalFormat_Type::SignificantDigits:
201  m_file << std::scientific << std::setprecision(e.precision);
202  }
203  m_file << d;
204  }
205  if ((++idx) < (m_elements.size()))
206  {
207  m_file << m_delimiter;
208  }
209  }
210  m_file << std::endl;
211  m_file.flush();
212 }
213 } // namespace imstk
void streamProbesToFile(double time)
Write the current probe values to a row in the data file.
Compound Geometry.
StopWatch & getStopWatch(int idx)
An available timer for each data item tracked.
Stop Watch utility class.
Definition: imstkTimer.h:19
void probe(int idx, double value)
Track a data value associated with a header id.
int configureProbe(const std::string &name, std::streamsize precision=3, eDecimalFormat_Type notation=eDecimalFormat_Type::SystemFormatting)
Create and configure a probe and how it is written to file.
eDecimalFormat_Type
C++ I/O manipulation flags.
void probeElapsedTime_s(int idx)
Track a time duration associated with a header.