Changeset 11715 for trunk/FACT++/src


Ignore:
Timestamp:
07/30/11 16:08:38 (13 years ago)
Author:
tbretz
Message:
Implemented using the new class FitsFile to write raw data and to write a file with the DRS calibration results.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/FACT++/src/EventBuilderWrapper.h

    r11703 r11715  
    1212#include <boost/date_time/posix_time/posix_time_types.hpp>
    1313
    14 
    15 #include <CCfits/CCfits>
     14#ifdef HAVE_FITS
     15#include "FitsFile.h"
     16#endif
    1617
    1718#include "EventBuilder.h"
     
    6162    //! @param extension a string containing the extension to be appened to the file name
    6263    //
    63     static string FormFileName(uint32_t runid, string extension)
     64    static string FormFileName(uint32_t runid, const string &extension)
    6465    {
    6566        ostringstream name;
     
    131132    static vector<float>   fStats;
    132133
    133     static uint32_t fNumOffset;
    134     static uint32_t fNumGain;
    135     static uint32_t fNumTrgOff;
     134    static uint64_t fNumOffset;
     135    static uint64_t fNumGain;
     136    static uint64_t fNumTrgOff;
    136137
    137138    static int fStep;
     
    203204        InitSize(1440, 1024);
    204205
     206        fFileName = FormFileName(GetRunId(), "drs.fits");
     207
    205208        return true;
    206209    }
     
    224227        return true;
    225228    }
     229
     230    void WriteFits()
     231    {
     232#ifdef HAVE_FITS
     233        FitsFile file(fMsg);
     234
     235        file.AddColumn('I', "RunNumberBaseline");
     236        file.AddColumn('I', "RunNumberGain");
     237        file.AddColumn('I', "RunNumberTriggerOffset");
     238        file.AddColumn('F', "BaselineMean", 1024*1440);
     239        file.AddColumn('F', "BaselineRms", 1024*1440);
     240        file.AddColumn('F', "GainMean", 1024*1440);
     241        file.AddColumn('F', "GainRms", 1024*1440);
     242        file.AddColumn('F', "TriggerOffsetMean", 1024*1440);
     243        file.AddColumn('F', "TriggerOffsetRms", 1024*1440);
     244
     245        if (!file.OpenFile(fFileName))
     246            return;
     247
     248        if (!file.OpenTable("DrsCalibration"))
     249            return;
     250
     251        if (!file.WriteDefaultKeys("fadctrl"))
     252            return;
     253
     254        if (!file.WriteKeyNT("STEP", fStep, ""))
     255            return;
     256
     257        vector<char> buf;
     258        buf.reserve(fStats.size()*sizeof(float));
     259
     260        char *src  = reinterpret_cast<char*>(fStats.data());
     261        char *end  = reinterpret_cast<char*>(fStats.data()+1024*1440*6+3);
     262        char *dest = buf.data();
     263
     264        while (src<end)
     265        {
     266            reverse_copy(src, src+sizeof(float), dest);
     267            src  += sizeof(float);
     268            dest += sizeof(float);
     269        }
     270
     271        if (!file.AddRow())
     272            return;
     273
     274        if (!file.WriteData(buf.data(), 1024*1440*sizeof(float)*6+3))
     275            return;
     276#endif
     277    }
     278
    226279    bool Close(RUN_TAIL * = 0)
    227280    {
     
    230283            fOffset.assign(fSum.begin(), fSum.end());
    231284            fNumOffset = fNumEntries;
     285
     286            // 0.5: Scale from ADC to Millivolt
     287            GetSampleStats(fStats.data()+3, 0.5);
    232288            reinterpret_cast<uint32_t*>(fStats.data())[0] = GetRunId();;
    233             GetSampleStats(fStats.data()+3, 0.5);
    234289        }
    235290        if (fStep==1)
    236291        {
    237292            fGain.assign(fSum.begin(), fSum.end());
    238             fNumGain = fNumEntries*1000;
     293            //fNumGain = fNumEntries*1000;
     294
     295            // DAC:  0..2.5V == 0..65535
     296            // V-mV: 1000
     297            for (int i=0; i<1024*1440; i++)
     298                fGain[i] *= 125;
     299            fNumGain = fNumEntries * 65535;
     300
     301            // 0.5: Scale from ADC to Millivolt
     302            GetSampleStats(fStats.data()+1024*1440*2+3, 0.5);
    239303            reinterpret_cast<uint32_t*>(fStats.data())[1] = GetRunId();;
    240             // Scale from Volt to Millivolt
    241             GetSampleStats(fStats.data()+1024*1440*2+3, 0.5);
    242304        }
    243305        if (fStep==2)
     
    245307            fTrgOff.assign(fSum.begin(), fSum.end());
    246308            fNumTrgOff = fNumEntries;
     309
     310            // 0.5: Scale from ADC to Millivolt
     311            GetSampleStats(fStats.data()+1024*1440*4+3, 0.5);
    247312            reinterpret_cast<uint32_t*>(fStats.data())[2] = GetRunId();;
    248             GetSampleStats(fStats.data()+1024*1440*4+3, 0.5);
    249         }
     313        }
     314
     315        if (fStep>=0 && fStep<=2)
     316            WriteFits();
    250317
    251318        fDim.Update(fStats);
     
    280347vector<float>   DataFileCalib::fStats (1440*1024*6+3);
    281348
    282 uint32_t DataFileCalib::fNumOffset = 1;
    283 uint32_t DataFileCalib::fNumGain   = 1;
    284 uint32_t DataFileCalib::fNumTrgOff = 1;
     349uint64_t DataFileCalib::fNumOffset = 1;
     350uint64_t DataFileCalib::fNumGain   = 1;
     351uint64_t DataFileCalib::fNumTrgOff = 1;
    285352
    286353
     
    493560
    494561#ifdef HAVE_FITS
     562
     563
    495564class DataFileFits : public DataFileImp
    496565{
    497     CCfits::FITS*  fFile;        /// The pointer to the CCfits FITS file
    498     CCfits::Table* fTable;       /// The pointer to the CCfits binary table
    499 
    500     uint64_t fNumRows;                ///the number of rows that have been written already to the FITS file.
    501 
    502566    Converter *fConv;
     567
     568    FitsFile fFile;
    503569
    504570public:
    505571    DataFileFits(uint32_t runid, MessageImp &imp) :
    506         DataFileImp(runid, imp), fFile(0), fNumRows(0), fConv(0)
     572        DataFileImp(runid, imp), fFile(imp)
    507573    {
    508574    }
     
    516582    ~DataFileFits() { Close(); delete fConv; }
    517583
    518     // --------------------------------------------------------------------------
    519     //
    520     //! Add a new column to the vectors storing the column data.
    521     //! @param names the vector of string storing the columns names
    522     //! @param types the vector of string storing the FITS data format
    523     //! @param numElems the number of elements in this column
    524     //! @param type the char describing the FITS data format
    525     //! @param name the name of the particular column to be added.
    526     //
    527     inline void AddColumnEntry(vector<string>& names, vector<string>& types, int numElems, char type, string name)
    528     {
    529         names.push_back(name);
    530 
    531         ostringstream str;
    532         if (numElems != 1)
    533             str << numElems;
    534         str << type;
    535         types.push_back(str.str());
    536     }
    537 
    538     // --------------------------------------------------------------------------
    539     //
    540     //! Writes a single header key entry
    541     //! @param name the name of the key
    542     //! @param value its value
    543     //! @param comment the comment associated to that key
    544     //
    545     //FIXME this function is a duplicate from the class Fits. should we try to merge it ?
    546     template <typename T>
    547     void WriteKey(const string &name, const T &value, const string &comment)
    548     {
    549         try
    550         {
    551             fTable->addKey(name, value, comment);
    552         }
    553         catch (CCfits::FitsException e)
    554         {
    555             ostringstream str;
    556             str << "Could not add header key " << name;
    557             Error(str);
    558         }
    559     }
    560 
    561584    template <typename T>
    562585    void WriteKey(const string &name, const int idx, const T &value, const string &comment)
     
    568591        com << "Board " << setw(2) << idx << ": " << comment;
    569592
    570         WriteKey(str.str(), value, com.str());
     593        fFile.WriteKey(str.str(), value, com.str());
    571594    }
    572595
     
    578601    //
    579602    bool OpenFile(RUN_HEAD* h)
    580         {
    581         //Form filename, based on runid and run-type
    582         const string fileName = FormFileName(GetRunId(), "fits");
    583         if (access(fileName.c_str(), F_OK)==0)
    584         {
    585             Error("File '"+fileName+"' already exists.");
    586             return false;
    587         }
    588 
    589         fFileName = fileName;
    590 
    591         /*
    592          out <<
    593          "SIMPLE  =                    T / file does conform to FITS standard             "
    594          "BITPIX  =                    8 / number of bits per data pixel                  "
    595          "NAXIS   =                    0 / number of data axes                            "
    596          "EXTEND  =                    T / FITS dataset may contain extensions            "
    597          "COMMENT   FITS (Flexible Image Transport System) format is defined in 'Astronomy"
    598          "COMMENT   and Astrophysics', volume 376, page 359; bibcode: 2001A&A...376..359H "
    599          "END                                                                             ";
    600          for (int i=0; i<29; i++)
    601          out << "                                                                                "
    602          */
    603 
    604         //create the FITS object
    605         try
    606         {
    607             fFile = new CCfits::FITS(fileName, CCfits::RWmode::Write);
    608         }
    609         catch (CCfits::FitsException e)
    610         {
    611             ostringstream str;
    612             str << "Could not open FITS file " << fileName << ": " << e.message();
    613             Error(str);
    614             return false;
    615         }
    616 
    617         vector<string> colNames;
    618         vector<string> dataTypes;
    619         AddColumnEntry(colNames, dataTypes, 1,                'J', "EventNum");
    620         AddColumnEntry(colNames, dataTypes, 1,                'J', "TriggerNum");
    621         AddColumnEntry(colNames, dataTypes, 1,                'I', "TriggerType");
    622         AddColumnEntry(colNames, dataTypes, 1,                'J', "NumBoards");
    623         AddColumnEntry(colNames, dataTypes, 1,                'J', "reserved");
    624         AddColumnEntry(colNames, dataTypes, 1,                'J', "SoftTrig");
    625         AddColumnEntry(colNames, dataTypes, 2,                'J', "PCTime");
    626         AddColumnEntry(colNames, dataTypes, NBOARDS/*h->NBoard*/, 'J', "BoardTime");
    627         AddColumnEntry(colNames, dataTypes, NPIX   /*h->NPix*/,   'I', "StartCellData");
    628         AddColumnEntry(colNames, dataTypes, NTMARK /*h->NTm*/,    'I', "StartCellTimeMarker");
    629         AddColumnEntry(colNames, dataTypes, h->NPix*h->Nroi,      'I', "Data");
    630         AddColumnEntry(colNames, dataTypes, h->NTm*h->NroiTM,     'I', "TimeMarker");
     603    {
     604        fFile.AddColumn('I', "EventNum");
     605        fFile.AddColumn('I', "TriggerNum");
     606        fFile.AddColumn('S', "TriggerType");
     607        fFile.AddColumn('I', "NumBoards");
     608        fFile.AddColumn('I', "reserved");
     609        fFile.AddColumn('I', "SoftTrig");
     610        fFile.AddColumn('I', "PCTime",              2);
     611        fFile.AddColumn('I', "BoardTime",           NBOARDS);
     612        fFile.AddColumn('S', "StartCellData",       NPIX);
     613        fFile.AddColumn('S', "StartCellTimeMarker", NTMARK);
     614        fFile.AddColumn('S', "Data",                h->NPix*h->Nroi);
     615        fFile.AddColumn('S', "TimeMarker",          h->NTm*h->NroiTM);
    631616
    632617        // Write length of physical pipeline (1024)
    633618
    634         fConv = new Converter(Converter::ToFormat(dataTypes));
     619        fConv = new Converter(Converter::ToFormat(fFile.GetColumnTypes()));
    635620
    636621        const size_t sz = (h->NPix*h->Nroi + h->NTm*h->NroiTM)*2;
     
    644629        }
    645630
    646         //actually create the table
    647         try
    648         {
    649             fTable = fFile->addTable("Events", 0, colNames, dataTypes);
    650         }
    651         catch (const CCfits::FitsException &e)
    652         {
    653             ostringstream str;
    654             str << "Could not create FITS table 'Events' in file " << fileName << " reason: " << e.message();
    655             Error(str);
     631        //Form filename, based on runid and run-type
     632        fFileName = FormFileName(GetRunId(), "fits");
     633
     634        if (!fFile.OpenFile(fFileName))
    656635            return false;
    657         }
    658 
    659         if (fTable->rows() != 0)
    660         {
    661             Error("FITS table created on the fly looks non-empty.");
     636
     637        if (!fFile.OpenTable("Events"))
    662638            return false;
    663         }
     639
     640        if (!fFile.WriteDefaultKeys("fadctrl"))
     641            return false;
     642
     643        Info("==> TODO: Write sampling frequency...");
    664644
    665645        //write header data
    666646        //first the "standard" keys
    667         WriteKey("EXTREL",   1.0f,   "Release Number");
    668         WriteKey("TELESCOP", "FACT",    "Telescope that acquired this data");
    669         WriteKey("ORIGIN",   "ISDC",    "Institution that wrote the file");
    670         WriteKey("CREATOR",  "fadctrl", "Program that wrote this file (FACT++ Event Builder)");
    671 
    672         WriteKey("PACKAGE",   PACKAGE_NAME, "Package name");
    673         WriteKey("VERSION",   PACKAGE_VERSION, "Package description");
    674         WriteKey("COMPILED",  __DATE__" "__TIME__, "Compile time");
    675         WriteKey("REVISION",  REVISION, "SVN revision");
    676         //WriteKey("CONTACT",   PACKAGE_BUGREPORT, "Current package maintainer");
    677         //WriteKey("URL",       PACKAGE_URL, "Current repositiory location");
    678 
    679         WriteKey("BLDVER",   h->Version,  "Builder version");
    680         WriteKey("RUNID",    GetRunId(),  "Run number");
    681         WriteKey("RUNTYPE",  h->RunType,  "Type of run");
    682         WriteKey("NBOARD",   h->NBoard,   "Number of acquisition boards");
    683         WriteKey("NPIX",     h->NPix,     "Number of pixels");
    684         WriteKey("NTMARK",   h->NTm,      "Number of Time marks");
    685         WriteKey("NROI",     h->Nroi,     "Number of slices per pixels");
    686         WriteKey("NROITM",   h->NroiTM,   "Number of slices per time-marker");
    687 
    688         const Time now;
    689         WriteKey("TIMESYS",  "UTC",       "Time system");
    690         WriteKey("DATE",     now.Iso(),   "File creation date");
    691         WriteKey("NIGHT",    now.NightAsInt(), "Night as int");
    692 
    693         //FIXME should we also put the start and stop time of the received data ?
    694         //now the events header related variables
    695         WriteKey("CAMERA",   "MGeomCamFACT", "");
    696         WriteKey("DAQ",      "DRS4", "");
    697 
    698         WriteKey("ADCCOUNT",  2.0f,       "ADC Counts per milliVolt");
    699 
    700         Info("==> TODO: Write sampling frequency...");
    701 
    702         // Write a single key for:
    703         // -----------------------
    704         // Start package flag
    705         // package length
    706         // version number
    707         // status
    708         // Prescaler
    709 
    710         // Write 40 kays for (?)
    711         // Phaseshift
    712         // DAC
    713 
    714         for (int i=0; i<h->NBoard; i++)
    715         {
    716             const PEVNT_HEADER &hh = h->FADhead[i];
    717 
    718             // Header values whihc won't change during the run
    719             WriteKey("ID",    i, hh.board_id,   "Board ID");
    720             WriteKey("DNA",   i, hh.DNA,        "DNA");
    721             WriteKey("FWVER", i, hh.version_no, "Firmware Version");
    722         }
    723 
     647        try
     648        {
     649            fFile.WriteKey("BLDVER",   h->Version,  "Builder version");
     650            fFile.WriteKey("RUNID",    GetRunId(),  "Run number");
     651            fFile.WriteKey("RUNTYPE",  h->RunType,  "Type of run");
     652            fFile.WriteKey("NBOARD",   h->NBoard,   "Number of acquisition boards");
     653            fFile.WriteKey("NPIX",     h->NPix,     "Number of pixels");
     654            fFile.WriteKey("NTMARK",   h->NTm,      "Number of Time marks");
     655            fFile.WriteKey("NROI",     h->Nroi,     "Number of slices per pixels");
     656            fFile.WriteKey("NROITM",   h->NroiTM,   "Number of slices per time-marker");
     657
     658            //FIXME should we also put the start and stop time of the received data ?
     659            //now the events header related variables
     660            fFile.WriteKey("CAMERA",   "MGeomCamFACT", "");
     661            fFile.WriteKey("DAQ",      "DRS4", "");
     662
     663            fFile.WriteKey("ADCCOUNT",  2.0f,       "ADC Counts per milliVolt");
     664
     665
     666            // Write a single key for:
     667            // -----------------------
     668            // Start package flag
     669            // package length
     670            // version number
     671            // status
     672            // Prescaler
     673
     674            // Write 40 kays for (?)
     675            // Phaseshift
     676            // DAC
     677
     678            for (int i=0; i<h->NBoard; i++)
     679            {
     680                const PEVNT_HEADER &hh = h->FADhead[i];
     681
     682                // Header values whihc won't change during the run
     683                WriteKey("ID",    i, hh.board_id,   "Board ID");
     684                WriteKey("DNA",   i, hh.DNA,        "DNA");
     685                WriteKey("FWVER", i, hh.version_no, "Firmware Version");
     686            }
     687        }
     688        catch (const CCfits::FitsException &e)
     689        {
     690            Error("CCfits::Table::addKey failed in "+fFileName+"': "+e.message());
     691            return false;
     692        }
    724693
    725694        /*
     
    759728
    760729        //Last but not least, add header keys that will be updated when closing the file
    761         WriteFooter(NULL);
    762 
    763         return true;
    764     }
    765 
    766 
    767     int WriteColumns(size_t &start, size_t size, const void *e)
    768     {
    769         int status = 0;
    770         fits_write_tblbytes(fFile->fitsPointer(), fNumRows, start, size,
    771                             (unsigned char*)e, &status);
    772         if (status)
    773         {
    774             char text[30];//max length of cfitsio error strings (from doc)
    775             fits_get_errstatus(status, text);
    776 
    777             ostringstream str;
    778             str << "Writing FITS row " << fNumRows << ": " << text << " (file_write_tblbytes, rc=" << status << ")";
    779             Error(str);
    780         }
    781 
    782         start += size;
    783         return status;
    784     }
     730        return WriteFooter(NULL);
     731    }
     732
     733
    785734
    786735    // --------------------------------------------------------------------------
     
    789738    //! @param e the pointer to the EVENT
    790739    //
    791     virtual bool WriteEvt(EVENT *e)
    792     {
    793         //FIXME As discussed earlier, we do not swap the bytes yet.
    794         fTable->makeThisCurrent();
    795 
    796         //insert a new row
    797         int status(0);
    798         if (fits_insert_rows(fTable->fitsPointer(), fNumRows, 1, &status))
    799         {
    800             char text[30];//max length of cfitsio error strings (from doc)
    801             fits_get_errstatus(status, text);
    802 
    803             ostringstream str;
    804             str << "Inserting row " << fNumRows << " into " << fFileName << ": " << text << " (fits_insert_rows, rc=" << status << ")";
    805             Error(str);
    806 
     740    bool WriteEvt(EVENT *e)
     741    {
     742        if (!fFile.AddRow())
    807743            return false;
    808         }
    809         fNumRows++;
    810 
    811         // FIXME: Get NPIX and NTMARK from header
     744
    812745        const size_t sz = sizeof(EVENT) + sizeof(e->StartPix)*e->Roi+sizeof(e->StartTM)*e->RoiTM;
    813746
    814747        const vector<char> data = fConv->ToFits(reinterpret_cast<char*>(e)+4, sz-4);
    815748
    816         // column size pointer
    817         size_t col = 1;
    818         if (!WriteColumns(col, data.size(), data.data()))
    819             return true;
    820 
    821         //TODO output an error
    822         return false;
    823 
    824         /*
    825         //write the data, chunk by chunk
    826         //FIXME hard-coded size corresponds to current variables of the event, in bytes.
    827         //FIXME no padding was taken into account. Because smallest member is 2 bytes, I don't think that this should be a problem.
    828         const long sizeInBytesOfEventBeforePointers = 16;
    829 
    830         long col = 1;
    831         if (FitsWriteTblBytes(col, sizeInBytesOfEventBeforePointers, e))
    832         {
    833             //TODO output an error
     749        return fFile.WriteData(data.data(), data.size());
     750    }
     751
     752    bool WriteFooter(RUN_TAIL *rt)
     753    {
     754        try
     755        {
     756            fFile.WriteKey("NBEVTOK",  rt ? rt->nEventsOk  : uint32_t(0),
     757                           "How many events were written");
     758
     759            fFile.WriteKey("NBEVTREJ", rt ? rt->nEventsRej : uint32_t(0),
     760                           "How many events were rejected by SW-trig");
     761
     762            fFile.WriteKey("NBEVTBAD", rt ? rt->nEventsBad : uint32_t(0),
     763                           "How many events were rejected by Error");
     764
     765            //FIXME shouldn't we convert start and stop time to MjD first ?
     766            //FIXME shouldn't we also add an MjD reference ?
     767
     768            fFile.WriteKey("TSTART",   rt ? rt->PCtime0    : uint32_t(0),
     769                           "Time when first event received");
     770
     771            fFile.WriteKey("TSTOP",    rt ? rt->PCtimeX    : uint32_t(0),
     772                           "Time when last event received");
     773        }
     774        catch (const CCfits::FitsException &e)
     775        {
     776            Error("CCfits::Table::addKey failed in '"+fFile.GetName()+"': "+e.message());
    834777            return false;
    835778        }
    836         if (FitsWriteTblBytes(col, NBOARDS*2, e->BoardTime))
    837         {
    838             //TODO output an error
    839             return false;
    840         }
    841         if (FitsWriteTblBytes(col, NPIX*2, e->StartPix))
    842         {
    843             //TODO output an error
    844             return false;
    845         }
    846         if (FitsWriteTblBytes(col, NTMARK*2, e->StartTM))
    847         {
    848             //TODO output an error
    849             return false;
    850         }
    851         if (FitsWriteTblBytes(col, NPIX*fRoi*2, e->Adc_Data))
    852         {
    853             //TODO output an error
    854             return false;
    855         }
    856         return true;*/
    857     }
    858 
    859     void WriteFooter(RUN_TAIL *rt)
    860     {
    861         //write final header keys
    862         fTable->makeThisCurrent();
    863 
    864         WriteKey("NBEVTOK",  rt ? rt->nEventsOk  : uint32_t(0),
    865                  "How many events were written");
    866 
    867         WriteKey("NBEVTREJ", rt ? rt->nEventsRej : uint32_t(0),
    868                  "How many events were rejected by SW-trig");
    869 
    870         WriteKey("NBEVTBAD", rt ? rt->nEventsBad : uint32_t(0),
    871                  "How many events were rejected by Error");
    872 
    873         //FIXME shouldn't we convert start and stop time to MjD first ?
    874         //FIXME shouldn't we also add an MjD reference ?
    875 
    876         WriteKey("TSTART",   rt ? rt->PCtime0    : uint32_t(0),
    877                  "Time when first event received");
    878 
    879         WriteKey("TSTOP",    rt ? rt->PCtimeX    : uint32_t(0),
    880                  "Time when last event received");
     779        return true;
    881780    }
    882781
     
    886785    //! @param rt the pointer to the RUN_TAIL data structure
    887786    //
    888     virtual bool Close(RUN_TAIL *rt = 0)
    889     {
    890         if (!fFile)
     787    bool Close(RUN_TAIL *rt = 0)
     788    {
     789        if (!fFile.IsOpen())
    891790            return false;
    892791
    893792        WriteFooter(rt);
    894793
    895         delete fFile;
    896         fFile = NULL;
     794        fFile.Close();
    897795
    898796        return true;
     
    992890                break;
    993891            if (access((name+"fits").c_str(), F_OK) == 0)
     892                break;
     893            if (access((name+"drs.fits").c_str(), F_OK) == 0)
    994894                break;
    995895        }
Note: See TracChangeset for help on using the changeset viewer.