//////////////////////////////////////////////////////////////// // // MFadc // // #include "MFadc.hxx" #include "MMcEvt.hxx" #include "TROOT.h" #include #include #include #include "TH1.h" #include "TObjArray.h" #include "MGFadcSignal.hxx" using namespace std; MFadc::MFadc(Int_t pix, Int_t shape, Float_t integral, Float_t fwhm, Int_t shapeout, Float_t integralout, Float_t fwhmout, Float_t trigger_delay) { // // Constructor overloaded II // // Input variables: // 1. integral(out) = integration of the single phe response for inner // (outer) pixels. // 2. fwhm(out) = width at half high of the single phe response for // inner (outer) pixels. // // trigger_delay: shift of signals towards later times in FADC, in order // to center the signals in a good range. It acts as a sort of delay of // the signals (before being sent to the FADC) with respect to the trigger. // // The procedure is the following: // 1. some parameters of the trigger are set to default. // this parameters of the trigger may be changed // 3. Then the all signals are set to zero numpix=pix; fwhm_resp = fwhm; integ_resp = integral; fwhm_resp_outer = fwhmout; integ_resp_outer = integralout; shape_resp=shape; shape_resp_outer=shapeout; cout<< "[MFadc] Setting up the MFadc with this values "<< endl ; cout<< "[MFadc] - Inner pixels : "<< endl ; switch(shape_resp){ case 0: cout<< "[MFadc] Pulse shape : Gaussian ("<0)?0.5:-0.5; sing_resp[i] = (p1*exp(-p2*(exp(-p2*zed_slices)+zed_slices))+p4+ p5*exp(-p2*(exp(-p2*zed_slices)+p6*zed_slices))+p7*d); response_sum_inner += sing_resp[i]; } break; default: cout<<"[MFadc] MFadc::MFadc : Shape of FADC pulse for inner pixel unknown." <0)?0.5:-0.5; sing_resp_outer[i] = (p1*exp(-p2*(exp(-p2*zed_slices)+zed_slices))+p4+ p5*exp(-p2*(exp(-p2*zed_slices)+p6*zed_slices))+p7*d); response_sum_outer += sing_resp_outer[i]; } break; default: cout<<"[MFadc] MFadc::MFadc : Shape of FADC pulse for inner pixel unknown." < numpix ) { cout << " WARNING: MFadc::Fill() : iPix greater than Pixels in Camera = " << numpix << endl ; exit(987) ; } if ( used[iPix] == FALSE ) { used [iPix] = TRUE ; for (i=0; i < (Int_t) SLICES_MFADC; i++ ) { sig[iPix][i] = 0. ; } } // // then select the time slice to use (ican) // if ( time < TOTAL_TRIGGER_TIME+fadc_time_offset ) { // // determine the slices number assuming the WIDTH_RESPONSE_MFADC // ichan marks the start of the pulse, in number of bins of width // WIDTH_RESPONSE_MFADC (2/3 of a ns), measured from the start of the // FADC. // ichan = (Int_t) ( time / ((Float_t) WIDTH_RESPONSE_MFADC )); // // putting the response slices in the right sig slices. // Be carefull, because both slices have different widths. // // // AM, Jan 2004: Replaced former FADC simulation (integration of signal) // with a more realistic one (measuring signal height at discrete points). // // We take the pulse height in the middle of FADC slices, we start in the // first such point after the time "time" (=ichan in response bins). Each // FADC slice corresponds to SUBBINS response bins (SUBBINS=5 by default). Int_t first_i = Int_t(SUBBINS/2) - ichan%(Int_t)SUBBINS; first_i = first_i < 0 ? (Int_t)SUBBINS+first_i : first_i; for ( i = first_i ; i < (Int_t)RESPONSE_SLICES; i += (Int_t)SUBBINS) { ichanfadc = (Int_t) ((ichan+i)/SUBBINS) ; if ( ichanfadc < 0 ) continue; // // SLICES_MFADC is by default 48. sig[][] is not the true FADC, which // is filled from sig[][] in MFadc::TriggeredFadc() // if ( (ichanfadc) < (Int_t)SLICES_MFADC ) { sig[iPix][ichanfadc] += (amplitude * sing_resp[i] ) ; } } } else { cout << " WARNING! Fadc::Fill " << time << " out of TriggerTimeRange " << TOTAL_TRIGGER_TIME+fadc_time_offset << endl ; } } void MFadc::FillOuter( Int_t iPix, Float_t time, Float_t amplitude ) { // // fills the information about one single Phe in the Trigger class // for an outer pixel // // parameter is the number of the pixel and the time-difference to the // first particle // // Int_t i, ichan, ichanfadc ; // // first we have to check if the pixel iPix is used or not until now // if this is the first use, reset all signal for that pixels // if ( iPix > numpix ) { cout << " WARNING: MFadc::FillOuter() : iPix greater than CAMERA_PIXELS" << endl ; exit(987) ; } if ( used[iPix] == FALSE ) { used [iPix] = TRUE ; for (i=0; i < (Int_t) SLICES_MFADC; i++ ) { sig[iPix][i] = 0. ; } } // // then select the time slice to use (ican) // if ( time < TOTAL_TRIGGER_TIME+fadc_time_offset ) { // // determine the slices number assuming the WIDTH_RESPONSE_MFADC // ichan = (Int_t) ( time / ((Float_t) WIDTH_RESPONSE_MFADC )); // // putting the response slices in the right sig slices. // Be carefull, because both slices have different widths. // // // AM, Jan 2004: Replaced former FADC simulation (integration of signal) // with a more realistic one (measuring signal height at discrete points). // // We take the pulse height in the middle of FADC slices, we start in the // first such point after the time "time" (=ichan in response bins). Each // FADC slice corresponds to SUBBINS response bins (SUBBINS=5 by default). Int_t first_i = Int_t(SUBBINS/2) - ichan%(Int_t)SUBBINS; first_i = first_i < 0 ? (Int_t)SUBBINS+first_i : first_i; for ( i = first_i ; i < (Int_t)RESPONSE_SLICES; i += (Int_t)SUBBINS) { ichanfadc = (Int_t) ((ichan+i)/SUBBINS) ; if ( ichanfadc < 0 ) continue; if ( (ichanfadc) < (Int_t)SLICES_MFADC ) { sig[iPix][ichanfadc] += (amplitude * sing_resp_outer[i] ) ; } } } else { cout << " WARNING! Fadc::FillOuter " << time << " out of TriggerTimeRange " << TOTAL_TRIGGER_TIME+fadc_time_offset << endl ; } } void MFadc::Set( Int_t iPix, Float_t resp[(Int_t) SLICES_MFADC]) { // // Sets the information about fadc reponse from a given array // // parameter is the number of the pixel and the values to be set // // Int_t i ; // // first we have to check if the pixel iPix is used or not until now // if this is the first use, reset all signal for that pixels // if ( iPix > numpix ) { cout << " WARNING: MFadc::Fill() : iPix greater than CAMERA_PIXELS" << endl ; exit(987) ; } if ( used[iPix] == FALSE ) { used [iPix] = TRUE ; for (i=0; i < (Int_t)SLICES_MFADC; i++ ) { sig[iPix][i] = 0. ; } } for ( i = 0 ; i<(Int_t)SLICES_MFADC; i++ ) { sig[iPix][i] = resp[i] ; } } void MFadc::AddSignal( Int_t iPix, Float_t resp[(Int_t) SLICES_MFADC]) { // // Adds signals to the fadc reponse from a given array // // parameters are the number of the pixel and the values to be added // // Int_t i ; // // first we have to check if the pixel iPix is used or not until now // if this is the first use, reset all signal for that pixels // if ( iPix > numpix ) { cout << " WARNING: MFadc::Fill() : iPix greater than CAMERA_PIXELS" << endl ; exit(987) ; } if ( used[iPix] == FALSE ) { used [iPix] = TRUE ; for (i=0; i < (Int_t)SLICES_MFADC; i++ ) { sig[iPix][i] = 0. ; } } for ( i = 0 ; i<(Int_t)SLICES_MFADC; i++ ) { sig[iPix][i] += resp[i] ; } } void MFadc::SetPedestals( Int_t ped) { // It sets pedestal for each pixel flat randomly dstributed between 0 and ped // It uses the instance of TRandom GenElec. Int_t i; for(i=0;iRndm()); } } void MFadc::SetPedestals( Float_t *ped) { // It sets pedestal for each pixel from ped array Int_t i; for(i=0;iRndm()); for(j=0;j<(Int_t) SLICES_MFADC;j++) sig[i][j]+=fdum; } } } else { // The program will put the specifies offset to the pixel "pixel". if (used[pixel]){ fdum=(10*GenOff->Rndm()); for(j=0;j<(Int_t) SLICES_MFADC;j++) sig[pixel][j]+=fdum; } } }else { // The "offset" will be the offset for the FADC if (pixel<0) { // It does not exist, so all pixels will have the same offset for(i=0;iGaus(0., value1 ); noise_outer[i]=GenElec->Gaus(0., value2 ); } cout<<"MFadc::SetElecNoise ... done"<Integer(((Int_t)SLICES_MFADC)*1000); if ( used[i] == FALSE ) { used [i] = TRUE ; if (i < fInnerPixelsNum) memcpy( (Float_t*)&sig[i][0], (Float_t*)&noise[startslice], ((Int_t) SLICES_MFADC)*sizeof(Float_t)); else memcpy( (Float_t*)&sig[i][0], (Float_t*)&noise_outer[startslice], ((Int_t) SLICES_MFADC)*sizeof(Float_t)); } // // If pixel already in use, the noise is added each time slice // else { if (i < fInnerPixelsNum) for ( Int_t is=0 ; is< (Int_t)SLICES_MFADC ; is++ ) sig[i][is] += noise[startslice+is]; else for ( Int_t is=0 ; is< (Int_t)SLICES_MFADC ; is++ ) sig[i][is] += noise_outer[startslice+is]; } } } void MFadc::SetDigitalNoise(Float_t value){ UInt_t i; Float_t xrdm; cout<<"MFadc::SetDigitalNoise ... generating database for electronic noise." <Gaus(0., value); digital_noise[i]=(xrdm>0?Int_t(xrdm+0.5):Int_t(xrdm-0.5)); } cout<<"MFadc::SetDigitalNoise ... done"<Integer((Int_t) SLICES_MFADC*999); // // Then the noise is introduced for each time slice // for ( Int_t is=0 ; is< FADC_SLICES; is++ ) { output[i][is] += digital_noise[startslice+is]; output_lowgain[i][is] += digital_noise[startslice+FADC_SLICES+is]; } } } void MFadc::Scan() { for ( Int_t ip=0; ip 0. ) { printf (" %4.1f/", sig[ip][is] ) ; } else { printf ("----/" ) ; } } printf ("\n"); } } } void MFadc::Scan(Float_t time) { // // first of all we subtract from the time a offset (8 ns) // Float_t t ; (0 > time - TIME_BEFORE_TRIGGER)? t=fadc_time_offset: t=(time-TIME_BEFORE_TRIGGER+fadc_time_offset) ; // to show also the start of the pulse before the trigger time if ( t < 0. ) { cout << " WARNING!! FROM MFADC::SCAN(t) " << endl ; exit (776) ; } // // calculate the first slice to write out // Int_t iFirstSlice ; iFirstSlice = (Int_t) ( t / WIDTH_FADC_TIMESLICE ) ; for ( Int_t ip=0; ipInteger((Int_t) SLICES_MFADC*999); for ( Int_t is=0; is < n_slices ; is++ ) { fvalue = pedestal[pix]+(sig[pix][is]-pedestal[pix])/factor; fvalue += digital_noise[startslice+is]; fvalue = fvalue < 0? fvalue-0.5 : fvalue+0.5; value = fvalue < 0.? (UChar_t) 0 : (fvalue > 255.? 255 : (UChar_t) fvalue); // Add up slices: sum += value - pedestal[pix]; } return sum; } //======================================================================= void MFadc::TriggeredFadc(Float_t time) { // // calculate the first slice to write out, according to trigger time: // Int_t iFirstSlice ; Int_t i; // // We had 0.5 for the correct rounding: // iFirstSlice = (Int_t) ( 0.5 + time / WIDTH_FADC_TIMESLICE ) ; for ( Int_t ip=0; ipSetBinContent (ibin, sig[i][ibin-1]) ; } // hist->SetMaximum( 5.); // hist->SetMinimum(-10.); hist->SetStats(kFALSE); // hist->SetAxisRange(0., 80. ) ; AList->Add(hist) ; ic++ ; } } // // create the Gui Tool // // new MGFadcSignal(McEvt, AList, trigTime, gClient->GetRoot(), gClient->GetRoot(), 400, 400 ) ; // // delete the List of histogramms // AList->Delete() ; delete AList ; } UChar_t MFadc::GetFadcSignal(Int_t pixel, Int_t slice){ // It returns the analog signal for a given pixel and a given FADC // time slice which would be read. // Since May 1 2004, we do the rounding and the truncation to the range // 0-255 counts here. (A. Moralejo) Float_t out = output[pixel][slice] > 0. ? output[pixel][slice]+0.5 : output[pixel][slice]-0.5; // (add or subtract 0.5 for correct rounding) return (out < 0.? (UChar_t) 0 : (out > 255.? (UChar_t) 255 : (UChar_t) out)); } UChar_t MFadc::GetFadcLowGainSignal(Int_t pixel, Int_t slice){ // It returns the analog signal for a given pixel and a given FADC // time slice which would be read. Same comment as above. Float_t outlow = output_lowgain[pixel][slice] > 0. ? output_lowgain[pixel][slice]+0.5 : output_lowgain[pixel][slice]-0.5; // (add or subtract 0.5 for correct rounding) return (outlow < 0.? (UChar_t) 0 : (outlow > 255.? (UChar_t) 255 : (UChar_t) outlow)); }