r11859: Canonicalize whitespace
[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-2001 Kevin Rosenberg
11 **
12 **  $Id$
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);
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);
61   m_strDate = ctime (&currentTime);
62   m_vecStrDescriptions.clear();
63   m_vecStrEzsetCommands.clear();
64 }
65
66 void
67 PlotFile::setCurveSize (int nCols, int nRecords, bool bScatterPlot)
68 {
69   m_iNumColumns = nCols;
70   m_iNumRecords = nRecords;
71   m_bScatterPlot = bScatterPlot;
72   m_vecCurves.clear();
73   m_vecCurves.reserve (m_iNumColumns * m_iNumRecords);
74 }
75
76 // Storage format
77 //   a Column's records are stored sequentially. It begins at iCol * m_iNumRecords
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
93 PlotFile::addColumn (int iCol, const float* const pdColData)
94 {
95   if (iCol < 0 || iCol >= m_iNumColumns) {
96     sys_error (ERR_SEVERE, "Illegal column number %d [PlotFile::addColumn]", iCol);
97     return (false);
98   }
99
100   for (int iRec = 0; iRec < m_iNumRecords; iRec++)
101     m_vecCurves[ iRec + (iCol * m_iNumRecords) ] = pdColData [iRec];
102
103   return true;
104 }
105
106 void
107 PlotFile::getColumn (int iCol, double* pdColData) const
108 {
109   if (iCol < 0 || iCol >= m_iNumColumns) {
110     sys_error (ERR_SEVERE, "Illegal column number %d [PlotFile::addColumn]", iCol);
111     return;
112   }
113
114   for (int iRec = 0; iRec < m_iNumRecords; iRec++)
115     pdColData[iRec] = m_vecCurves[ iRec + (iCol * m_iNumRecords) ];
116
117 }
118
119 bool
120 PlotFile::getMinMax (int iStartingCol, double& dMin, double& dMax) const
121 {
122   if (iStartingCol >= m_iNumColumns) {
123     sys_error (ERR_WARNING, "iStartingCol >= iNumColumns");
124     return false;
125   }
126
127   int iOffset = iStartingCol * m_iNumRecords;
128   dMin = m_vecCurves[ 0 + iOffset ];
129   dMax = dMin;
130
131   for (int iCol = iStartingCol; iCol < m_iNumColumns; iCol++) {
132     int iOffset = iCol * m_iNumRecords;
133     for (int iRec = 0; iRec < m_iNumRecords; iRec++) {
134       double dVal = m_vecCurves[ iRec + iOffset ];
135       if (dVal < dMin)
136         dMin = dVal;
137       else if (dVal > dMax)
138         dMax = dVal;
139     }
140   }
141
142   return true;
143 }
144
145 bool
146 PlotFile::statistics (int iStartingCol, double& min, double& max, double& mean, double& mode, double& median, double &stddev) const
147 {
148   if (iStartingCol >= m_iNumColumns) {
149     sys_error (ERR_WARNING, "iStartingCol >= iNumColumns");
150     return false;
151   }
152
153   int iNPoints = (m_iNumColumns - iStartingCol) * m_iNumRecords;
154   std::vector<double> vec;
155   vec.resize (iNPoints);
156
157   int iVec = 0;
158   for (int iCol = iStartingCol; iCol < m_iNumColumns; iCol++) {
159     int iOffset = iCol * m_iNumRecords;
160     for (int iRec = 0; iRec < m_iNumRecords; iRec++)
161       vec[iVec++] = m_vecCurves[ iRec + iOffset ];
162   }
163
164   vectorNumericStatistics (vec, iNPoints, min, max, mean, mode, median, stddev);
165
166   return true;
167 }
168
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();
222   fs.seekg (0);
223   bool bFinishedHeaders = false;
224
225   fs >> m_iNumColumns;
226   fs >> m_iNumRecords;
227
228   if (fs.fail() || m_iNumColumns == 0 || m_iNumRecords == 0)
229     return false;
230
231   while (! bFinishedHeaders && ! fs.eof() && ! fs.fail()) {
232     char line[1024];
233     fs.getline (line, sizeof(line));
234     int iSP = 0;
235     while (line[iSP] == ' ')
236       iSP++;
237     if (line[iSP] == '\n' || ! line[iSP])
238       ;
239     else if (line[iSP] == '#') {
240       iSP++;
241       while (line[iSP] == ' ')
242         iSP++;
243       if (line[iSP] == '\n' || ! line[iSP])
244         ;
245       else
246         addDescription (&line[iSP]);
247     } else if (strstr (&line[iSP], "<datapoints>") != NULL) {
248          bFinishedHeaders = true;
249     } else
250       addEzsetCommand (&line[iSP]);
251   }
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";
267
268   unsigned int i;
269   for (i = 0; i < m_vecStrEzsetCommands.size(); i++)
270       fs << m_vecStrEzsetCommands[i] << "\n";
271
272   for (i = 0; i < m_vecStrDescriptions.size(); i++)
273       fs << "# " << m_vecStrDescriptions[i] << "\n";
274
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
301   fs << "</plotfile>\n";
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
320   bool bTerminateEarly = false;
321   for (int iRec = 0; iRec < m_iNumRecords; iRec++) {
322     for (int iCol = 0; iCol < m_iNumColumns; iCol++) {
323       if (fs.eof()) {
324         bTerminateEarly = true;
325         break;
326       }
327       if (fs.fail())
328         break;
329       double d;
330       fs >> d;
331       m_vecCurves[ iRec + (iCol * m_iNumRecords) ] = d;
332     }
333   }
334
335   return ! (bTerminateEarly || fs.fail());
336 }
337
338
339 void
340 PlotFile::printHeaders (std::ostream& os) const
341 {
342   os << "EZSet Commands\n";
343   for (unsigned int iEZ = 0; iEZ < m_vecStrEzsetCommands.size(); iEZ++)
344     os << m_vecStrEzsetCommands[iEZ] << "\n";
345
346   os << "Descriptions\n";
347   for (unsigned int iDesc = 0; iDesc < m_vecStrDescriptions.size(); iDesc++)
348     os << m_vecStrDescriptions[iDesc] << "\n";
349 }
350
351 void
352 PlotFile::printHeaders (std::ostringstream& os) const
353 {
354   os << "EZSet Commands\n";
355   for (unsigned int iEZ = 0; iEZ < m_vecStrEzsetCommands.size(); iEZ++)
356     os << m_vecStrEzsetCommands[iEZ] << "\n";
357
358   os << "Descriptions\n";
359   for (unsigned int iDesc = 0; iDesc < m_vecStrDescriptions.size(); iDesc++)
360     os << m_vecStrDescriptions[iDesc] << "\n";
361 }
362
363 void
364 PlotFile::printHeadersBrief (std::ostream& os) const
365 {
366   os << "EZSet Commands\n";
367   for (unsigned int iEZ = 0; iEZ < m_vecStrEzsetCommands.size(); iEZ++)
368     os << m_vecStrEzsetCommands[iEZ] << "; ";
369   if (m_vecStrEzsetCommands.size() > 0)
370     os << "\n";
371
372   os << "Descriptions\n";
373   for (unsigned int iDesc = 0; iDesc < m_vecStrDescriptions.size(); iDesc++)
374     os << m_vecStrDescriptions[iDesc] << "\n";
375 }
376
377 void
378 PlotFile::printHeadersBrief (std::ostringstream& os) const
379 {
380   os << "EZSet Commands\n";
381   for (unsigned int iEZ = 0; iEZ < m_vecStrEzsetCommands.size(); iEZ++)
382     os << m_vecStrEzsetCommands[iEZ] << "; ";
383   if (m_vecStrEzsetCommands.size() > 0)
384     os << "\n";
385
386   os << "Descriptions\n";
387   for (unsigned int iDesc = 0; iDesc < m_vecStrDescriptions.size(); iDesc++)
388     os << m_vecStrDescriptions[iDesc] << "\n";
389 }