///////////////////////////////////////////////////////// /// $Id: ITripTOldHistoBank.cxx,v 1.2 2009/09/25 06:02:33 nickwest Exp $ /// /// Implement the COMET::ITripTOldHistoBank class... #include "IMidasBankProxyRegistry.hxx" #include "ITripTOldHistoBank.hxx" #include "IMidasTripTOldHisto.hxx" #include "IDptByteEncode.hxx" // Register the bank MIDAS bank mask for the family of bank names that map to this class // The ProHisto class is for the prototype histogram bank used in the first implementation // of the DPT. The ITripTHistoBank and IMidasTripTHisto banks are used for the new // version of the DPT (developed in July 2009, installed a month or two later). // We accept banks of type [PIES]H*0 and [PIES]L*0. There are a few files in existence // with banks where the last letter is an A (and in principle the DPT code can produce them // with any capitsal letter as the last letter (but none are believed to exist). // If you need to decode any of those, add their names to the list below... REGISTER_MIDAS_BANK(ITripTOldHistoBank,PH*0;IH*0;EH*0;SH*0;PL*0;IL*0;EL*0;SL*0) // Typically the class constructors do nothing beyond passing their arguments // to the IMidasBank base class and the destructor does nothing. //_____________________________________________________________________________ COMET::ITripTOldHistoBank::ITripTOldHistoBank() : IMidasBank(0,TTRIPT_OLDHISTO_BANK_TITLE) { // Default constructor COMETTrace("ITripTOldHistoBank: Default ctor at:" << (void*) this); } //_____________________________________________________________________________ COMET::ITripTOldHistoBank::ITripTOldHistoBank(const ULong64_t *bank, const char* title /* = TTRIPT_OLDHISTO_BANK_TITLE */) : IMidasBank(bank,title) { // Normal constructor COMETTrace("COMET::ITripTOldHistoBank: Normal ctor at:" << (void*) this << "\n Name:'" << this->GetName() << "'; Title:" << title << "; Bank size:" << this->GetBankSize() << "; starts at:" << (void*) this->GetBank()); } //_____________________________________________________________________________ COMET::ITripTOldHistoBank::~ITripTOldHistoBank() { COMETTrace("COMET::ITripTOldHistoBank: dtor at:" << (void*) this); } //_____________________________________________________________________________ /// Apart from the methods to move through the list of histograms, the iterator has one Getter method itr->GetBinContents(UInt_t *c); Where c is an array of at least this->GetMaxHistSize() COMET::IMidasTripTOldHistoItr COMET::ITripTOldHistoBank::GetMidasTripTOldHistoItr() const { return IMidasTripTOldHistoItr(this); } #ifdef TESTBINDEF //_____________________________________________________________________________ void COMET::ITripTOldHistoBank::TestBinDef(const char* title, const UInt_t *bd) const { // Call with a bin definition in bd[] (It could be the one for this bank, or // just one to test), and it will print the dump of bins UInt_t maxbin = this->GetMaxBinDef(); const Int_t MAXLINE = 10000; Char_t line[MAXLINE]; Int_t nline = 0; for (Int_t i=0; ; i+=2) { nline += snprintf(line+nline,MAXLINE-nline," %d-%d",bd[i],bd[i+1]); if (!bd[i] || !bd[i+1] || bd[i+1]==1023) break; // End of sequence } COMETLog("\n---TESTBINDEF-----------------------------------------" << title); COMETLog("Bin definition: " << line); UInt_t le[maxbin],w[maxbin]; UInt_t nbin = this->DecodeBins(le,w,bd); nline = 0; for (UInt_t i=0; iTestBinDef("First test, 1 1023 0 0",bdt); // Second test, 2 1023 0 0 bdt[0]=2; bdt[1]=1023; bdt[2]=0; bdt[3]=0; this->TestBinDef("Second test, 2 1023 0 0",bdt); // Third test, 512 1023 0 0 bdt[0]=512; bdt[1]=1023; bdt[2]=0; bdt[3]=0; this->TestBinDef("Third test, 512 1023 0 0",bdt); // Forth test, 1024 1023 0 0 bdt[0]=1024; bdt[1]=1023; bdt[2]=0; bdt[3]=0; this->TestBinDef("Forth test, 1024 1023 0 0",bdt); // Fifth test, 16 95 1 255 64 1023 0 0 bdt[0]=16; bdt[1]=95; bdt[2]=1; bdt[3]=255; bdt[4]=64; bdt[5]=1023; bdt[6]=0; bdt[7]=0; this->TestBinDef("Fifth test, 16 95 1 255 64 1023 0 0",bdt); // Sixth test, (should be the same, but the spec contains correctible errors // 16 91 1 255 64 500 0 0 // ^Should expand to 96 // ^Should extend to 1023 bdt[0]=16; bdt[1]=91; bdt[2]=1; bdt[3]=255; bdt[4]=64; bdt[5]=500; bdt[6]=0; bdt[7]=0; this->TestBinDef("Sixth test, (should be the same, but the spec contains " "correctible errors\n 16 91 1 255 64 500 0 0\n " " ^Should expand to 96\n ^Should extend to 1023" ,bdt); // Seventh test, (should be the same, but the spec contains uncorrectible errors // 16 95 8 15 1 127 0 255 64 1025 0 0 // ^Should complain and ignore this pair (16 is less than 96) // ^Should complain and change to 1 // ^Should complain and change to 1023 bdt[0]=16; bdt[1]=95; bdt[2]=8; bdt[3]=15; bdt[4] =1; bdt[5] =127; bdt[6]= -1;bdt[7]=255; bdt[8]=64; bdt[9]=1025; bdt[10]=0; bdt[11]=0; this->TestBinDef("Seventh test, (should be the same, but the spec contains " "uncorrectible errors\n 16 95 8 15 1 127 -1 255 64 1025 0 0\n" " ^Should complain and ignore this pair (16 is less than 96)\n" " ^Should complain and change to 1\n" " ^Should complain and change to 1023" ,bdt); } #endif //_____________________________________________________________________________ void COMET::ITripTOldHistoBank::Print(const Option_t* opt /* = "" */) const { #ifdef TESTBINDEF static int test = 1; if (test) { // Do the first time print is called test = 0; this->DoTestBinDef(); } #endif this->COMET::IMidasBank::Print(""); this->PrintPackedHistoBlock(this->GetData8(),this->GetSize8()); COMETLog(" RMM no:" << this->GetRMM() << " Sequence:" << this->GetSeq() << " of:" << this->GetSeqMax() << " Encoding:" << this->GetEncoding() << " NChanX:" << this->GetNExtraChan() << " Total #Histograms:" << this->GetNumAllHisto()); COMETLog(" Encoded length of BinDef:" << this->GetBinDefLen() << " Max Decoded Histo Length:" << this->GetMaxHistSize() << " BinDef Length:" << this->GetMaxBinDef()); TString option = opt; option.ToLower(); // Print out the bin definition sequence if ( option.Contains("i") || option.Contains("v")) { UInt_t maxbin = this->GetMaxBinDef(); UInt_t bd[maxbin]; this->GetBinDef(bd); const Int_t MAXLINE = 1000; Char_t line[MAXLINE]; Int_t nline = 0; for (Int_t i=0; ; i+=2) { nline += snprintf(line+nline,MAXLINE-nline," %d-%d",bd[i],bd[i+1]); if (!bd[i] || !bd[i+1] || bd[i+1]==1023) break; // End of sequence } COMETLog("Bin definition: " << line); } // Print out the (long) decoded bin definitions if ( option.Contains("vv")) { UInt_t maxbin = this->GetMaxBinDef(); UInt_t le[maxbin],w[maxbin]; UInt_t nbin = this->DecodeBins(le,w); const Int_t MAXLINE = 10000; Char_t line[MAXLINE]; Int_t nline = 0; for (UInt_t i=0; iGetMidasTripTOldHistoItr().Print(opt); } //_____________________________________________________________________________ /// Return the bin definition in raw pairs (starting ADC value, /// no of bins). You must pass in a preallocated area of memory /// at least this->GetMaxBinDef() Int_t long. void COMET::ITripTOldHistoBank::GetBinDef(UInt_t *bd) const { // The user has been told to provide an array c[] with // at least 1024 words in it */ IDptByteEncode e; UInt_t n = 0; // Count through the bytes we have used // Protect against fSize = 0 (accessed by GetBankSize()) - just do nothing if (this->GetBankSize() == 0) return; UInt_t datum = 0; const UChar_t *d = this->GetBinDefStart(); // printf("GetBinDefStart()=(ptr) 0x%llx\n",(unsigned long long)(d)); while (n < this->GetBinDefLen()) { n += e.Decode(d+n,bd[datum]); // COMETLog(" Debug GetBinDef d[n]:"< this->GetMaxBinDef()) { COMETError(" Bad problem! (Overflowed users array)" << " datum [written] = " << datum << " n = " << n << " this->GetMaxBinDef() [user array size] = " << this->GetMaxBinDef()); } #endif } // Add some zeroes on the end for termination bd[datum++]=0; bd[datum++]=0; // Check we used exactly the right number of bytes if (n != this->GetBinDefLen()) { COMETWarn(" Histogram not decoded exactly " << " datum = " << datum << " n = " << n << " this->GetBinDefLen() = " << this->GetBinDefLen()); } } //_____________________________________________________________________________ /// Return number of bins in histogram, and fill user-suplied arrays with /// bin low edges and bin widths UInt_t COMET::ITripTOldHistoBank::DecodeBins(UInt_t *le, UInt_t *w) const { UInt_t bd[this->GetMaxBinDef()]; this->GetBinDef(bd); return this->DecodeBins(le,w,bd); } //_____________________________________________________________________________ /// As UInt_t GetDecodeBins(UInt_t *le, UInt_t *w); but faster if the /// raw bin definition bd[] has already been obtained UInt_t COMET::ITripTOldHistoBank::DecodeBins(UInt_t *le, UInt_t *w, const UInt_t *bd) const { const UInt_t NADCVAL=1024; // Construct the map UInt_t nbin = 0; UInt_t i=0; // ADC number where we are at the moment UInt_t j=0; // Where we are reading the binborder list while (1) { // Loop over reading items from the binborder list UInt_t imax = bd[j+1]+1; // Make this +1 so it is the conventional // way of doing loop termination in c/c++ UInt_t iwid = bd[j]; printf("Debug DecodeBins(at i=%d) j=%d, (iwid,imax)=(%d,%d) [next]=(%d,%d)\n" ,i,j,iwid,imax-1,bd[j+2],bd[j+3]); // Safety, if the sequence stops here because the next group of two // numbers are zero, extend this sequence to 1023 if ((imax < NADCVAL) && (bd[j+2] == 0 || bd[j+3] == 0)) { imax = NADCVAL; } if (imax < 0 || imax > NADCVAL) { COMETLog("Bad value of imax: " << imax << " found in bd list at j=" << j); imax = NADCVAL; } if (iwid <= 0 || iwid > NADCVAL) { COMETLog("Bad value of iwid: " << iwid << " found in bd list at j=" << j); iwid = 1; } UInt_t ib1 = 1; // Count how many ADC values we have in this bin for (; i>4)&0x3); printf("PrintPackedHistoBlock: %c%c%c%c Len %d RMM %d Fmt %d(nbuffx=%d)\n" " lBinDef %d Seq %d/%d\n" ,buff[0],buff[1],buff[2],buff[3] ,nbuffmax,buff16[2]&0x3,(buff16[2]>>2)&0x3,nchanx ,buff16[3],buff16[4],buff16[5]); int nbuff = (nchanx*NTRIP*NTFB+6)*2; // Current read pointer u32 size = buff16[3]; u32 val = 0; int zerohist = 0; if (nbuff > nbuffmax) goto oversize; printf("BinBoun size %d (ptr 0x%llx) ",size,(unsigned long long)(buff+nbuff)); while(size>0) { int s = e.Decode(buff+nbuff,val); printf(" %d",val); size -= s; nbuff += s; } printf("\n"); if (size<0) goto mismatch; for (int tfb=0;tfb 1) { printf("%2d-%1d-%2.2d %4d",tfb,trip,chan,size); int zero=0; while (size>0) { int s = e.Decode(buff+nbuff,val); if (val == 0) { zero++; } else { if (zero != 0) { printf((zero==1)?" 0":" [%d*0]",zero); zero = 0; } printf(" %d",val); } size -= s; nbuff += s; } if (zero != 0) { printf((zero==1)?" 0":" [%d*0]",zero); zero = 0; } printf("\n"); if (size<0) goto mismatch; } else if (size == 1) { zerohist++; } else { } if (nbuff > nbuffmax) goto oversize; } } } // End of loop over tfbs if (zerohist) printf("There were %d empty histograms\n",zerohist); return; oversize: printf("Ran off end of block %d %d %d\n" ,nbuff,size,nbuffmax); return; mismatch: printf("Encoding mismatch %d %d %d\n" ,nbuff,size,nbuffmax); return; }