source: trunk/FACT++/src/FactFits.cc@ 10367

Last change on this file since 10367 was 10365, checked in by lyard, 14 years ago
Moved from FactFits to Fits
File size: 8.1 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//
19//! This gives a standard variable to the file writter.
20//! This variable should not be related to the DIM service being logged.
21//! @param desc the description of the variable to add
22//! @param dataFormat the FITS data format corresponding to the variable to add.
23//! @param dataPointer the memory location where the variable is stored
24//! @param numDataBytes the number of bytes taken by the variable
25//
26void Fits::AddStandardColumn(Description& desc, std::string dataFormat, void* dataPointer, long unsigned int numDataBytes)
27{
28 fStandardColDesc.push_back(desc);
29 fStandardFormats.push_back(dataFormat);
30 fStandardPointers.push_back(dataPointer);
31 fStandardNumBytes.push_back(numDataBytes);
32}
33// --------------------------------------------------------------------------
34//
35//! This gives the file writter access to the DIM data
36//! @param desc a vector containing the description of all the columns to log
37//! @param dataFormat a vector containing the FITS data format of all the columsn to log
38//! @param dataPointer the memory location where the DIM data starts
39//! @param numDataBytes the number of bytes taken by the DIM data.
40//
41void Fits::InitDataColumns(std::vector<Description> desc, std::vector<std::string>& dataFormat, void* dataPointer, int numDataBytes)
42{//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
43 if (desc.size() == dataFormat.size())
44 {
45 fDataColDesc = desc;
46 }
47 else
48 {
49 for (unsigned int i=0;i<dataFormat.size();i++)
50 {
51 std::stringstream stt;
52 stt << "Data" << i;
53 fDataColDesc.push_back(Description(stt.str(), "unit", "comment"));
54 }
55 }
56 fDataFormats = dataFormat;
57 fDataPointer = dataPointer;
58 fDataNumBytes = numDataBytes;
59}
60// --------------------------------------------------------------------------
61//
62//! This opens the FITS file (after the columns have been passed)
63//! @param fileName the filename with complete or relative path of the file to open
64//! @param tableName the name of the table that will receive the logged data.
65//
66void Fits::Open(const std::string& fileName, const std::string& tableName)
67{
68 try
69 {
70 fFile = new FITS(fileName, RWmode::Write);
71 }
72 catch (FITS::CantOpen)
73 {
74 std::ostringstream err;
75 err << "Could not open " << fileName << ".Skipping it.";
76 throw runtime_error(err.str());
77 }
78 //concatenate the standard and data columns
79 //do it the inneficient way first: its easier and faster to code.
80 std::vector<std::string> allNames;
81 std::vector<std::string> allDataTypes;
82 std::vector<std::string> allUnits;
83 fTotalNumBytes = 0;
84 for (unsigned int i=0;i<fStandardColDesc.size();i++)
85 {
86 allNames.push_back(fStandardColDesc[i].name);
87 allDataTypes.push_back(fStandardFormats[i]);
88 allUnits.push_back(fStandardColDesc[i].unit);
89 fTotalNumBytes += fStandardNumBytes[i];
90 }
91 //for (int i=static_cast<int>(fDataColDesc.size())-1;i>=0;i--)
92 for (int i=0; i< static_cast<int>(fDataColDesc.size()); i++)
93 {
94 if (fDataColDesc[i].name != "")
95 allNames.push_back(fDataColDesc[i].name);
96 else
97 {
98 std::stringstream stt;
99 stt << "Data" << i;
100 allNames.push_back(stt.str());
101 }
102 allDataTypes.push_back(fDataFormats[i]);
103 allUnits.push_back(fDataColDesc[i].unit);
104 }
105 fTotalNumBytes += fDataNumBytes;
106
107 bool updating = false;
108 try
109 {
110 fTable = fFile->addTable(tableName, 0, allNames, allDataTypes, allUnits);
111 fCopyBuffer = new unsigned char[fTotalNumBytes];
112 fNumRows = fTable->rows();
113 if (fNumRows !=0)
114 {//If the file already existed, then we must load its data to memory before writing to it.
115 std::vector<std::string> tableNameString;
116 tableNameString.push_back(tableName);
117 fFile->read(tableNameString);
118 std::map<std::string, Column*> cMap = fTable->column();
119 std::map<std::string, Column*>::iterator cMapIt;
120 for (cMapIt = cMap.begin(); cMapIt != cMap.end(); cMapIt++)
121 {
122 //TODO this only works for scalar columns I assume. upgrade it to fully read vector columns
123 cMapIt->second->readData(1, fNumRows);
124 }
125 updating = true;
126 }
127 }
128 catch(CCfits::FitsError e)
129 {
130 std::ostringstream err;
131 err << "Error when adding table " << tableName << " : " << e.message();
132 throw runtime_error(err.str());
133 }
134
135 fEndMjD = * static_cast<double*>(fStandardPointers[0]);
136 if (!updating)
137 WriteHeaderKeys();
138}
139// --------------------------------------------------------------------------
140//
141//! This writes the standard header
142//
143void Fits::WriteHeaderKeys()
144{
145 std::string name;
146 std::string comment;
147
148 float floatValue;
149 double doubleValue;
150 std::string stringValue;
151
152 name = "EXTREL";
153 comment = "Release Number";
154 floatValue = 1.0f;
155 fTable->addKey(name, floatValue, comment);
156
157 name = "BASETYPE";
158 comment = "Base class that wrote this file";
159 stringValue = "CCFits_table";
160 fTable->addKey(name, stringValue, comment);
161
162 name = "TELESCOP";
163 comment = "Telescope that acquired this data";
164 stringValue = "FACT";
165 fTable->addKey(name, stringValue, comment);
166
167 name = "ORIGIN";
168 comment = "Institution that wrote the file";
169 stringValue = "ISDC";
170 fTable->addKey(name, stringValue, comment);
171
172 name = "CREATOR";
173 comment = "Program that wrote this file";
174 stringValue = "FACT++_DataLogger";
175 fTable->addKey(name, stringValue, comment);
176
177 name = "DATE";
178 stringValue = Time().GetAsStr();
179 stringValue[10] = 'T';
180 comment = "File creation date";
181 fTable->addKey(name, stringValue, comment);
182
183 name = "TIMEREF";
184 stringValue = "UTC";
185 comment = "Time reference system";
186 fTable->addKey(name, stringValue, comment);
187
188 name = "TSTART";
189 doubleValue = fEndMjD;
190 comment = "Time of the first received data";
191 fTable->addKey(name, doubleValue, comment);
192
193 //More ?
194}
195// --------------------------------------------------------------------------
196//
197//! This writes one line of data to the file.
198//! @param conv the converter corresponding to the service being logged
199//
200void Fits::Write(Converter* conv)
201{
202 try
203 {
204 fTable->insertRows(fNumRows);
205 }
206 catch(CCfits::FitsError e)
207 {
208 std::ostringstream err;
209 err << "Error when inserting a row: " << e.message();
210 throw runtime_error(err.str());
211 }
212 fNumRows++;
213
214 //the first standard variable is the current MjD
215 fEndMjD = * static_cast<double*>(fStandardPointers[0]);
216
217 //first copy the standard variables to the copy buffer
218 int shift = 0;
219
220 for (unsigned int i=0;i<fStandardNumBytes.size();i++)
221 {
222 for (int j=0; j<fStandardNumBytes[i]; j++)
223 fCopyBuffer[shift+j] = static_cast<char*>(fStandardPointers[i])[fStandardNumBytes[i]-(j+1)];
224 shift+= fStandardNumBytes[i];
225 }
226
227 //now take care of the DIM data. The Converter is here for that purpose
228 conv->ToFits(static_cast<void*>(&fCopyBuffer[shift]), fDataPointer, fDataNumBytes);
229
230 //data copied to buffer, can write to fits
231 int status = 0;
232 //TODO check the status after the write operation
233 fits_write_tblbytes(fFile->fitsPointer(), fNumRows, 1, fTotalNumBytes, fCopyBuffer, &status);
234
235 //This forces the writting of each row to the disk. Otherwise all rows are written when the file is closed.
236 fFile->flush();
237}
238// --------------------------------------------------------------------------
239//
240//! This closes the currently openned FITS file.
241//! it also updates the header to reflect the time of the last logged row
242//
243void Fits::Close()
244{
245//WARNING: do NOT delete the table as it gets deleted by the fFile object
246// if (fTable != NULL)
247// delete fTable;
248 std::string name = "TEND";
249 double doubleValue = fEndMjD;
250 std::string comment = "Time of the last received data";
251 fTable->addKey(name, doubleValue, comment);
252
253 if (fFile != NULL)
254 delete fFile;
255 fFile = NULL;
256 if (fCopyBuffer != NULL)
257 delete [] fCopyBuffer;
258 fCopyBuffer = NULL;
259}
Note: See TracBrowser for help on using the repository browser.