Changeset 12723
- Timestamp:
- 12/15/11 10:39:26 (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/FACT++/src/fitsdump.cc
r12687 r12723 11 11 #include <fstream> 12 12 13 #include <CCfits/CCfits>14 15 //#define PLOTTING_PLEASE13 #include "externals/fits.h" 14 15 #define PLOTTING_PLEASE 16 16 17 17 #ifdef PLOTTING_PLEASE … … 32 32 using namespace std; 33 33 34 class MyColumn : public CCfits::Column35 {36 public:37 const string &comment() const { return CCfits::Column::comment(); }38 long width() const39 {//the width() method seems to be buggy (or empty ?) as it always return 1... redo it ourselves.40 string inter = format();41 inter = inter.substr(0, inter.size()-1);42 return atoi(inter.c_str());43 }44 };45 34 46 35 #ifdef PLOTTING_PLEASE … … 68 57 69 58 private: 70 71 CCfits::FITS *fFile; /// FITS pointer 72 CCfits::Table *fTable; /// Table pointer 73 map<string, MyColumn*> fColMap; /// map between the column names and their CCfits objects 59 bool fDotsPlease; 60 fits* fFile; 61 string fFilename; 62 63 fits::Table::Columns fColMap; 64 fits::Table::Keys fKeyMap; 74 65 75 66 // Convert CCfits::ValueType into a human readable string 76 string ValueTypeToStr( CCfits::ValueTypetype) const;67 string ValueTypeToStr(char type) const; 77 68 78 69 // Convert CCfits::ValueType into a number of associated bytes 79 int ValueTypeToSize( CCfits::ValueTypetype) const;70 int ValueTypeToSize(char type) const; 80 71 81 72 /// Calculate the buffer size required to read a row of the fits table, as well as the offsets to each column 82 vector<int> CalculateOffsets() const;73 // vector<int> CalculateOffsets() const; 83 74 84 75 template<class T> … … 89 80 90 81 /// Write a single row of the selected data 91 int WriteRow(ostream &, const vector<MyColumn*> &, const vector<int> &, unsigned char *, const vector<pair<int, int> >&) const;82 // int WriteRow(ostream &, const vector<MyColumn*> &, const vector<int> &, unsigned char *, const vector<pair<int, int> >&) const; 92 83 93 84 bool OpenFile(const string &); /// Open a file … … 108 99 int doCurvesDisplay( const vector<string> &list, const string& tableName); 109 100 #endif 101 int doStatsPlease(const string &filename, const vector<string>& list, int precision); 110 102 // bool Plot(const vector<string> &list); 111 103 … … 121 113 //! the ostream where to redirect the outputs 122 114 // 123 FitsDumper::FitsDumper() : fFile(0), f Table(0)115 FitsDumper::FitsDumper() : fFile(0), fDotsPlease(false) 124 116 { 125 117 } … … 136 128 137 129 138 string FitsDumper::ValueTypeToStr( CCfits::ValueTypetype) const130 string FitsDumper::ValueTypeToStr(char type) const 139 131 { 140 132 switch (type) 141 133 { 142 case CCfits::Tbyte: return "uint8_t"; 143 case CCfits::Tushort: return "uint16_t"; 144 case CCfits::Tshort: return "int16_t"; 145 case CCfits::Tuint: return "uint32_t"; 146 case CCfits::Tint: return "int32_t"; 147 case CCfits::Tulong: return "uint32_t"; 148 case CCfits::Tlong: return "int32_t"; 149 case CCfits::Tlonglong: return "int64_t"; 150 case CCfits::Tfloat: return "float"; 151 case CCfits::Tdouble: return "double"; 152 134 case 'L': return "bool(8)"; 135 case 'B': return "byte(8)"; 136 case 'I': return "short(16)"; 137 case 'J': return "int(32)"; 138 case 'K': return "int(64)"; 139 case 'E': return "float(32)"; 140 case 'D': return "double(64)"; 153 141 default: 154 142 return "unknwown"; … … 156 144 } 157 145 158 int FitsDumper::ValueTypeToSize( CCfits::ValueTypetype) const146 int FitsDumper::ValueTypeToSize(char type) const 159 147 { 160 148 switch (type) 161 149 { 162 case CCfits::Tbyte: return sizeof(uint8_t); 163 case CCfits::Tushort: 164 case CCfits::Tshort: return sizeof(uint16_t); 165 case CCfits::Tuint: 166 case CCfits::Tint: 167 case CCfits::Tulong: 168 case CCfits::Tlong: return sizeof(uint32_t); 169 case CCfits::Tlonglong: return sizeof(uint64_t); 170 case CCfits::Tfloat: return sizeof(float); 171 case CCfits::Tdouble: return sizeof(double); 172 150 case 'L': return sizeof(uint8_t); 151 case 'B': return sizeof(int8_t); 152 case 'I': return sizeof(int16_t); 153 case 'J': return sizeof(int32_t); 154 case 'K': return sizeof(int64_t); 155 case 'E': return sizeof(float); 156 case 'D': return sizeof(double); 173 157 default: 174 158 return 0; … … 185 169 return t; 186 170 } 187 /*188 template<class T>189 double FitsDumper::PtrToDouble(const unsigned char *ptr) const190 {191 T t;192 reverse_copy(ptr, ptr+sizeof(T), reinterpret_cast<unsigned char*>(&t));193 return t;194 }195 196 double FitsDumper::PtrToDouble(const unsigned char *ptr, CCfits::ValueType type) const197 {198 switch (type)199 {200 case CCfits::Tbyte: return PtrToDouble<uint8_t> (ptr);201 case CCfits::Tushort: return PtrToDouble<uint16_t>(ptr);202 case CCfits::Tuint:203 case CCfits::Tulong: return PtrToDouble<uint32_t>(ptr);204 case CCfits::Tshort: return PtrToDouble<int16_t> (ptr);205 case CCfits::Tint:206 case CCfits::Tlong: return PtrToDouble<int32_t> (ptr);207 case CCfits::Tlonglong: return PtrToDouble<int64_t> (ptr);208 case CCfits::Tfloat: return PtrToDouble<float> (ptr);209 case CCfits::Tdouble: return PtrToDouble<double> (ptr);210 211 default:212 throw runtime_error("Data type not implemented yet.");213 }214 }215 */216 217 // --------------------------------------------------------------------------218 //219 //! Writes a single row of the selected FITS data to the output file.220 //!221 //! Data type \b not yet implemented:222 //! CCfits::Tnull, CCfits::Tbit, CCfits::Tlogical, CCfits::Tstring,223 //! CCfits::Tcomplex, CCfits::Tdblcomplex, CCfits::VTbit,224 //! CCfits::VTbyte, CCfits::VTlogical, CCfits::VTushort,225 //! CCfits::VTshort, CCfits::VTuint, CCfits::VTint, CCfits::VTulong,226 //! CCfits::VTlong, CCfits::VTlonglong, CCfits::VTfloat,227 //! CCfits::VTdouble, CCfits::VTcomplex, CCfits::VTdblcomplex228 //!229 //! @param offsets230 //! a vector containing the offsets to the columns (in bytes)231 //! @param targetFile232 //! the ofstream where to write to233 //! @param fitsBuffer234 //! the memory were the row has been loaded by cfitsio235 //236 int FitsDumper::WriteRow(ostream &out, const vector<MyColumn*> &list, const vector<int> &offsets, unsigned char* fitsBuffer, const vector<pair<int, int> >& ranges) const237 {238 int cnt = 0;239 vector<pair<int, int> >::const_iterator jt = ranges.begin();240 for (vector<MyColumn*>::const_iterator it=list.begin(); it!=list.end(); it++, jt++)241 {242 if (jt == ranges.end())243 {244 cout << "ERROR: END OF RANGE POINTER REACHED" << endl;245 return false;246 }247 const MyColumn *col = *it;248 249 // CCfits starts counting at 1 not 0250 const int offset = offsets[col->index()-1];251 252 // Get the pointer to the array which we are supposed to print253 const unsigned char *ptr = fitsBuffer + offset;254 255 // Loop over all array entries256 int sizeToSkip = 0;257 switch (col->type())258 {259 case CCfits::Tbyte: sizeToSkip = sizeof(uint8_t); break;260 case CCfits::Tushort: sizeToSkip = sizeof(uint16_t); break;261 case CCfits::Tuint:262 case CCfits::Tulong: sizeToSkip = sizeof(uint32_t); break;263 case CCfits::Tshort: sizeToSkip = sizeof(int16_t); break;264 case CCfits::Tint:265 case CCfits::Tlong: sizeToSkip = sizeof(int32_t); break;266 case CCfits::Tlonglong: sizeToSkip = sizeof(int64_t); break;267 case CCfits::Tfloat: sizeToSkip = sizeof(float); break;268 case CCfits::Tdouble: sizeToSkip = sizeof(double); break;269 default:270 cerr << "Data type not implemented yet." << endl;271 return 0;272 }273 ptr += sizeToSkip*jt->first;274 for (int width=jt->first; width<jt->second; width++)275 {276 switch (col->type())277 {278 case CCfits::Tbyte: out << PtrToValue<uint8_t> (ptr); break;279 case CCfits::Tushort: out << PtrToValue<uint16_t>(ptr); break;280 case CCfits::Tuint:281 case CCfits::Tulong: out << PtrToValue<uint32_t>(ptr); break;282 case CCfits::Tshort: out << PtrToValue<int16_t> (ptr); break;283 case CCfits::Tint:284 case CCfits::Tlong: out << PtrToValue<int32_t> (ptr); break;285 case CCfits::Tlonglong: out << PtrToValue<int64_t> (ptr); break;286 case CCfits::Tfloat: out << PtrToValue<float> (ptr); break;287 case CCfits::Tdouble: out << PtrToValue<double> (ptr); break;288 289 default:290 cerr << "Data type not implemented yet." << endl;291 return 0;292 }293 294 out << " ";295 cnt++;296 }297 }298 299 if (cnt>0)300 out << endl;301 302 if (out.fail())303 {304 cerr << "ERROR - writing output: " << strerror(errno) << endl;305 return -1;306 }307 308 return cnt;309 }310 311 // --------------------------------------------------------------------------312 //313 //! Calculates the required buffer size for reading one row of the current314 //! table. Also calculates the offsets to all the columns315 //316 vector<int> FitsDumper::CalculateOffsets() const317 {318 map<int,int> sizes;319 320 for (map<string, MyColumn*>::const_iterator it=fColMap.begin();321 it!=fColMap.end(); it++)322 {323 const int &width = it->second->width();324 const int &idx = it->second->index();325 326 const int size = ValueTypeToSize(it->second->type());327 if (size==0)328 {329 cerr << "Data type " << (int)it->second->type() << " not implemented yet." << endl;330 return vector<int>();331 }332 //cout << "data size: " << size << " width: " << width << " index: " << idx << endl;333 int realwidth = (width == 0)? 1 : width;334 sizes[idx] = size*realwidth;335 }336 337 //calculate the offsets in the vector.338 vector<int> result(1, 0);339 340 int size = 0;341 int idx = 0;342 343 for (map<int,int>::const_iterator it=sizes.begin(); it!=sizes.end(); it++)344 {345 size += it->second;346 result.push_back(size);347 348 if (it->first == ++idx)349 continue;350 351 cerr << "Expected index " << idx << ", but found " << it->first << endl;352 return vector<int>();353 }354 355 return result;356 }357 358 171 // -------------------------------------------------------------------------- 359 172 // … … 363 176 { 364 177 if (fFile) 178 { 179 fFile->close(); 365 180 delete fFile; 366 367 ostringstream str; 368 try 369 {370 fFile = new CCfits::FITS(filename);371 }372 catch (CCfits::FitsException e)373 {374 c err << "Could not open FITS file " << filename << " reason: " << e.message()<< endl;181 } 182 183 try { 184 fFile = new fits(filename); 185 } 186 catch (std::runtime_error e) 187 { 188 cout << "Something went wrong while trying to open " << filename; 189 cout << ": " << e.what() << " Aborting dump." << endl; 375 190 return false; 376 191 } 192 fFilename = filename; 193 194 const fits::Table::Columns& tCols = fFile->getColumns(); 195 196 for (auto it=tCols.begin(); it != tCols.end(); it++) 197 fColMap.insert(*it); 198 199 const fits::Table::Keys& tkeys = fFile->getKeys(); 200 201 for (auto it=tkeys.begin(); it != tkeys.end(); it++) 202 fKeyMap.insert(*it); 377 203 378 204 return true; … … 387 213 } 388 214 389 const multimap< string, CCfits::ExtHDU * > extMap = fFile->extension();390 if (extMap.find(tablename) == extMap.end())391 {392 cerr << "Table '" << tablename << "' not found." << endl;393 return false;394 }395 396 fTable = dynamic_cast<CCfits::Table*>(extMap.find(tablename)->second);397 if (!fTable)398 {399 cerr << "Object '" << tablename << "' returned not a CCfits::Table." << endl;400 return false;401 }402 403 map<string, CCfits::Column*>& tCols = fTable->column();404 for (map<string, CCfits::Column*>::const_iterator it = tCols.begin(); it != tCols.end(); it++)405 {406 fColMap.insert(make_pair(it->first, static_cast<MyColumn*>(it->second)));407 }408 // fColMap = fTable->column();409 410 fTable->makeThisCurrent();411 412 fTable->getComments();413 fTable->getHistory();414 fTable->readAllKeys();415 215 416 216 return true; … … 426 226 } 427 227 428 cout << "\nFile: " << fFile->name() << "\n"; 429 430 const multimap< string, CCfits::ExtHDU * > extMap = fFile->extension(); 431 for (std::multimap<string, CCfits::ExtHDU*>::const_iterator it=extMap.begin(); it != extMap.end(); it++) 432 { 433 434 CCfits::Table *table = dynamic_cast<CCfits::Table*>(extMap.find(it->first)->second); 435 436 table->makeThisCurrent(); 437 table->readData(); 438 439 cout << " " << it->first << " [" << table->rows() << "]\n"; 440 441 const map<string, CCfits::Column*> &cols = table->column(); 442 443 // for (map<string, CCfits::Column*>::const_iterator id = cols.begin(); ib != cols.end(); ib++) 444 // { 445 // TFORM 446 // } 447 448 for (map<string, CCfits::Column*>::const_iterator ic=cols.begin(); 449 ic != cols.end(); ic++) 450 { 451 const MyColumn *col = static_cast<MyColumn*>(ic->second); 452 453 cout << " " << col->name() << "[" ; 454 if (col->width() == 0) 455 cout << 1; 456 else 457 cout << col->width(); 458 cout << "] * " << col->scale() << " (" << col->unit() << ":" << ValueTypeToStr(col->type())<< ") " << col->comment() << "\n"; 459 /* 460 inline size_t Column::repeat () const 461 inline bool Column::varLength () const 462 inline double Column::zero () const 463 inline const String& Column::display () const 464 inline const String& Column::dimen () const 465 inline const String& Column::TBCOL () 466 inline const String& Column::TTYPE () 467 inline const String& Column::TFORM () 468 inline const String& Column::TDISP () 469 inline const String& Column::TZERO () 470 inline const String& Column::TDIM () 471 inline const String& Column::TNULL () 472 inline const String& Column::TLMIN () 473 inline const String& Column::TLMAX () 474 inline const String& Column::TDMAX () 475 inline const String& Column::TDMIN () 476 */ 477 } 478 cout << '\n'; 479 } 228 cout << "\nFile: " << fFilename << "\n"; 229 230 cout << " " << fKeyMap.find("EXTNAME")->second.value << " ["; 231 cout << fKeyMap.find("NAXIS2")->second.value << "]\n"; 232 233 for (auto it = fColMap.begin(); it != fColMap.end(); it++) 234 { 235 cout << " " << it->first << "[" << it->second.num << "] (" << it->second.unit << ":" << ValueTypeToStr(it->second.type) << ") "; 236 for (auto jt = fKeyMap.begin(); jt != fKeyMap.end(); jt++) 237 if (jt->second.value == it->first) 238 cout << jt->second.comment << endl; 239 } 240 241 cout << endl; 480 242 cout << flush; 481 243 } 482 244 483 class MyKeyword : public CCfits::Keyword484 {485 public:486 CCfits::ValueType keytype() const { return CCfits::Keyword::keytype(); }487 };488 489 245 void FitsDumper::ListKeywords(ostream &out) 490 246 { 491 map<string,CCfits::Keyword*> keys = fTable->keyWord(); 492 for (map<string,CCfits::Keyword*>::const_iterator it=keys.begin(); 493 it!=keys.end(); it++) 494 { 495 string str; 496 double d; 497 int l; 498 499 const MyKeyword *kw = static_cast<MyKeyword*>(it->second); 500 kw->keytype(); 501 out << "## " << setw(8) << kw->name() << " = " << setw(10); 502 if (kw->keytype()==16) 503 out << ("'"+kw->value(str)+"'"); 504 if (kw->keytype()==31) 505 out << kw->value(l); 506 if (kw->keytype()==82) 507 out << kw->value(d); 508 out << " / " << kw->comment() << endl; 247 for (auto it=fKeyMap.begin(); it != fKeyMap.end(); it++) { 248 out << "## " << setw(8) << it->first << " = " << setw(10); 249 out << "'" << it->second.value << "'" << " / " << it->second.comment << endl; 509 250 } 510 251 } … … 512 253 void FitsDumper::ListHeader() 513 254 { 514 if (!f Table)255 if (!fFile) 515 256 { 516 257 cerr << "No table open." << endl; … … 518 259 } 519 260 520 cout << "\nTable: " << fTable->name() << " (rows=" << fTable->rows() << ")\n"; 521 if (!fTable->comment().empty()) 522 cout << "Comment: \t" << fTable->comment() << '\n'; 523 if (!fTable->history().empty()) 524 cout << "History: \t" << fTable->history() << '\n'; 261 cout << "\nTable: " << fKeyMap.find("EXTNAME")->second.value << " (rows=" << fKeyMap.find("NAXIS2")->second.value << ")\n"; 262 if (fKeyMap.find("COMMENT") != fKeyMap.end()) 263 cout << "Comment: \t" << fKeyMap.find("COMMENT")->second.value << "\n"; 525 264 526 265 ListKeywords(cout); 527 266 cout << endl; 267 528 268 } 529 269 … … 538 278 unsigned long bracketIndex1 = columnNameOnly.find_first_of(']'); 539 279 unsigned long colonIndex = columnNameOnly.find_first_of(':'); 540 // cout << bracketIndex0 << " " << bracketIndex1 << " " << colonIndex << endl;541 280 int columnStart = -1; 542 281 int columnEnd = -1; … … 553 292 columnStart = atoi(columnNameOnly.substr(bracketIndex0+1, bracketIndex1 - (bracketIndex0+1)).c_str()); 554 293 columnEnd = columnStart+1; 555 // cout << "Cstart " << columnStart << " end: " << columnEnd << endl;556 294 } 557 295 columnNameOnly = columnNameOnly.substr(0, bracketIndex0); … … 563 301 return false; 564 302 } 565 // cout << "The column name is: " << columnNameOnly << endl; 566 MyColumn *cCol = static_cast<MyColumn*>(fColMap.find(columnNameOnly)->second); 303 fits::Table::Column& cCol = fColMap.find(columnNameOnly)->second; 567 304 if (bracketIndex0 == string::npos) 568 305 {//no range given: use the full range 569 ranges.push_back(make_pair(0, cCol ->width()));306 ranges.push_back(make_pair(0, cCol.num)); 570 307 columnStart = 0; 571 308 columnEnd = 1; … … 578 315 return false; 579 316 } 580 if (columnEnd>1 && columnEnd > cCol->width())317 if (columnEnd>1 && columnEnd > (int)(cCol.num)) 581 318 { 582 cerr << "ERROR - End range for column " << columnNameOnly << " is greater than the last element (" << cCol ->width()<< " vs " << columnEnd << "). Aborting" << endl;319 cerr << "ERROR - End range for column " << columnNameOnly << " is greater than the last element (" << cCol.num << " vs " << columnEnd << "). Aborting" << endl; 583 320 return false; 584 321 } … … 607 344 } 608 345 609 // FIXME: Maybe do this when opening a table?610 const vector<int> offsets = CalculateOffsets();611 // for (int i=0;i<offsets.size(); i++)612 // cout << offsets[i] << " ";613 // cout << endl;614 if (offsets.size()==0)615 return false;616 617 346 ofstream out(filename=="-"?"/dev/stdout":filename); 618 347 if (!out) … … 627 356 if (filename!="-") 628 357 out << "## File: \t" << filename << '\n'; 629 out << "## Table: \t" << fTable->name() << '\n'; 630 if (!fTable->comment().empty()) 631 out << "## Comment: \t" << fTable->comment() << '\n'; 632 if (!fTable->history().empty()) 633 out << "## History: \t" << fTable->history() << '\n'; 634 out << "## NumRows: \t" << fTable->rows() << '\n'; 358 out << "## Table: \t" << fKeyMap.find("EXTNAME")->second.value << '\n'; 359 out << "## Comment: \t" << ((fKeyMap.find("COMMENT") != fKeyMap.end()) ? fKeyMap.find("COMMENT")->second.value : "") << '\n'; 360 361 out << "## NumRows: \t" << fFile->GetInt("NAXIS2") << '\n'; 635 362 out << "## --------------------------------------------------------------------------\n"; 636 363 ListKeywords(out); 637 364 out << "## --------------------------------------------------------------------------\n"; 638 365 out << "#\n"; 639 //vector<pair<int, int> >::const_iterator rangesIt = ranges.begin(); 640 //the above is soooo yesterday ;) let's try the new auto feature of c++0x 366 641 367 auto rangesIt = ranges.begin(); 642 368 for (vector<string>::const_iterator it=listNamesOnly.begin(); it!=listNamesOnly.end(); it++, rangesIt++) 643 369 { 644 const MyColumn *col = static_cast<MyColumn*>(fTable->column()[*it]); 645 if (rangesIt->first != 0 || rangesIt->second != col->width()) 370 const fits::Table::Column& col = fColMap[*it]; 371 // const MyColumn *col = static_cast<MyColumn*>(fTable->column()[*it]); 372 if (rangesIt->first != 0 || rangesIt->second != col.num) 646 373 { 647 374 out << "#"; 648 375 for (int i=rangesIt->first; i<rangesIt->second; i++) 649 out << " " << col->name()<< "[" << i << "]";650 out << ": " << col ->unit();376 out << " " << *it << "[" << i << "]"; 377 out << ": " << col.unit; 651 378 } 652 379 else 653 out << "# " << col->name() << "[" << col->width() << "]: " << col->unit(); 654 655 if (!col->comment().empty()) 656 out << " (" <<col->comment() << ")"; 380 out << "# " << *it << "[" << col.num << "]: " << col.unit; 381 382 // FIXME: retrive the column comment 383 // if (!col->comment().empty()) 384 // out << " (" <<col->comment() << ")"; 657 385 out << '\n'; 658 386 } … … 661 389 662 390 // Loop over all columns in our list of requested columns 663 vector<MyColumn*> columns; 391 vector<pair<char, char*> > columnsData; 392 664 393 for (vector<string>::const_iterator it=listNamesOnly.begin(); it!=listNamesOnly.end(); it++) 665 394 { 666 MyColumn *cCol = static_cast<MyColumn*>(fColMap.find(*it)->second); 667 columns.push_back(cCol); 668 } 669 const int size = offsets[offsets.size()-1]; 670 unsigned char* fitsBuffer = new unsigned char[size]; 671 672 int status = 0; 673 int endIndex = (fColMap.find("Time") == fColMap.end()) ? fTable->rows()-1 : fTable->rows(); 674 for (int i=1; i<=endIndex; i++) 675 { 676 fits_read_tblbytes(fFile->fitsPointer(), i, 1, size, fitsBuffer, &status); 677 if (status) 395 fits::Table::Column& cCol = fColMap.find(*it)->second; 396 columnsData.push_back(make_pair(cCol.type, new char[cCol.num*cCol.size])); 397 fFile->SetPtrAddress(*it, columnsData[columnsData.size()-1].second); 398 } 399 int numRows = fFile->GetInt("NAXIS2"); 400 int row = 0; 401 while (fFile->GetNextRow() && row < numRows) 402 { 403 row++; 404 rangesIt = ranges.begin(); 405 for (auto it=columnsData.begin(); it != columnsData.end(); it++, rangesIt++) 678 406 { 679 char text[30];//max length of cfitsio error strings (from doc) 680 fits_get_errstatus(status, text); 681 682 cerr << "Reading row " << i << " failed: " << text << " (fits_insert_rows,rc=" << status << ")" << endl; 683 break; 684 } 685 if (WriteRow(out, columns, offsets, fitsBuffer, ranges)<0) 686 { 687 status=1; 688 break; 689 } 690 } 691 delete[] fitsBuffer; 692 693 return status==0; 694 } 695 696 // -------------------------------------------------------------------------- 697 // 698 //! Perform the actual dump, based on the current parameters 699 // 700 /* 701 bool FitsDumper::Plot(const vector<string> &list) 702 { 703 for (vector<string>::const_iterator it=list.begin(); it!=list.end(); it++) 704 if (fColMap.find(*it) == fColMap.end()) 705 { 706 cerr << "WARNING - Column '" << *it << "' not found in table." << endl; 707 return false; 708 } 709 710 // FIXME: Maybe do this when opening a table? 711 const vector<int> offsets = CalculateOffsets(); 712 if (offsets.size()==0) 713 return false; 714 715 // Loop over all columns in our list of requested columns 716 const CCfits::Column *col[3] = 717 { 718 list.size()>0 ? fColMap.find(list[0])->second : 0, 719 list.size()>1 ? fColMap.find(list[1])->second : 0, 720 list.size()>2 ? fColMap.find(list[2])->second : 0 721 }; 722 723 const int size = offsets[offsets.size()-1]; 724 unsigned char* fitsBuffer = new unsigned char[size]; 725 726 const int idx = 0; 727 728 // CCfits starts counting at 1 not 0 729 const size_t pos[3] = 730 { 731 col[0] ? offsets[col[0]->index()-1] + idx*col[0]->width()*ValueTypeToSize(col[0]->type()) : 0, 732 col[1] ? offsets[col[1]->index()-1] + idx*col[1]->width()*ValueTypeToSize(col[1]->type()) : 0, 733 col[2] ? offsets[col[2]->index()-1] + idx*col[2]->width()*ValueTypeToSize(col[2]->type()) : 0 734 }; 735 736 int status = 0; 737 for (int i=1; i<=fTable->rows(); i++) 738 { 739 fits_read_tblbytes(fFile->fitsPointer(), i, 1, size, fitsBuffer, &status); 740 if (status) 741 { 742 cerr << "An error occurred while reading fits row #" << i << " error code: " << status << endl; 743 break; 744 } 745 746 try 747 { 748 const double x[3] = 407 for (int i=rangesIt->first; i<rangesIt->second; i++) 749 408 { 750 col[0] ? PtrToDouble(fitsBuffer+pos[0], col[0]->type()) : 0, 751 col[1] ? PtrToDouble(fitsBuffer+pos[1], col[1]->type()) : 0, 752 col[2] ? PtrToDouble(fitsBuffer+pos[2], col[2]->type()) : 0 753 }; 754 } 755 catch (const runtime_error &e) 756 { 757 cerr << e.what() << endl; 758 status=1; 759 break; 760 } 761 } 762 delete[] fitsBuffer; 763 764 return status==0; 765 } 766 */ 409 switch (it->first) { 410 case 'L': 411 out << reinterpret_cast<bool*>(it->second)[i] << " "; 412 break; 413 case 'B': 414 out << reinterpret_cast<char*>(it->second)[i] << " "; 415 break; 416 case 'I': 417 out << reinterpret_cast<int16_t*>(it->second)[i] << " "; 418 break; 419 case 'J': 420 out << reinterpret_cast<int32_t*>(it->second)[i] << " "; 421 break; 422 case 'K': 423 out << reinterpret_cast<int64_t*>(it->second)[i] << " "; 424 break; 425 case 'E': 426 out << reinterpret_cast<float*>(it->second)[i] << " "; 427 break; 428 case 'D': 429 out << reinterpret_cast<double*>(it->second)[i] << " "; 430 break; 431 default: 432 ; 433 } 434 } 435 } 436 } 437 for (auto it = columnsData.begin(); it != columnsData.end(); it++) 438 delete[] it->second; 439 return true; 440 } 767 441 768 442 // -------------------------------------------------------------------------- … … 780 454 } 781 455 456 if (conf.Get<bool>("stat") && conf.Get<bool>("graph")) 457 { 458 cout << "Invalid conbination of options: cannot graph stats. Aborting" << endl; 459 return -1; 460 } 461 782 462 if (conf.Get<bool>("list")) 783 463 List(); … … 789 469 } 790 470 791 #ifdef PLOTTING_PLEASE 792 if (conf.Get<bool>("graph")) 471 if (conf.Get<bool>("stat")) 793 472 { 794 473 if (!conf.Has("col")) … … 797 476 return 0; 798 477 } 478 doStatsPlease(conf.Get<string>("outfile"), conf.Get<vector<string>>("col"), conf.Get<int>("precision")); 479 return 0; 480 } 481 482 #ifdef PLOTTING_PLEASE 483 if (conf.Get<bool>("graph")) 484 { 485 if (!conf.Has("col")) 486 { 487 cout << "Please specify the columns that should be dumped as arguments. Aborting" << endl; 488 return 0; 489 } 490 if (conf.Get<bool>("dots")) 491 fDotsPlease = true; 799 492 doCurvesDisplay(conf.Get<vector<string>>("col"), 800 493 conf.Get<string>("tablename")); … … 839 532 { 840 533 // 534 } 535 536 template<typename T> 537 void displayStats(char* array, int numElems) 538 { 539 sort(reinterpret_cast<T*>(array), &reinterpret_cast<T*>(array)[numElems]); 540 cout << "Min: " << reinterpret_cast<T*>(array)[0] << endl; 541 cout << "Max: " << reinterpret_cast<T*>(array)[numElems-1] << endl; 542 if (numElems%2 == 0) 543 cout << "Med: " << (reinterpret_cast<T*>(array)[numElems/2] + reinterpret_cast<int16_t*>(array)[numElems/2+1])/2.f << endl; 544 else 545 cout << "Med: " << reinterpret_cast<T*>(array)[numElems/2+1] << endl; 546 547 double average = 0; 548 for (int i=0;i<numElems;i++) 549 average += reinterpret_cast<T*>(array)[i]; 550 cout << "Mea: " << average/(double)numElems << endl; 551 552 } 553 int FitsDumper::doStatsPlease(const string &filename, const vector<string>& list, int precision) 554 { 555 556 //first of all, let's separate the columns from their ranges and check that the requested columns are indeed part of the file 557 vector<pair<int, int> > ranges; 558 vector<string> listNamesOnly; 559 560 if (!separateColumnsFromRanges(list, ranges, listNamesOnly)) 561 { 562 cerr << "Something went wrong while extracting the columns names from parameters. Aborting" << endl; 563 return false; 564 } 565 566 ofstream out(filename=="-"?"/dev/stdout":filename); 567 if (!out) 568 { 569 cerr << "Cannot open file " << filename << ": " << strerror(errno) << endl; 570 return false; 571 } 572 573 out.precision(precision); 574 575 // Loop over all columns in our list of requested columns 576 vector<pair<char, char*> > columnsData; 577 vector<char*> statData; 578 int numRows = fFile->GetInt("NAXIS2"); 579 auto rangesIt = ranges.begin(); 580 for (vector<string>::const_iterator it=listNamesOnly.begin(); it!=listNamesOnly.end(); it++, rangesIt++) 581 { 582 fits::Table::Column& cCol = fColMap.find(*it)->second; 583 columnsData.push_back(make_pair(cCol.type, new char[cCol.num*cCol.size])); 584 statData.push_back(new char[(rangesIt->second - rangesIt->first)*cCol.size*numRows]); 585 fFile->SetPtrAddress(*it, columnsData[columnsData.size()-1].second); 586 } 587 588 int row = 0; 589 while (fFile->GetNextRow() && row < numRows) 590 { 591 rangesIt = ranges.begin(); 592 auto statsIt = statData.begin(); 593 for (auto it=columnsData.begin(); it != columnsData.end(); it++, rangesIt++, statsIt++) 594 { 595 int span = rangesIt->second - rangesIt->first; 596 for (int i=rangesIt->first; i<rangesIt->second; i++) 597 { 598 switch (it->first) { 599 case 'L': 600 reinterpret_cast<bool*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<bool*>(it->second)[i]; 601 break; 602 case 'B': 603 reinterpret_cast<char*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<char*>(it->second)[i]; 604 break; 605 case 'I': 606 reinterpret_cast<int16_t*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<int16_t*>(it->second)[i]; 607 break; 608 case 'J': 609 reinterpret_cast<int32_t*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<int32_t*>(it->second)[i]; 610 break; 611 case 'K': 612 reinterpret_cast<int64_t*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<int64_t*>(it->second)[i]; 613 break; 614 case 'E': 615 reinterpret_cast<float*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<float*>(it->second)[i]; 616 break; 617 case 'D': 618 reinterpret_cast<float*>(*statsIt)[i - rangesIt->first + row*span] = reinterpret_cast<double*>(it->second)[i]; 619 break; 620 default: 621 ; 622 } 623 } 624 } 625 row++; 626 } 627 for (auto it = columnsData.begin(); it != columnsData.end(); it++) 628 delete[] it->second; 629 630 //okay. So now I've got ALL the data, loaded. 631 //let's do the summing and averaging in a safe way (i.e. avoid overflow of variables as much as possible) 632 rangesIt = ranges.begin(); 633 auto statsIt = statData.begin(); 634 int round; 635 auto nameIt = listNamesOnly.begin(); 636 for (auto it=columnsData.begin(); it != columnsData.end(); it++, rangesIt++, statsIt++, nameIt++) 637 { 638 int span = rangesIt->second - rangesIt->first; 639 cout << *nameIt << ": " << endl; 640 switch (it->first) { 641 case 'L': 642 displayStats<bool>(*statsIt, numRows*span); 643 break; 644 case 'B': 645 displayStats<char>(*statsIt, numRows*span); 646 break; 647 case 'I': 648 displayStats<int16_t>(*statsIt, numRows*span); 649 break; 650 case 'J': 651 displayStats<int32_t>(*statsIt, numRows*span); 652 break; 653 case 'K': 654 displayStats<int64_t>(*statsIt, numRows*span); 655 break; 656 case 'E': 657 displayStats<float>(*statsIt, numRows*span); 658 break; 659 case 'D': 660 displayStats<double>(*statsIt, numRows*span); 661 break; 662 default: 663 ; 664 } 665 } 666 return true; 841 667 } 842 668 #ifdef PLOTTING_PLEASE … … 894 720 for (unsigned int i=0;i<list.size();i++) 895 721 totalSize += ranges[i].second - ranges[i].first; 896 // cout << "Total size: " << totalSize << endl; 722 897 723 vector<QwtPlotCurve*> curves(totalSize); 898 724 int ii=0; … … 924 750 }; 925 751 ii++; 926 (*it)->setStyle(QwtPlotCurve::Lines); 752 if (fDotsPlease) 753 (*it)->setStyle(QwtPlotCurve::Dots); 754 else 755 (*it)->setStyle(QwtPlotCurve::Lines); 927 756 (*it)->attach(plot); 928 757 } 929 758 plot->insertLegend(new QwtLegend(), QwtPlot::RightLegend); 930 759 931 const vector<int> offsets = CalculateOffsets(); 932 if (offsets.size()==0) 933 return false; 934 935 936 // Loop over all columns in our list of requested columns 937 vector<MyColumn*> columns; 760 761 vector<pair<char, char*> > columnsData; 762 938 763 for (vector<string>::const_iterator it=listNamesOnly.begin(); it!=listNamesOnly.end(); it++) 939 764 { 940 MyColumn *cCol = static_cast<MyColumn*>(fColMap.find(*it)->second); 941 columns.push_back(cCol); 765 fits::Table::Column& cCol = fColMap.find(*it)->second; 766 columnsData.push_back(make_pair(cCol.type, new char[cCol.num*cCol.size])); 767 fFile->SetPtrAddress(*it, columnsData[columnsData.size()-1].second); 942 768 } 769 943 770 //add the time column to the given columns 944 771 if (fColMap.find("Time") == fColMap.end() && fColMap.find("UnixTimeUTC") == fColMap.end()) … … 947 774 return false; 948 775 } 949 MyColumn* timeCol; 950 bool unixTime = false; 951 int endIndex = 0; 952 if (fColMap.find("Time") != fColMap.end()) 953 { 954 timeCol = static_cast<MyColumn*>(fColMap.find("Time")->second); 776 const fits::Table::Column& timeCol = (fColMap.find("Time") != fColMap.end()) ? fColMap.find("Time")->second : fColMap.find("UnixTimeUTC")->second; 777 bool unixTime = (fColMap.find("Time") == fColMap.end()); 778 if (unixTime) 779 ranges.push_back(make_pair(0,2)); 780 else 955 781 ranges.push_back(make_pair(0,1)); 956 endIndex = fTable->rows(); 957 } 958 if (fColMap.find("UnixTimeUTC") != fColMap.end()) 959 { 960 timeCol = static_cast<MyColumn*>(fColMap.find("UnixTimeUTC")->second); 961 ranges.push_back(make_pair(0,2)); 962 endIndex = fTable->rows()-1; 963 unixTime = true; 964 } 965 columns.push_back(timeCol); 966 ///// 967 const int size = offsets[offsets.size()-1]; 968 unsigned char* fitsBuffer = new unsigned char[size]; 782 columnsData.push_back(make_pair(timeCol.type, new char[timeCol.num*timeCol.size])); 783 fFile->SetPtrAddress(unixTime ? "UnixTimeUTC" : "Time", columnsData[columnsData.size()-1].second); 969 784 970 785 // stringstream str; … … 977 792 str.precision(20); 978 793 for (auto it=xValues.begin(); it!=xValues.end(); it++) 979 *it = new double[f Table->rows()];980 981 yValues = new double[f Table->rows()];794 *it = new double[fFile->GetInt("NAXIS2")]; 795 796 yValues = new double[fFile->GetInt("NAXIS2")]; 982 797 983 798 cout.precision(3); 984 for (int i=1; i<=endIndex; i++) 799 int endIndex = 0; 800 int numRows = fFile->GetInt("NAXIS2"); 801 for (int i=1;i<numRows;i++) 985 802 { 986 cout << "/r" << "Constructing graph " << ((float)(i)/(float)(endIndex))*100.0 << "%"; 987 fits_read_tblbytes(fFile->fitsPointer(), i, 1, size, fitsBuffer, &status); 988 if (status) 803 fFile->GetNextRow(); 804 cout << "\r" << "Constructing graph " << ((float)(endIndex)/(float)(fFile->GetInt("NAXIS2")))*100.0 << "%"; 805 endIndex++; 806 auto rangesIt = ranges.begin(); 807 for (auto it=columnsData.begin(); it != columnsData.end(); it++, rangesIt++) 989 808 { 990 cerr << "An error occurred while reading fits row #" << i << " error code: " << status << endl; 991 break; 809 for (int i=rangesIt->first; i<rangesIt->second; i++) 810 { 811 switch (it->first) { 812 case 'L': 813 str << reinterpret_cast<bool*>(it->second)[i] << " "; 814 break; 815 case 'B': 816 str << reinterpret_cast<char*>(it->second)[i] << " "; 817 break; 818 case 'I': 819 str << reinterpret_cast<int16_t*>(it->second)[i] << " "; 820 break; 821 case 'J': 822 str << reinterpret_cast<int32_t*>(it->second)[i] << " "; 823 break; 824 case 'K': 825 str << reinterpret_cast<int64_t*>(it->second)[i] << " "; 826 break; 827 case 'E': 828 str << reinterpret_cast<float*>(it->second)[i] << " "; 829 break; 830 case 'D': 831 str << reinterpret_cast<double*>(it->second)[i] << " "; 832 break; 833 default: 834 ; 835 } 836 } 992 837 } 993 if (WriteRow(str, columns, offsets, fitsBuffer, ranges)<0) 994 { 995 status=1; 996 cerr << "An Error occured while reading the fits row " << i << endl; 997 return -1; 998 } 999 // yValues[i-1] = i; 838 1000 839 for (auto it=xValues.begin(); it!= xValues.end(); it++) 1001 840 { 1002 841 str >> (*it)[i-1]; 1003 // cout << (*it)[i-1] << " ";1004 842 } 1005 843 if (unixTime) … … 1007 845 long u1, u2; 1008 846 str >> u1 >> u2; 1009 // cout << u1 << " " << u2; 847 1010 848 boost::posix_time::ptime unixTimeT( boost::gregorian::date(1970, boost::gregorian::Jan, 1), 1011 849 boost::posix_time::seconds(u1) + boost::posix_time::microsec(u2)); … … 1013 851 Time mjdTime(unixTimeT); 1014 852 yValues[i-1] = mjdTime.Mjd(); 1015 // cout << " " << mjdTime.Mjd() << endl;1016 853 } 1017 854 else … … 1020 857 if (yValues[i-1] < 40587) 1021 858 yValues[i-1] += 40587; 859 860 Time t(yValues[i-1]); 861 string time = t.GetAsStr("%H:%M:%S%F"); 862 while (time[time.size()-1] == '0' && time.size() > 2) 863 { 864 time = time.substr(0, time.size()-1); 865 } 1022 866 } 1023 867 if (i==1) … … 1027 871 plot->setTitle(title.c_str()); 1028 872 } 1029 // cout << yValues[i-1] << " ";1030 // cout << endl;1031 873 } 1032 874 //set the actual data. 1033 875 auto jt = xValues.begin(); 1034 876 for (auto it=curves.begin(); it != curves.end(); it++, jt++) 1035 (*it)->setRawData(yValues, *jt, endIndex );877 (*it)->setRawData(yValues, *jt, endIndex-1); 1036 878 1037 879 QStack<QRectF> stack; … … 1061 903 zoom.setZoomStack(stack); 1062 904 1063 delete[] fitsBuffer; 905 // delete[] fitsBuffer; 906 for (auto it = columnsData.begin(); it != columnsData.end(); it++) 907 delete[] it->second; 1064 908 window.resize(600, 400); 1065 909 window.show(); … … 1101 945 ("list,l", po_switch(), "List all tables and columns in file") 1102 946 ("header,h", po_switch(), "Dump header of given table") 947 ("stat,s", po_switch(), "Perform statistics instead of dump") 1103 948 #ifdef PLOTTING_PLEASE 1104 949 ("graph,g", po_switch(), "Plot the columns instead of dumping them") 950 ("dots,d", po_switch(), "Plot using dots instead of lines") 1105 951 #endif 1106 952 ;
Note:
See TracChangeset
for help on using the changeset viewer.