Changeset 17687
- Timestamp:
- 04/24/14 15:58:56 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
fact/tools/pyscripts/pyfact/fits.h
r13504 r17687 6 6 #include <map> 7 7 #include <string> 8 #include <fstream> 8 9 #include <sstream> 9 10 #include <algorithm> 10 11 #ifdef __EXCEPTIONS12 11 #include <stdexcept> 13 #endif 14 15 #ifdef __CINT__ 12 13 #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) 14 15 #ifndef __CINT__ 16 #include <unordered_map> 17 #else 16 18 #define off_t size_t 19 namespace std 20 { 21 template<class T, class S> class unordered_map<T, S>; 22 } 17 23 #endif 18 24 … … 21 27 #include <iomanip> 22 28 #include <iostream> 23 #define gLog cerr 24 #define ___err___ "" 25 #define ___all___ "" 29 #ifndef gLog 30 #define gLog std::cerr 31 #define ___err___ "" 32 #define ___warn___ "" 33 #define ___all___ "" 34 #endif 26 35 #else 27 36 #include "MLog.h" 28 37 #include "MLogManip.h" 29 #define ___err___ err 30 #define ___all___ all 38 #define ___err___ err 39 #define ___warn___ warn 40 #define ___all___ all 31 41 #endif 32 42 33 43 #define HAVE_ZLIB 34 #if def HAVE_ZLIB35 #include " izstream.h"44 #if defined(HAVE_ZLIB) || defined(__CINT__) 45 #include "extern_Mars_mcore/izstream.h" 36 46 #else 37 47 #include <fstream> 38 48 #define izstream ifstream 39 //#warning Support for zipped FITS files disabled. 40 #endif 41 42 #warning This file is considered DEPRICATED. Please use pyfits.h instead 43 44 namespace std 45 { 49 #warning Support for zipped FITS files disabled. 50 #endif 51 52 #include "extern_Mars_mcore/checksum.h" 46 53 47 54 class fits : public izstream 48 55 { 49 56 public: 57 //I know I know, you're going to yiell that this does not belong here. 58 //It will belong in the global scope eventually, and it makes the coding of zfits much simpler this way. 59 enum Compression_t 60 { 61 kCompUnknown, 62 kCompFACT 63 }; 64 50 65 struct Entry 51 66 { 52 char type; 53 string value; 54 string comment; 67 char type; 68 std::string value; 69 std::string comment; 70 std::string fitsString; 55 71 56 72 template<typename T> … … 59 75 T t; 60 76 61 istringstream str(value);77 std::istringstream str(value); 62 78 str >> t; 63 79 … … 70 86 off_t offset; 71 87 72 string name; 88 bool is_compressed; 89 90 std::string name; 73 91 size_t bytes_per_row; 74 92 size_t num_rows; 75 93 size_t num_cols; 94 size_t total_bytes; // NAXIS1*NAXIS2 76 95 77 96 struct Column … … 80 99 size_t num; 81 100 size_t size; 101 size_t bytes; // num*size 82 102 char type; 83 string unit; 103 std::string unit; 104 Compression_t comp; 84 105 }; 85 106 86 typedef map<string, Entry> Keys; 87 typedef map<string, Column> Columns; 107 typedef std::map<std::string, Entry> Keys; 108 typedef std::map<std::string, Column> Columns; 109 typedef std::vector<Column> SortedColumns; 88 110 89 111 Columns cols; 112 SortedColumns sorted_cols; 90 113 Keys keys; 91 92 string Trim(const string &str, char c=' ') const 114 115 //------------ vectors containing the same info as cols and keys------ 116 // They are filled at the end of the contstuctor 117 // They are used py python, for retrieving the contents of the maps 118 // I did not find out how to return a map of <string, struct> via ROOT to python 119 // So I use this ugly hack. I guess its no problem, its just ugly 120 // 121 // btw: The way these variables are named, is imho as ugly as possible, 122 // but I will stick to it. 123 // usually a std::map contains key-value pairs 124 // that means the e.g. map<string, Entry> contains keys of type string 125 // and values of type Entry. 126 // but now the map itself was called 'keys', which means one should say: 127 // the keys of 'keys' are of type string 128 // and 129 // the value of 'keys' are of type Entry. 130 // not to forget that: 131 // one field of a value of 'keys' is named 'value' 132 133 // vectors for Keys keys; 134 vector<string> Py_KeyKeys; 135 vector<string> Py_KeyValues; 136 vector<string> Py_KeyComments; 137 vector<char> Py_KeyTypes; 138 139 // vectors for Columns cols; 140 vector<string> Py_ColumnKeys; 141 vector<size_t> Py_ColumnOffsets; 142 vector<size_t> Py_ColumnNums; 143 vector<size_t> Py_ColumnSizes; 144 vector<char> Py_ColumnTypes; 145 vector<string> Py_ColumnUnits; 146 //-end of----- vectors containing the same info as cols and keys------ 147 148 149 int64_t datasum; 150 151 std::string Trim(const std::string &str, char c=' ') const 93 152 { 94 153 // Trim Both leading and trailing spaces … … 97 156 98 157 // if all spaces or empty return an empty string 99 if (st ring::npos==pstart ||string::npos==pend)100 return st ring();158 if (std::string::npos==pstart || std::string::npos==pend) 159 return std::string(); 101 160 102 161 return str.substr(pstart, pend-pstart+1); 103 162 } 104 163 105 bool Check(const st ring &key, char type, conststring &value="") const164 bool Check(const std::string &key, char type, const std::string &value="") const 106 165 { 107 166 const Keys::const_iterator it = keys.find(key); 108 167 if (it==keys.end()) 109 168 { 110 ostringstream str;169 std::ostringstream str; 111 170 str << "Key '" << key << "' not found."; 112 171 #ifdef __EXCEPTIONS 113 throw runtime_error(str.str());114 #else 115 gLog << ___err___ << "ERROR - " << str.str() << endl;172 throw std::runtime_error(str.str()); 173 #else 174 gLog << ___err___ << "ERROR - " << str.str() << std::endl; 116 175 return false; 117 176 #endif … … 120 179 if (it->second.type!=type) 121 180 { 122 ostringstream str;181 std::ostringstream str; 123 182 str << "Wrong type for key '" << key << "': expected " << type << ", found " << it->second.type << "."; 124 183 #ifdef __EXCEPTIONS 125 throw runtime_error(str.str());126 #else 127 gLog << ___err___ << "ERROR - " << str.str() << endl;184 throw std::runtime_error(str.str()); 185 #else 186 gLog << ___err___ << "ERROR - " << str.str() << std::endl; 128 187 return false; 129 188 #endif … … 132 191 if (!value.empty() && it->second.value!=value) 133 192 { 134 ostringstream str;193 std::ostringstream str; 135 194 str << "Wrong value for key '" << key << "': expected " << value << ", found " << it->second.value << "."; 136 195 #ifdef __EXCEPTIONS 137 throw runtime_error(str.str());138 #else 139 gLog << ___err___ << "ERROR - " << str.str() << endl;196 throw std::runtime_error(str.str()); 197 #else 198 gLog << ___err___ << "ERROR - " << str.str() << std::endl; 140 199 return false; 141 200 #endif … … 145 204 } 146 205 147 Keys ParseBlock(const vector<string> &vec) const148 { 149 map<string,Entry> rc;206 Keys ParseBlock(const std::vector<std::string> &vec) const 207 { 208 std::map<std::string,Entry> rc; 150 209 151 210 for (unsigned int i=0; i<vec.size(); i++) 152 211 { 153 const st ring key = Trim(vec[i].substr(0,8));212 const std::string key = Trim(vec[i].substr(0,8)); 154 213 // Keywords without a value, like COMMENT / HISTORY 155 214 if (vec[i].substr(8,2)!="= ") … … 158 217 char type = 0; 159 218 160 string com; 161 string val = Trim(vec[i].substr(10)); 219 std::string com; 220 std::string val = Trim(vec[i].substr(10)); 221 162 222 if (val[0]=='\'') 163 223 { … … 167 227 { 168 228 const size_t pp = val.find_first_of('\'', p); 169 if (pp==st ring::npos)229 if (pp==std::string::npos) 170 230 break; 171 231 … … 177 237 178 238 // Set value, comment and type 179 com = ppp==string::npos ? "" : Trim(val.substr(ppp+1)); 239 // comments could be just spaces. take care of this. 240 if (ppp!=std::string::npos && val.size() != ppp+1) 241 com = Trim(val.substr(ppp+1)); 242 180 243 val = Trim(val.substr(1, p-2)); 181 244 type = 'T'; … … 185 248 const size_t p = val.find_first_of('/'); 186 249 187 com = Trim(val.substr(p+2)); 250 if (val.size() != p+1) 251 com = Trim(val.substr(p+2)); 252 188 253 val = Trim(val.substr(0, p)); 189 254 190 if (val.empty() || val.find_first_of('T')!=st ring::npos || val.find_first_of('F')!=string::npos)255 if (val.empty() || val.find_first_of('T')!=std::string::npos || val.find_first_of('F')!=std::string::npos) 191 256 type = 'B'; 192 257 else 193 type = val.find_last_of('.')==st ring::npos ? 'I' : 'F';258 type = val.find_last_of('.')==std::string::npos ? 'I' : 'F'; 194 259 } 195 260 196 const Entry e = { type, val, com }; 261 const Entry e = { type, val, com, vec[i] }; 262 197 263 rc[key] = e; 198 264 } … … 201 267 } 202 268 203 Table() : offset(0) { } 204 Table(const vector<string> &vec, off_t off) : 205 offset(off), keys(ParseBlock(vec)) 206 { 269 Table() : offset(0), is_compressed(false) { } 270 Table(const std::vector<std::string> &vec, off_t off) : offset(off), 271 keys(ParseBlock(vec)) 272 { 273 is_compressed = HasKey("ZTABLE") && Check("ZTABLE", 'B', "T"); 274 207 275 if (!Check("XTENSION", 'T', "BINTABLE") || 208 276 !Check("NAXIS", 'I', "2") || 209 277 !Check("BITPIX", 'I', "8") || 210 !Check("PCOUNT", 'I', "0") ||211 278 !Check("GCOUNT", 'I', "1") || 212 279 !Check("EXTNAME", 'T') || … … 216 283 return; 217 284 218 bytes_per_row = Get<size_t>("NAXIS1"); 219 num_rows = Get<size_t>("NAXIS2"); 285 if (is_compressed) 286 { 287 if (!Check("ZNAXIS1", 'I') || 288 !Check("ZNAXIS2", 'I') || 289 !Check("ZPCOUNT", 'I', "0")) 290 return; 291 } 292 else 293 { 294 if (!Check("PCOUNT", 'I', "0")) 295 return; 296 } 297 298 total_bytes = Get<size_t>("NAXIS1")*Get<size_t>("NAXIS2"); 299 bytes_per_row = is_compressed ? Get<size_t>("ZNAXIS1") : Get<size_t>("NAXIS1"); 300 num_rows = is_compressed ? Get<size_t>("ZNAXIS2") : Get<size_t>("NAXIS2"); 220 301 num_cols = Get<size_t>("TFIELDS"); 221 302 datasum = is_compressed ? Get<int64_t>("DATASUM", -1) : Get<int64_t>("DATASUM", -1); 303 //cout << "IS COMPRESSED =-========= " << is_compressed << " " << Get<size_t>("NAXIS1") << endl; 222 304 size_t bytes = 0; 223 for (size_t i=1; i<=num_cols; i++) 224 { 225 ostringstream num; 226 num << i; 227 228 if (!Check("TTYPE"+num.str(), 'T') || 229 !Check("TFORM"+num.str(), 'T')) 305 306 const std::string tFormName = is_compressed ? "ZFORM" : "TFORM"; 307 for (long long unsigned int i=1; i<=num_cols; i++) 308 { 309 const std::string num(std::to_string(i)); 310 311 if (!Check("TTYPE"+num, 'T') || 312 !Check(tFormName+num, 'T')) 230 313 return; 231 314 232 const string id = Get<string>("TTYPE"+num.str()); 233 const string fmt = Get<string>("TFORM"+num.str()); 234 const string unit = Get<string>("TUNIT"+num.str(), ""); 235 236 istringstream sin(fmt); 315 const std::string id = Get<std::string>("TTYPE"+num); 316 const std::string fmt = Get<std::string>(tFormName+num); 317 const std::string unit = Get<std::string>("TUNIT"+num, ""); 318 const std::string comp = Get<std::string>("ZCTYP"+num, ""); 319 320 Compression_t compress = kCompUnknown; 321 if (comp == "FACT") 322 compress = kCompFACT; 323 324 std::istringstream sin(fmt); 237 325 int n = 0; 238 326 sin >> n; … … 247 335 // We could use negative values to mark floats 248 336 // otheriwse we could just cast them to int64_t? 249 case 'L': size = 1; break;// logical250 // case 'X': size = n; break; // bits (n=number of bytes needed to contain all bits)337 case 'L': // logical 338 case 'A': // char 251 339 case 'B': size = 1; break; // byte 252 340 case 'I': size = 2; break; // short … … 255 343 case 'E': size = 4; break; // float 256 344 case 'D': size = 8; break; // double 345 // case 'X': size = n; break; // bits (n=number of bytes needed to contain all bits) 257 346 // case 'C': size = 8; break; // complex float 258 347 // case 'M': size = 16; break; // complex double … … 261 350 default: 262 351 { 263 ostringstream str;352 std::ostringstream str; 264 353 str << "FITS format TFORM='" << fmt << "' not yet supported."; 265 354 #ifdef __EXCEPTIONS 266 throw runtime_error(str.str());267 #else 268 gLog << ___err___ << "ERROR - " << str.str() << endl;355 throw std::runtime_error(str.str()); 356 #else 357 gLog << ___err___ << "ERROR - " << str.str() << std::endl; 269 358 return; 270 359 #endif … … 272 361 } 273 362 274 const Table::Column col = { bytes, n, size, type, unit};363 const Table::Column col = { bytes, n, size, n*size, type, unit, compress}; 275 364 276 365 cols[id] = col; 366 sorted_cols.push_back(col); 277 367 bytes += n*size; 278 368 } … … 281 371 { 282 372 #ifdef __EXCEPTIONS 283 throw runtime_error("Column size mismatch");284 #else 285 gLog << ___err___ << "ERROR - Column size mismatch" << endl;373 throw std::runtime_error("Column size mismatch"); 374 #else 375 gLog << ___err___ << "ERROR - Column size mismatch" << std::endl; 286 376 return; 287 377 #endif 288 378 } 289 379 290 name = Get<string>("EXTNAME"); 380 name = Get<std::string>("EXTNAME"); 381 382 Fill_Py_Vectors(); 383 } 384 385 void Fill_Py_Vectors(void) 386 { 387 // Fill the Py_ vectors see line: 90ff 388 // vectors for Keys keys; 389 for (Keys::const_iterator it=keys.begin(); it!=keys.end(); it++) 390 { 391 Py_KeyKeys.push_back(it->first); 392 Py_KeyValues.push_back(it->second.value); 393 Py_KeyComments.push_back(it->second.comment); 394 Py_KeyTypes.push_back(it->second.type); 395 } 396 397 // vectors for Columns cols; 398 for (Columns::const_iterator it=cols.begin(); it!=cols.end(); it++) 399 { 400 Py_ColumnKeys.push_back(it->first); 401 Py_ColumnTypes.push_back(it->second.type); 402 Py_ColumnOffsets.push_back(it->second.offset); 403 Py_ColumnNums.push_back(it->second.num); 404 Py_ColumnSizes.push_back(it->second.size); 405 Py_ColumnUnits.push_back(it->second.unit); 406 } 291 407 } 292 408 293 409 void PrintKeys(bool display_all=false) const 294 410 { 295 for (Keys::const_iterator it=keys. begin(); it!=keys.end(); it++)411 for (Keys::const_iterator it=keys.cbegin(); it!=keys.cend(); it++) 296 412 { 297 413 if (!display_all && … … 308 424 continue; 309 425 310 gLog << ___all___ << s etw(2) << it->second.type << '|' << it->first << '=' << it->second.value << '/' << it->second.comment << '|' <<endl;426 gLog << ___all___ << std::setw(2) << it->second.type << '|' << it->first << '=' << it->second.value << '/' << it->second.comment << '|' << std::endl; 311 427 }} 312 428 313 429 void PrintColumns() const 314 430 { 315 typedef map<pair<size_t,string>, Column> Sorted;431 typedef std::map<std::pair<size_t, std::string>, Column> Sorted; 316 432 317 433 Sorted sorted; 318 434 319 for (Columns::const_iterator it=cols. begin(); it!=cols.end(); it++)320 sorted[ make_pair(it->second.offset, it->first)] = it->second;321 322 for (Sorted::const_iterator it=sorted. begin(); it!=sorted.end(); it++)323 { 324 gLog << ___all___ << s etw(6) << it->second.offset << "| ";435 for (Columns::const_iterator it=cols.cbegin(); it!=cols.cend(); it++) 436 sorted[std::make_pair(it->second.offset, it->first)] = it->second; 437 438 for (Sorted::const_iterator it=sorted.cbegin(); it!=sorted.cend(); it++) 439 { 440 gLog << ___all___ << std::setw(6) << it->second.offset << "| "; 325 441 gLog << it->second.num << 'x'; 326 442 switch (it->second.type) 327 443 { 444 case 'A': gLog << "char(8)"; break; 328 445 case 'L': gLog << "bool(8)"; break; 329 446 case 'B': gLog << "byte(8)"; break; … … 334 451 case 'D': gLog << "double(64)"; break; 335 452 } 336 gLog << ": " << it->first.second << " [" << it->second.unit << "]" << endl;453 gLog << ": " << it->first.second << " [" << it->second.unit << "]" << std::endl; 337 454 } 338 455 } … … 340 457 operator bool() const { return !name.empty(); } 341 458 342 bool HasKey(const st ring &key) const459 bool HasKey(const std::string &key) const 343 460 { 344 461 return keys.find(key)!=keys.end(); 345 462 } 346 463 347 // Values of keys are always signed 464 bool HasColumn(const std::string& col) const 465 { 466 return cols.find(col)!=cols.end(); 467 } 468 469 const Columns &GetColumns() const 470 { 471 return cols; 472 } 473 474 const Keys &GetKeys() const 475 { 476 return keys; 477 } 478 479 // Values of keys are always signed 348 480 template<typename T> 349 T Get(const st ring &key) const350 { 351 const map<string,Entry>::const_iterator it = keys.find(key);481 T Get(const std::string &key) const 482 { 483 const std::map<std::string,Entry>::const_iterator it = keys.find(key); 352 484 if (it==keys.end()) 353 485 { 354 ostringstream str; 355 str << "Key '" << key << "' not found." << endl; 356 #ifdef __EXCEPTIONS 357 throw runtime_error(str.str()); 358 #else 359 gLog << ___err___ << "ERROR - " << str.str() << endl; 486 std::ostringstream str; 487 str << "Key '" << key << "' not found."; 488 #ifdef __EXCEPTIONS 489 throw std::runtime_error(str.str()); 490 #else 491 gLog << ___err___ << "ERROR - " << str.str() << std::endl; 492 return T(); 493 #endif 494 } 495 return it->second.Get<T>(); 496 } 497 498 // Values of keys are always signed 499 template<typename T> 500 T Get(const std::string &key, const T &deflt) const 501 { 502 const std::map<std::string,Entry>::const_iterator it = keys.find(key); 503 return it==keys.end() ? deflt :it->second.Get<T>(); 504 } 505 506 size_t GetN(const std::string &key) const 507 { 508 const Columns::const_iterator it = cols.find(key); 509 return it==cols.end() ? 0 : it->second.num; 510 } 511 512 513 514 // There may be a gap between the main table and the start of the heap: 515 // this computes the offset 516 streamoff GetHeapShift() const 517 { 518 if (!HasKey("ZHEAPPTR")) 360 519 return 0; 361 #endif 362 } 363 return it->second.Get<T>(); 364 } 365 366 // Values of keys are always signed 367 template<typename T> 368 T Get(const string &key, const string &deflt) const 369 { 370 const map<string,Entry>::const_iterator it = keys.find(key); 371 return it==keys.end() ? deflt :it->second.Get<T>(); 372 } 373 374 size_t GetN(const string &key) const 375 { 376 const Columns::const_iterator it = cols.find(key); 377 if (it==cols.end()){ 378 ostringstream str; 379 str << "Key '" << key << "' not found." << endl; 380 str << "Possible keys are:" << endl; 381 for ( Columns::const_iterator it=cols.begin() ; it != cols.end(); ++it){ 382 str << it->first << endl; 383 } 384 #ifdef __EXCEPTIONS 385 throw runtime_error(str.str()); 386 #else 387 gLog << ___err___ << "ERROR - " << str.str() << endl; 388 return 0; 389 #endif 390 } 391 return it==cols.end() ? 0 : it->second.num; 520 521 const size_t shift = Get<size_t>("ZHEAPPTR"); 522 return shift <= total_bytes ? 0 : shift - total_bytes; 523 } 524 525 // return total number of bytes 'all inclusive' 526 streamoff GetTotalBytes() const 527 { 528 //get offset of special data area from start of main table 529 const streamoff shift = GetHeapShift(); 530 531 //and special data area size 532 const streamoff size = HasKey("PCOUNT") ? Get<streamoff>("PCOUNT") : 0; 533 534 // Get the total size 535 const streamoff total = total_bytes + size + shift; 536 537 // check for padding 538 if (total%2880==0) 539 return total; 540 541 // padding necessary 542 return total + (2880 - (total%2880)); 392 543 } 393 544 }; 394 545 395 private: 546 protected: 547 std::ofstream fCopy; 548 std::vector<std::string> fListOfTables; // List of skipped tables. Last table is open table 549 396 550 Table fTable; 397 551 398 typedef pair<void*, Table::Column> Address;399 typedef vector<Address> Addresses;552 typedef std::pair<void*, Table::Column> Address; 553 typedef std::vector<Address> Addresses; 400 554 //map<void*, Table::Column> fAddresses; 401 555 Addresses fAddresses; 402 556 403 vector<char> fBufferRow; 404 vector<char> fBufferDat; 557 typedef std::unordered_map<std::string, void*> Pointers; 558 Pointers fPointers; 559 560 std::vector<std::vector<char>> fGarbage; 561 562 std::vector<char> fBufferRow; 563 std::vector<char> fBufferDat; 405 564 406 565 size_t fRow; 407 566 408 vector<string> ReadBlock(vector<string> &vec) 409 { 410 bool endtag = false; 567 Checksum fChkHeader; 568 Checksum fChkData; 569 570 bool ReadBlock(std::vector<std::string> &vec) 571 { 572 int endtag = 0; 411 573 for (int i=0; i<36; i++) 412 574 { … … 417 579 break; 418 580 419 if (c[0]==0) 420 return vector<string>(); 421 422 string str(c); 581 fChkHeader.add(c, 80); 582 583 // if (c[0]==0) 584 // return vector<string>(); 585 586 std::string str(c); 423 587 424 588 // if (!str.empty()) 425 589 // cout << setw(2) << i << "|" << str << "|" << (endtag?'-':'+') << endl; 426 590 427 if (str=="END ") 428 { 429 endtag = true; 430 431 // Make sure that no empty vector is returned 432 if (vec.size()%36==0) 433 vec.push_back(string("END = '' / ")); 434 } 435 436 if (endtag) 591 if (endtag==2 || str=="END ") 592 { 593 endtag = 2; // valid END tag found 437 594 continue; 595 } 596 597 if (endtag==1 || str==" ") 598 { 599 endtag = 1; // end tag not found, but expected to be there 600 continue; 601 } 438 602 439 603 vec.push_back(str); 440 604 } 441 605 442 return vec; 443 } 444 445 string Compile(const string &key, int16_t i=-1) 446 { 447 if (i<0) 448 return key; 449 450 ostringstream str; 451 str << key << i; 452 return str.str(); 453 } 454 455 public: 456 fits(const string &fname) : izstream(fname.c_str()) 606 // Make sure that no empty vector is returned 607 if (endtag && vec.size()%36==0) 608 vec.emplace_back("END = '' / "); 609 610 return endtag==2; 611 } 612 613 std::string Compile(const std::string &key, int16_t i=-1) const 614 { 615 #if GCC_VERSION < 40603 616 return i<0 ? key : key+std::to_string((long long int)(i)); 617 #else 618 return i<0 ? key : key+std::to_string(i); 619 #endif 620 } 621 622 void Constructor(const std::string &fname, std::string fout="", const std::string& tableName="", bool force=false) 457 623 { 458 624 char simple[10]; … … 463 629 if (memcmp(simple, "SIMPLE = ", 10)) 464 630 { 465 clear(rdstate()| ios::badbit);466 #ifdef __EXCEPTIONS 467 throw runtime_error("File is not a FITS file.");468 #else 469 gLog << ___err___ << "ERROR - File is not a FITS file." << endl;631 clear(rdstate()|std::ios::badbit); 632 #ifdef __EXCEPTIONS 633 throw std::runtime_error("File is not a FITS file."); 634 #else 635 gLog << ___err___ << "ERROR - File is not a FITS file." << std::endl; 470 636 return; 471 637 #endif … … 476 642 while (good()) 477 643 { 478 vector<string> block;644 std::vector<std::string> block; 479 645 while (1) 480 646 { 647 // If we search for a table, we implicitly assume that 648 // not finding the table is not an error. The user 649 // can easily check that by eof() && !bad() 650 peek(); 651 if (eof() && !bad() && !tableName.empty()) 652 { 653 break; 654 } 481 655 // FIXME: Set limit on memory consumption 482 ReadBlock(block);656 const int rc = ReadBlock(block); 483 657 if (!good()) 484 658 { 485 clear(rdstate()| ios::badbit);486 #ifdef __EXCEPTIONS 487 throw runtime_error("FITS file corrupted.");488 #else 489 gLog << ___err___ << "ERROR - FITS file corrupted." << endl;659 clear(rdstate()|std::ios::badbit); 660 #ifdef __EXCEPTIONS 661 throw std::runtime_error("FITS file corrupted."); 662 #else 663 gLog << ___err___ << "ERROR - FITS file corrupted." << std::endl; 490 664 return; 491 665 #endif … … 493 667 494 668 if (block.size()%36) 669 { 670 if (!rc && !force) 671 { 672 clear(rdstate()|std::ios::badbit); 673 #ifdef __EXCEPTIONS 674 throw std::runtime_error("END keyword missing in FITS header."); 675 #else 676 gLog << ___err___ << "ERROR - END keyword missing in FITS file... file might be corrupted." << std::endl; 677 return; 678 #endif 679 } 495 680 break; 496 } 497 498 if (block.size()==0) 681 } 682 } 683 684 if (block.empty()) 499 685 break; 500 686 501 687 if (block[0].substr(0, 9)=="SIMPLE =") 688 { 689 fChkHeader.reset(); 502 690 continue; 691 } 503 692 504 693 if (block[0].substr(0, 9)=="XTENSION=") 505 694 { 506 // FIXME: Check for table name507 508 695 fTable = Table(block, tellg()); 509 696 fRow = (size_t)-1; 510 697 511 //fTable.PrintKeys();512 513 698 if (!fTable) 514 699 { 515 clear(rdstate()| ios::badbit);700 clear(rdstate()|std::ios::badbit); 516 701 return; 517 702 } 518 703 519 fBufferRow.resize(fTable.bytes_per_row); 704 const std::string &tname = fTable.Get<std::string>("EXTNAME"); 705 706 fListOfTables.emplace_back(tname); 707 708 // Check for table name. Skip until eof or requested table are found. 709 // skip the current table? 710 if ((!tableName.empty() && tableName!=tname) || (tableName.empty() && "ZDrsCellOffsets"==tname)) 711 { 712 const streamoff skip = fTable.GetTotalBytes(); 713 seekg(skip, std::ios_base::cur); 714 715 fChkHeader.reset(); 716 717 continue; 718 } 719 720 fBufferRow.resize(fTable.bytes_per_row + 8-fTable.bytes_per_row%4); 520 721 fBufferDat.resize(fTable.bytes_per_row); 521 722 522 /*523 // Next table should start at:524 const size_t size = fTable.bytes_per_row*fTable.num_rows;525 const size_t blks = size/(36*80);526 const size_t rest = size%(36*80);527 528 seekg((blks+(rest>0?1:0))*(36*80), ios::cur);529 if (!good())530 gLog << ___err___ << "File seems to be incomplete (less data than expected from header)." << endl;531 532 fRow = fTable.num_rows;533 */534 535 723 break; 536 724 } 537 725 } 538 } 539 540 void ReadRow(size_t row) 726 727 if (fout.empty()) 728 return; 729 730 if (*fout.rbegin()=='/') 731 { 732 const size_t p = fname.find_last_of('/'); 733 fout.append(fname.substr(p+1)); 734 } 735 736 fCopy.open(fout); 737 if (!fCopy) 738 { 739 clear(rdstate()|std::ios::badbit); 740 #ifdef __EXCEPTIONS 741 throw std::runtime_error("Could not open output file."); 742 #else 743 gLog << ___err___ << "ERROR - Failed to open output file." << std::endl; 744 return; 745 #endif 746 } 747 748 const streampos p = tellg(); 749 seekg(0); 750 751 std::vector<char> buf(p); 752 read(buf.data(), p); 753 754 fCopy.write(buf.data(), p); 755 if (!fCopy) 756 clear(rdstate()|std::ios::badbit); 757 } 758 759 public: 760 fits(const std::string &fname, const std::string& tableName="", bool force=false) : izstream(fname.c_str()) 761 { 762 Constructor(fname, "", tableName, force); 763 if ((fTable.is_compressed ||fTable.name=="ZDrsCellOffsets") && !force) 764 { 765 #ifdef __EXCEPTIONS 766 throw std::runtime_error("You are trying to read a compressed fits with the base fits class. Please use factfits instead."); 767 #else 768 gLog << ___err___ << "ERROR - You are trying to read a compressed fits with the base fits class. Please use factfits instead." << std::endl; 769 #endif 770 clear(rdstate()|std::ios::badbit); 771 } 772 } 773 774 fits(const std::string &fname, const std::string &fout, const std::string& tableName, bool force=false) : izstream(fname.c_str()) 775 { 776 Constructor(fname, fout, tableName, force); 777 if ((fTable.is_compressed || fTable.name=="ZDrsCellOffsets") && !force) 778 { 779 #ifdef __EXCEPTIONS 780 throw std::runtime_error("You are trying to read a compressed fits with the base fits class. Please use factfits instead."); 781 #else 782 gLog << ___err___ << "ERROR - You are trying to read a compressed fits with the base fits class. Please use factfits instead." << std::endl; 783 #endif 784 clear(rdstate()|std::ios::badbit); 785 } 786 } 787 788 fits() : izstream() 789 { 790 791 } 792 793 ~fits() 794 { 795 std::copy(std::istreambuf_iterator<char>(*this), 796 std::istreambuf_iterator<char>(), 797 std::ostreambuf_iterator<char>(fCopy)); 798 } 799 800 virtual void StageRow(size_t row, char* dest) 541 801 { 542 802 // if (row!=fRow+1) // Fast seeking is ensured by izstream 543 803 seekg(fTable.offset+row*fTable.bytes_per_row); 804 read(dest, fTable.bytes_per_row); 805 //fin.clear(fin.rdstate()&~ios::eofbit); 806 } 807 808 virtual void WriteRowToCopyFile(size_t row) 809 { 810 if (row==fRow+1) 811 { 812 const uint8_t offset = (row*fTable.bytes_per_row)%4; 813 814 fChkData.add(fBufferRow); 815 if (fCopy.is_open() && fCopy.good()) 816 fCopy.write(fBufferRow.data()+offset, fTable.bytes_per_row); 817 if (!fCopy) 818 clear(rdstate()|std::ios::badbit); 819 } 820 else 821 if (fCopy.is_open()) 822 clear(rdstate()|std::ios::badbit); 823 } 824 825 void ZeroBufferForChecksum(std::vector<char>& vec, const uint64_t extraZeros=0) 826 { 827 auto ib = vec.begin(); 828 auto ie = vec.end(); 829 830 *ib++ = 0; 831 *ib++ = 0; 832 *ib++ = 0; 833 *ib = 0; 834 835 for (uint64_t i=0;i<extraZeros+8;i++) 836 *--ie = 0; 837 } 838 839 uint8_t ReadRow(size_t row) 840 { 841 // For the checksum we need everything to be correctly aligned 842 const uint8_t offset = (row*fTable.bytes_per_row)%4; 843 844 ZeroBufferForChecksum(fBufferRow); 845 846 StageRow(row, fBufferRow.data()+offset); 847 848 WriteRowToCopyFile(row); 544 849 545 850 fRow = row; 546 851 547 read(fBufferRow.data(), fBufferRow.size()); 548 //fin.clear(fin.rdstate()&~ios::eofbit); 852 return offset; 549 853 } 550 854 551 855 template<size_t N> 552 void revcpy(char *dest, const char *src, intnum)856 void revcpy(char *dest, const char *src, const int &num) 553 857 { 554 858 const char *pend = src + num*N; 555 859 for (const char *ptr = src; ptr<pend; ptr+=N, dest+=N) 556 reverse_copy(ptr, ptr+N, dest); 557 } 558 559 bool GetRow(size_t row) 560 { 561 ReadRow(row); 860 std::reverse_copy(ptr, ptr+N, dest); 861 } 862 863 virtual void MoveColumnDataToUserSpace(char *dest, const char *src, const Table::Column& c) 864 { 865 // Let the compiler do some optimization by 866 // knowing that we only have 1, 2, 4 and 8 867 switch (c.size) 868 { 869 case 1: memcpy (dest, src, c.bytes); break; 870 case 2: revcpy<2>(dest, src, c.num); break; 871 case 4: revcpy<4>(dest, src, c.num); break; 872 case 8: revcpy<8>(dest, src, c.num); break; 873 } 874 } 875 876 virtual bool GetRow(size_t row, bool check=true) 877 { 878 if (check && row>=fTable.num_rows) 879 return false; 880 881 const uint8_t offset = ReadRow(row); 562 882 if (!good()) 563 883 return good(); 564 884 565 for (Addresses::const_iterator it=fAddresses.begin(); it!=fAddresses.end(); it++) 885 const char *ptr = fBufferRow.data() + offset; 886 887 for (Addresses::const_iterator it=fAddresses.cbegin(); it!=fAddresses.cend(); it++) 566 888 { 567 889 const Table::Column &c = it->second; 568 890 569 const char *src = fBufferRow.data()+ c.offset;891 const char *src = ptr + c.offset; 570 892 char *dest = reinterpret_cast<char*>(it->first); 571 893 572 // Let the compiler do some optimization by 573 // knowing the we only have 1, 2, 4 and 8 574 switch (c.size) 575 { 576 case 1: memcpy (dest, src, c.num*c.size); break; 577 case 2: revcpy<2>(dest, src, c.num); break; 578 case 4: revcpy<4>(dest, src, c.num); break; 579 case 8: revcpy<8>(dest, src, c.num); break; 580 } 894 MoveColumnDataToUserSpace(dest, src, c); 581 895 } 582 896 … … 584 898 } 585 899 586 bool GetNextRow( )587 { 588 return GetRow(fRow+1 );589 } 590 591 bool SkipNextRow()900 bool GetNextRow(bool check=true) 901 { 902 return GetRow(fRow+1, check); 903 } 904 905 virtual bool SkipNextRow() 592 906 { 593 907 seekg(fTable.offset+(++fRow)*fTable.bytes_per_row); … … 600 914 } 601 915 916 template<class T, class S> 917 const T &GetAs(const std::string &name) 918 { 919 return *reinterpret_cast<S*>(fPointers[name]); 920 } 921 922 void *SetPtrAddress(const std::string &name) 923 { 924 if (fTable.cols.count(name)==0) 925 { 926 std::ostringstream str; 927 str << "SetPtrAddress('" << name << "') - Column not found."; 928 #ifdef __EXCEPTIONS 929 throw std::runtime_error(str.str()); 930 #else 931 gLog << ___err___ << "ERROR - " << str.str() << std::endl; 932 return NULL; 933 #endif 934 } 935 936 Pointers::const_iterator it = fPointers.find(name); 937 if (it!=fPointers.end()) 938 return it->second; 939 940 fGarbage.emplace_back(fTable.cols[name].bytes); 941 942 void *ptr = fGarbage.back().data(); 943 944 fPointers[name] = ptr; 945 fAddresses.emplace_back(ptr, fTable.cols[name]); 946 sort(fAddresses.begin(), fAddresses.end(), Compare); 947 return ptr; 948 } 949 602 950 template<typename T> 603 bool SetPtrAddress(const st ring &name, T *ptr, size_t cnt)951 bool SetPtrAddress(const std::string &name, T *ptr, size_t cnt) 604 952 { 605 953 if (fTable.cols.count(name)==0) 606 954 { 607 ostringstream str;608 str << "SetPtrAddress('" << name << "') - Column not found." << endl;609 #ifdef __EXCEPTIONS 610 throw runtime_error(str.str());611 #else 612 gLog << ___err___ << "ERROR - " << str.str() << endl;955 std::ostringstream str; 956 str << "SetPtrAddress('" << name << "') - Column not found."; 957 #ifdef __EXCEPTIONS 958 throw std::runtime_error(str.str()); 959 #else 960 gLog << ___err___ << "ERROR - " << str.str() << std::endl; 613 961 return false; 614 962 #endif … … 617 965 if (sizeof(T)!=fTable.cols[name].size) 618 966 { 619 ostringstream str;967 std::ostringstream str; 620 968 str << "SetPtrAddress('" << name << "') - Element size mismatch: expected " 621 << fTable.cols[name].size << " from header, got " << sizeof(T) << endl;622 #ifdef __EXCEPTIONS 623 throw runtime_error(str.str());624 #else 625 gLog << ___err___ << "ERROR - " << str.str() << endl;969 << fTable.cols[name].size << " from header, got " << sizeof(T); 970 #ifdef __EXCEPTIONS 971 throw std::runtime_error(str.str()); 972 #else 973 gLog << ___err___ << "ERROR - " << str.str() << std::endl; 626 974 return false; 627 975 #endif … … 630 978 if (cnt!=fTable.cols[name].num) 631 979 { 632 ostringstream str;980 std::ostringstream str; 633 981 str << "SetPtrAddress('" << name << "') - Element count mismatch: expected " 634 << fTable.cols[name].num << " from header, got " << cnt << endl;635 #ifdef __EXCEPTIONS 636 throw runtime_error(str.str());637 #else 638 gLog << ___err___ << "ERROR - " << str.str() << endl;982 << fTable.cols[name].num << " from header, got " << cnt; 983 #ifdef __EXCEPTIONS 984 throw std::runtime_error(str.str()); 985 #else 986 gLog << ___err___ << "ERROR - " << str.str() << std::endl; 639 987 return false; 640 988 #endif … … 645 993 646 994 //fAddresses[ptr] = fTable.cols[name]; 647 fAddresses.push_back(make_pair(ptr, fTable.cols[name])); 995 fPointers[name] = ptr; 996 fAddresses.emplace_back(ptr, fTable.cols[name]); 648 997 sort(fAddresses.begin(), fAddresses.end(), Compare); 649 998 return true; … … 651 1000 652 1001 template<class T> 653 bool SetRefAddress(const st ring &name, T &ptr)1002 bool SetRefAddress(const std::string &name, T &ptr) 654 1003 { 655 1004 return SetPtrAddress(name, &ptr, sizeof(ptr)/sizeof(T)); … … 657 1006 658 1007 template<typename T> 659 bool SetVecAddress(const st ring &name,vector<T> &vec)1008 bool SetVecAddress(const std::string &name, std::vector<T> &vec) 660 1009 { 661 1010 return SetPtrAddress(name, vec.data(), vec.size()); … … 663 1012 664 1013 template<typename T> 665 T Get(const st ring &key) const1014 T Get(const std::string &key) const 666 1015 { 667 1016 return fTable.Get<T>(key); … … 669 1018 670 1019 template<typename T> 671 T Get(const st ring &key, conststring &deflt) const1020 T Get(const std::string &key, const std::string &deflt) const 672 1021 { 673 1022 return fTable.Get<T>(key, deflt); 674 1023 } 675 1024 676 bool SetPtrAddress(const st ring &name, void *ptr)1025 bool SetPtrAddress(const std::string &name, void *ptr, size_t cnt=0) 677 1026 { 678 1027 if (fTable.cols.count(name)==0) 679 1028 { 680 ostringstream str; 681 str <<"SetPtrAddress('" << name << "') - Column not found." << endl; 682 #ifdef __EXCEPTIONS 683 throw runtime_error(str.str()); 684 #else 685 gLog << ___err___ << "ERROR - " << str.str() << endl; 1029 std::ostringstream str; 1030 str <<"SetPtrAddress('" << name << "') - Column not found."; 1031 #ifdef __EXCEPTIONS 1032 throw std::runtime_error(str.str()); 1033 #else 1034 gLog << ___err___ << "ERROR - " << str.str() << std::endl; 1035 return false; 1036 #endif 1037 } 1038 1039 if (cnt && cnt!=fTable.cols[name].num) 1040 { 1041 std::ostringstream str; 1042 str << "SetPtrAddress('" << name << "') - Element count mismatch: expected " 1043 << fTable.cols[name].num << " from header, got " << cnt; 1044 #ifdef __EXCEPTIONS 1045 throw std::runtime_error(str.str()); 1046 #else 1047 gLog << ___err___ << "ERROR - " << str.str() << std::endl; 686 1048 return false; 687 1049 #endif … … 692 1054 693 1055 //fAddresses[ptr] = fTable.cols[name]; 694 fAddresses.push_back(make_pair(ptr, fTable.cols[name])); 1056 fPointers[name] = ptr; 1057 fAddresses.emplace_back(ptr, fTable.cols[name]); 695 1058 sort(fAddresses.begin(), fAddresses.end(), Compare); 696 1059 return true; 697 1060 } 698 1061 699 bool HasKey(const string &key) const { return fTable.HasKey(key); } 700 int64_t GetInt(const string &key) const { return fTable.Get<int64_t>(key); } 701 uint64_t GetUInt(const string &key) const { return fTable.Get<uint64_t>(key); } 702 double GetFloat(const string &key) const { return fTable.Get<double>(key); } 703 string GetStr(const string &key) const { return fTable.Get<string>(key); } 704 705 size_t GetN(const string &key) const 1062 bool HasKey(const std::string &key) const { return fTable.HasKey(key); } 1063 bool HasColumn(const std::string& col) const { return fTable.HasColumn(col);} 1064 const Table::Columns &GetColumns() const { return fTable.GetColumns();} 1065 const Table::SortedColumns& GetSortedColumns() const { return fTable.sorted_cols;} 1066 const Table::Keys &GetKeys() const { return fTable.GetKeys();} 1067 1068 int64_t GetInt(const std::string &key) const { return fTable.Get<int64_t>(key); } 1069 uint64_t GetUInt(const std::string &key) const { return fTable.Get<uint64_t>(key); } 1070 double GetFloat(const std::string &key) const { return fTable.Get<double>(key); } 1071 std::string GetStr(const std::string &key) const { return fTable.Get<std::string>(key); } 1072 1073 size_t GetN(const std::string &key) const 706 1074 { 707 1075 return fTable.GetN(key); 708 1076 } 709 1077 710 size_t GetNumRows() const { return fTable.num_rows; }711 size_t GetRow() const { return fRow ; }1078 // size_t GetNumRows() const { return fTable.num_rows; } 1079 size_t GetRow() const { return fRow==(size_t)-1 ? 0 : fRow; } 712 1080 713 1081 operator bool() const { return fTable && fTable.offset!=0; } … … 715 1083 void PrintKeys() const { fTable.PrintKeys(); } 716 1084 void PrintColumns() const { fTable.PrintColumns(); } 1085 1086 // 'Wrappers' for the Table's Getters of the Py Vectors 1087 vector<string> GetPy_KeyKeys() {return fTable.Py_KeyKeys; } 1088 vector<string> GetPy_KeyValues() {return fTable.Py_KeyValues; } 1089 vector<string> GetPy_KeyComments() {return fTable.Py_KeyComments; } 1090 vector<char> GetPy_KeyTypes() {return fTable.Py_KeyTypes; } 1091 1092 vector<string> GetPy_ColumnKeys() {return fTable.Py_ColumnKeys; } 1093 vector<size_t> GetPy_ColumnOffsets() {return fTable.Py_ColumnOffsets; } 1094 vector<size_t> GetPy_ColumnNums() {return fTable.Py_ColumnNums; } 1095 vector<size_t> GetPy_ColumnSizes() {return fTable.Py_ColumnSizes;} 1096 vector<char> GetPy_ColumnTypes() {return fTable.Py_ColumnTypes;} 1097 vector<string> GetPy_ColumnUnits() {return fTable.Py_ColumnUnits;} 1098 1099 bool IsHeaderOk() const { return fTable.datasum<0?false:(fChkHeader+Checksum(fTable.datasum)).valid(); } 1100 virtual bool IsFileOk() const { return (fChkHeader+fChkData).valid(); } 1101 1102 bool IsCompressedFITS() const { return fTable.is_compressed;} 1103 1104 virtual size_t GetNumRows() const 1105 { 1106 return fTable.Get<size_t>("NAXIS2"); 1107 } 1108 1109 virtual size_t GetBytesPerRow() const 1110 { 1111 return fTable.Get<size_t>("NAXIS1"); 1112 } 1113 1114 const std::vector<std::string> &GetTables() const 1115 { 1116 return fListOfTables; 1117 } 717 1118 }; 718 1119 719 }; 720 #endif 1120 #endif
Note:
See TracChangeset
for help on using the changeset viewer.