r322: *** empty log message ***
[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.7 2000/12/29 20:09:46 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 iNPoints = (m_iNumColumns - iStartingCol) * m_iNumRecords;\r
153   std::vector<double> vec;\r
154   vec.resize (iNPoints);\r
155   \r
156   int iVec = 0;\r
157   for (int iCol = iStartingCol; iCol < m_iNumColumns; iCol++) {\r
158     int iOffset = iCol * m_iNumRecords;\r
159     for (int iRec = 0; iRec < m_iNumRecords; iRec++)\r
160       vec[iVec++] = m_vecCurves[ iRec + iOffset ];\r
161   }\r
162   \r
163   vectorNumericStatistics (vec, iNPoints, min, max, mean, mode, median, stddev);\r
164   \r
165   return true;\r
166 }\r
167 \r
168 bool
169 PlotFile::fileWrite (const char* const filename)
170 {
171   m_strFilename = filename;
172   
173   fstream fs (m_strFilename.c_str(), std::ios::out | std::ios::trunc);
174   if (fs.fail()) {
175     sys_error (ERR_WARNING, "Error opening file %s for writing [fileCreate]", m_strFilename.c_str());
176     return false;
177   }
178   
179   if (! headerWrite(fs) || ! columnsWrite (fs))
180     return false;
181   
182   return true;
183 }
184
185 bool
186 PlotFile::fileRead (const char* const filename)
187 {
188   m_strFilename = filename;
189   
190 #ifdef MSVC
191   fstream fs (m_strFilename.c_str(), std::ios::in);
192 #else
193   fstream fs (m_strFilename.c_str(), std::ios::in | std::ios::nocreate);
194 #endif
195   
196   if (fs.fail()) {
197     sys_error (ERR_WARNING, "Unable to open file %s [fileRead]", m_strFilename.c_str());
198     return false;
199   }
200   
201   if (! headerRead(fs))
202     return false;
203   
204   setCurveSize (m_iNumColumns, m_iNumRecords);
205   
206   if (! columnsRead(fs))
207     return false;;
208   
209   return true;
210 }
211
212 bool
213 PlotFile::headerRead (std::iostream& fs)
214 {
215   if (! fs) {
216     sys_error (ERR_WARNING, "Tried to read header with file closed [headerRead]");
217     return false;
218   }
219   
220   initHeaders();\r
221   fs.seekg (0);\r
222   bool bFinishedHeaders = false;\r
223 \r
224   while (! bFinishedHeaders && ! fs.eof() && ! fs.fail()) {\r
225     char line[1024];\r
226     fs.getline (line, sizeof(line));\r
227     if (strstr (line, "<datapoints>") != NULL)\r
228          bFinishedHeaders = true;\r
229   }\r
230
231   return ! fs.fail();
232 }
233
234
235 bool
236 PlotFile::headerWrite (std::iostream& fs)
237 {
238   if (! fs) {
239     sys_error (ERR_WARNING, "Tried to write header with ! fs");
240     return false;
241   }
242   
243   fs.seekp (0);
244   fs << "<plotfile " << m_iNumColumns << " " << m_iNumRecords << " >\n";\r
245   
246   int iNEzset = m_vecStrEzsetCommands.size();\r
247   if (iNEzset > 0) {\r
248     fs << "<ezset>\n";\r
249     for (int i = 0; i < iNEzset; i++)\r
250       fs << m_vecStrEzsetCommands[i] << "\n";\r
251     fs << "</ezset>\n";\r
252   }\r
253   \r
254   if (! m_strDate.empty())
255     fs << "<date>" << m_strDate << "</date>\n";
256   
257   int iNDesc = m_vecStrDescriptions.size();\r
258   if (iNDesc > 0) {\r
259     fs << "<description>\n";
260     for (int i = 0; i < iNDesc; i++)
261       fs << m_vecStrDescriptions[i] << "\n";\r
262     fs << "</description>\n";\r
263   }
264   
265   return ! fs.fail();
266 }
267
268
269 bool
270 PlotFile::columnsWrite (std::iostream& fs)
271 {
272   if (! fs) {
273     sys_error (ERR_WARNING, "Tried to columnWrite with !fs");
274     return false;
275   }
276   
277   fs << "<datapoints>\n";
278   
279   int iStride = m_iNumRecords;
280   for (int iRec = 0; iRec < m_iNumRecords; iRec++) {
281     for (int iCol = 0; iCol < m_iNumColumns; iCol++)
282       fs << m_vecCurves [iRec + (iCol * iStride)] << " ";
283     fs << "\n";
284   }
285   
286   fs << "</datapoints>\n";
287   \r
288   fs << "</plotfile>\n";\r
289   
290   return ! fs.fail();
291 }
292
293
294 bool
295 PlotFile::columnsRead (std::iostream& fs)
296 {
297   if (! fs) {
298     sys_error (ERR_WARNING, "Tried to arrayDataRead with ! fs");
299     return false;
300   }
301   
302   return ! fs.fail();
303   
304   if (m_iNumColumns == 0 || m_iNumRecords == 0) {
305     sys_error (ERR_WARNING, "Called PlotFile::columnsRead with 0 columns or records");
306     return false;
307   }
308 \r
309   bool bTerminateEarly = false;\r
310   for (int iRec = 0; iRec < m_iNumRecords; iRec++) {\r
311     for (int iCol = 0; iCol < m_iNumColumns; iCol++) {\r
312       if (fs.eof()) {\r
313         bTerminateEarly = true;\r
314         break;\r
315       }\r
316       if (fs.fail())\r
317         break;\r
318       double d;\r
319       fs >> d;\r
320       m_vecCurves[ iRec + (iCol * m_iNumRecords) ] = d;\r
321     }\r
322   }\r
323
324   return ! (bTerminateEarly || fs.fail());
325 }
326
327
328 void
329 PlotFile::printHeaders (std::ostream& os) const
330 {
331 }