- Timestamp:
- 05/27/13 01:26:35 (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Mars/mcore/fits.h
r15364 r16284 69 69 { 70 70 public: 71 //I know I know, you're going to yiell that this does not belong here. 72 //It will belong in the global scope eventually, and it makes the coding of zfits much simpler this way. 73 typedef enum 74 { 75 UNCOMPRESSED, 76 SMOOTHMAN 77 } FitsCompression; 78 71 79 struct Entry 72 80 { … … 74 82 string value; 75 83 string comment; 84 string fitsString; 76 85 77 86 template<typename T> … … 90 99 { 91 100 off_t offset; 101 102 bool isCompressed; 92 103 93 104 string name; … … 103 114 char type; 104 115 string unit; 116 FitsCompression comp; 105 117 }; 106 118 107 119 typedef map<string, Entry> Keys; 108 120 typedef map<string, Column> Columns; 121 typedef vector<Column> SortedColumns; 109 122 110 123 Columns cols; 124 SortedColumns sortedCols; 111 125 Keys keys; 112 126 … … 200 214 201 215 // Set value, comment and type 202 com = ppp==string::npos ? "" : Trim(val.substr(ppp+1)); 216 if (ppp==string::npos) 217 com = ""; 218 else 219 {// comments could be just spaces. take care of this. 220 if (val.size() == ppp+1) 221 com = ""; 222 else 223 com = Trim(val.substr(ppp+1)); 224 } 225 // com = ppp==string::npos ? "" : Trim(val.substr(ppp+1)); 203 226 val = Trim(val.substr(1, p-2)); 204 227 type = 'T'; … … 208 231 const size_t p = val.find_first_of('/'); 209 232 210 com = Trim(val.substr(p+2)); 233 if (val.size() == p+1) 234 com = ""; 235 else 236 com = Trim(val.substr(p+2)); 211 237 val = Trim(val.substr(0, p)); 212 238 … … 217 243 } 218 244 219 const Entry e = { type, val, com };245 const Entry e = { type, val, com, vec[i] }; 220 246 rc[key] = e; 221 247 } … … 226 252 Table() : offset(0) { } 227 253 Table(const vector<string> &vec, off_t off) : 228 offset(off), keys(ParseBlock(vec)) 229 { 254 offset(off), isCompressed(false), keys(ParseBlock(vec)) 255 { 256 if (HasKey("ZTABLE")) 257 if (Check("ZTABLE", 'B', "T")) 258 { 259 isCompressed = true; 260 } 261 230 262 if (!Check("XTENSION", 'T', "BINTABLE") || 231 263 !Check("NAXIS", 'I', "2") || 232 264 !Check("BITPIX", 'I', "8") || 233 !Check("PCOUNT", 'I', "0") ||234 265 !Check("GCOUNT", 'I', "1") || 235 266 !Check("EXTNAME", 'T') || … … 239 270 return; 240 271 241 bytes_per_row = Get<size_t>("NAXIS1"); 242 num_rows = Get<size_t>("NAXIS2"); 272 if (isCompressed) 273 { 274 if (!Check("ZPCOUNT", 'I', "0")) 275 return; 276 } 277 else 278 { 279 if (!Check("PCOUNT", 'I', "0")) 280 return; 281 } 282 283 bytes_per_row = isCompressed ? Get<size_t>("ZNAXIS1") : Get<size_t>("NAXIS1"); 284 num_rows = isCompressed ? Get<size_t>("ZNAXIS2") : Get<size_t>("NAXIS2"); 243 285 num_cols = Get<size_t>("TFIELDS"); 244 datasum = Get<int64_t>("DATASUM", -1);286 datasum = isCompressed ? Get<int64_t>("ZDATASUM", -1) : Get<int64_t>("DATASUM", -1); 245 287 246 288 size_t bytes = 0; 289 string tFormName = isCompressed ? "ZFORM" : "TFORM"; 247 290 for (size_t i=1; i<=num_cols; i++) 248 291 { … … 251 294 252 295 if (!Check("TTYPE"+num.str(), 'T') || 253 !Check( "TFORM"+num.str(), 'T'))296 !Check(tFormName+num.str(), 'T')) 254 297 return; 255 298 256 299 const string id = Get<string>("TTYPE"+num.str()); 257 const string fmt = Get<string>( "TFORM"+num.str());300 const string fmt = Get<string>(tFormName+num.str()); 258 301 const string unit = Get<string>("TUNIT"+num.str(), ""); 302 const string comp = Get<string>("ZCTYP"+num.str(), ""); 303 304 FitsCompression compress = UNCOMPRESSED; 305 if (comp == "SMOO") 306 compress = SMOOTHMAN; 259 307 260 308 istringstream sin(fmt); … … 297 345 } 298 346 299 const Table::Column col = { bytes, n, size, type, unit 347 const Table::Column col = { bytes, n, size, type, unit, compress}; 300 348 301 349 cols[id] = col; 350 sortedCols.push_back(col); 302 351 bytes += n*size; 303 352 } … … 420 469 }; 421 470 422 pr ivate:471 protected: 423 472 ofstream fCopy; 424 473 … … 500 549 } 501 550 502 void Constructor(const string &fname, string fout, bool force) 551 //There may be a gap between the main table and the start of the heap: this computes the offset 552 size_t ComputeGapFromDataToHeap(const Table& table) 553 { 554 //get row width 555 const size_t rowWidth = table.Get<size_t>("NAXIS1"); 556 const size_t numRows = table.Get<size_t>("NAXIS2"); 557 558 //get offset of special data area from start of main table 559 size_t heapShift = HasKey("THEAP") ? table.Get<size_t>("THEAP") : 0; 560 if (heapShift > rowWidth*numRows) 561 heapShift -= rowWidth*numRows; 562 else 563 heapShift = 0; 564 565 return heapShift; 566 } 567 568 //skip the current table 569 bool SkipCurrentTable(const vector<string>& vector) 570 { 571 Table currentTable(vector, tellg()); 572 //get row width 573 const size_t rowWidth = currentTable.Get<size_t>("NAXIS1"); 574 const size_t numRows = currentTable.Get<size_t>("NAXIS2"); 575 576 //get offset of special data area from start of main table 577 const off_t heapShift = ComputeGapFromDataToHeap(currentTable); 578 579 //and special data area size 580 const off_t heapSize = HasKey("PCOUNT") ? currentTable.Get<size_t>("PCOUNT") : 0; 581 582 //skip the row of the table, padded to 2880 bytes 583 off_t paddingSize = (rowWidth*numRows + heapSize + heapShift)%2880; 584 paddingSize += (paddingSize==0) ? 0 : 2880 - paddingSize; 585 586 const off_t whereDoIGo = tellg() + (off_t)(rowWidth*numRows) + heapSize + heapShift + paddingSize; 587 seekg(whereDoIGo); 588 589 return good(); 590 } 591 592 void Constructor(const string &fname, string fout, const string& tableName, bool force, bool mightFail) 503 593 { 504 594 char simple[10]; … … 529 619 if (!good()) 530 620 { 621 //we allow that the table is not found (to be checked later on with bool casting) 622 if (mightFail) { return;} 623 531 624 clear(rdstate()|ios::badbit); 532 625 #ifdef __EXCEPTIONS … … 565 658 if (block[0].substr(0, 9)=="XTENSION=") 566 659 { 567 // FIXME: Check for table name 568 660 //Check for table name. Skip until eof or requested table are found. 661 if (tableName != "") 662 { 663 Table currentTable(block, tellg()); 664 string currentName = currentTable.Get<string>("EXTNAME"); 665 if (currentName != tableName) 666 { 667 SkipCurrentTable(block); 668 fChkHeader.reset(); 669 continue; 670 } 671 } 569 672 fTable = Table(block, tellg()); 570 673 fRow = (size_t)-1; … … 630 733 631 734 public: 632 fits(const string &fname, bool force=false) : izstream(fname.c_str())633 { 634 Constructor(fname, "", force);635 } 636 637 fits(const string &fname, const string &fout, bool force=false) : izstream(fname.c_str())638 { 639 Constructor(fname, fout, force);735 fits(const string &fname, const string& tableName="", bool force=false, bool mightFail=false) : izstream(fname.c_str()) 736 { 737 Constructor(fname, "", tableName, force, mightFail); 738 } 739 740 fits(const string &fname, const string &fout, const string& tableName="", bool force=false, bool mightFail=false) : izstream(fname.c_str()) 741 { 742 Constructor(fname, fout, tableName, force, mightFail); 640 743 } 641 744 … … 647 750 } 648 751 649 uint8_t ReadRow(size_t row)752 virtual void StageRow(size_t row, char* dest) 650 753 { 651 754 // if (row!=fRow+1) // Fast seeking is ensured by izstream 652 755 seekg(fTable.offset+row*fTable.bytes_per_row); 653 756 read(dest, fTable.bytes_per_row); 757 //fin.clear(fin.rdstate()&~ios::eofbit); 758 } 759 760 uint8_t ReadRow(size_t row) 761 { 654 762 // For the checksum we need everything to be correctly aligned 655 763 const uint8_t offset = (row*fTable.bytes_per_row)%4; … … 671 779 *--ie = 0; 672 780 673 read(fBufferRow.data()+offset, fTable.bytes_per_row); 674 //fin.clear(fin.rdstate()&~ios::eofbit); 781 StageRow(row, fBufferRow.data()+offset); 675 782 676 783 if (row==fRow+1) … … 699 806 } 700 807 808 virtual void MoveColumnDataToUserSpace(char* dest, const char*src, const Table::Column& c) 809 { 810 // Let the compiler do some optimization by 811 // knowing that we only have 1, 2, 4 and 8 812 switch (c.size) 813 { 814 case 1: memcpy (dest, src, c.num*c.size); break; 815 case 2: revcpy<2>(dest, src, c.num); break; 816 case 4: revcpy<4>(dest, src, c.num); break; 817 case 8: revcpy<8>(dest, src, c.num); break; 818 } 819 } 820 701 821 #if !defined(__MARS__) && !defined(__CINT__) 702 bool GetRow(size_t row, bool check=true)703 #else 704 bool GetRowNum(size_t row, bool check=true)822 virtual bool GetRow(size_t row, bool check=true) 823 #else 824 virtual bool GetRowNum(size_t row, bool check=true) 705 825 #endif 706 826 { … … 721 841 char *dest = reinterpret_cast<char*>(it->first); 722 842 723 // Let the compiler do some optimization by 724 // knowing that we only have 1, 2, 4 and 8 725 switch (c.size) 726 { 727 case 1: memcpy (dest, src, c.num*c.size); break; 728 case 2: revcpy<2>(dest, src, c.num); break; 729 case 4: revcpy<4>(dest, src, c.num); break; 730 case 8: revcpy<8>(dest, src, c.num); break; 731 } 843 MoveColumnDataToUserSpace(dest, src, c); 732 844 } 733 845 … … 744 856 } 745 857 746 bool SkipNextRow()858 virtual bool SkipNextRow() 747 859 { 748 860 seekg(fTable.offset+(++fRow)*fTable.bytes_per_row); … … 891 1003 bool HasColumn(const string& col) const { return fTable.HasColumn(col);} 892 1004 const Table::Columns &GetColumns() const { return fTable.GetColumns();} 1005 const Table::SortedColumns& GetSortedColumns() const { return fTable.sortedCols;} 893 1006 const Table::Keys &GetKeys() const { return fTable.GetKeys();} 894 1007 … … 914 1027 bool IsFileOk() const { return (fChkHeader+fChkData).valid(); } 915 1028 1029 bool IsCompressedFITS() const { return fTable.isCompressed;} 916 1030 }; 917 1031
Note:
See TracChangeset
for help on using the changeset viewer.