#include "Digitizer.h" void Digitizer::DigitizeTOF(int np,float *atte1,float *atte2,float *lambda1,float *lambda2){ //fDataTof: 12 x 23 bytes (=276 bytes) UChar_t *pTof=fDataTof; Bool_t DEBUG=false; Int_t cdp[75] = {0,1,1,0,1,1,0,1,1,0,1,1,0,1,1, //0-14 0,0,0,1,0,1,0,1,1,0,0,1,0,1,0, //15-29 1,1,1,1,2,2,2,3,3,3,3,4,4,4,1, //30-44 1,2,0,2,0,0,5,5,5,5,6,6,6,6,7, //45-59 3,3,4,4,5,5,6,7,8,9,10,11,12,13,14 }; //60-74 int Z = cdp[Ipa-1]; float time_res[8] = {425.,210.,170.,130.,120.,120.,120.,120.}; for(Int_t i=0;i<8;i++)time_res[i]/=1.4;//1.17;1.5;1.3*/ Float_t dt1 = 0.;// = 1.e-12*time_res[0]; // single PMT resolution for Z=1 (WM, Nov'07) if ((Z > 1) && (Z < 9)) dt1=1.e-12*time_res[(Z-1)]; if (Z > 8) dt1=120.e-12; // ------ evaluate energy in each pmt: ------ // strip geometry (lenght/width) Float_t dimel[6] = {33.0, 40.8 ,18.0, 15.0, 15.0, 18.0}; // S11 8 paddles 33.0 x 5.1 cm // S12 6 paddles 40.8 x 5.5 cm // S21 2 paddles 18.0 x 7.5 cm // S22 2 paddles 15.0 x 9.0 cm // S31 3 paddles 15.0 x 6.0 cm // S32 3 paddles 18.0 x 5.0 cm Float_t FGeo[2]={0., 0.}; /* geometrical factor */ const Float_t Pho_keV = 10.; // photons per keV in scintillator const Float_t echarge = 1.6e-19; // electron charge Float_t Npho=0.; Float_t QevePmt_pC[48]; Float_t QhitPad_pC[2]={0.,0.}; Float_t QhitPmt_pC[2]={0.,0.}; Float_t pmGain = 3.5e6; /* PMT Gain: the same for all PMTs */ Float_t effi=0.21; /* Efficienza di fotocatodo */ // pC < 800 Float_t ADC_pC0A =-4.437616e+01; Float_t ADC_pC1A = 1.573329e+00; Float_t ADC_pC2A = 2.780518e-04; Float_t ADC_pC3A =-2.302160e-07; // pC > 800: Float_t ADC_pC0B =-2.245756e+02; Float_t ADC_pC1B = 2.184156e+00; Float_t ADC_pC2B =-4.171825e-04; Float_t ADC_pC3B = 3.789715e-08; Float_t pCthres=40.; // threshold in charge Int_t ADClast=4095; // no signal --> ADC ch=4095 Int_t ADCsat=3100; // saturation value for the ADCs Int_t ADCtof[48]; Float_t ScaleFact[48]={0.39, 0.49, 0.38, 0.40, 0.65, 0.51, 0.43, 0.49, 0.58, 0.38, 0.53, 0.57, 0.53, 0.45, 0.49, 0.22, 0.21, 0.44, 0.28, 0.57, 0.26, 0.72, 0.37, 0.29, 0.30, 0.89, 0.37, 0.12, 0.27, 0.23, 0.15, 0.22, 0.19, 0.20, 0.21, 0.19, 0.41, 0.32, 0.39, 0.38, 0.28, 0.66, 0.28, 0.40, 0.39, 0.40, 0.37, 0.35};//15:0.7--0.95, 16:0.9--1.25, 27:0.9--1.3, 30:0.9--1.15, 32:0.85--1.05, 33:0.85--1.05 for(Int_t i=0; i<48; i++){ QevePmt_pC[i] = 0; ADCtof[i]=0; } Int_t ip,ipad,pmtleft=0,pmtright=0; // TDC variables: Int_t TDClast=4095,TDCint[48]; Float_t tdc[48],tdc1[48],tdcpmt[48]; for(Int_t i=0; i<48; i++) { tdcpmt[i] = 1000.; tdc[i] = 0.; // 18-oct WM tdc1[i] = 0.; // 18-oct WM } Float_t thresh=20.; // to be defined better... (Wolfgang) // === TDC: simulate timing for each paddle Float_t tdcres[50],c1_S[50],c2_S[50],c3_S[50]; for(Int_t j=0;j<48;j++){ tdcres[j] = 50.E-12; // TDC resolution 50 picosec c1_S[j] = 500.; // cable length in channels c2_S[j] = 0.; c3_S[j] = 1000.; c1_S[j] = c1_S[j]*tdcres[j]; // cable length in sec c2_S[j] = c2_S[j]*tdcres[j]; } /* ********************************** start loop over hits */ if(Nthtof>*ntof)cout<<"NTHTOF > "<<*ntof<<" , event rejected ! "<-1)&&(ip<6)) { //ToF paddles only, not S4 Paddle2Pmt(ip, ipad, &pmtleft, &pmtright); // DC: evaluates mean position and path inside the paddle Float_t tpos=0.; Float_t path[2] = {0., 0.}; //--- Strip in Y = S11,S22,S31 ------ if(ip==0 || ip==3 || ip==4) tpos = (Yintof[nh]+Youttof[nh])/2.; else if(ip==1 || ip==2 || ip==5) //--- Strip in X for S12,S21,S32 tpos = (Xintof[nh]+Xouttof[nh])/2.; else //if (ip!=6) printf("*** WARNING TOF: this option should never occur! (ip=%2i, nh=%2i)\n",ip,nh); path[0]= tpos + dimel[ip]/2.; // path to left PMT path[1]= dimel[ip]/2.- tpos; // path to right PMT if (DEBUG) { cout <<" plane "< t1 = t1 + fabs(path[0]/veff) + s_l_g[ip]/veff1; t2 = t2 + fabs(path[1]/veff) + s_l_g[ip]/veff1 ; // Signal reaches PMT t1 = gRandom->Gaus(t1,dt1); //apply gaussian error dt t2 = gRandom->Gaus(t2,dt1); //apply gaussian error dt t1 = t1 + c1_S[pmtleft] ; // Signal reaches Discriminator ,TDC starts to run t2 = t2 + c1_S[pmtright] ; // check if signal is above threshold // then check if tdcpmt is already filled by another hit... // only re-fill if time is smaller if (QhitPmt_pC[0] > thresh) { if (tdcpmt[pmtleft] == 1000.) { // fill for the first time tdcpmt[pmtleft] = t1; tdc[pmtleft] = t1 + c2_S[pmtleft] ; // Signal reaches Coincidence } if (tdcpmt[pmtleft] < 1000.) // is already filled! if (t1 < tdcpmt[pmtleft]) { tdcpmt[pmtleft] = t1; t1 = t1 + c2_S[pmtleft] ; // Signal reaches Coincidence tdc[pmtleft] = t1; } } if (QhitPmt_pC[1] > thresh) { if (tdcpmt[pmtright] == 1000.) { // fill for the first time tdcpmt[pmtright] = t2; tdc[pmtright] = t2 + c2_S[pmtright] ; // Signal reaches Coincidence } if (tdcpmt[pmtright] < 1000.) // is already filled! if (t2 < tdcpmt[pmtright]) { tdcpmt[pmtright] = t2; t2 = t2 + c2_S[pmtright] ; tdc[pmtright] = t2; } } if(DEBUG)cout< -1 && ip < 6 } // **************************************** end loop over hits } // NTHTOF < 200 // ====== ADC ====== for(Int_t i=0; i<48; i++){ if (QevePmt_pC[i] <= 800.) ADCtof[i]= (Int_t)(ADC_pC0A + ADC_pC1A*QevePmt_pC[i] + ADC_pC2A*pow(QevePmt_pC[i],2) + ADC_pC3A*pow(QevePmt_pC[i],3)); if (QevePmt_pC[i] > 800.) ADCtof[i]= (Int_t)(ADC_pC0B + ADC_pC1B*QevePmt_pC[i] + ADC_pC2B*pow(QevePmt_pC[i],2) + ADC_pC3B*pow(QevePmt_pC[i],3)); if (QevePmt_pC[i] > 2485.) ADCtof[i]= (Int_t)(1758. + 0.54*QevePmt_pC[i]); //assuming a fictional 0.54 ch/pC above ADCsat if (ADCtof[i]>ADCsat) ADCtof[i]=ADCsat; if (QevePmt_pC[i] < pCthres) ADCtof[i]= ADClast; if (ADCtof[i] < 0) ADCtof[i]=ADClast; if (ADCtof[i] > ADClast) ADCtof[i]=ADClast; //if(ADCtof[i]!=4095)cout<>ciao; // ====== build TDC coincidence ====== // for(Int_t i=0; i<48; i++) { if((tdcpmt[i] - c1_S[i]) > 1e-7) { tdcpmt[i] = 0.; tdc[i] = 0.; } }// cycle to introduce a window for tdc Float_t t_coinc = 0; Int_t ilast = 100; for (Int_t ii=0; ii<48;ii++) if (tdc[ii] > t_coinc) { t_coinc = tdc[ii]; ilast = ii; } // cout<4093) TDCint[i]=TDClast; // 18-oct WM if (DEBUG)cout<SetBranchStatus("Ievnt",&Ievnt); UInt_t cTrg = (UInt_t)Ievnt; //counter UInt_t cTrg2 = 0; //counter with bits inverted, according to document //"formato dati provenienti dalla trigger board" for (Int_t i=0; i < 24; i++){ // Use the first 24 bits if (cTrg & (0x1 << i) ) cTrg2 = cTrg2 | (0x1 << (24-i)); } fDataTrigger[7] = (UChar_t)(cTrg2 >> 16); // 8 MSbits (out of 24) fDataTrigger[8] = (UChar_t)(cTrg2 >> 8); // 8 "middle" bits fDataTrigger[9] = (UChar_t)(cTrg2); // 8 LSbits pTrg=fDataTrigger+7; fDataTrigger[10]=EvaluateCrcTrigger(pTrg, 3); // TB_READ_PATTERN_TRIGGER: bytes 141-148: // PatternTrigMap[i] corresponds to bit i in TB_READ_PATTERN_TRIGGER: // mapping according to documents: // 1. "formato dati provenienti dalla trigger board" // 2. "The ToF quicklook software", Appendix A (Campana, Nagni) Int_t PatternTrigMap[]={29,42,43,1,16,7,17,28,33,41,46,2,15,8,18,27, 30,40,44,3,14,9,19,26,32,37,47,4,13,10,20,25, 34,31,38,45,5,12,21,24,36,35,39,48,6,11,22,23}; for (Int_t i=0; i < 48; i++) //if (ADCtof[i]>thrTrg) if (tdc1[channelmap[i]]!=0) fDataTrigger[147-(Int_t)((PatternTrigMap[i]+1)/8)]=fDataTrigger[147-(Int_t)((PatternTrigMap[i]+1)/8)] | (0x1 << (PatternTrigMap[i]%8)); pTrg=fDataTrigger+141; fDataTrigger[148]=EvaluateCrcTrigger(pTrg, 7); // TB_READ_TRIGGER_CONF : set always acq.mode TOF4 // // TOF1: S1-S2-S3 (&,|) // TOF4: S2-S3 (&,&) fDataTrigger[149]=0x02; fDataTrigger[150]=0x0; pTrg=fDataTrigger+149; fDataTrigger[151]=EvaluateCrcTrigger(pTrg, 2); } UChar_t Digitizer::Bin2GrayTof(UChar_t binaTOF,UChar_t grayTOF){ union graytof_data { UChar_t word; struct bit_field { unsigned b0:1; unsigned b1:1; unsigned b2:1; unsigned b3:1; unsigned b4:1; unsigned b5:1; unsigned b6:1; unsigned b7:1; } bit; } bi,gr; // bi.word = binaTOF; gr.word = grayTOF; // gr.bit.b0 = bi.bit.b1 ^ bi.bit.b0; gr.bit.b1 = bi.bit.b2 ^ bi.bit.b1; gr.bit.b2 = bi.bit.b3 ^ bi.bit.b2; gr.bit.b3 = bi.bit.b3; // /* bin to gray conversion 4 bit per time*/ // gr.bit.b4 = bi.bit.b5 ^ bi.bit.b4; gr.bit.b5 = bi.bit.b6 ^ bi.bit.b5; gr.bit.b6 = bi.bit.b7 ^ bi.bit.b6; gr.bit.b7 = bi.bit.b7; // return(gr.word); } UChar_t Digitizer::EvaluateCrcTof(UChar_t *pTof) { Bool_t DEBUG=false; if (DEBUG) return(0x00); UChar_t crcTof=0x00; UChar_t *pc=&crcTof, *pc2; pc2=pTof; for (Int_t jp=0; jp < 22; jp++){ // cecilia: fixed 23->22 //crcTof = crc8(...) Crc8Tof(pc2++,pc); // printf("%2i --- %x\n",jp,crcTof); } return(crcTof); } UChar_t Digitizer::EvaluateCrcTrigger(UChar_t *pTrg, Int_t nb) { Bool_t DEBUG=false; if (DEBUG) return(0x00); UChar_t crcTrg=0x00; UChar_t *pc=&crcTrg, *pc2; pc2=pTrg; for (Int_t jp=0; jp < nb; jp++) Crc8Tof(pc2++,pc); return(crcTrg); } void Digitizer::Crc8Tof(UChar_t *oldCRC, UChar_t *crcTof){ union crctof_data { UChar_t word; struct bit_field { unsigned b0:1; unsigned b1:1; unsigned b2:1; unsigned b3:1; unsigned b4:1; unsigned b5:1; unsigned b6:1; unsigned b7:1; } bit; } c,d,r; c.word = *oldCRC; //d.word = *newCRC; d.word = *crcTof; r.word = 0; r.bit.b0 = c.bit.b7 ^ c.bit.b6 ^ c.bit.b0 ^ d.bit.b0 ^ d.bit.b6 ^ d.bit.b7; r.bit.b1 = c.bit.b6 ^ c.bit.b1 ^ c.bit.b0 ^ d.bit.b0 ^ d.bit.b1 ^ d.bit.b6; r.bit.b2 = c.bit.b6 ^ c.bit.b2 ^ c.bit.b1 ^ c.bit.b0 ^ d.bit.b0 ^ d.bit.b1 ^ d.bit.b2 ^ d.bit.b6; r.bit.b3 = c.bit.b7 ^ c.bit.b3 ^ c.bit.b2 ^ c.bit.b1 ^ d.bit.b1 ^ d.bit.b2 ^ d.bit.b3 ^ d.bit.b7; r.bit.b4 = c.bit.b4 ^ c.bit.b3 ^ c.bit.b2 ^ d.bit.b2 ^ d.bit.b3 ^ d.bit.b4; r.bit.b5 = c.bit.b5 ^ c.bit.b4 ^ c.bit.b3 ^ d.bit.b3 ^ d.bit.b4 ^ d.bit.b5; r.bit.b6 = c.bit.b6 ^ c.bit.b5 ^ c.bit.b4 ^ d.bit.b4 ^ d.bit.b5 ^ d.bit.b6; r.bit.b7 = c.bit.b7 ^ c.bit.b6 ^ c.bit.b5 ^ d.bit.b5 ^ d.bit.b6 ^ d.bit.b7 ; *crcTof=r.word; //return r.word; }; void Digitizer::Paddle2Pmt(Int_t plane, Int_t paddle, Int_t *pl, Int_t *pr){ //* @param plane (0 - 5) //* @param paddle (plane=0, paddle = 0,...5) //* @param padid (0 - 23) // Int_t padid=-1; Int_t pads[6]={8,6,2,2,3,3}; // Int_t somma=0; Int_t np=plane; for(Int_t j=0; jQuery_GL_PARAM(3,202,fDbc); if(!error){ calfile.str(""); calfile << glparam->PATH.Data() << "/"; calfile << glparam->NAME.Data(); printf("\n Using TOF calibration file: \n %s\n",calfile.str().c_str()); ifstream fileTriggerCalib; fileTriggerCalib.open(calfile.str().c_str()); for(Int_t i=0; i> temp; fileTriggerCalib >> atte1[i]; fileTriggerCalib >> lambda1[i]; fileTriggerCalib >> atte2[i]; fileTriggerCalib >> lambda2[i]; fileTriggerCalib >> temp; } fileTriggerCalib.close(); } else{ cout<