ef8d26420a5dfb95aec58445d17eac3d4667c4ea
[ctsim.git] / libctsupport / plotfile.cpp
1 /*****************************************************************************
2 ** FILE IDENTIFICATION
3 **
4 **      Name:         plotfile.cpp
5 **      Purpose:      plotfile class
6 **      Programmer:   Kevin Rosenberg
7 **      Date Started: Dec 2000
8 **
9 **  This is part of the CTSim program
10 **  Copyright (C) 1983-2000 Kevin Rosenberg
11 **
12 **  $Id: plotfile.cpp,v 1.8 2001/01/02 05:34:57 kevin Exp $
13 **
14 **  This program is free software; you can redistribute it and/or modify
15 **  it under the terms of the GNU General Public License (version 2) as
16 **  published by the Free Software Foundation.
17 **
18 **  This program is distributed in the hope that it will be useful,
19 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
20 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 **  GNU General Public License for more details.
22 **
23 **  You should have received a copy of the GNU General Public License
24 **  along with this program; if not, write to the Free Software
25 **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 ******************************************************************************/
27
28 #include "ct.h"
29 #include <ctime>
30
31
32 ///////////////////////////////////////////////////////////////////////////
33 // CLASS IMPLEMENTATION
34 //
35 //     Name: PlotFile
36 //     Purpose: Plot File storage
37 ///////////////////////////////////////////////////////////////////////////
38
39
40 PlotFile::PlotFile (int nCurves, int nRecords)
41 {
42   initHeaders ();
43   setCurveSize (nCurves, nRecords);\r
44 }
45
46 PlotFile::PlotFile ()
47 {
48   initHeaders ();
49 }
50
51 PlotFile::~PlotFile ()
52 {
53 }
54
55 void
56 PlotFile::initHeaders ()
57 {
58   m_iNumColumns = 0;
59   m_iNumRecords = 0;
60   time_t currentTime = time (NULL);\r
61   m_strDate = ctime (&currentTime);\r
62   m_vecStrDescriptions.clear();\r
63   m_vecStrEzsetCommands.clear();
64 }
65
66 void
67 PlotFile::setCurveSize (int nCols, int nRecords)
68 {
69   m_iNumColumns = nCols;
70   m_iNumRecords = nRecords;
71   m_vecCurves.clear();
72   m_vecCurves.reserve (m_iNumColumns * m_iNumRecords);
73 }
74 \r
75 // Storage format\r
76 //   a Column's records are stored sequentially. It begins at iCol * m_iNumRecords\r
77
78 bool
79 PlotFile::addColumn (int iCol, const double* const pdColData)
80 {
81   if (iCol < 0 || iCol >= m_iNumColumns) {
82     sys_error (ERR_SEVERE, "Illegal column number %d [PlotFile::addColumn]", iCol);
83     return (false);
84   }
85   
86   for (int iRec = 0; iRec < m_iNumRecords; iRec++)
87     m_vecCurves[ iRec + (iCol * m_iNumRecords) ] = pdColData [iRec];
88   
89   return true;
90 }
91
92 bool\r
93 PlotFile::addColumn (int iCol, const float* const pdColData)\r
94 {\r
95   if (iCol < 0 || iCol >= m_iNumColumns) {\r
96     sys_error (ERR_SEVERE, "Illegal column number %d [PlotFile::addColumn]", iCol);\r
97     return (false);\r
98   }\r
99   \r
100   for (int iRec = 0; iRec < m_iNumRecords; iRec++)\r
101     m_vecCurves[ iRec + (iCol * m_iNumRecords) ] = pdColData [iRec];\r
102   \r
103   return true;\r
104 }\r
105 \r
106 void\r
107 PlotFile::getColumn (int iCol, double* pdColData) const\r
108 {\r
109   if (iCol < 0 || iCol >= m_iNumColumns) {\r
110     sys_error (ERR_SEVERE, "Illegal column number %d [PlotFile::addColumn]", iCol);\r
111     return;\r
112   }\r
113   \r
114   for (int iRec = 0; iRec < m_iNumRecords; iRec++)\r
115     pdColData[iRec] = m_vecCurves[ iRec + (iCol * m_iNumRecords) ];\r
116   \r
117 }\r
118 \r
119 bool\r
120 PlotFile::getMinMax (int iStartingCol, double& dMin, double& dMax) const\r
121 {\r
122   if (iStartingCol >= m_iNumColumns) {\r
123     sys_error (ERR_WARNING, "iStartingCol >= iNumColumns");\r
124     return false;\r
125   }\r
126   \r
127   int iOffset = iStartingCol * m_iNumRecords;\r
128   dMin = m_vecCurves[ 0 + iOffset ];\r
129   dMax = dMin;\r
130   \r
131   for (int iCol = iStartingCol; iCol < m_iNumColumns; iCol++) {\r
132     int iOffset = iCol * m_iNumRecords;\r
133     for (int iRec = 0; iRec < m_iNumRecords; iRec++) {\r
134       double dVal = m_vecCurves[ iRec + iOffset ];\r
135       if (dVal < dMin)\r
136         dMin = dVal;\r
137       else if (dVal > dMax)\r
138         dMax = dVal;\r
139     }\r
140   }\r
141   \r
142   return true;\r
143 }\r
144 \r
145 bool \r
146 PlotFile::statistics (int iStartingCol, double& min, double& max, double& mean, double& mode, double& median, double &stddev) const\r
147 {\r
148   if (iStartingCol >= m_iNumColumns) {\r
149     sys_error (ERR_WARNING, "iStartingCol >= iNumColumns");\r
150     return false;\r
151   }\r
152  \r
153   int iNPoints = (m_iNumColumns - iStartingCol) * m_iNumRecords;\r
154   std::vector<double> vec;\r
155   vec.resize (iNPoints);\r
156   \r
157   int iVec = 0;\r
158   for (int iCol = iStartingCol; iCol < m_iNumColumns; iCol++) {\r
159     int iOffset = iCol * m_iNumRecords;\r
160     for (int iRec = 0; iRec < m_iNumRecords; iRec++)\r
161       vec[iVec++] = m_vecCurves[ iRec + iOffset ];\r
162   }\r
163   \r
164   vectorNumericStatistics (vec, iNPoints, min, max, mean, mode, median, stddev);\r
165   \r
166   return true;\r
167 }\r
168 \r
169 bool
170 PlotFile::fileWrite (const char* const filename)
171 {
172   m_strFilename = filename;
173   
174   fstream fs (m_strFilename.c_str(), std::ios::out | std::ios::trunc);
175   if (fs.fail()) {
176     sys_error (ERR_WARNING, "Error opening file %s for writing [fileCreate]", m_strFilename.c_str());
177     return false;
178   }
179   
180   if (! headerWrite(fs) || ! columnsWrite (fs))
181     return false;
182   
183   return true;
184 }
185
186 bool
187 PlotFile::fileRead (const char* const filename)
188 {
189   m_strFilename = filename;
190   
191 #ifdef MSVC
192   fstream fs (m_strFilename.c_str(), std::ios::in);
193 #else
194   fstream fs (m_strFilename.c_str(), std::ios::in | std::ios::nocreate);
195 #endif
196   
197   if (fs.fail()) {
198     sys_error (ERR_WARNING, "Unable to open file %s [fileRead]", m_strFilename.c_str());
199     return false;
200   }
201   
202   if (! headerRead(fs))
203     return false;
204   
205   setCurveSize (m_iNumColumns, m_iNumRecords);
206   
207   if (! columnsRead(fs))
208     return false;;
209   
210   return true;
211 }
212
213 bool
214 PlotFile::headerRead (std::iostream& fs)
215 {
216   if (! fs) {
217     sys_error (ERR_WARNING, "Tried to read header with file closed [headerRead]");
218     return false;
219   }
220   
221   initHeaders();\r
222   fs.seekg (0);\r
223   bool bFinishedHeaders = false;\r
224 \r
225   fs >> m_iNumColumns;\r
226   fs >> m_iNumRecords;\r
227 \r
228   if (fs.fail() || m_iNumColumns == 0 || m_iNumRecords == 0)\r
229     return false;\r
230 \r
231   while (! bFinishedHeaders && ! fs.eof() && ! fs.fail()) {\r
232     char line[1024];\r
233     fs.getline (line, sizeof(line));\r
234     int iSP = 0;\r
235     while (line[iSP] == ' ')\r
236       iSP++;\r
237     if (line[iSP] == '\n' || ! line[iSP])\r
238       ;\r
239     else if (line[iSP] == '#') {\r
240       iSP++;\r
241       while (line[iSP] == ' ')\r
242         iSP++;\r
243       if (line[iSP] == '\n' || ! line[iSP])\r
244         ;\r
245       else\r
246         addDescription (&line[iSP]);\r
247     } else if (strstr (&line[iSP], "<datapoints>") != NULL) {\r
248          bFinishedHeaders = true;\r
249     } else\r
250       addEzsetCommand (&line[iSP]);\r
251   }\r
252
253   return ! fs.fail();
254 }
255
256
257 bool
258 PlotFile::headerWrite (std::iostream& fs)
259 {
260   if (! fs) {
261     sys_error (ERR_WARNING, "Tried to write header with ! fs");
262     return false;
263   }
264   
265   fs.seekp (0);
266   fs << m_iNumColumns << " " << m_iNumRecords << "\n";\r
267 \r
268   int i;
269   for (i = 0; i < m_vecStrEzsetCommands.size(); i++)\r
270       fs << m_vecStrEzsetCommands[i] << "\n";\r
271   \r
272   for (i = 0; i < m_vecStrDescriptions.size(); i++)\r
273       fs << "# " << m_vecStrDescriptions[i] << "\n";\r
274   \r
275   if (! m_strDate.empty())
276     fs << "# Date: " << m_strDate << "\n";
277     
278   return ! fs.fail();
279 }
280
281
282 bool
283 PlotFile::columnsWrite (std::iostream& fs)
284 {
285   if (! fs) {
286     sys_error (ERR_WARNING, "Tried to columnWrite with !fs");
287     return false;
288   }
289   
290   fs << "<datapoints>\n";
291   
292   int iStride = m_iNumRecords;
293   for (int iRec = 0; iRec < m_iNumRecords; iRec++) {
294     for (int iCol = 0; iCol < m_iNumColumns; iCol++)
295       fs << m_vecCurves [iRec + (iCol * iStride)] << " ";
296     fs << "\n";
297   }
298   
299   fs << "</datapoints>\n";
300   \r
301   fs << "</plotfile>\n";\r
302   
303   return ! fs.fail();
304 }
305
306
307 bool
308 PlotFile::columnsRead (std::iostream& fs)
309 {
310   if (! fs) {
311     sys_error (ERR_WARNING, "Tried to arrayDataRead with ! fs");
312     return false;
313   }
314   
315   if (m_iNumColumns == 0 || m_iNumRecords == 0) {
316     sys_error (ERR_WARNING, "Called PlotFile::columnsRead with 0 columns or records");
317     return false;
318   }
319 \r
320   bool bTerminateEarly = false;\r
321   for (int iRec = 0; iRec < m_iNumRecords; iRec++) {\r
322     for (int iCol = 0; iCol < m_iNumColumns; iCol++) {\r
323       if (fs.eof()) {\r
324         bTerminateEarly = true;\r
325         break;\r
326       }\r
327       if (fs.fail())\r
328         break;\r
329       double d;\r
330       fs >> d;\r
331       m_vecCurves[ iRec + (iCol * m_iNumRecords) ] = d;\r
332     }\r
333   }\r
334
335   return ! (bTerminateEarly || fs.fail());
336 }
337
338
339 void
340 PlotFile::printHeaders (std::ostream& os) const
341 {\r
342   os << "EZSet Commands\n";\r
343   for (unsigned int iEZ = 0; iEZ < m_vecStrEzsetCommands.size(); iEZ++)\r
344     os << m_vecStrEzsetCommands[iEZ] << "\n";\r
345 \r
346   os << "Descriptions\n";\r
347   for (unsigned int iDesc = 0; iDesc < m_vecStrDescriptions.size(); iDesc++)\r
348     os << m_vecStrDescriptions[iDesc] << "\n";
349 }