Changeset 16284 for trunk


Ignore:
Timestamp:
05/27/13 01:26:35 (12 years ago)
Author:
lyard
Message:
added fitsCompressor and compressed files read headers
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Mars/mcore/fits.h

    r15364 r16284  
    6969{
    7070public:
     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
    7179    struct Entry
    7280    {
     
    7482        string value;
    7583        string comment;
     84        string fitsString;
    7685
    7786        template<typename T>
     
    9099    {
    91100        off_t offset;
     101
     102        bool isCompressed;
    92103
    93104        string name;
     
    103114            char   type;
    104115            string unit;
     116            FitsCompression comp;
    105117        };
    106118
    107119        typedef map<string, Entry>  Keys;
    108120        typedef map<string, Column> Columns;
     121        typedef vector<Column> SortedColumns;
    109122
    110123        Columns cols;
     124        SortedColumns sortedCols;
    111125        Keys    keys;
    112126
     
    200214
    201215                    // 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));
    203226                    val  = Trim(val.substr(1, p-2));
    204227                    type = 'T';
     
    208231                    const size_t p = val.find_first_of('/');
    209232
    210                     com = Trim(val.substr(p+2));
     233                    if (val.size() == p+1)
     234                        com = "";
     235                    else
     236                        com = Trim(val.substr(p+2));
    211237                    val = Trim(val.substr(0, p));
    212238
     
    217243                }
    218244
    219                 const Entry e = { type, val, com };
     245                const Entry e = { type, val, com, vec[i] };
    220246                rc[key] = e;
    221247            }
     
    226252        Table() : offset(0) { }
    227253        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
    230262            if (!Check("XTENSION", 'T', "BINTABLE") ||
    231263                !Check("NAXIS",    'I', "2")        ||
    232264                !Check("BITPIX",   'I', "8")        ||
    233                 !Check("PCOUNT",   'I', "0")        ||
    234265                !Check("GCOUNT",   'I', "1")        ||
    235266                !Check("EXTNAME",  'T')             ||
     
    239270                return;
    240271
    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");
    243285            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);
    245287
    246288            size_t bytes = 0;
     289            string tFormName = isCompressed ? "ZFORM" : "TFORM";
    247290            for (size_t i=1; i<=num_cols; i++)
    248291            {
     
    251294
    252295                if (!Check("TTYPE"+num.str(), 'T') ||
    253                     !Check("TFORM"+num.str(), 'T'))
     296                    !Check(tFormName+num.str(), 'T'))
    254297                    return;
    255298
    256299                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());
    258301                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;
    259307
    260308                istringstream sin(fmt);
     
    297345                }
    298346
    299                 const Table::Column col = { bytes, n, size, type, unit };
     347                const Table::Column col = { bytes, n, size, type, unit, compress};
    300348
    301349                cols[id] = col;
     350                sortedCols.push_back(col);
    302351                bytes  += n*size;
    303352            }
     
    420469    };
    421470
    422 private:
     471protected:
    423472    ofstream fCopy;
    424473
     
    500549    }
    501550
    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)
    503593    {
    504594        char simple[10];
     
    529619                if (!good())
    530620                {
     621                    //we allow that the table is not found (to be checked later on with bool casting)
     622                    if (mightFail) { return;}
     623
    531624                    clear(rdstate()|ios::badbit);
    532625#ifdef __EXCEPTIONS
     
    565658            if (block[0].substr(0, 9)=="XTENSION=")
    566659            {
    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                }
    569672                fTable = Table(block, tellg());
    570673                fRow   = (size_t)-1;
     
    630733
    631734public:
    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);
    640743    }
    641744
     
    647750    }
    648751
    649     uint8_t ReadRow(size_t row)
     752    virtual void StageRow(size_t row, char* dest)
    650753    {
    651754        // if (row!=fRow+1) // Fast seeking is ensured by izstream
    652755        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    {
    654762        // For the checksum we need everything to be correctly aligned
    655763        const uint8_t offset = (row*fTable.bytes_per_row)%4;
     
    671779        *--ie = 0;
    672780
    673         read(fBufferRow.data()+offset, fTable.bytes_per_row);
    674         //fin.clear(fin.rdstate()&~ios::eofbit);
     781        StageRow(row, fBufferRow.data()+offset);
    675782
    676783        if (row==fRow+1)
     
    699806    }
    700807
     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
    701821#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)
    705825#endif
    706826    {
     
    721841            char *dest = reinterpret_cast<char*>(it->first);
    722842
    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);
    732844        }
    733845
     
    744856    }
    745857
    746     bool SkipNextRow()
     858    virtual bool SkipNextRow()
    747859    {
    748860        seekg(fTable.offset+(++fRow)*fTable.bytes_per_row);
     
    8911003    bool     HasColumn(const string& col) const { return fTable.HasColumn(col);}
    8921004    const Table::Columns &GetColumns() const { return fTable.GetColumns();}
     1005    const Table::SortedColumns& GetSortedColumns() const { return fTable.sortedCols;}
    8931006    const Table::Keys &GetKeys() const { return fTable.GetKeys();}
    8941007
     
    9141027    bool IsFileOk() const { return (fChkHeader+fChkData).valid(); }
    9151028
     1029    bool IsCompressedFITS() const { return fTable.isCompressed;}
    9161030};
    9171031
Note: See TracChangeset for help on using the changeset viewer.