///////////////////////////////////////////////////////////////// // // MTrigger // // #include "MTrigger.hxx" #include "TROOT.h" #include "TFile.h" #include "TH1.h" #include "TObjArray.h" #include "MGTriggerSignal.hxx" #include "MGeomCam.h" #include "MGeomPix.h" using namespace std; MTrigger::MTrigger(int pix) { // ============================================================ // // default constructor // // The procedure is the following: // // 1. Allocation of some memory needed // 2. some parameters of the trigger are set to default. // 3. if a File MTrigger.card exists in the current directory, // this parameters of the trigger may be changed // 4. Then the all signals are set to zero FILE *unit_mtrig ; Int_t endflag = 1 ; Int_t bthresholdpixel = FALSE; char datac[256] ; char dummy[50] ; char input_thres[50]; Int_t i, ii ; Float_t threshold ; // Number of pixels in the trigger region pixnum=pix; // // allocate the memory for the 2dim arrays (a_sig, d_sig ) // used = new Bool_t[pix]; nphotshow = new Int_t[pix]; nphotnsb = new Int_t[pix]; nphotstar = new Int_t[pix]; a_sig = new Float_t * [pix]; d_sig = new Float_t * [pix]; baseline = new Float_t[pix]; dknt = new Bool_t[pix]; noise = new Float_t[TRIGGER_TIME_SLICES*1001]; chan_thres = new Float_t[pix]; for(Int_t j=0;j<6;j++) NN[j] = new Int_t[pix]; for(Int_t j=0;j %s <--", datac ) ; // // now compare the line with controlcard words // if ( strncmp (datac, "channel_threshold", 17 ) == 0 ) { sscanf (datac, "%s %f", dummy, &threshold ) ; } else if ( strncmp (datac, "gate_length", 11 ) == 0 ) { sscanf (datac, "%s %f", dummy, &gate_leng ) ; } else if ( strncmp (datac, "response_fwhm", 13 ) == 0 ) { sscanf (datac, "%s %f", dummy, &fwhm_resp ) ; } else if ( strncmp (datac, "response_ampl", 13 ) == 0 ) { sscanf (datac, "%s %f", dummy, &l_resp ) ; } else if ( strncmp (datac, "overlaping", 10 ) == 0 ) { sscanf (datac, "%s %f", dummy, &overlaping_time ) ; } else if ( strncmp (datac, "multiplicity", 12 ) == 0 ) { sscanf (datac, "%s %f", dummy, &trigger_multi ) ; } else if ( strncmp (datac, "topology", 8 ) == 0 ) { sscanf (datac, "%s %i", dummy, &trigger_geometry ) ; } else if ( strncmp (datac, "threshold_file", 14 ) == 0 ) { sscanf (datac, "%s %s", dummy, input_thres ) ; bthresholdpixel=kTRUE; } if ( feof(unit_mtrig) != 0 ) { endflag = 0 ; } } fclose ( unit_mtrig ) ; } else { cout << "[MTrigger] use the standard values for MTrigger "<< endl ; } cout << endl << "[MTrigger] Setting up the MTrigger with this values "<< endl ; if(bthresholdpixel){ cout< max ) { imax = i ; max = sing_resp[i] ; } } peak_time = ( (Float_t) imax ) / ( (Float_t) TRIG_SLICES_PER_NSEC ) ; // Initialize histogram histPmt which represents the distribution of amplitudes // of the PMT response to a single photpelectron. InitGainFluctuations(); // // create the random generator for the Electronic Noise // GenElec = new TRandom() ; GenElec->SetSeed(0); // // Read in the lookup table for NN trigger // FILE *unit ; int id ; i = 0 ; if ( (unit = fopen("../include-MTrigger/TABLE_NEXT_NEIGHBOUR", "r" )) == 0 ) { cout << "ERROR: not able to read ../include-MTrigger/TABLE_NEXT_NEIGHBOUR" << endl ; exit(123) ; } else { while ( i < pix ) { fscanf ( unit, " %d", &id ) ; for ( Int_t k=0; k<6; k++ ) { fscanf ( unit, "%d ", &NN[k][i] ) ; } i++ ; } fclose (unit) ; } // // Read in the lookup table for trigger cells // i = 0 ; if ( (unit = fopen("../include-MTrigger/TABLE_PIXELS_IN_CELLS", "r" )) == 0 ) { cout << "ERROR: not able to read ../include-MTrigger/TABLE_PIXELS_IN_CELLS" << endl ; exit(123) ; } else { while ( i < pix ) { for ( Int_t k=0; k max ) { imax = i ; max = sing_resp[i] ; } } peak_time = ( (Float_t) imax ) / ( (Float_t) TRIG_SLICES_PER_NSEC ) ; // Initialize histogram histPmt which represents the distribution of amplitudes // of the PMT response to a single photpelectron. InitGainFluctuations(); // // Change name of histogram (tag with CT id) to avoid confusion in the case of // multi-telescope simulations. // char histname[32]; sprintf(histname, "histPmt_%d", ct_id); histPmt->SetName(histname); // // create the random generator for the Electronic Noise // GenElec = new TRandom() ; // // Read in the lookup table for NN trigger // for(i=0; i < pixnum;i++ ) { MGeomPix &pixel = (*camgeom)[i]; for ( Int_t k=0; k<6; k++ ) { NN[k][i]=pixel.GetNeighbor(k); } } // // Read in the lookup table for trigger cells // FILE *unit; i = 0 ; if ( (unit = fopen("../include-MTrigger/TABLE_PIXELS_IN_CELLS", "r" )) == 0 ) { cout << "ERROR: not able to read ../include-MTrigger/TABLE_PIXELS_IN_CELLS" << endl ; exit(123) ; } else { while ( i < pixnum ) { for ( Int_t k=0; k max ) { imax = i ; max = sing_resp[i] ; } } peak_time = ( (Float_t) imax ) / ( (Float_t) TRIG_SLICES_PER_NSEC ) ; // Initialize histogram histPmt which represents the distribution of amplitudes // of the PMT response to a single photpelectron. InitGainFluctuations(); // // create the random generator for the Electronic Noise // GenElec = new TRandom() ; // // // set all the booleans used to FALSE, indicating that the pixel is not // used in this event. // for ( i =0 ; i TOTAL_TRIGGER_TIME ) { cout << " WARNING: time of phe out of time range: " << time << endl; return 0. ; } else { return ( Fill( iPix, time, CASE_SHOW ) ) ; } } Float_t MTrigger::FillNSB(Int_t iPix, Float_t time) { // ============================================================ // // Fills the information of one single Phe electron that // comes from the NSB // // // First check the time // if ( time < 0. || time > TOTAL_TRIGGER_TIME ) { cout << " WARNING: time of phe out of time range: " << time << endl; return 0. ; } else { return ( Fill( iPix, time - peak_time, CASE_NSB ) ) ; } } Float_t MTrigger::FillStar(Int_t iPix, Float_t time) { // ============================================================ // // Fills the information of one single Phe electron that // comes from a star // // First check the time // if ( time < 0. || time > TOTAL_TRIGGER_TIME ) { cout << " WARNING: time of phe out of time range: " << time << endl; return 0. ; } else { return ( Fill( iPix, time - peak_time, CASE_STAR ) ) ; } } Float_t MTrigger::Fill( Int_t iPix, Float_t time, Int_t fall ) { // ============================================================ // // Fills the information in the array for the analog signal // Float_t PmtAmp = 0 ; // Amplitude of the PMT signal (results from noise) if ( iPix < 0 ) { cout << " ERROR: in MTrigger::Fill() " << endl ; cout << " ERROR: Pixel Id < 0 ---> Exit " << endl ; exit (1) ; } else if ( iPix >= CAMERA_PIXELS ) { cout << " ERROR: in MTrigger::Fill() " << endl ; cout << " ERROR: Pixel Id > CAMERA_PIXELS ---> Exit " << endl ; exit (1) ; } else if ( iPix >= pixnum ) { // // We do not have to fill information in the trigger part, // but we must create the height of the pulse going into // the FADC simulation // if (fGainFluctuations) PmtAmp = (histPmt->GetRandom()/histMean) ; else PmtAmp = 1.0; // AM April 2004: removed updating of counters nphotshow, nphotnsb, // nphotstar for outer pixels... these arrays (see constructors) are // initialized only with as many elements as trigger pixels!! This // made the camera crash at random in some ocassions. } else { // // we have a trigger pixel and we fill it // Int_t i ; // // but at the beginning we must check if this pixel is // hitted the first time // if ( used[iPix] == kFALSE ) { used [iPix] = kTRUE ; // baseline[iPix] = 0. ; for (i=0; i < TRIGGER_TIME_SLICES; i++ ) { a_sig[iPix][i] = 0. ; d_sig[iPix][i] = 0. ; } } // // get the randomized amplitude (unless fGainFluctuations == kFALSE) // if (fGainFluctuations) PmtAmp = (histPmt->GetRandom()/histMean) ; else PmtAmp = 1.0; // // select the first slice to fill // Int_t ichan = (Int_t) ( time * ((Float_t) TRIG_SLICES_PER_NSEC) ) ; // // look over the response signal and put it in the signal line // for ( i = 0 ; i= 0 && (ichan+i) < TRIGGER_TIME_SLICES ) { a_sig[iPix][ichan+i] += PmtAmp * sing_resp[i] ; } } // // we fill the information in the counters of phe's // if ( fall == CASE_SHOW ) nphotshow[iPix]++ ; else if ( fall == CASE_NSB ) nphotnsb[iPix]++ ; else if ( fall == CASE_STAR ) nphotstar[iPix]++ ; // // return PmtAmp ; } return PmtAmp ; } void MTrigger::AddNSB( Int_t iPix, Float_t resp[TRIGGER_TIME_SLICES]){ // ================================================================ // // Sets the information in the array for the analog signal // from a given array // if ( iPix < 0 ) { cout << " ERROR: in MTrigger::SetNSB() " << endl ; cout << " ERROR: Pixel Id < 0 ---> Exit " << endl ; exit (1) ; } else if ( iPix >= CAMERA_PIXELS ) { cout << " ERROR: in MTrigger::SetNSB() " << endl ; cout << " ERROR: Pixel Id > CAMERA_PIXELS ---> Exit " << endl ; exit (1) ; } else if ( iPix >= pixnum ) { // // We have not to fill information in the trigger part. // } else { // // we have a trigger pixel and we fill it // Int_t i ; // // but at the beginning we must check if this pixel is // hitted the first time // if ( used[iPix] == kFALSE ) { used [iPix] = kTRUE ; for (i=0; i < TRIGGER_TIME_SLICES; i++ ) { a_sig[iPix][i] = 0. ; d_sig[iPix][i] = 0. ; } } // // look over the response signal and put it in the signal line // for ( i = 0 ; iGaus(0., rausch ); } cout<<"MTrigger::SetElecNoise ... done"<Integer(TRIGGER_TIME_SLICES*1000); if ( used[i] == kFALSE ) { used [i] = kTRUE ; memcpy( (Float_t*)a_sig[i], (Float_t*)&noise[startslice], TRIGGER_TIME_SLICES*sizeof(Float_t)); memset( (Float_t*)d_sig[i], 0, TRIGGER_TIME_SLICES*sizeof(Float_t)); } // // Then the noise is introduced for each time slice // else for ( Int_t ii=0 ; ii= chan_thres[i] ) { { if ( dknt[i] == kFALSE ) { dknt [i] = kTRUE ; iM++ ; } // cout << " disk " << ii ; // // put the standard diskriminator signal in // the diskriminated signal // for ( Int_t j=0 ; j < jmax ; j++ ) { if ( ii+j < TRIGGER_TIME_SLICES ) { d_sig [i][ii+j] = 1. ; } } ii = ii + jmax ; } } else d_sig[i][ii]=0.; } } } } void MTrigger::ShowSignal (MMcEvt *McEvt) { // ============================================================ // // This method is used to book the histogramm to show the signal in // a special gui frame (class MGTriggerSignal). After the look onto the // signals for a better understanding of the things we will expect // the gui frame and all histogramms will be destroyed. // // // first of all create a list of the histograms to show // // take only that one with a entry TH1F *hist ; TH1F *dhist ; Char_t dumm[10]; Char_t name[256]; TObjArray *AList ; AList = new TObjArray(10) ; TObjArray *DList ; DList = new TObjArray(10) ; // the list of analog signal histograms // at the beginning we initalise 10 elements // but this array expand automaticly if neccessay Int_t ic = 0 ; for ( Int_t i=0 ; i < pixnum; i++ ) { if ( used [i] == kTRUE ) { sprintf (dumm, "A_%d", i ) ; sprintf (name, "analog %d", i ) ; hist = new TH1F(dumm, name, TRIGGER_TIME_SLICES, 0., TOTAL_TRIGGER_TIME); // // fill the histogram // for (Int_t ibin=1; ibin <=TRIGGER_TIME_SLICES; ibin++) { hist->SetBinContent (ibin, a_sig[i][ibin-1]) ; } hist->SetMaximum(8.); hist->SetMinimum(-8.); hist->SetStats(kFALSE); AList->Add(hist) ; sprintf (dumm, "D_%d", i ) ; sprintf (name, "digital %d", i ) ; dhist = new TH1F(dumm, name, TRIGGER_TIME_SLICES, 0., TOTAL_TRIGGER_TIME); if ( dknt[i] == kTRUE ) { // // fill the histogram of digital signal // for (Int_t ibin=1; ibin <=TRIGGER_TIME_SLICES; ibin++) { dhist->SetBinContent (ibin, d_sig[i][ibin-1]) ; dhist->SetStats(kFALSE); } } dhist->SetMaximum(1.5); DList->Add(dhist); ic++ ; } } // // create the Gui Tool // // new MGTriggerSignal(McEvt, AList, DList, gClient->GetRoot(), gClient->GetRoot(), 400, 400 ) ; // // delete the List of histogramms // AList->Delete() ; DList->Delete() ; delete AList ; delete DList ; } Int_t MTrigger::ZeroLevel() { // ============================================================ // // This is a level introduced just to speed up the program. // It makes sense to look for next neighbours only if there // are at least trigger_multi pixels with a diskriminator // signal. // // // first count the pixels with a diskriminator signal // Int_t iMul = 0 ; for ( Int_t iP =0 ; iP < pixnum; iP++ ) { // // if ( dknt[iP] == kTRUE ) { iMul++ ; } } // // only if there are at least more pixels than requested // it make sense to look into details if ( iMul >= trigger_multi ) { // // fill the sum signal of all diskriminator signals // for ( Int_t iP =0 ; iP < pixnum; iP++ ) { // // if ( dknt[iP] == kTRUE ) { // // sum it up // for (Int_t iS=0; iS< TRIGGER_TIME_SLICES; iS++ ) { // // sum_d_sig [iS] += d_sig[iP][iS] ; } } } // // run over the sum_d_sig and check each time slice // Int_t iReturn = 0 ; for (Int_t iS=0; iS< TRIGGER_TIME_SLICES; iS++ ) { if ( sum_d_sig[iS] >= trigger_multi ) { iReturn++ ; nZero++; SlicesZero[iS] = kTRUE ; } else SlicesZero[iS] = kFALSE; } return ( iReturn ) ; } else { return 0 ; } } Int_t MTrigger::FirstLevel() { //================================================= // // This is a level trigger which can look for several // multiplicities (trigger_multi) // and topologies (trigger_geometry) // Int_t iReturn = 0 ; // Return value for this function // Definition of needed variables Bool_t Muster[pixnum] ; Bool_t Neighb[pixnum] ; Int_t iMulti = 0 ; // We put several wrong topologies which we already know that they // are not possible. It can save time. if (trigger_geometry==0 && trigger_multi>7) { cout <<"You are looking for a topology that needs more than six neighbours of the same pixel"<2) { cout << "This trigger topology is not implemented"< 0. ) { Muster[iPix] = kTRUE ; } } } // end of loop over the pixels // // Here we check which of the "muster" pixels will be fired for // the minimum required overlaping time // OverlapingTime(Muster, &Muster[0],iSli); // // here we have to look for the topologies // switch(trigger_geometry){ case 0:{ // It looks for a pixel above threshold which has // trigger_multi-1 neighbour pixels above threshold Bool_t Dummy[pixnum] ; // Loop over all pixels for (int j=0;j= pixnum ) { } // the nextneighbour is not inside the pixnum else { // // look if the boolean of nn pixels is true // if ( m[ NN[kk][i] ] && !n[NN[kk][i]] ) { n[NN[kk][i]]=kTRUE ; return_val =kTRUE; } } } else break; } } } return(return_val); } Float_t MTrigger::GetFirstLevelTime( Int_t il ){ //============================================================= // // It gives the time for the il trigger at first level return((Float_t) ((Float_t) SlicesFirst[il]/((Float_t) TRIG_SLICES_PER_NSEC))); } Int_t MTrigger::GetFirstLevelPixel( Int_t il ){ //============================================================= // // It gives the pixel that triggers for the il trigger at first level return(PixelsFirst[il]); } void MTrigger::OverlapingTime ( Bool_t m[], Bool_t *n, Int_t ifSli){ //============================================================ // // It returns in n the pixels of m that are fired during the // required overlaping time for trigger after ifSli int i,j; int iNumSli; // Translation from ns to slices iNumSli=(int) (overlaping_time*TRIG_SLICES_PER_NSEC); if (iNumSli<1) iNumSli=1; // Put pixels that fulfill the requirement in n for (i=0;iSetBinContent(i+1 ,ValRazmik[i]); histMean = histPmt->GetMean() ; fGainFluctuations = kTRUE; // Default value return; }