r315: Coverted POL to C++ class
[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.6 2000/12/27 03:16:02 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);
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   m_strDate = "";
61   m_vecStrDescriptions.clear();\r
62   m_vecStrEzsetCommands.clear();
63 }
64
65 void
66 PlotFile::setCurveSize (int nCols, int nRecords)
67 {
68   m_iNumColumns = nCols;
69   m_iNumRecords = nRecords;
70   m_vecCurves.clear();
71   m_vecCurves.reserve (m_iNumColumns * m_iNumRecords);
72 }
73 \r
74 // Storage format\r
75 //   a Column's records are stored sequentially. It begins at iCol * m_iNumRecords\r
76
77 bool
78 PlotFile::addColumn (int iCol, const double* const pdColData)
79 {
80   if (iCol < 0 || iCol >= m_iNumColumns) {
81     sys_error (ERR_SEVERE, "Illegal column number %d [PlotFile::addColumn]", iCol);
82     return (false);
83   }
84   
85   for (int iRec = 0; iRec < m_iNumRecords; iRec++)
86     m_vecCurves[ iRec + (iCol * m_iNumRecords) ] = pdColData [iRec];
87   
88   return true;
89 }
90
91 bool\r
92 PlotFile::addColumn (int iCol, const float* const pdColData)\r
93 {\r
94   if (iCol < 0 || iCol >= m_iNumColumns) {\r
95     sys_error (ERR_SEVERE, "Illegal column number %d [PlotFile::addColumn]", iCol);\r
96     return (false);\r
97   }\r
98   \r
99   for (int iRec = 0; iRec < m_iNumRecords; iRec++)\r
100     m_vecCurves[ iRec + (iCol * m_iNumRecords) ] = pdColData [iRec];\r
101   \r
102   return true;\r
103 }\r
104 \r
105 void\r
106 PlotFile::getColumn (int iCol, double* pdColData) const\r
107 {\r
108   if (iCol < 0 || iCol >= m_iNumColumns) {\r
109     sys_error (ERR_SEVERE, "Illegal column number %d [PlotFile::addColumn]", iCol);\r
110     return;\r
111   }\r
112   \r
113   for (int iRec = 0; iRec < m_iNumRecords; iRec++)\r
114     pdColData[iRec] = m_vecCurves[ iRec + (iCol * m_iNumRecords) ];\r
115   \r
116 }\r
117 \r
118 bool\r
119 PlotFile::getMinMax (int iStartingCol, double& dMin, double& dMax) const\r
120 {\r
121   if (iStartingCol >= m_iNumColumns) {\r
122     sys_error (ERR_WARNING, "iStartingCol >= iNumColumns");\r
123     return false;\r
124   }\r
125   \r
126   int iOffset = iStartingCol * m_iNumRecords;\r
127   dMin = m_vecCurves[ 0 + iOffset ];\r
128   dMax = dMin;\r
129   \r
130   for (int iCol = iStartingCol; iCol < m_iNumColumns; iCol++) {\r
131     int iOffset = iCol * m_iNumRecords;\r
132     for (int iRec = 0; iRec < m_iNumRecords; iRec++) {\r
133       double dVal = m_vecCurves[ iRec + iOffset ];\r
134       if (dVal < dMin)\r
135         dMin = dVal;\r
136       else if (dVal > dMax)\r
137         dMax = dVal;\r
138     }\r
139   }\r
140   \r
141   return true;\r
142 }\r
143 \r
144 bool \r
145 PlotFile::statistics (int iStartingCol, double& min, double& max, double& mean, double& mode, double& median, double &stddev) const\r
146 {\r
147   if (iStartingCol >= m_iNumColumns) {\r
148     sys_error (ERR_WARNING, "iStartingCol >= iNumColumns");\r
149     return false;\r
150   }\r
151   \r
152   int iOffset = iStartingCol * m_iNumRecords;\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   while (! bFinishedHeaders && ! fs.eof() && ! fs.fail()) {\r
226     char line[1024];\r
227     fs.getline (line, sizeof(line));\r
228     if (strstr (line, "<datapoints>") != NULL)\r
229          bFinishedHeaders = true;\r
230   }\r
231
232   return ! fs.fail();
233 }
234
235
236 bool
237 PlotFile::headerWrite (std::iostream& fs)
238 {
239   if (! fs) {
240     sys_error (ERR_WARNING, "Tried to write header with ! fs");
241     return false;
242   }
243   
244   fs.seekp (0);
245   fs << "<plotfile " << m_iNumColumns << " " << m_iNumRecords << " >\n";\r
246   
247   int iNEzset = m_vecStrEzsetCommands.size();\r
248   if (iNEzset > 0) {\r
249     fs << "<ezset>\n";\r
250     for (int i = 0; i < iNEzset; i++)\r
251       fs << m_vecStrEzsetCommands[i] << "\n";\r
252     fs << "</ezset>\n";\r
253   }\r
254   \r
255   if (! m_strDate.empty())
256     fs << "<date>" << m_strDate << "</date>\n";
257   
258   int iNDesc = m_vecStrDescriptions.size();\r
259   if (iNDesc > 0) {\r
260     fs << "<description>\n";
261     for (int i = 0; i < iNDesc; i++)
262       fs << m_vecStrDescriptions[i] << "\n";\r
263     fs << "</description>\n";\r
264   }
265   
266   return ! fs.fail();
267 }
268
269
270 bool
271 PlotFile::columnsWrite (std::iostream& fs)
272 {
273   if (! fs) {
274     sys_error (ERR_WARNING, "Tried to columnWrite with !fs");
275     return false;
276   }
277   
278   fs << "<datapoints>\n";
279   
280   int iStride = m_iNumRecords;
281   for (int iRec = 0; iRec < m_iNumRecords; iRec++) {
282     for (int iCol = 0; iCol < m_iNumColumns; iCol++)
283       fs << m_vecCurves [iRec + (iCol * iStride)] << " ";
284     fs << "\n";
285   }
286   
287   fs << "</datapoints>\n";
288   \r
289   fs << "</plotfile>\n";\r
290   
291   return ! fs.fail();
292 }
293
294
295 bool
296 PlotFile::columnsRead (std::iostream& fs)
297 {
298   if (! fs) {
299     sys_error (ERR_WARNING, "Tried to arrayDataRead with ! fs");
300     return false;
301   }
302   
303   return ! fs.fail();
304   
305   if (m_iNumColumns == 0 || m_iNumRecords == 0) {
306     sys_error (ERR_WARNING, "Called PlotFile::columnsRead with 0 columns or records");
307     return false;
308   }
309 \r
310   bool bTerminateEarly = false;\r
311   for (int iRec = 0; iRec < m_iNumRecords; iRec++) {\r
312     for (int iCol = 0; iCol < m_iNumColumns; iCol++) {\r
313       if (fs.eof()) {\r
314         bTerminateEarly = true;\r
315         break;\r
316       }\r
317       if (fs.fail())\r
318         break;\r
319       double d;\r
320       fs >> d;\r
321       m_vecCurves[ iRec + (iCol * m_iNumRecords) ] = d;\r
322     }\r
323   }\r
324
325   return ! (bTerminateEarly || fs.fail());
326 }
327
328
329 void
330 PlotFile::printHeaders (std::ostream& os) const
331 {
332 }