- Timestamp:
- 07/30/11 16:08:38 (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/FACT++/src/EventBuilderWrapper.h
r11703 r11715 12 12 #include <boost/date_time/posix_time/posix_time_types.hpp> 13 13 14 15 #include <CCfits/CCfits> 14 #ifdef HAVE_FITS 15 #include "FitsFile.h" 16 #endif 16 17 17 18 #include "EventBuilder.h" … … 61 62 //! @param extension a string containing the extension to be appened to the file name 62 63 // 63 static string FormFileName(uint32_t runid, stringextension)64 static string FormFileName(uint32_t runid, const string &extension) 64 65 { 65 66 ostringstream name; … … 131 132 static vector<float> fStats; 132 133 133 static uint 32_t fNumOffset;134 static uint 32_t fNumGain;135 static uint 32_t fNumTrgOff;134 static uint64_t fNumOffset; 135 static uint64_t fNumGain; 136 static uint64_t fNumTrgOff; 136 137 137 138 static int fStep; … … 203 204 InitSize(1440, 1024); 204 205 206 fFileName = FormFileName(GetRunId(), "drs.fits"); 207 205 208 return true; 206 209 } … … 224 227 return true; 225 228 } 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 226 279 bool Close(RUN_TAIL * = 0) 227 280 { … … 230 283 fOffset.assign(fSum.begin(), fSum.end()); 231 284 fNumOffset = fNumEntries; 285 286 // 0.5: Scale from ADC to Millivolt 287 GetSampleStats(fStats.data()+3, 0.5); 232 288 reinterpret_cast<uint32_t*>(fStats.data())[0] = GetRunId();; 233 GetSampleStats(fStats.data()+3, 0.5);234 289 } 235 290 if (fStep==1) 236 291 { 237 292 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); 239 303 reinterpret_cast<uint32_t*>(fStats.data())[1] = GetRunId();; 240 // Scale from Volt to Millivolt241 GetSampleStats(fStats.data()+1024*1440*2+3, 0.5);242 304 } 243 305 if (fStep==2) … … 245 307 fTrgOff.assign(fSum.begin(), fSum.end()); 246 308 fNumTrgOff = fNumEntries; 309 310 // 0.5: Scale from ADC to Millivolt 311 GetSampleStats(fStats.data()+1024*1440*4+3, 0.5); 247 312 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(); 250 317 251 318 fDim.Update(fStats); … … 280 347 vector<float> DataFileCalib::fStats (1440*1024*6+3); 281 348 282 uint 32_t DataFileCalib::fNumOffset = 1;283 uint 32_t DataFileCalib::fNumGain = 1;284 uint 32_t DataFileCalib::fNumTrgOff = 1;349 uint64_t DataFileCalib::fNumOffset = 1; 350 uint64_t DataFileCalib::fNumGain = 1; 351 uint64_t DataFileCalib::fNumTrgOff = 1; 285 352 286 353 … … 493 560 494 561 #ifdef HAVE_FITS 562 563 495 564 class DataFileFits : public DataFileImp 496 565 { 497 CCfits::FITS* fFile; /// The pointer to the CCfits FITS file498 CCfits::Table* fTable; /// The pointer to the CCfits binary table499 500 uint64_t fNumRows; ///the number of rows that have been written already to the FITS file.501 502 566 Converter *fConv; 567 568 FitsFile fFile; 503 569 504 570 public: 505 571 DataFileFits(uint32_t runid, MessageImp &imp) : 506 DataFileImp(runid, imp), fFile( 0), fNumRows(0), fConv(0)572 DataFileImp(runid, imp), fFile(imp) 507 573 { 508 574 } … … 516 582 ~DataFileFits() { Close(); delete fConv; } 517 583 518 // --------------------------------------------------------------------------519 //520 //! Add a new column to the vectors storing the column data.521 //! @param names the vector of string storing the columns names522 //! @param types the vector of string storing the FITS data format523 //! @param numElems the number of elements in this column524 //! @param type the char describing the FITS data format525 //! @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 entry541 //! @param name the name of the key542 //! @param value its value543 //! @param comment the comment associated to that key544 //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 try550 {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 561 584 template <typename T> 562 585 void WriteKey(const string &name, const int idx, const T &value, const string &comment) … … 568 591 com << "Board " << setw(2) << idx << ": " << comment; 569 592 570 WriteKey(str.str(), value, com.str());593 fFile.WriteKey(str.str(), value, com.str()); 571 594 } 572 595 … … 578 601 // 579 602 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); 631 616 632 617 // Write length of physical pipeline (1024) 633 618 634 fConv = new Converter(Converter::ToFormat( dataTypes));619 fConv = new Converter(Converter::ToFormat(fFile.GetColumnTypes())); 635 620 636 621 const size_t sz = (h->NPix*h->Nroi + h->NTm*h->NroiTM)*2; … … 644 629 } 645 630 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)) 656 635 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")) 662 638 return false; 663 } 639 640 if (!fFile.WriteDefaultKeys("fadctrl")) 641 return false; 642 643 Info("==> TODO: Write sampling frequency..."); 664 644 665 645 //write header data 666 646 //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 } 724 693 725 694 /* … … 759 728 760 729 //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 785 734 786 735 // -------------------------------------------------------------------------- … … 789 738 //! @param e the pointer to the EVENT 790 739 // 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()) 807 743 return false; 808 } 809 fNumRows++; 810 811 // FIXME: Get NPIX and NTMARK from header 744 812 745 const size_t sz = sizeof(EVENT) + sizeof(e->StartPix)*e->Roi+sizeof(e->StartTM)*e->RoiTM; 813 746 814 747 const vector<char> data = fConv->ToFits(reinterpret_cast<char*>(e)+4, sz-4); 815 748 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()); 834 777 return false; 835 778 } 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; 881 780 } 882 781 … … 886 785 //! @param rt the pointer to the RUN_TAIL data structure 887 786 // 888 virtualbool Close(RUN_TAIL *rt = 0)889 { 890 if (!fFile )787 bool Close(RUN_TAIL *rt = 0) 788 { 789 if (!fFile.IsOpen()) 891 790 return false; 892 791 893 792 WriteFooter(rt); 894 793 895 delete fFile; 896 fFile = NULL; 794 fFile.Close(); 897 795 898 796 return true; … … 992 890 break; 993 891 if (access((name+"fits").c_str(), F_OK) == 0) 892 break; 893 if (access((name+"drs.fits").c_str(), F_OK) == 0) 994 894 break; 995 895 }
Note:
See TracChangeset
for help on using the changeset viewer.