source: trunk/FACT++/src/Fits.cc@ 10488

Last change on this file since 10488 was 10442, checked in by lyard, 14 years ago
Added dataLogger services and use only one file for fits runs
File size: 9.2 KB
Line 
1// **************************************************************************
2/** @class FactFits
3
4@brief FITS writter for the FACT project.
5
6The FactFits class is able to open, manage and update FITS files.
7
8The file columns should be given to the class before the file is openned. Once
9a file has been created, the structure of its columns cannot be changed. Only
10row can be added.
11
12This class relies on the CCfits and CFitsIO packages.
13
14*/
15// **************************************************************************
16#include "Fits.h"
17
18#include "Time.h"
19#include "Converter.h"
20
21//for file stats
22#include <sys/stat.h>
23
24using namespace std;
25
26// --------------------------------------------------------------------------
27//
28//! This gives a standard variable to the file writter.
29//! This variable should not be related to the DIM service being logged.
30//! @param desc the description of the variable to add
31//! @param dataFormat the FITS data format corresponding to the variable to add.
32//! @param dataPointer the memory location where the variable is stored
33//! @param numDataBytes the number of bytes taken by the variable
34//
35void Fits::AddStandardColumn(Description& desc, std::string dataFormat, void* dataPointer, long unsigned int numDataBytes)
36{
37 //check if entry already exist
38 for (std::vector<Description>::iterator it=fStandardColDesc.begin(); it != fStandardColDesc.end(); it++)
39 if (it->name == desc.name)
40 return;
41 fStandardColDesc.push_back(desc);
42 fStandardFormats.push_back(dataFormat);
43 fStandardPointers.push_back(dataPointer);
44 fStandardNumBytes.push_back(numDataBytes);
45}
46// --------------------------------------------------------------------------
47//
48//! This gives the file writter access to the DIM data
49//! @param desc a vector containing the description of all the columns to log
50//! @param dataFormat a vector containing the FITS data format of all the columsn to log
51//! @param dataPointer the memory location where the DIM data starts
52//! @param numDataBytes the number of bytes taken by the DIM data.
53//
54void Fits::InitDataColumns(std::vector<Description> desc, std::vector<std::string>& dataFormat, void* dataPointer, int numDataBytes)
55{//we will copy this information here. It duplicates the data, which is not great, but it is the easiest way of doing it right now
56 if (desc.size() == dataFormat.size())
57 {
58 fDataColDesc = desc;
59 }
60 else
61 {
62 fDataColDesc.clear();
63 for (unsigned int i=0;i<dataFormat.size();i++)
64 {
65 std::stringstream stt;
66 stt << "Data" << i;
67 fDataColDesc.push_back(Description(stt.str(), "comment", "unit"));
68 }
69 }
70 fDataFormats = dataFormat;
71 fDataPointer = dataPointer;
72 fDataNumBytes = numDataBytes;
73}
74// --------------------------------------------------------------------------
75//
76//! This opens the FITS file (after the columns have been passed)
77//! @param fileName the filename with complete or relative path of the file to open
78//! @param tableName the name of the table that will receive the logged data.
79//! @param file a pointer to an existing FITS file. If NULL, file will be opened and managed internally
80//
81void Fits::Open(const std::string& fileName, const std::string& tableName, FITS* file)
82{
83 fFileName = fileName;
84 if (file == NULL)
85 {
86 try
87 {
88 fFile = new FITS(fileName, RWmode::Write);
89 }
90 catch (FITS::CantOpen)
91 {
92 std::ostringstream err;
93 err << "Could not open " << fileName << ".Skipping it.";
94 throw runtime_error(err.str());
95 }
96 fOwner = true;
97 }
98 else
99 {
100 fFile = file;
101 fOwner = false;
102 }
103 //concatenate the standard and data columns
104 //do it the inneficient way first: its easier and faster to code.
105 std::vector<std::string> allNames;
106 std::vector<std::string> allDataTypes;
107 std::vector<std::string> allUnits;
108 fTotalNumBytes = 0;
109 for (unsigned int i=0;i<fStandardColDesc.size();i++)
110 {
111 allNames.push_back(fStandardColDesc[i].name);
112 allDataTypes.push_back(fStandardFormats[i]);
113 allUnits.push_back(fStandardColDesc[i].unit);
114 fTotalNumBytes += fStandardNumBytes[i];
115 }
116 //for (int i=static_cast<int>(fDataColDesc.size())-1;i>=0;i--)
117 for (int i=0; i< static_cast<int>(fDataColDesc.size()); i++)
118 {
119 if (fDataColDesc[i].name != "")
120 allNames.push_back(fDataColDesc[i].name);
121 else
122 {
123 std::stringstream stt;
124 stt << "Data" << i;
125 allNames.push_back(stt.str());
126 }
127 allDataTypes.push_back(fDataFormats[i]);
128 allUnits.push_back(fDataColDesc[i].unit);
129 }
130 fTotalNumBytes += fDataNumBytes;
131
132 bool updating = false;
133 try
134 {
135 fTable = fFile->addTable(tableName, 0, allNames, allDataTypes, allUnits);
136 fCopyBuffer = new unsigned char[fTotalNumBytes];
137 fNumRows = fTable->rows();
138 if (fNumRows !=0)
139 {//If the file already existed, then we must load its data to memory before writing to it.
140 std::vector<std::string> tableNameString;
141 tableNameString.push_back(tableName);
142 fFile->read(tableNameString);
143 std::map<std::string, Column*> cMap = fTable->column();
144 std::map<std::string, Column*>::iterator cMapIt;
145 for (cMapIt = cMap.begin(); cMapIt != cMap.end(); cMapIt++)
146 {
147 //TODO this only works for scalar columns I assume. upgrade it to fully read vector columns
148 cMapIt->second->readData(1, fNumRows);
149 }
150 updating = true;
151 }
152 }
153 catch(CCfits::FitsError e)
154 {
155 std::ostringstream err;
156 err << "Error when adding table " << tableName << " : " << e.message();
157 throw runtime_error(err.str());
158 }
159
160 fEndMjD = * static_cast<double*>(fStandardPointers[0]);
161 if (!updating)
162 WriteHeaderKeys();
163}
164// --------------------------------------------------------------------------
165//
166//! This writes the standard header
167//
168void Fits::WriteHeaderKeys()
169{
170 std::string name;
171 std::string comment;
172
173 float floatValue;
174 double doubleValue;
175 std::string stringValue;
176
177 name = "EXTREL";
178 comment = "Release Number";
179 floatValue = 1.0f;
180 fTable->addKey(name, floatValue, comment);
181
182 name = "BASETYPE";
183 comment = "Base class that wrote this file";
184 stringValue = "CCFits_table";
185 fTable->addKey(name, stringValue, comment);
186
187 name = "TELESCOP";
188 comment = "Telescope that acquired this data";
189 stringValue = "FACT";
190 fTable->addKey(name, stringValue, comment);
191
192 name = "ORIGIN";
193 comment = "Institution that wrote the file";
194 stringValue = "ISDC";
195 fTable->addKey(name, stringValue, comment);
196
197 name = "CREATOR";
198 comment = "Program that wrote this file";
199 stringValue = "FACT++_DataLogger";
200 fTable->addKey(name, stringValue, comment);
201
202 name = "DATE";
203 stringValue = Time().GetAsStr();
204 stringValue[10] = 'T';
205 comment = "File creation date";
206 fTable->addKey(name, stringValue, comment);
207
208 name = "TIMEREF";
209 stringValue = "UTC";
210 comment = "Time reference system";
211 fTable->addKey(name, stringValue, comment);
212
213 name = "TSTART";
214 doubleValue = fEndMjD;
215 comment = "Time of the first received data";
216 fTable->addKey(name, doubleValue, comment);
217
218 //More ?
219}
220// --------------------------------------------------------------------------
221//
222//! This writes one line of data to the file.
223//! @param conv the converter corresponding to the service being logged
224//
225void Fits::Write(Converter* conv)
226{
227
228 fTable->makeThisCurrent();
229 try
230 {
231 fTable->insertRows(fNumRows);
232 }
233 catch(CCfits::FitsError e)
234 {
235 std::ostringstream err;
236 err << "Error when inserting a row: " << e.message();
237 throw runtime_error(err.str());
238 }
239 fNumRows++;
240
241 //the first standard variable is the current MjD
242 fEndMjD = * static_cast<double*>(fStandardPointers[0]);
243
244 //first copy the standard variables to the copy buffer
245 int shift = 0;
246
247 for (unsigned int i=0;i<fStandardNumBytes.size();i++)
248 {
249 for (int j=0; j<fStandardNumBytes[i]; j++)
250 fCopyBuffer[shift+j] = static_cast<char*>(fStandardPointers[i])[fStandardNumBytes[i]-(j+1)];
251 shift+= fStandardNumBytes[i];
252 }
253
254 //now take care of the DIM data. The Converter is here for that purpose
255 conv->ToFits(static_cast<void*>(&fCopyBuffer[shift]), fDataPointer, fDataNumBytes);
256
257 //data copied to buffer, can write to fits
258 int status = 0;
259 //TODO check the status after the write operation
260 fits_write_tblbytes(fFile->fitsPointer(), fNumRows, 1, fTotalNumBytes, fCopyBuffer, &status);
261
262 //This forces the writting of each row to the disk. Otherwise all rows are written when the file is closed.
263 ///TODO check whether this consumes too much resources or not. If it does, flush every N write operations instead
264 fFile->flush();
265}
266// --------------------------------------------------------------------------
267//
268//! This closes the currently openned FITS file.
269//! it also updates the header to reflect the time of the last logged row
270//
271void Fits::Close()
272{
273//WARNING: do NOT delete the table as it gets deleted by the fFile object
274// if (fTable != NULL)
275// delete fTable;
276
277 std::string name = "TEND";
278 double doubleValue = fEndMjD;
279 std::string comment = "Time of the last received data";
280 fTable->addKey(name, doubleValue, comment);
281
282 if (fFile != NULL && fOwner)
283 delete fFile;
284 fFile = NULL;
285 if (fCopyBuffer != NULL)
286 delete [] fCopyBuffer;
287 fCopyBuffer = NULL;
288}
289
290// --------------------------------------------------------------------------
291//
292//! This closes the currently openned FITS file.
293//! it also updates the header to reflect the time of the last logged row
294//
295int Fits::GetWrittenSize()
296{
297 if (!IsOpen())
298 return 0;
299
300 struct stat st;
301 if (stat(fFileName.c_str(), &st))
302 return 0;
303 else
304 return st.st_size;
305}
Note: See TracBrowser for help on using the repository browser.