FACT++  1.0
fitsloader.cc
Go to the documentation of this file.
1 //****************************************************************
23  //****************************************************************
24 #include "Event.h"
25 #include "StateMachineDim.h"
26 #include "WindowLog.h"
27 #include "Configuration.h"
28 #include "LocalControl.h"
29 #include "Description.h"
30 
31 
32 #include <boost/bind.hpp>
33 #if BOOST_VERSION < 104400
34 #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 4))
35 #undef BOOST_HAS_RVALUE_REFS
36 #endif
37 #endif
38 #include <boost/thread.hpp>
39 
40 #include <iostream>
41 
42 #include <CCfits/CCfits>
43 
45 {
46 
47 public:
48  enum
49  {
51  } localstates_t;
52 
53  FitsLoader(ostream& out);
54  ~FitsLoader();
55 
57  static const char* fLoadFits;
58  static const char* fUnloadFits;
59  static const char* fListColumns;
60  static const char* fDumpColumns;
61  static const char* fClearDumpList;
62  static const char* fDoDump;
63  static const char* fConfigFileName;
64  static const char* fConfigTableName;
65  static const char* fConfigPrecName;
66  static const char* fConfigFileOutName;
67 
68 private:
70  string fFileName;
72  string fTableName;
74  CCfits::FITS* fFile;
76  CCfits::Table* fTable;
80  string fFileOut;
82  map<string, CCfits::Column*> fColMap;
84  vector<string> fDumpList;
86  int LoadPlease();
88  int UnloadPlease();
90  int ListColumnsPlease(const Event&);
92  int AddDumpColumnsPlease(const Event&);
94  int ClearDumpListPlease(const Event&);
96  int DoDumpPlease(const Event&);
98  int ConfigFileNamePlease(const Event&);
100  int ConfigTableNamePlease(const Event&);
102  int SetOFStreamPrecisionPlease(const Event&);
104  int SetFileOutPlease(const Event&);
106  vector<int> CalculateBufferSize();
108  void writeValuesFromFits(vector<int>& offsets,ofstream& targetFile, unsigned char* fitsBuffer);
109 
110 public:
112  void SetupConfig(Configuration& conf);
113 };
114 
115 const char* FitsLoader::fLoadFits = "load";
116 const char* FitsLoader::fUnloadFits = "unload";
117 const char* FitsLoader::fListColumns = "list_columns";
118 const char* FitsLoader::fDumpColumns = "add_dump";
119 const char* FitsLoader::fClearDumpList = "clear_dump";
120 const char* FitsLoader::fDoDump = "dump";
121 const char* FitsLoader::fConfigFileName = "set_file";
122 const char* FitsLoader::fConfigTableName = "set_table";
123 const char* FitsLoader::fConfigPrecName = "set_prec";
124 const char* FitsLoader::fConfigFileOutName = "set_outfile";
125 
126 // --------------------------------------------------------------------------
127 //
131 //
133 {
134  fFileOut = evt.GetText();
135  ostringstream str;
136  str << "Output file is now " << fFileOut;
137  Message(str);
138  return 0;
139 }
140 // --------------------------------------------------------------------------
141 //
145 //
147 {
148  fStreamPrecision = evt.GetInt();
149  ostringstream str;
150  str << "ofstream precision is now " << fStreamPrecision;
151  Message(str);
152  return 0;
153 }
154 // --------------------------------------------------------------------------
155 //
163 //
164 void FitsLoader::writeValuesFromFits(vector<int>& offsets,ofstream& targetFile, unsigned char* fitsBuffer)
165 {
166  targetFile.precision(fStreamPrecision);
167  map<string, CCfits::Column*>::iterator it;
168  for (it=fColMap.begin(); it != fColMap.end(); it++)
169  {
170  bool found = false;
171  for (vector<string>::iterator jt=fDumpList.begin(); jt != fDumpList.end(); jt++)
172  {
173  if (it->first == *jt)
174  {
175  found = true;
176  break;
177  }
178  }
179  if (!found)
180  continue;
181  int offset = offsets[it->second->index()-1];
182  const char* charSrc = reinterpret_cast<char*>(&fitsBuffer[offset]);
183  unsigned char copyBuffer[30];//max size of a single variable
184  for (int width = 0; width<it->second->width(); width++)
185  {
186  switch (it->second->type())
187  {
188  case CCfits::Tbyte:
189  targetFile << *charSrc;
190  charSrc += sizeof(char);
191  break;
192  case CCfits::Tushort:
193  targetFile << *reinterpret_cast<const unsigned short*>(charSrc);
194  charSrc += sizeof(char);
195  break;
196  case CCfits::Tshort:
197  targetFile << *reinterpret_cast<const short*>(charSrc);
198  charSrc += sizeof(char);
199  break;
200  case CCfits::Tuint:
201  reverse_copy(charSrc, charSrc+sizeof(unsigned int), copyBuffer);
202  //warning suppressed in gcc4.0.2
203  targetFile << *reinterpret_cast<unsigned int*>(copyBuffer);
204  charSrc += sizeof(int);
205  break;
206  case CCfits::Tint:
207  reverse_copy(charSrc, charSrc+sizeof(int), copyBuffer);
208  targetFile << *reinterpret_cast<int*>(copyBuffer);
209  charSrc += sizeof(int);
210  break;
211  case CCfits::Tulong:
212  reverse_copy(charSrc, charSrc+sizeof(unsigned long), copyBuffer);
213  targetFile << *reinterpret_cast<unsigned long*>(copyBuffer);
214  charSrc += sizeof(int);
215  break;
216  case CCfits::Tlong:
217  reverse_copy(charSrc, charSrc+sizeof(long), copyBuffer);
218  targetFile << *reinterpret_cast<long*>(copyBuffer);
219  charSrc += sizeof(int);
220  break;
221  case CCfits::Tlonglong:
222  reverse_copy(charSrc, charSrc+sizeof(long long), copyBuffer);
223  targetFile << *reinterpret_cast<long long*>(copyBuffer);
224  charSrc += sizeof(long long);
225  break;
226  case CCfits::Tfloat:
227  reverse_copy(charSrc, charSrc+sizeof(float), copyBuffer);
228  targetFile << *reinterpret_cast<float*>(copyBuffer);
229  charSrc += sizeof(float);
230  break;
231  case CCfits::Tdouble:
232  reverse_copy(charSrc, charSrc+sizeof(double), copyBuffer);
233  targetFile << *reinterpret_cast<double*>(copyBuffer);
234  charSrc += sizeof(double);
235  break;
236  case CCfits::Tnull:
237  case CCfits::Tbit:
238  case CCfits::Tlogical:
239  case CCfits::Tstring:
240  case CCfits::Tcomplex:
241  case CCfits::Tdblcomplex:
242  case CCfits::VTbit:
243  case CCfits::VTbyte:
244  case CCfits::VTlogical:
245  case CCfits::VTushort:
246  case CCfits::VTshort:
247  case CCfits::VTuint:
248  case CCfits::VTint:
249  case CCfits::VTulong:
250  case CCfits::VTlong:
251  case CCfits::VTlonglong:
252  case CCfits::VTfloat:
253  case CCfits::VTdouble:
254  case CCfits::VTcomplex:
255  case CCfits::VTdblcomplex:
256  Error("Data type not implemented yet.");
257  return;
258  break;
259  default:
260  Error("THIS SHOULD NEVER BE REACHED");
261  return;
262  }//switch
263  targetFile << " ";
264  }//width loop
265  }//iterator over the columns
266  targetFile << endl;
267 }
268 
269 // --------------------------------------------------------------------------
270 //
273 //
275 {
276  vector<int> result;
277  map<int,int> sizes;
278  int size = 0;
279 
280  for (map<string, CCfits::Column*>::iterator it=fColMap.begin(); it != fColMap.end(); it++)
281  {
282  int width = it->second->width();
283  switch (it->second->type())
284  {
285  case CCfits::Tbyte:
286  case CCfits::Tushort:
287  case CCfits::Tshort:
288  Message("short");
289  sizes[it->second->index()] = sizeof(char)*width;
290  break;
291  case CCfits::Tuint:
292  case CCfits::Tint:
293  Message("int");
294  sizes[it->second->index()] = sizeof(int)*width;
295  break;
296  case CCfits::Tulong:
297  case CCfits::Tlong:
298  Message("long");
299  sizes[it->second->index()] = sizeof(int)*width;
300  break;
301  case CCfits::Tlonglong:
302  Message("longlong");
303  sizes[it->second->index()] = sizeof(long long)*width;
304  break;
305  case CCfits::Tfloat:
306  Message("float");
307  sizes[it->second->index()] = sizeof(float)*width;
308  break;
309  case CCfits::Tdouble:
310  Message("double");
311  sizes[it->second->index()] = sizeof(double)*width;
312  break;
313  case CCfits::Tnull:
314  case CCfits::Tbit:
315  case CCfits::Tlogical:
316  case CCfits::Tstring:
317  case CCfits::Tcomplex:
318  case CCfits::Tdblcomplex:
319  case CCfits::VTbit:
320  case CCfits::VTbyte:
321  case CCfits::VTlogical:
322  case CCfits::VTushort:
323  case CCfits::VTshort:
324  case CCfits::VTuint:
325  case CCfits::VTint:
326  case CCfits::VTulong:
327  case CCfits::VTlong:
328  case CCfits::VTlonglong:
329  case CCfits::VTfloat:
330  case CCfits::VTdouble:
331  case CCfits::VTcomplex:
332  case CCfits::VTdblcomplex:
333  Error("Data type not implemented yet.");
334  return vector<int>();
335  break;
336  default:
337  Error("THIS SHOULD NEVER BE REACHED");
338  return vector<int>();
339  }
340  }
341  //calculate the offsets in the vector.
342  int checkIndex = 1;
343  for (map<int,int>::iterator it=sizes.begin(); it != sizes.end(); it++)
344  {
345  result.push_back(size);
346  size += it->second;
347  if (it->first != checkIndex)
348  {
349  ostringstream str;
350  str << "Expected index " << checkIndex << " found " << it->first;
351  Error(str);
352  }
353  checkIndex++;
354  }
355  result.push_back(size);
356  return result;
357 }
358 // --------------------------------------------------------------------------
359 //
363 //
364 FitsLoader::FitsLoader(ostream& out) : StateMachineDim(out, "FITS_LOADER")
365 {
366  //Add the existing states
367  AddStateName(kSM_FileLoaded, "FileLoaded", "A Fits file has been loaded");
368 
369  //Add the possible transitions
371  (boost::bind(&FitsLoader::LoadPlease, this))
372  ("Loads the given Fits file");
374  (boost::bind(&FitsLoader::UnloadPlease, this))
375  ("Unloads the given Fits file");
376 
377  //Add the possible configurations
379  (boost::bind(&FitsLoader::ListColumnsPlease, this, _1))
380  ("List the columns that were loaded from that file");
382  (boost::bind(&FitsLoader::AddDumpColumnsPlease, this, _1))
383  ("Add a given column to the dumping list");
385  (boost::bind(&FitsLoader::ClearDumpListPlease, this, _1))
386  ("Clear the dumping list");
388  (boost::bind(&FitsLoader::DoDumpPlease, this, _1))
389  ("Perform the dump of columns data, based on the to dump list");
391  (boost::bind(&FitsLoader::ConfigFileNamePlease, this, _1))
392  ("Gives the name of the Fits file to be loaded");
394  (boost::bind(&FitsLoader::ConfigTableNamePlease, this, _1))
395  ("Gives the name of the Table to be loaded");
397  (boost::bind(&FitsLoader::SetOFStreamPrecisionPlease, this, _1))
398  ("Set the precision of the ofstream, i.e. the number of significant digits being outputted");
400  (boost::bind(&FitsLoader::SetFileOutPlease, this, _1))
401  ("Set the name of the outputted file.");
402 
403  fFile = NULL;
404  fStreamPrecision = 20;
405 
406 }
407 // --------------------------------------------------------------------------
408 //
410 //
412 {
413  if (fFile)
414  delete fFile;
415  fFile = NULL;
416 }
417 // --------------------------------------------------------------------------
418 //
420 //
422 {
423  ostringstream str;
424  try
425  {
426  fFile = new CCfits::FITS(fFileName);
427  }
428  catch (CCfits::FitsException e)
429  {
430  str << "Could not open FITS file " << fFileName << " reason: " << e.message();
431  Error(str);
432  return kSM_Ready;
433  }
434  str.str("");
435  const multimap< string, CCfits::ExtHDU * > extMap = fFile->extension();
436  if (extMap.find(fTableName) == extMap.end())
437  {
438  str.str("");
439  str << "Could not open table " << fTableName << ". Tables in file are: ";
440  for (std::multimap<string, CCfits::ExtHDU*>::const_iterator it=extMap.begin(); it != extMap.end(); it++)
441  str << it->first << " ";
442  Error(str);
443  return kSM_Ready;
444  }
445  else
446  fTable = dynamic_cast<CCfits::Table*>(extMap.find(fTableName)->second);
447  int numRows = fTable->rows();
448  str.str("");
449  str << "Loaded table has " << numRows << " rows";
450  Message(str);
451 
452  fColMap = fTable->column();
453  if (fDumpList.size() != 0)
454  {
455  bool should_clear = false;
456  for (vector<string>::iterator it=fDumpList.begin(); it!= fDumpList.end(); it++)
457  {
458  if (fColMap.find(*it) == fColMap.end())
459  {
460  should_clear = true;
461  Error("Config-given dump list contains invalid entry " + *it + " clearing the list");
462  }
463  }
464  if (should_clear)
465  fDumpList.clear();
466  }
467  return kSM_FileLoaded;
468 }
469 // --------------------------------------------------------------------------
470 //
472 //
474 {
475  if (fFile)
476  delete fFile;
477  else
478  Error("Error: Fits file is NULL while it should not have been");
479  fFile = NULL;
480  return kSM_Ready;
481 }
482 // --------------------------------------------------------------------------
483 //
485 //
487 {
488  Message("Columns in the loaded table are:");
489  map<string, CCfits::Column*>::iterator it;
490  for (it=fColMap.begin(); it != fColMap.end(); it++)
491  Message(it->first);
492  return GetCurrentState();
493 }
494 // --------------------------------------------------------------------------
495 //
499 //
501 {
502  string evtText(evt.GetText());
503  //TODO check that this column indeed exist in the file
504  if (fColMap.find(evtText) != fColMap.end())
505  fDumpList.push_back(evtText);
506  else
507  Error("Could not find column " + evtText + " int table");
508  Message("New dump list:");
509  for (vector<string>::iterator it=fDumpList.begin(); it != fDumpList.end(); it++)
510  Message(*it);
511  return GetCurrentState();
512 }
513 // --------------------------------------------------------------------------
514 //
516 //
518 {
519  fDumpList.clear();
520  Message("Dump list is now empty");
521  return GetCurrentState();
522 }
523 // --------------------------------------------------------------------------
524 //
526 //
528 {
529  fTable->makeThisCurrent();
530  vector<int> offsets = CalculateBufferSize();
531  int size = offsets[offsets.size()-1];
532  offsets.pop_back();
533  unsigned char* fitsBuffer = new unsigned char[size];
534 
535  ofstream targetFile(fFileOut);
536  int status = 0;
537 
538  for (int i=1;i<=fTable->rows(); i++)
539  {
540  fits_read_tblbytes(fFile->fitsPointer(), i, 1, size, fitsBuffer, &status);
541  if (status)
542  {
543  ostringstream str;
544  str << "An error occurred while reading fits row #" << i << " error code: " << status;
545  Error(str);
546  str.str("");
547  for (unsigned int j=0;j<offsets.size(); j++)
548  str << offsets[j] << " ";
549  Error(str);
550  }
551  writeValuesFromFits(offsets, targetFile, fitsBuffer);
552  }
553  delete[] fitsBuffer;
554  return GetCurrentState();
555 }
556 // --------------------------------------------------------------------------
557 //
561 //
563 {
564  fFileName = string(evt.GetText());
565  Message("New Fits file: " + fFileName);
566  return GetCurrentState();
567 }
568 // --------------------------------------------------------------------------
569 //
573 //
575 {
576  fTableName = string(evt.GetText());
577  Message("New Fits table: " + fTableName);
578  return GetCurrentState();
579 }
580 // --------------------------------------------------------------------------
581 //
585 //
587 {
588  if (conf.Has("outfile"))
589  {
590  fFileOut = conf.Get<string>("outfile");
591  Message("Output file is: " + fFileOut);
592  }
593  if (conf.Has("fitsfile"))
594  {
595  fFileName = conf.Get<string>("fitsfile");
596  Message("Input fits is: " + fFileName);
597  }
598  if (conf.Has("tablename"))
599  {
600  fTableName = conf.Get<string>("tablename");
601  Message("Input Table is: " + fTableName);
602  }
603  if (conf.Has("dump"))
604  {
605  fDumpList = conf.Get<vector<string>>("dump");
606  Message("Dump list is:");
607  for (vector<string>::iterator it=fDumpList.begin(); it != fDumpList.end(); it++)
608  Message(*it);
609  }
610  if (conf.Has("precision"))
611  {
612  fStreamPrecision = conf.Get<int>("precision");
613 
614  ostringstream str;
615  str << "OFStream precision is: " << fStreamPrecision;
616  Message(str);
617  }
618 }
619 void RunThread(FitsLoader* loader)
620 {
621  loader->Run(true);
622  Readline::Stop();
623 }
624 template<class T>
626 {
627  static T shell(conf.GetName().c_str(), conf.Get<int>("console")!=1);
628 
629  WindowLog& wout = shell.GetStreamOut();
630 
631  FitsLoader loader(wout);
632  loader.SetupConfig(conf);
633  shell.SetReceiver(loader);
634 
635  boost::thread t(boost::bind(RunThread, &loader));
636 
637  shell.Run();
638 
639  loader.Stop();
640 
641  t.join();
642 
643  return 0;
644 }
646 {
647  cout << "This is a usage. to be completed" << endl;
648 }
649 void PrintHelp()
650 {
651  cout << "This is the help. I know, not so helpfull at the moment..." << endl;
652 }
654 {
655  po::options_description configp("Programm options");
656  configp.add_options()
657  ("console,c", var<int>(), "Use console (0=shell, 1=simple buffered, X=simple unbuffered)");
658 
659  po::options_description configs("Fits Loader options");
660  configs.add_options()
661  ("outfile,o", var<string>(), "Output file")
662  ("fitsfile,f", var<string>(), "Input Fits file")
663  ("tablename,t", var<string>(), "Input Table")
664  ("dump,d", vars<string>(), "List of columns to dump")
665  ("precision,p", var<int>(), "Precision of ofstream")
666  ;
667 // conf.AddEnv("dns", "DIM_DNS_NODE");
668 
669  conf.AddOptions(configp);
670  conf.AddOptions(configs);
671 }
672 int main(int argc, const char** argv)
673 {
674  Configuration conf(argv[0]);
676  SetupConfiguration(conf);
677 
678  if (!conf.DoParse(argc, argv, PrintHelp))
679  return -1;
680 
681 // if (!conf.Has("console"))
682 // return Run(conf);
683  if (conf.Get<int>("console")==0)
684  return RunShell<LocalShell>(conf);
685  else
686  return RunShell<LocalConsole>(conf);
687 
688  return 0;
689 }
map< string, CCfits::Column * > fColMap
map between the column names and their CCfits objects
Definition: fitsloader.cc:82
int LoadPlease()
Transition from ready to fileLoaded.
Definition: fitsloader.cc:421
EventImp & AddEvent(const std::string &name, const std::string &states, const std::string &fmt)
virtual void Stop(int code=0)
Request to stop the mainloop.
static const char * fLoadFits
Define command names.
Definition: fitsloader.cc:57
int SetOFStreamPrecisionPlease(const Event &)
Set the ofstream precision.
Definition: fitsloader.cc:146
int main(int argc, const char **argv)
Definition: fitsloader.cc:672
Mainloop running, state machine in operation.
int GetCurrentState() const
return the current state of the machine
const char * GetText() const
Definition: EventImp.h:88
void writeValuesFromFits(vector< int > &offsets, ofstream &targetFile, unsigned char *fitsBuffer)
Write a single row of the selected data.
Definition: fitsloader.cc:164
int UnloadPlease()
Transition from fileLoaded to ready.
Definition: fitsloader.cc:473
int DoDumpPlease(const Event &)
Perform the dumping, based on the current dump list.
Definition: fitsloader.cc:527
static const char * fListColumns
Definition: fitsloader.cc:59
int i
Definition: db_dim_client.c:21
~FitsLoader()
Destructor.
Definition: fitsloader.cc:411
static const char * fConfigTableName
Definition: fitsloader.cc:64
char str[80]
Definition: test_client.c:7
A C++ ostream to an ncurses window supporting attributes and colors.
Definition: WindowLog.h:50
void SetPrintUsage(const std::function< void(void)> &func)
T Get(const std::string &var)
static const char * fDumpColumns
Definition: fitsloader.cc:60
static const char * fConfigFileName
Definition: fitsloader.cc:63
static void Stop()
Definition: Readline.cc:1534
int32_t GetInt() const
Definition: EventImp.h:93
void RunThread(FitsLoader *loader)
Definition: fitsloader.cc:619
string fFileOut
Name of the output file.
Definition: fitsloader.cc:80
static const char * fDoDump
Definition: fitsloader.cc:62
enum FitsLoader::@19 localstates_t
int SetFileOutPlease(const Event &)
Set the name of the output file.
Definition: fitsloader.cc:132
bool Has(const std::string &var)
void AddOptions(const po::options_description &opt, bool visible=true)
Definition: Configuration.h:92
static const char * fUnloadFits
Definition: fitsloader.cc:58
int ClearDumpListPlease(const Event &)
Clear the dump list.
Definition: fitsloader.cc:517
CCfits::FITS * fFile
FITS pointer.
Definition: fitsloader.cc:74
int Error(const std::string &str)
Definition: MessageImp.h:49
vector< string > fDumpList
List of the column names to be dumped.
Definition: fitsloader.cc:84
int ListColumnsPlease(const Event &)
Lists the loaded column names.
Definition: fitsloader.cc:486
FitsLoader(ostream &out)
Definition: fitsloader.cc:364
Commandline parsing, resource file parsing and database access.
Definition: Configuration.h:9
Load a given Fits file and table, and dump selected columns if requested.
Definition: fitsloader.cc:44
int AddDumpColumnsPlease(const Event &)
Add a column name to the dump list.
Definition: fitsloader.cc:500
int ConfigFileNamePlease(const Event &)
Set the name of the Fits file to be loaded.
Definition: fitsloader.cc:562
void SetupConfiguration(Configuration &conf)
Definition: fitsloader.cc:653
int size
Definition: db_dim_server.c:17
string fFileName
Name of the fits file to load.
Definition: fitsloader.cc:70
void PrintUsage()
Definition: fitsloader.cc:645
Class for a state machine implementation within a DIM network.
Concerete implementation of an EventImp stroring name, format, data and time.
Definition: Event.h:6
int fStreamPrecision
Precision of the ofstream. Used to output a given number of significant digits for floats or doubles...
Definition: fitsloader.cc:78
CCfits::Table * fTable
Table pointer.
Definition: fitsloader.cc:76
string fTableName
Name of the table to load from the file.
Definition: fitsloader.cc:72
virtual int Run(bool dummy)
Start the mainloop.
TT t
Definition: test_client.c:26
int RunShell(Configuration &conf)
Definition: fitsloader.cc:625
static const char * fConfigFileOutName
Definition: fitsloader.cc:66
void PrintHelp()
Definition: fitsloader.cc:649
int Message(const std::string &str)
Definition: MessageImp.h:46
int ConfigTableNamePlease(const Event &)
Set the name of the table to be loaded.
Definition: fitsloader.cc:574
uint32_t numRows
Definition: FITS.h:72
void SetupConfig(Configuration &conf)
Configures the fitsLoader from the config file and/or command arguments.
Definition: fitsloader.cc:586
static const char * fConfigPrecName
Definition: fitsloader.cc:65
vector< int > CalculateBufferSize()
Calculate the buffer size required to read a row of the fits table, as well as the offsets to each co...
Definition: fitsloader.cc:274
static const char * fClearDumpList
Definition: fitsloader.cc:61
bool DoParse(int argc, const char **argv, const std::function< void()> &func=std::function< void()>())
bool AddStateName(const int state, const std::string &name, const std::string &doc="")
const std::string & GetName() const