Changeset 17147


Ignore:
Timestamp:
09/08/13 21:20:17 (11 years ago)
Author:
tbretz
Message:
Added more options to format the output stream. Added filter support to the stats option and fixed some issues with the calculation.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/FACT++/src/fitsdump.cc

    r17000 r17147  
    1515#include <boost/regex.hpp>
    1616
     17#include "tools.h"
    1718#include "Time.h"
    1819#include "externals/factfits.h"
     
    4546    minMaxStruct() : min(FLT_MAX), max(-FLT_MAX), average(0), squared(0), numValues(0) { }
    4647
    47     void add(double val)
     48    void add(long double val)
    4849    {
    4950        average += val;
     
    7879
    7980    double GetDouble(const MyColumn &, size_t) const;
     81    int64_t GetInteger(const MyColumn &, size_t) const;
     82    string Format(const string &fmt, const double &val) const;
     83    string Format(const string &fmt, const MyColumn &, size_t) const;
    8084
    8185    ///Display the selected columns values VS time
    82     void Dump(ofstream &, const vector<MyColumn> &, const string &, size_t, size_t, const string &);
     86    void Dump(ofstream &, const vector<string> &, const vector<MyColumn> &, const string &, size_t, size_t, const string &);
    8387    void DumpRoot(ofstream &, const vector<string> &, const string &, size_t, size_t, const string &);
    8488    void DumpMinMax(ofstream &, const vector<MyColumn> &, size_t, size_t, bool);
    85     void DumpStats(ofstream &, const vector<MyColumn> &, size_t, size_t);
     89    void DumpStats(ofstream &, const vector<MyColumn> &, const string &, size_t, size_t);
    8690
    8791public:
     
    284288}
    285289
     290int64_t FitsDumper::GetInteger(const MyColumn &it, size_t i) const
     291{
     292    switch (it.col.type)
     293    {
     294    case 'A':
     295        return reinterpret_cast<const char*>(it.ptr)[i];
     296
     297    case 'L':
     298        return reinterpret_cast<const bool*>(it.ptr)[i];
     299
     300    case 'B':
     301        return (unsigned int)reinterpret_cast<const uint8_t*>(it.ptr)[i];
     302
     303    case 'I':
     304        return reinterpret_cast<const int16_t*>(it.ptr)[i];
     305
     306    case 'J':
     307        return reinterpret_cast<const int32_t*>(it.ptr)[i];
     308
     309    case 'K':
     310        return reinterpret_cast<const int64_t*>(it.ptr)[i];
     311
     312    case 'E':
     313        return reinterpret_cast<const float*>(it.ptr)[i];
     314
     315    case 'D':
     316        return reinterpret_cast<const double*>(it.ptr)[i];
     317    }
     318
     319    return 0;
     320}
     321
     322string FitsDumper::Format(const string &format, const MyColumn &col, size_t i) const
     323{
     324    switch (*format.rbegin())
     325    {
     326    case 'd':
     327    case 'i':
     328    case 'o':
     329    case 'u':
     330    case 'x':
     331    case 'X':
     332        return Tools::Form(format.c_str(), GetDouble(col, i));
     333
     334    case 'e':
     335    case 'E':
     336    case 'f':
     337    case 'F':
     338    case 'g':
     339    case 'G':
     340    case 'a':
     341    case 'A':
     342        return Tools::Form(format.c_str(), GetInteger(col, i));
     343
     344    case 'h':
     345        {
     346            string rc = Tools::Scientific(GetDouble(col, i));
     347            *remove_if(rc.begin(), rc.end(), ::isspace)=0;
     348            return rc;
     349        }
     350    }
     351
     352    return "";
     353}
     354
     355string FitsDumper::Format(const string &format, const double &val) const
     356{
     357    switch (*format.rbegin())
     358    {
     359    case 'd':
     360    case 'i':
     361    case 'o':
     362    case 'u':
     363    case 'x':
     364    case 'X':
     365        return Tools::Form(format.c_str(), int64_t(val));
     366
     367    case 'e':
     368    case 'E':
     369    case 'f':
     370    case 'F':
     371    case 'g':
     372    case 'G':
     373    case 'a':
     374    case 'A':
     375        return Tools::Form(format.c_str(), val);
     376
     377    case 'h':
     378        {
     379            string rc = Tools::Scientific(val);
     380            *remove_if(rc.begin(), rc.end(), ::isspace)=0;
     381            return rc;
     382        }
     383    }
     384
     385    return "";
     386}
     387
     388
    286389// --------------------------------------------------------------------------
    287390//
    288391//! Perform the actual dump, based on the current parameters
    289392//
    290 void FitsDumper::Dump(ofstream &fout, const vector<MyColumn> &cols, const string &filter, size_t first, size_t limit, const string &filename)
     393void FitsDumper::Dump(ofstream &fout, const vector<string> &format, const vector<MyColumn> &cols, const string &filter, size_t first, size_t limit, const string &filename)
    291394{
    292395    const fits::Table::Keys &fKeyMap = GetKeys();
     
    357460        ostringstream sout;
    358461        sout.precision(fout.precision());
    359         for (auto it=cols.begin(); it!=cols.end(); it++)
     462        sout.flags(fout.flags());
     463
     464        uint32_t col = 0;
     465        for (auto it=cols.begin(); it!=cols.end(); it++, col++)
    360466        {
    361467            string msg;
    362468            for (uint32_t i=it->first; i<=it->last; i++, p++)
    363469            {
    364                 switch (it->col.type)
     470                if (col<format.size())
     471                    sout << Format("%"+format[col], *it, i) << " ";
     472                else
    365473                {
    366                 case 'A':
    367                     msg += reinterpret_cast<const char*>(it->ptr)[i];
    368                     break;
    369                 case 'B':
    370                     sout << (unsigned int)reinterpret_cast<const unsigned char*>(it->ptr)[i] << " ";
    371                     break;
    372                 case 'L':
    373                     sout << reinterpret_cast<const bool*>(it->ptr)[i] << " ";
    374                     break;
    375                 case 'I':
    376                     sout << reinterpret_cast<const int16_t*>(it->ptr)[i] << " ";
    377                     break;
    378                 case 'J':
    379                     sout << reinterpret_cast<const int32_t*>(it->ptr)[i] << " ";
    380                     break;
    381                 case 'K':
    382                     sout << reinterpret_cast<const int64_t*>(it->ptr)[i] << " ";
    383                     break;
    384                 case 'E':
    385                     sout << reinterpret_cast<const float*>(it->ptr)[i] << " ";
    386                     break;
    387                 case 'D':
    388                     sout << reinterpret_cast<const double*>(it->ptr)[i] << " ";
    389                     break;
    390                 default:
    391                     ;
     474                    switch (it->col.type)
     475                    {
     476                    case 'A':
     477                        msg += reinterpret_cast<const char*>(it->ptr)[i];
     478                        break;
     479                    case 'B':
     480                        sout << (unsigned int)reinterpret_cast<const unsigned char*>(it->ptr)[i] << " ";
     481                        break;
     482                    case 'L':
     483                        sout << reinterpret_cast<const bool*>(it->ptr)[i] << " ";
     484                        break;
     485                    case 'I':
     486                        sout << reinterpret_cast<const int16_t*>(it->ptr)[i] << " ";
     487                        break;
     488                    case 'J':
     489                        sout << reinterpret_cast<const int32_t*>(it->ptr)[i] << " ";
     490                        break;
     491                    case 'K':
     492                        sout << reinterpret_cast<const int64_t*>(it->ptr)[i] << " ";
     493                        break;
     494                    case 'E':
     495                        sout << reinterpret_cast<const float*>(it->ptr)[i] << " ";
     496                        break;
     497                    case 'D':
     498                        sout << reinterpret_cast<const double*>(it->ptr)[i] << " ";
     499                        break;
     500                    default:
     501                        ;
     502                    }
    392503                }
    393 
    394504#ifdef HAVE_ROOT
    395505                if (!filter.empty())
     
    680790    out << "Max: " << double(val[numElems-1]) << '\n';
    681791
    682     if (numElems>2)
    683     {
    684         if (numElems%2 == 0)
    685             out << "Med: " << (double(val[numElems/2]) + double(val[numElems/2+1]))/2 << '\n';
    686         else
    687             out << "Med: " << double(val[numElems/2+1]) << '\n';
    688     }
     792    if (numElems%2 == 0)
     793        out << "Med: " << (double(val[numElems/2-1]) + double(val[numElems/2]))/2 << '\n';
     794    else
     795        out << "Med: " << double(val[numElems/2]) << '\n';
    689796
    690797    long double avg = 0;
     
    692799    for (uint32_t i=0;i<numElems;i++)
    693800    {
    694         avg += double(val[i]);
    695         rms += double(val[i])*double(val[i]);
     801        const long double v = val[i];
     802        avg += v;
     803        rms += v*v;
    696804    }
    697805
     
    704812}
    705813
    706 void FitsDumper::DumpStats(ofstream &fout, const vector<MyColumn> &cols, size_t first, size_t limit)
    707 {
     814void FitsDumper::DumpStats(ofstream &fout, const vector<MyColumn> &cols, const string &filter, size_t first, size_t limit)
     815{
     816#ifdef HAVE_ROOT
     817    TFormula select;
     818    if (!filter.empty() && select.Compile(filter.c_str()))
     819        throw runtime_error("Syntax Error: TFormula::Compile failed for '"+filter+"'");
     820#endif
     821
    708822    // Loop over all columns in our list of requested columns
    709823    vector<vector<char>> statData;
     
    712826
    713827    for (auto it=cols.begin(); it!=cols.end(); it++)
    714         statData.push_back(vector<char>(it->col.size*num*(it->last-it->first+1)));
     828        statData.emplace_back(vector<char>(it->col.size*num*(it->last-it->first+1)));
     829
     830#ifdef HAVE_ROOT
     831    vector<Double_t> data(num+1);
     832#endif
    715833
    716834    // Loop over all columns in our list of requested columns
    717835    const size_t last = limit ? first + limit : size_t(-1);
     836
     837    uint64_t counter = 0;
    718838
    719839    while (GetRow(first++))
     
    723843            break;
    724844
     845#ifdef HAVE_ROOT
     846        if (!filter.empty())
     847        {
     848            size_t p = 0;
     849
     850            data[p++] = first-1;
     851
     852            for (auto it=cols.begin(); it!=cols.end(); it++)
     853                for (uint32_t i=it->first; i<=it->last; i++, p++)
     854                    data[p] = GetDouble(*it, i);
     855
     856            if (select.EvalPar(0, data.data())<0.5)
     857                continue;
     858        }
     859#endif
    725860
    726861        auto statsIt = statData.begin();
     
    729864            const char *src = reinterpret_cast<const char*>(it->ptr);
    730865            const size_t sz = (it->last-it->first+1)*it->col.size;
    731             memcpy(statsIt->data()+row*sz, src+it->first*it->col.size, sz);
    732         }
     866            memcpy(statsIt->data()+counter*sz, src+it->first*it->col.size, sz);
     867        }
     868
     869        counter++;
    733870    }
    734871
     
    740877            fout << ':' << it->last;
    741878        fout << "]\n";
     879
     880        const size_t sz = (it->last-it->first+1)*it->col.size;
     881        statsIt->resize(counter*sz);
    742882
    743883        switch (it->col.type)
     
    792932    if (conf.Get<bool>("minmax") && conf.Get<bool>("stat"))
    793933    {
    794         cerr << "Invalid combination of options: cannot do stats and minmax. Aborting" << endl;
     934        cerr << "Invalid combination of options: cannot do stats and minmax." << endl;
    795935        return -1;
    796936    }
    797937    if (conf.Get<bool>("stat") && conf.Get<bool>("nozero"))
    798938    {
    799         cerr << "Invalid combination of options: nozero only works with minmax. Aborting" << endl;
     939        cerr << "Invalid combination of options: nozero only works with minmax." << endl;
     940        return -1;
     941    }
     942
     943    if (conf.Get<bool>("scientific") && conf.Get<bool>("fixed"))
     944    {
     945        cerr << "Switched --scientific and --fixed are mutually exclusive." << endl;
     946        return -1;
     947    }
     948
     949    if (conf.Has("%") && conf.Has("%%"))
     950    {
     951        cerr << "Switched --% and --%% are mutually exclusive." << endl;
    800952        return -1;
    801953    }
     
    812964    }
    813965    fout.precision(conf.Get<int>("precision"));
     966    if (conf.Get<bool>("fixed"))
     967        fout << fixed;
     968    if (conf.Get<bool>("scientific"))
     969        fout << scientific;
    814970
    815971    const string filter = conf.Has("filter") ? conf.Get<string>("filter") : "";
    816 
    817972    const size_t first  = conf.Get<size_t>("first");
    818973    const size_t limit  = conf.Get<size_t>("limit");
     
    825980    }
    826981#endif
     982
     983    const vector<string> format = conf.Vec<string>("%");
     984    for (auto it=format.begin(); it<format.end(); it++)
     985    {
     986        static const boost::regex expr("-?[0-9]*[.]?[0-9]*[diouxXeEfFgGaAh]");
     987
     988        boost::smatch what;
     989        if (!boost::regex_match(*it, what, expr, boost::match_extra))
     990        {
     991            cerr << "Format '" << *it << "' not supported." << endl;
     992            return -1;
     993        }
     994    }
    827995
    828996    const vector<MyColumn> cols = InitColumns(conf.Vec<string>("col"));
     
    830998        return false;
    831999
    832 
    8331000    if (conf.Get<bool>("minmax"))
    8341001    {
     
    8391006    if (conf.Get<bool>("stat"))
    8401007    {
    841         DumpStats(fout, cols, first, limit);
     1008        DumpStats(fout, cols, filter, first, limit);
    8421009        return 0;
    8431010    }
    8441011
    845     Dump(fout, cols, filter, first, limit, filename);
     1012    Dump(fout, format, cols, filter, first, limit, filename);
    8461013
    8471014    return 0;
     
    8971064        "\n"
    8981065        "  fitsdump -r \"#\" --filter=\"#>10 && #<100\"\n"
     1066        "\n"
     1067        "To format a single column you can do\n"
     1068        "\n"
     1069        "  fitsdump col1 -%.1f col2 -%d\n"
     1070        "\n"
     1071        "A special format is provided converting to 'human readable format'\n"
     1072        "\n"
     1073        "  fitsdump col1 -%h\n"
    8991074        "\n";
    9001075    cout << endl;
     
    9201095        ("minmax,m",    po_switch(),            "Calculates min and max of data")
    9211096        ("nozero,z",    po_switch(),            "skip 0 values for stats")
     1097        ("fixed",       po_switch(),            "Switch output stream to floating point values in fixed-point notation")
     1098        ("scientific",  po_switch(),            "Switch output stream to floating point values in scientific notation")
     1099        ("%,%",         vars<string>(),         "Format for the output (currently not available in root-mode)")
    9221100        ("force",       po_switch(),            "Force reading the fits file even if END key is missing")
    923         ("first",       var<size_t>(size_t(0)), "First number of row to read")
    924         ("limit",       var<size_t>(size_t(0)), "Limit for the maximum number of rows to read (0=unlimited)")
     1101        ("first",       var<size_t>(0),        "First number of row to read")
     1102        ("limit",       var<size_t>(0),        "Limit for the maximum number of rows to read (0=unlimited)")
    9251103        ("tablename,t", var<string>(""),        "Name of the table to open. If not specified, first binary table is opened")
    9261104#ifdef HAVE_ROOT
Note: See TracChangeset for help on using the changeset viewer.