///////////////////////////////////////////////////////////////// // // MTrigger // // #include "MTrigger.hxx" #include "TROOT.h" #include "TFile.h" #include "TH1.h" #include "TObjArray.h" #include "MGTriggerSignal.hxx" MTrigger::MTrigger() { // ============================================================ // // 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 ; // // allocate the memory for the 2dim arrays (a_sig, d_sig ) // 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=TRUE; } 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) SLICES_PER_NSEC ) ; // // the amplitude of one single photo electron is not a constant. // There exists a measured distribution from Razmik. This distribution // is used to simulate the noise of the amplitude. // For this a histogramm (histPmt) is created and filled with the // values. // histPmt = new TH1F ("histPmt","Noise of PMT", 40, 0., 40.) ; Stat_t ValRazmik[41] = { 0., 2.14, 2.06, 2.05, 2.05, 2.06, 2.07, 2.08, 2.15, 2.27, 2.40, 2.48, 2.55, 2.50, 2.35, 2.20, 2.10, 1.90, 1.65, 1.40, 1.25, 1.00, 0.80, 0.65, 0.50, 0.35, 0.27, 0.20, 0.18, 0.16, 0.14, 0.12, 0.10, 0.08, 0.06, 0.04, 0.02, 0.01, 0.005,0.003, 0.001} ; histMean = histPmt->GetMean() ; for (i=0;i<41;i++){ histPmt->SetBinContent(i,ValRazmik[i]); } histMean = histPmt->GetMean() ; // // create the random generator for the Electronic Noise // GenElec = new TRandom() ; // // 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 < TRIGGER_PIXELS ) { fscanf ( unit, " %d", &id ) ; for ( Int_t k=0; k<6; k++ ) { fscanf ( unit, "%d ", &NN[i][k] ) ; } 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 < TRIGGER_PIXELS ) { for ( Int_t k=0; k max ) { imax = i ; max = sing_resp[i] ; } } peak_time = ( (Float_t) imax ) / ( (Float_t) SLICES_PER_NSEC ) ; // // the amplitude of one single photo electron is not a constant. // There exists a measured distribution from Razmik. This distribution // is used to simulate the noise of the amplitude. // For this a histogramm (histPmt) is created and filled with the // values. // histPmt = new TH1F ("histPmt","Noise of PMT", 40, 0., 40.) ; Stat_t ValRazmik[41] = { 0., 2.14, 2.06, 2.05, 2.05, 2.06, 2.07, 2.08, 2.15, 2.27, 2.40, 2.48, 2.55, 2.50, 2.35, 2.20, 2.10, 1.90, 1.65, 1.40, 1.25, 1.00, 0.80, 0.65, 0.50, 0.35, 0.27, 0.20, 0.18, 0.16, 0.14, 0.12, 0.10, 0.08, 0.06, 0.04, 0.02, 0.01, 0.005,0.003, 0.001} ; histMean = histPmt->GetMean() ; for (i=0;i<41;i++){ histPmt->SetBinContent(i,ValRazmik[i]); } histMean = histPmt->GetMean() ; // // create the random generator for the Electronic Noise // GenElec = new TRandom() ; // // 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 < TRIGGER_PIXELS ) { fscanf ( unit, " %d", &id ) ; for ( Int_t k=0; k<6; k++ ) { fscanf ( unit, "%d ", &NN[i][k] ) ; } 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 < TRIGGER_PIXELS ) { for ( Int_t k=0; k 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 shower // // // 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 the shower // // // 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 >= TRIGGER_PIXELS ) { // // We have not to fill information in the trigger part, // but we must create the height of the puls going into // the FADC simulation // PmtAmp = (histPmt->GetRandom()/histMean) ; // // But we fill the information in the counters of phe's // if ( fall == CASE_SHOW ) nphotshow[iPix]++ ; else if ( fall == CASE_NSB ) nphotshow[iPix]++ ; else if ( fall == CASE_STAR ) nphotstar[iPix]++ ; } 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] == FALSE ) { used [iPix] = TRUE ; // 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 // PmtAmp = (histPmt->GetRandom()/histMean) ; // // select the first slice to fill // Int_t ichan = (Int_t) ( time * ((Float_t) 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 ) nphotshow[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 >= TRIGGER_PIXELS ) { // // 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] == FALSE ) { used [iPix] = TRUE ; 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 ) ; } } } void MTrigger::SetFwhm(Float_t fwhm){ //=========================================================== // // It sets the fwhm for the single phe signal and // updates the sing_resp for it Float_t sigma ; Float_t x, x0 ; Int_t i; fwhm_resp = fwhm; sigma = fwhm_resp / 2.35 ; x0 = 3*sigma ; for (i=0; i< RESPONSE_SLICES ; i++ ) { x = i * (1./((Float_t)SLICES_PER_NSEC)) + (1./( 2 * (Float_t)SLICES_PER_NSEC )) ; sing_resp[i] = ampl_resp * expf(-0.5 * (x-x0)*(x-x0) / (sigma*sigma) ) ; } } void MTrigger::SetMultiplicity(Int_t multi){ //============================================================= // // It sets the private member trigger_multi trigger_multi=multi; } void MTrigger::SetTopology(Int_t topo){ //============================================================= // // It sets the private member trigger_geometry trigger_geometry=topo; } void MTrigger::SetThreshold(Float_t thres[]){ //============================================================= // // It sets the private member chan_thres[TRIGGER_PIXELS] Int_t i; for(i=0;i= chan_thres[i] ) { { if ( dknt[i] == FALSE ) { dknt [i] = TRUE ; 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 < TRIGGER_PIXELS; i++ ) { if ( used [i] == TRUE ) { 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] == TRUE ) { // // 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 < TRIGGER_PIXELS; iP++ ) { // // if ( dknt[iP] == TRUE ) { 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 < TRIGGER_PIXELS; iP++ ) { // // if ( dknt[iP] == TRUE ) { // // 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] = TRUE ; } else SlicesZero[iS] = FALSE; } 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[TRIGGER_PIXELS] ; Bool_t Neighb[TRIGGER_PIXELS] ; 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[TRIGGER_PIXELS] ; // Loop over all pixels for (int j=0;j= TRIGGER_PIXELS ) { } // the nextneighbour is not inside the TRIGGER_PIXELS else { // // look if the boolean of nn pixels is true // if ( m[ NN[i][kk] ] && !n[NN[i][kk]] ) { n[NN[i][kk]]=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) 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*SLICES_PER_NSEC); if (iNumSli<1) iNumSli=1; // Put pixels that fulfill the requirement in n for (i=0;i