FACT++  1.0
FitsFile.cc
Go to the documentation of this file.
1 // **************************************************************************
15 // **************************************************************************
16 #include "FitsFile.h"
17 
18 using namespace std;
19 using namespace CCfits;
20 
21 bool FitsFile::WriteDefaultKeys(const string &prgname, float version)
22 {
23  if (!fTable)
24  return false;
25 
26  try
27  {
28  const Time now;
29  WriteKey("TELESCOP", "FACT", "Telescope that acquired this data");
30  WriteKey("PACKAGE", PACKAGE_NAME, "Package name");
31  WriteKey("VERSION", PACKAGE_VERSION, "Package description");
32  WriteKey("CREATOR", prgname, "Program that wrote this file");
33  WriteKey("EXTREL", version, "Release Number");
34  WriteKey("COMPILED", __DATE__ " " __TIME__, "Compile time");
35  WriteKey("REVISION", REVISION, "SVN revision");
36  WriteKey("ORIGIN", "FACT", "Institution that wrote the file");
37  WriteKey("DATE", now.Iso(), "File creation date");
38  WriteKey("NIGHT", now.NightAsInt(), "Night as int");
39  WriteKey("TIMESYS", "UTC", "Time system");
40  WriteKey("TIMEUNIT", "d", "Time given in days w.r.t. to MJDREF");
41  WriteKey("MJDREF", 40587, "Store times in UNIX time (for convenience, seconds since 1970/1/1)");
42 
43  //WriteKey("CONTACT", PACKAGE_BUGREPORT, "Current package maintainer");
44  //WriteKey("URL", PACKAGE_URL, "Current repositiory location");
45  }
46  catch (const CCfits::FitsException &e)
47  {
48  Error("CCfits::Table::addKey failed for '"+fTable->name()+"' in '"+fFile->name()+"': "+e.message());
49  return false;
50  }
51 
52  return true;
53 }
54 
55 // --------------------------------------------------------------------------
56 //
63 //
64 void FitsFile::AddColumn(char type, const string &name, int numElems, const string &unit)
65 {
66  fColNames.push_back(name);
67  fColUnits.push_back(unit);
68 
69  ostringstream str;
70  if (numElems != 1)
71  str << numElems;
72 
73  switch (toupper(type))
74  {
75  case 'B': str << 'L'; break; // logical
76  case 'C': str << 'B'; break; // byte
77  case 'S': str << 'I'; break; // short
78  case 'I': str << 'J'; break; // int
79  case 'X': str << 'K'; break; // long long
80  case 'F': str << 'E'; break; // float
81  case 'D': str << 'D'; break; // double
82  }
83 
84  fColTypes.push_back(str.str());
85 }
86 
87 void FitsFile::AddColumn(const string &name, const string &format, const string &unit)
88 {
89  fColNames.push_back(name);
90  fColUnits.push_back(unit);
91  fColTypes.push_back(format);
92 }
93 
94 bool FitsFile::OpenFile(const string &filename, bool allow_open)
95 {
96  if (fFile || fTable)
97  {
98  Error("FitsFile::OpenFile - File already open.");
99  return false;
100  }
101  // fFileName = fileName;
102  if (!allow_open && access(filename.c_str(), F_OK)==0)
103  {
104  Error("File '"+filename+"' already existing.");
105  return false;
106  }
107  //create the FITS object
108  try
109  {
110  fFile = new CCfits::FITS(filename, CCfits::RWmode::Write);
111  }
112  catch (CCfits::FitsException e)
113  {
114  Error("CCfits::FITS failed for '"+filename+"': "+e.message());
115  return false;
116  }
117  /*
118  "SIMPLE = T / file does conform to FITS standard "
119  "BITPIX = 8 / number of bits per data pixel "
120  "NAXIS = 0 / number of data axes "
121  "EXTEND = T / FITS dataset may contain extensions "
122  "COMMENT FITS (Flexible Image Transport System) format is defined in 'Astronomy"
123  "COMMENT and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H "
124  "END ";
125  */
126 
127  fIsOwner = true;
128 
129  return true;
130 }
131 
133 {
134  fColNames.clear();
135  fColTypes.clear();
136  fColUnits.clear();
137 }
138 
139 bool FitsFile::SetFile(CCfits::FITS *file)
140 {
141  if (!file)
142  {
143  Error("Fits::SetFile failed: NULL argument.");
144  return false;
145  }
146 
147  if (fFile)
148  {
149  Error("Fits::SetFile failed: File already set.");
150  return false;
151  }
152 
153  fFile = file;
154  fIsOwner = false;
155 
156  return true;
157 }
158 
159 bool FitsFile::OpenTable(const string &tablename)
160 {
161  if (!fFile)
162  {
163  Error("FitsFile::OpenTable - No file open.");
164  return false;
165  }
166  if (fTable)
167  {
168  Error("FitsFile::OpenTable - Table already open.");
169  return false;
170  }
171 
172  //actually create the table
173  CCfits::Table *table = 0;
174  try
175  {
176  table = fFile->addTable(tablename, 0, fColNames, fColTypes, fColUnits);
177  }
178  catch (const CCfits::FitsException &e)
179  {
180  Error("CCfits::Table::addTable failed for '"+tablename+"' in '"+fFile->name()+"': "+e.message());
181  return false;
182  }
183 
184  if (table->rows() != 0)
185  {
186  Error("FITS table '"+tablename+"' created in '"+fFile->name()+"' on the fly looks non-empty.");
187  return false;
188  }
189 
190  // Set this as last - we use it for IsOpen()
191  fTable = table;
192  fNumRows = 0;
193 
194  return true;
195 }
196 
197 // --------------------------------------------------------------------------
198 //
205 //
206 bool FitsFile::OpenNewTable(const string &tableName, int maxtry)
207 {
208  if (!fFile)
209  {
210  Error("FitsFile::OpenNewTable - No file open.");
211  return false;
212  }
213 
214  if (fTable)
215  {
216  Error("FitsFile::OpenNewTable - Table already open.");
217  return false;
218  }
219 
220  //first, let's check if the table already exist in the file
221  fFile->read(vector<string>(1, tableName));
222 
223  // FIXME: Check for fFile and fTable
224  const multimap<string, CCfits::ExtHDU *> &extMap = fFile->extension();
225 
226  for (int i=0; i<maxtry; i++)
227  {
228  //if (i==10)
229  // fMess->Warn("Already 10 different tables with different formats exist in this file. Please consider re-creating the file entirely (i.e. delete it please)");
230 
231  ostringstream str;
232  str << tableName;
233  if (i != 0)
234  str << "-" << i;
235 
236  const string tname = str.str();
237 
238  const multimap<string,CCfits::ExtHDU*>::const_iterator it = extMap.find(tname);
239 
240  //current table name does not exist yet. return its associated fits table newly created
241  if (it == extMap.end())
242  {
243  // What is this for?
244  //for (multimap<string, CCfits::ExtHDU*>::const_iterator it=extMap.begin();
245  // it!= extMap.end(); it++)
246  // fMess->Debug(it->first);
247 
248  return OpenTable(tname);
249  }
250 
251  CCfits::Table *table = dynamic_cast<CCfits::Table*>(it->second);
252 
253  // something wrong happened while getting the table pointer
254  if (!table)
255  {
256  Error("HDU '"+tname+"' found in file, but it is not a proper CCfits::Table.");
257  return false;
258  }
259 
260  //now check that the table columns are the same
261  //as the service columns
262  table->makeThisCurrent();
263 
264  // FIXME: To be checked...
265  /*
266  const map<string, Column*> cMap = table->column();
267  for (vector<string>::const_iterator ii=fFile->fColNames;
268  ii!=fFile->fColNames.end(); ii++)
269  if (cMap.find(*ii) == cMap.end())
270  continue;
271  */
272 
273  fNumRows = table->rows();
274 
275  // ----------- This is just a simple sanity check ----------
276 
277  // This is not necessary this is done already in
278  // findSuitableTable (either directly or indirectly through OpenTable)
279  // fFile->fTable->makeThisCurrent();
280 
281  //If the file already existed, then we must load its data to memory before writing to it.
282  if (fNumRows>0)
283  {
284  CCfits::BinTable* bTable = dynamic_cast<CCfits::BinTable*>(table);
285  if (!bTable)
286  {
287  Error("Table '"+tableName+"' found in '"+fFile->name()+"' is not a binary table.");
288  return false;
289  }
290 
291  //read the table binary data.
292  vector<string> colName;
293  bTable->readData(true, colName);
294 
295  // double check that the data was indeed read from the disk.
296  // Go through the fTable instead as colName is empty (yes, it is !)
297  const map<string,CCfits::Column*> &cMap = table->column();
298 
299  //check that the existing columns are the same as the ones we want to write
300  for (map<string, CCfits::Column*>::const_iterator mapIt = cMap.begin(); mapIt != cMap.end(); mapIt++)
301  {
302  bool found = false;
303  for (unsigned int ii=0;ii<fColNames.size();ii++)
304  {
305  if (mapIt->first == fColNames[ii])
306  {
307  found = true;
308  if (mapIt->second->format() != fColTypes[ii])
309  {
310  Error("Column "+fColNames[ii]+" has wrong format ("+fColTypes[ii]+" vs "+mapIt->second->format()+" in file)");
311  return false;
312  }
313  }
314  }
315  if (!found)
316  {
317  Error("Column "+mapIt->first+" only exist in written file");
318  return false;
319  }
320  }
321  //now we know that all the file's columns are requested. Let's do it the other way around
322  for (unsigned int ii=0;ii<fColNames.size();ii++)
323  {
324  bool found = false;
325  for (map<string, CCfits::Column*>::const_iterator mapIt = cMap.begin(); mapIt != cMap.end(); mapIt++)
326  {
327  if (fColNames[ii] == mapIt->first)
328  {
329  found = true;
330  if (fColTypes[ii] != mapIt->second->format())
331  {
332  Error("Column "+fColNames[ii]+" has wrong format ("+fColTypes[ii]+" vs "+mapIt->second->format()+" in file)");
333  return false;
334  }
335  }
336  }
337  if (!found)
338  {
339  Error("Column "+fColNames[ii]+" only exist in requested description");
340  return false;
341  }
342  }
343 
344  for (map<string,CCfits::Column*>::const_iterator cMapIt = cMap.begin();
345  cMapIt != cMap.end(); cMapIt++)
346  {
347  if (!cMapIt->second->isRead())
348  {
349  Error("Reading column '"+cMapIt->first+"' back from '"+fFile->name()+"' failed.");
350  return false;
351  }
352  }
353  }
354 
355  // Set this as last - we use it for IsOpen()
356  fTable = table;
357 
358  return true;
359  }
360 
361  ostringstream str;
362  str << "FitsFile::OpenNewTable failed - more than " << maxtry << " tables tried." << endl;
363  Error(str);
364 
365  return false;
366 }
367 
369 {
370  if (!fFile || !fTable)
371  {
372  Error("FitsFile::AddRow - No table open.");
373  return false;
374  }
375 
376  //insert a new row (1==number of rows to insert)
377  int status(0);
378  fits_insert_rows(fFile->fitsPointer(), fNumRows, 1, &status);
379 
380  // Status is also directly returned, but we need to give the
381  // pointer anyway
382  if (status)
383  {
384  char text[30];//max length of cfitsio error strings (from doc)
385  fits_get_errstatus(status, text);
386 
387  ostringstream str;
388  str << "Inserting row " << fNumRows << " failed in '"+fFile->name()+"': " << text << " (fits_insert_rows,rc=" << status << ")";
389  Error(str);
390 
391  return false;
392  }
393 
394  fNumRows++;
395  fCursor = 1;
396 
397  return true;
398 }
399 
400 bool FitsFile::WriteData(size_t &start, const void *ptr, size_t size)
401 {
402  if (!fFile || !fTable)
403  {
404  Error("FitsFile::AddRow - No table open.");
405  return false;
406  }
407 
408  int status = 0;
409  fits_write_tblbytes(fFile->fitsPointer(), fNumRows, start, size,
410  (unsigned char*)ptr, &status);
411 
412  // Status is also directly returned, but we need to give the
413  // pointer anyway
414  if (status)
415  {
416  char text[30];//max length of cfitsio error strings (from doc)
417  fits_get_errstatus(status, text);
418 
419  ostringstream str;
420  str << "Writing row " << fNumRows << " failed in '"+fFile->name()+"': " << text << " (file_write_tblbytes,rc=" << status << ")";
421  Error(str);
422  }
423 
424  start += size;
425  return status==0;
426 }
427 
429 {
430  if (!fFile)
431  return;
432 
433  if (fIsOwner)
434  {
435  const string name = fFile->name();
436  delete fFile;
437  }
438 
439  //WARNING: do NOT delete the table as it gets deleted by the
440  // fFile object
441  fFile = NULL;
442  fTable = NULL;
443 }
444 
446 {
447  if (!fFile)
448  return;
449 
450  int status = 0;
451  fits_flush_file(fFile->fitsPointer(), &status);
452 
453  if (status)
454  {
455  char text[30];
456  fits_get_errstatus(status, text);
457 
458  ostringstream str;
459  str << "Flushing file " << fFile->name() << " failed: " << text << " (fits_flush_file, rc=" << status << ")";
460  Error(str);
461  }
462 }
463 size_t FitsFile::GetDataSize() const
464 {
465  size_t size = 0;
466 
467  for (vector<string>::const_iterator it=fColTypes.begin();
468  it!=fColTypes.end(); it++)
469  {
470  size_t id=0;
471 
472  int n=1;
473  try { n = stoi(*it, &id); }
474  catch (const exception&) { }
475 
476  if (n==0)
477  continue;
478 
479  switch ((*it)[id])
480  {
481  case 'L':
482  case 'A': size += n*1; break; // ascii
483  case 'B': size += n*1; break; // logical/byte
484  case 'I': size += n*2; break; // short
485  case 'J': size += n*4; break; // int
486  case 'K': size += n*8; break; // long long
487  case 'E': size += n*4; break; // float
488  case 'D': size += n*8; break; // double
489  default:
490  throw runtime_error("FitsFile::GetDataSize - id not known.");
491  }
492  }
493 
494  return size;
495 }
int start(int initState)
Definition: feeserver.c:1740
#define PACKAGE_NAME
Definition: ofits.h:8
size_t GetDataSize() const
Definition: FitsFile.cc:463
int i
Definition: db_dim_client.c:21
std::string Iso() const
Definition: Time.cc:253
Adds some functionality to boost::posix_time::ptime for our needs.
Definition: Time.h:30
char str[80]
Definition: test_client.c:7
uint32_t NightAsInt() const
Definition: Time.cc:397
STL namespace.
bool SetFile(CCfits::FITS *file=0)
Definition: FitsFile.cc:139
#define PACKAGE_VERSION
Definition: ofits.h:12
bool WriteDefaultKeys(const string &prgname, float version=1.0)
Definition: FitsFile.cc:21
#define REVISION
Definition: ofits.h:16
bool AddRow()
Definition: FitsFile.cc:368
void ResetColumns()
Definition: FitsFile.cc:132
int type
void Flush()
Definition: FitsFile.cc:445
bool OpenFile(const string &filename, bool allow_open=false)
Definition: FitsFile.cc:94
bool OpenTable(const string &tablename)
Definition: FitsFile.cc:159
int size
Definition: db_dim_server.c:17
void AddColumn(char type, const string &name, int numElems=1, const string &unit="")
bool WriteData(size_t &start, const void *ptr, size_t size)
Definition: FitsFile.cc:400
void Close()
Definition: FitsFile.cc:428
Error()
Definition: HeadersFTM.h:197
bool OpenNewTable(const string &tableName, int maxtry=1)
Definition: FitsFile.cc:206
Changes for version
Definition: README_v11.txt:85