1 | //****************************************************************
|
---|
2 | /** @class FitsLoader
|
---|
3 |
|
---|
4 | @brief Load a given Fits file and table, and dump selected columns if requested.
|
---|
5 |
|
---|
6 | It derives from StateMachineDim. the first parent is here to enforce
|
---|
7 | a state machine behaviour
|
---|
8 | The possible states and transitions of the machine are:
|
---|
9 | \dot
|
---|
10 | digraph FitsLoader {
|
---|
11 | node [shape=record, fontname=Helvetica, fontsize=10];
|
---|
12 | e [label="Error" color="red"];
|
---|
13 | r [label="Ready"]
|
---|
14 | d [label="FileLoaded"]
|
---|
15 |
|
---|
16 | e -> r
|
---|
17 | r -> e
|
---|
18 | r -> d
|
---|
19 | d -> r
|
---|
20 | }
|
---|
21 | \enddot
|
---|
22 | */
|
---|
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 |
|
---|
44 | class FitsLoader : public StateMachineDim
|
---|
45 | {
|
---|
46 |
|
---|
47 | public:
|
---|
48 | enum
|
---|
49 | {
|
---|
50 | kSM_FileLoaded = 20,
|
---|
51 | } localstates_t;
|
---|
52 |
|
---|
53 | FitsLoader(ostream& out);
|
---|
54 | ~FitsLoader();
|
---|
55 |
|
---|
56 | ///Define command names
|
---|
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:
|
---|
69 | ///Name of the fits file to load
|
---|
70 | string fFileName;
|
---|
71 | ///Name of the table to load from the file
|
---|
72 | string fTableName;
|
---|
73 | ///FITS pointer
|
---|
74 | CCfits::FITS* fFile;
|
---|
75 | ///Table pointer
|
---|
76 | CCfits::Table* fTable;
|
---|
77 | ///Precision of the ofstream. Used to output a given number of significant digits for floats or doubles
|
---|
78 | int fStreamPrecision;
|
---|
79 | ///Name of the output file
|
---|
80 | string fFileOut;
|
---|
81 | ///map between the column names and their CCfits objects
|
---|
82 | map<string, CCfits::Column*> fColMap;
|
---|
83 | ///List of the column names to be dumped
|
---|
84 | vector<string> fDumpList;
|
---|
85 | ///Transition from ready to fileLoaded.
|
---|
86 | int LoadPlease();
|
---|
87 | ///Transition from fileLoaded to ready
|
---|
88 | int UnloadPlease();
|
---|
89 | ///Lists the loaded column names
|
---|
90 | int ListColumnsPlease(const Event&);
|
---|
91 | ///Add a column name to the dump list
|
---|
92 | int AddDumpColumnsPlease(const Event&);
|
---|
93 | ///Clear the dump list
|
---|
94 | int ClearDumpListPlease(const Event&);
|
---|
95 | ///Perform the dumping, based on the current dump list
|
---|
96 | int DoDumpPlease(const Event&);
|
---|
97 | ///Set the name of the Fits file to be loaded
|
---|
98 | int ConfigFileNamePlease(const Event&);
|
---|
99 | ///Set the name of the table to be loaded
|
---|
100 | int ConfigTableNamePlease(const Event&);
|
---|
101 | ///Set the ofstream precision
|
---|
102 | int SetOFStreamPrecisionPlease(const Event&);
|
---|
103 | ///Set the name of the output file
|
---|
104 | int SetFileOutPlease(const Event&);
|
---|
105 | ///Calculate the buffer size required to read a row of the fits table, as well as the offsets to each column
|
---|
106 | vector<int> CalculateBufferSize();
|
---|
107 | ///Write a single row of the selected data
|
---|
108 | void writeValuesFromFits(vector<int>& offsets,ofstream& targetFile, unsigned char* fitsBuffer);
|
---|
109 |
|
---|
110 | public:
|
---|
111 | ///Configures the fitsLoader from the config file and/or command arguments.
|
---|
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 | //
|
---|
128 | //! Set the name of the output file
|
---|
129 | //! @param evt
|
---|
130 | //! the event transporting the file name
|
---|
131 | //
|
---|
132 | int FitsLoader::SetFileOutPlease(const Event& evt)
|
---|
133 | {
|
---|
134 | fFileOut = evt.GetText();
|
---|
135 | ostringstream str;
|
---|
136 | str << "Output file is now " << fFileOut;
|
---|
137 | Message(str);
|
---|
138 | return 0;
|
---|
139 | }
|
---|
140 | // --------------------------------------------------------------------------
|
---|
141 | //
|
---|
142 | //! Set the precision of the ofstream. So that an appropriate number of significant digits are outputted.
|
---|
143 | //! @param evt
|
---|
144 | //! the event transporting the precision
|
---|
145 | //
|
---|
146 | int FitsLoader::SetOFStreamPrecisionPlease(const Event& evt)
|
---|
147 | {
|
---|
148 | fStreamPrecision = evt.GetInt();
|
---|
149 | ostringstream str;
|
---|
150 | str << "ofstream precision is now " << fStreamPrecision;
|
---|
151 | Message(str);
|
---|
152 | return 0;
|
---|
153 | }
|
---|
154 | // --------------------------------------------------------------------------
|
---|
155 | //
|
---|
156 | //! Writes a single row of the selected FITS data to the output file.
|
---|
157 | //! @param offsets
|
---|
158 | //! a vector containing the offsets to the columns (in bytes)
|
---|
159 | //! @param targetFile
|
---|
160 | //! the ofstream where to write to
|
---|
161 | //! @param fitsBuffer
|
---|
162 | //! the memory were the row has been loaded by cfitsio
|
---|
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 | //
|
---|
271 | //! Calculates the required buffer size for reading one row of the current table.
|
---|
272 | //! Also calculates the offsets to all the columns
|
---|
273 | //
|
---|
274 | vector<int> FitsLoader::CalculateBufferSize()
|
---|
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 | //
|
---|
360 | //! Constructor
|
---|
361 | //! @param out
|
---|
362 | //! the ostream where to redirect the outputs
|
---|
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
|
---|
370 | AddEvent(kSM_FileLoaded, fLoadFits, kSM_Ready)
|
---|
371 | (boost::bind(&FitsLoader::LoadPlease, this))
|
---|
372 | ("Loads the given Fits file");
|
---|
373 | AddEvent(kSM_Ready, fUnloadFits, kSM_FileLoaded)
|
---|
374 | (boost::bind(&FitsLoader::UnloadPlease, this))
|
---|
375 | ("Unloads the given Fits file");
|
---|
376 |
|
---|
377 | //Add the possible configurations
|
---|
378 | AddEvent(fListColumns, "", kSM_FileLoaded)
|
---|
379 | (boost::bind(&FitsLoader::ListColumnsPlease, this, _1))
|
---|
380 | ("List the columns that were loaded from that file");
|
---|
381 | AddEvent(fDumpColumns, "C", kSM_FileLoaded)
|
---|
382 | (boost::bind(&FitsLoader::AddDumpColumnsPlease, this, _1))
|
---|
383 | ("Add a given column to the dumping list");
|
---|
384 | AddEvent(fClearDumpList, "", kSM_FileLoaded)
|
---|
385 | (boost::bind(&FitsLoader::ClearDumpListPlease, this, _1))
|
---|
386 | ("Clear the dumping list");
|
---|
387 | AddEvent(fDoDump, "", kSM_FileLoaded)
|
---|
388 | (boost::bind(&FitsLoader::DoDumpPlease, this, _1))
|
---|
389 | ("Perform the dump of columns data, based on the to dump list");
|
---|
390 | AddEvent(fConfigFileName, "C", kSM_Ready, kSM_FileLoaded)
|
---|
391 | (boost::bind(&FitsLoader::ConfigFileNamePlease, this, _1))
|
---|
392 | ("Gives the name of the Fits file to be loaded");
|
---|
393 | AddEvent(fConfigTableName, "C", kSM_Ready, kSM_FileLoaded)
|
---|
394 | (boost::bind(&FitsLoader::ConfigTableNamePlease, this, _1))
|
---|
395 | ("Gives the name of the Table to be loaded");
|
---|
396 | AddEvent(fConfigPrecName, "I", kSM_Ready, kSM_FileLoaded)
|
---|
397 | (boost::bind(&FitsLoader::SetOFStreamPrecisionPlease, this, _1))
|
---|
398 | ("Set the precision of the ofstream, i.e. the number of significant digits being outputted");
|
---|
399 | AddEvent(fConfigFileOutName, "C", kSM_Ready, kSM_FileLoaded)
|
---|
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 | //
|
---|
409 | //! Destructor
|
---|
410 | //
|
---|
411 | FitsLoader::~FitsLoader()
|
---|
412 | {
|
---|
413 | if (fFile)
|
---|
414 | delete fFile;
|
---|
415 | fFile = NULL;
|
---|
416 | }
|
---|
417 | // --------------------------------------------------------------------------
|
---|
418 | //
|
---|
419 | //! Loads the fits file based on the current parameters
|
---|
420 | //
|
---|
421 | int FitsLoader::LoadPlease()
|
---|
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 | //
|
---|
471 | //! Unloads the Fits file
|
---|
472 | //
|
---|
473 | int FitsLoader::UnloadPlease()
|
---|
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 | //
|
---|
484 | //! List the columns that are in the loaded Fits table
|
---|
485 | //
|
---|
486 | int FitsLoader::ListColumnsPlease(const Event&)
|
---|
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 | //
|
---|
496 | //! Add a given column name to the list of columns to dump
|
---|
497 | //! @param evt
|
---|
498 | //! the event transporting the column name
|
---|
499 | //
|
---|
500 | int FitsLoader::AddDumpColumnsPlease(const Event& evt)
|
---|
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 | //
|
---|
515 | //! Clear the list of columns to dump
|
---|
516 | //
|
---|
517 | int FitsLoader::ClearDumpListPlease(const Event&)
|
---|
518 | {
|
---|
519 | fDumpList.clear();
|
---|
520 | Message("Dump list is now empty");
|
---|
521 | return GetCurrentState();
|
---|
522 | }
|
---|
523 | // --------------------------------------------------------------------------
|
---|
524 | //
|
---|
525 | //! Perform the actual dump, based on the current parameters
|
---|
526 | //
|
---|
527 | int FitsLoader::DoDumpPlease(const Event&)
|
---|
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 | //
|
---|
558 | //! Set the name of the intput Fits file
|
---|
559 | //! @param evt
|
---|
560 | //! the event transporting the file name
|
---|
561 | //
|
---|
562 | int FitsLoader::ConfigFileNamePlease(const Event& evt)
|
---|
563 | {
|
---|
564 | fFileName = string(evt.GetText());
|
---|
565 | Message("New Fits file: " + fFileName);
|
---|
566 | return GetCurrentState();
|
---|
567 | }
|
---|
568 | // --------------------------------------------------------------------------
|
---|
569 | //
|
---|
570 | //! Set the name of the input table
|
---|
571 | //! @param evt
|
---|
572 | //! the event transporting the table name
|
---|
573 | //
|
---|
574 | int FitsLoader::ConfigTableNamePlease(const Event& evt)
|
---|
575 | {
|
---|
576 | fTableName = string(evt.GetText());
|
---|
577 | Message("New Fits table: " + fTableName);
|
---|
578 | return GetCurrentState();
|
---|
579 | }
|
---|
580 | // --------------------------------------------------------------------------
|
---|
581 | //
|
---|
582 | //! Retrieves the configuration parameters
|
---|
583 | //! @param conf
|
---|
584 | //! the configuration object
|
---|
585 | //
|
---|
586 | void FitsLoader::SetupConfig(Configuration& conf)
|
---|
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>
|
---|
625 | int RunShell(Configuration& conf)
|
---|
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 | }
|
---|
645 | void PrintUsage()
|
---|
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 | }
|
---|
653 | void SetupConfiguration(Configuration& conf)
|
---|
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]);
|
---|
675 | conf.SetPrintUsage(PrintUsage);
|
---|
676 | SetupConfiguration(conf);
|
---|
677 |
|
---|
678 | po::variables_map vm;
|
---|
679 | try
|
---|
680 | {
|
---|
681 | vm = conf.Parse(argc, argv);
|
---|
682 | }
|
---|
683 | #if BOOST_VERSION > 104000
|
---|
684 | catch (po::multiple_occurrences &e)
|
---|
685 | {
|
---|
686 | cerr << "Program options invalid due to: " << e.what() << " of '" << e.get_option_name() << "'." << endl;
|
---|
687 | return -1;
|
---|
688 | }
|
---|
689 | #endif
|
---|
690 | catch (exception& e)
|
---|
691 | {
|
---|
692 | cerr << "Program options invalid due to: " << e.what() << endl;
|
---|
693 | return -1;
|
---|
694 | }
|
---|
695 |
|
---|
696 | if (conf.HasVersion() || conf.HasPrint())
|
---|
697 | return -1;
|
---|
698 |
|
---|
699 | if (conf.HasHelp())
|
---|
700 | {
|
---|
701 | PrintHelp();
|
---|
702 | return -1;
|
---|
703 | }
|
---|
704 |
|
---|
705 | // if (!conf.Has("console"))
|
---|
706 | // return Run(conf);
|
---|
707 | if (conf.Get<int>("console")==0)
|
---|
708 | return RunShell<LocalShell>(conf);
|
---|
709 | else
|
---|
710 | return RunShell<LocalConsole>(conf);
|
---|
711 |
|
---|
712 | return 0;
|
---|
713 | }
|
---|