#include #include #include #include #include #include #include "TVector3.h" #ifndef NOSKLIBRARIES #include "skheadC.h" #else #define COUNT_PER_NSEC (1.92000) #endif #include "fQEventManager.h" #include "spliTChan.h" #include "spliTChanOutC.h" #include "TRuntimeParameters.hxx" extern"C" { // ${CERN}/2005/src/packlib/kernlib/kerngen/tcgen/sortzv.F // http://wwwasdoc.web.cern.ch/wwwasdoc/shortwrupsdir/m101/top.html void sortzv_(float *, int *, int *, int *, int *, int *); } int spliTChan::fMAXPMTZ = 334380; int spliTChan::fNPMT = 11146; int spliTChan::fNMULT = 30; using namespace std; spliTChan::spliTChan(int aWriteHistos, int anPMT, int anMult ){ writeHistos = aWriteHistos; fMAXPMTZ = anPMT*anMult; fNPMT = anPMT; fNMULT = anMult; // "Constant" parameters q_thresh = 0.3; nwtr = 1.38; cwt = 30/nwtr; doTOFcorr = 1; //t_ind.reserve( fMAXPMTZ ); //t_ind.resize( fMAXPMTZ ); t_ind = new int [ fMAXPMTZ ]; chrgz = new float [ fMAXPMTZ ]; tHitz = new float [ fMAXPMTZ ]; t = new float [ fMAXPMTZ ]; q = new float [ fMAXPMTZ ]; //amis ttc[1] = new float [ fMAXPMTZ ]; ttc[0] = new float [ fMAXPMTZ ]; for (int ic=0; icSet_fQuiet(TRuntimeParameters::Get().GetParameterI("spliTChan.fQuiet")); this->SetCluster_nBinsScanWin(TRuntimeParameters::Get().GetParameterI("spliTChan.Cluster_nBinsScanWin")); this->SetCluster_nHitThr(TRuntimeParameters::Get().GetParameterI("spliTChan.Cluster_nHitThr")); this->SetCluster_nHitThrFall(TRuntimeParameters::Get().GetParameterI("spliTChan.Cluster_nHitThrFall")); this->SetCluster_tBinSepThresh(TRuntimeParameters::Get().GetParameterI("spliTChan.Cluster_tBinSepThresh")); //this->SetCluster_tExtendMin(TRuntimeParameters::Get().GetParameterI("spliTChan.Cluster_tExtendMin")); this->SetdoTOFcorr(TRuntimeParameters::Get().GetParameterI("spliTChan.doTOFcorr")); this->SetWaterRefractiveIndex(TRuntimeParameters::Get().GetParameterD("spliTChan.WaterRefractiveIndex")); this->Setq_thresh(TRuntimeParameters::Get().GetParameterD("spliTChan.q_thresh")); this->SetMuechk_TimeWindowCoarse(TRuntimeParameters::Get().GetParameterD("spliTChan.Muechk_TimeWindowCoarse")); this->SetMuechk_TimeWindowFine(TRuntimeParameters::Get().GetParameterD("spliTChan.Muechk_TimeWindowFine")); this->SetMuechk_nThrFrac(TRuntimeParameters::Get().GetParameterI("spliTChan.Muechk_nThrFrac")); this->SetMuechk_nThrMin(TRuntimeParameters::Get().GetParameterI("spliTChan.Muechk_nThrMin")); this->SetMuechk_fstBin(TRuntimeParameters::Get().GetParameterI("spliTChan.Muechk_fstBin")); this->SetMuechk_nBinsScanWin(TRuntimeParameters::Get().GetParameterI("spliTChan.Muechk_nBinsScanWin")); this->SetMuechk_prntPeakScanEnd(TRuntimeParameters::Get().GetParameterI("spliTChan.Muechk_prntPeakScanEnd")); this->SetMuechk_n50Thr(TRuntimeParameters::Get().GetParameterI("spliTChan.Muechk_n50Thr")); this->SetMuechk_excessThr(TRuntimeParameters::Get().GetParameterD("spliTChan.Muechk_excessThr")); this->SetMuechk_signifThr(TRuntimeParameters::Get().GetParameterD("spliTChan.Muechk_signifThr")); //TOF method parameters this->SetFixedTBeforePk(TRuntimeParameters::Get().GetParameterD("spliTChan.FixedTBeforePk")); this->SetFixedTAfterPk(TRuntimeParameters::Get().GetParameterD("spliTChan.FixedTAfterPk")); this->SetNHitThreshFact(TRuntimeParameters::Get().GetParameterD("spliTChan.nHitThreshFact")); if (!fQuiet) cout << "Cluster_nBinsScanWin ==== " << Cluster_nBinsScanWin << endl; // Debugging histograms // //double t_low = -200; // For TOF corrected h_tisk's //double t_high = 1500; double t_low = -5000; double t_high = 20000; double t_width = 10; int nbins = (int)((t_high-t_low)/t_width); if (writeHistos) { h_tiskz = new TH1F("h_tiskz","Hit Times (All);Time (ns)",nbins,t_low,t_high); for (int icand=0; icand<10; icand++) { h_tisk_corr0[icand] = new TH1F(Form("h_tisk_corr0_%d",icand),Form("Hit Times for Cluster %d;Raw Time (ns)",icand),nbins,t_low,t_high); h_tisk_corr1[icand] = new TH1F(Form("h_tisk_corr1_%d",icand),Form("Hit Times for Cluster %d;TOF Corrected Time (ns)",icand),nbins,t_low,t_high); } } t_low = -5000; t_high = 10000; t_width = 10; int nbinsx = (int)((t_high-t_low)/t_width); double q_low = -1; double q_high = 20; double q_width = 0.1; int nbinsy = (int)((q_high-q_low)/q_width); h_qiskz_vs_tiskz = 0; if (writeHistos) h_qiskz_vs_tiskz = new TH2F("h_qiskz_vs_tiskz","Hit Charge vs Time;Time (ns); Charge (pe)", nbinsx, t_low, t_high, nbinsy, q_low, q_high); } spliTChan::~spliTChan(){ if (h_tiskz) h_tiskz->Delete(); for (int icand=0; icandDelete(); if (h_tisk_corr1[icand]) h_tisk_corr1[icand]->Delete(); } if (h_qiskz_vs_tiskz) h_qiskz_vs_tiskz->Delete(); if (t_ind) delete [] t_ind; if (chrgz) delete [] chrgz; if (tHitz) delete [] tHitz; if (t) delete [] t; if (q) delete [] q; for (int ic=0; icPMTall_nhit; nUse = 0; if (vertex) { if (!fQuiet) cout << "spliTChan::GetHitInfo(): Applying TOF correction with vertex = " << vertex[0] << " " << vertex[1] << " " << vertex[2] << endl; } else if (!fQuiet) cout << "spliTChan::GetHitInfo(): No TOF correction." << endl; for (int ihit=0; ihitPMTall_q[ihit]; tHitz[ihit]=fQEventManager::Get()->PMTall_t[ihit]; int icab = fQEventManager::Get()->PMTall_icab[ihit]; // C++ indexing // Ignore hits that are below some charge threshold if (chrgz[ihit]<=q_thresh) continue; // Ignore hits with no time info if (tHitz[ihit]==0) { if (!fQuiet) cout << "spliTChan::GetHitInfo() Warning: tiskz[" << ihit << "] = 0" << endl; continue; } // Subtract TOF if given a vertex double dist=0; //if (vertex && doTOFcorr) { if (vertex) { TVector3 d; d[0] = fiTQun_shared::Get()->PMTpos[icab][0]-vertex[0]; d[1] = fiTQun_shared::Get()->PMTpos[icab][1]-vertex[1]; d[2] = fiTQun_shared::Get()->PMTpos[icab][2]-vertex[2]; dist = d.Mag(); } // Create array of useable hits //array for MakeClusters//amis ttc[0][nUse] = tHitz[ihit]; ttc[1][nUse] = tHitz[ihit]-dist/cwt; // t[nUse] = tHitz[ihit]-dist/cwt; q[nUse] = chrgz[ihit]; nUse++; } if(!nUse) return nUse; // Sort PMT hit times in ascending order int sortzv_mode = 1; int sortzv_nway = 0; int sortzv_nsort = 0; sortzv_(t, t_ind, &nUse, &sortzv_mode, &sortzv_nway, &sortzv_nsort); // Convert to C++ indexing for (int ihit=0; ihitSetGate(-1000/COUNT_PER_NSEC+1000.,1496/COUNT_PER_NSEC+1000.,false,false); int nThr = skq_nqisk/Muechk_nThrFrac; if (nThr <= Muechk_nThrMin) nThr = Muechk_nThrMin; if (!fQuiet) cout << "spliTChan::Muechk_GetParentPeakTime(): nThr, NQISK = " << nThr << ", " << skq_nqisk << endl; int i=0; do { //cout << "fitqun " << i << " " << t[t_ind[i+nThr]] << " " << t[t_ind[i]] << " " << t[t_ind[i+nThr]]-t[t_ind[i]] << endl; i++; //if (i+nThr >= nUse) return Muechk_tOya; if (i+nThr >= nUse) return i; } while ( t[t_ind[i+nThr]]-t[t_ind[i]] > Muechk_TimeWindowCoarse ); int i0 = i; //cout << "fitqun i0 = " << i0 << endl; int j = i0+1; int n_oya = 0; int i_oya = -1; do { do { j=j+1; } while ( t[t_ind[j]]-t[t_ind[i]] <= Muechk_TimeWindowFine ); // 30 ns time window int n=j-i; // # of hits in this 30 ns time window if(n > n_oya) { n_oya = n; // Set the most number of hits in a 30 ns time window i_oya = i; // Starting index of this time window } i++; } while( t[t_ind[i]]-t[t_ind[i0]] <= Muechk_TimeWindowCoarse ); if (i_oya>=0) Muechk_tOya = t[t_ind[i_oya]]; // <-Patrick starting time of 30 ns cluster of hits else if (!fQuiet) cout << "spliTChan::Muechk_GetParentPeakTime() Warning: i_oya < 0" << endl; if (!fQuiet) cout << "Primary peak time (Muechk_tOya), hits (n_oya) = " << Muechk_tOya << ", " << n_oya << endl << endl; return i_oya; } void spliTChan::Muechk_FindPeakCands(int i_oya) { const int nBinMax = 3000; float binWidth = 10; TH1I h_tdiff("h_tdiff","Time Difference from Parent Peak; #Deltat (ns)", nBinMax, 0, nBinMax*binWidth); int use_bin[nBinMax+2] = {0}; Muechk_tOya = t[t_ind[i_oya]]; // Fill histogram with time differences from parent peak // for (int ihit=0; ihit Muechk_tOya ) h_tdiff.Fill(t[ihit]-Muechk_tOya); //for (int ibin=1; ibin<=nBinMax; ibin++) //cout << "fitqun thist " << ibin << " " << h_tdiff.GetBinContent(ibin) << endl; // Coarse search near parent peak // for (int bin=Muechk_fstBin; bin<=Muechk_prntPeakScanEnd+Muechk_nBinsScanWin; bin++) { //for (int bin=Muechk_fstBin; bin<=45; bin++) { // 450 ns (original from muechk_gate.F) if( h_tdiff[bin] > h_tdiff[bin-1]+5 ) { if( h_tdiff[bin]+h_tdiff[bin+1] > h_tdiff[bin-1]+10 ) { float mean = (h_tdiff[bin-1]+h_tdiff[bin-2]+h_tdiff[bin-3])/3; float sigma = sqrt(mean); if( h_tdiff[bin] > mean+sigma*3 ) { use_bin[bin] = 1; } } } } // Coarse search far away from parent peak // int itimer = 0; for (int bin=Muechk_prntPeakScanEnd; bin<=nBinMax-(Muechk_nBinsScanWin-1); bin++) { //for (int bin=40; bin<=nBinMax-4; bin++) { // 400 ns (original from muechk_gate.F) int n50 = 0; for (int i=0; i Muechk_n50Thr) { if (itimer == 0) { itimer = 1; n50max = n50; binmax = bin; binsta = bin; } else { if (n50 > n50max) { n50max = n50; binmax = bin; } } } else { if (itimer == 1) { //if (bin-binsta > 4) { (original from muechk_gate.F) if (bin-binsta >= Muechk_nBinsScanWin) { use_bin[binmax]=1; } } itimer = 0; } } // Do not use re-counted neighbouring bins that are probably part of the same peak for (int bin=Muechk_fstBin; bin<=nBinMax-1; bin++) { if (use_bin[bin] == 1) { if (use_bin[bin-2] == 1 && use_bin[bin-1] == 1 ) { use_bin[bin]=0; } } } for (int bin=Muechk_fstBin; bin<=nBinMax-1; bin++) { if (use_bin[bin] == 1) { if (use_bin[bin-1] == 1 ) { use_bin[bin]=0; } } } //cout << "spliTChan::Muechk_FindPeakCands(): Candidate bins from coarse search" << endl; //cout << "bin bin_low_edge" << endl; //for (int bin=1; bin<=nBinMax; bin++) // if (use_bin[bin] == 1) // cout << bin << " " << h_tdiff.GetBinLowEdge(bin) << endl; //cout << endl; // Fine search // //cout << "spliTChan::Muechk_FindPeakCands(): Starting fine search..." << endl; int i0 = i_oya; for (int bin=1; bin<=Muechk_fstBin-1; bin++) i0 = i0+h_tdiff[bin]; Muechk_nCand = 0; for (int bin=Muechk_fstBin; bin<=nBinMax-1; bin++) { if (use_bin[bin] == 1) { // find peak and count nhit in window // int n_peak = 0; int i_peak = -1; float t_peak; int i0_min = i0 - h_tdiff[bin-1]; int i0_max = i0 + h_tdiff[bin] + h_tdiff[bin+1]; //cout << "fitqun blah " << bin << " " << i0 << " " << h_tdiff.GetBinContent(bin-1) << " " << h_tdiff.GetBinContent(bin) << " " << h_tdiff.GetBinContent(bin+1) << endl; //cout << "fitqun blah " << bin << " " << i0_min << " " << i0_max << " " << nUse << endl; if (i0_max >= nUse-1) i0_max = nUse-2; for (int i=i0_min; i<=i0_max; i++) { int n=1; do { n++; } while (t[t_ind[i+n]] - t[t_ind[i]] <= Muechk_TimeWindowFine ); if (n > n_peak) { n_peak = n; i_peak = i; t_peak = t[t_ind[i_peak]]; } } Muechk_tDiff[Muechk_nCand] = t_peak - Muechk_tOya; //cout << "bin = " << bin << endl; //cout << "t_peak, n_peak, tDiff = " << t_peak << ", " << n_peak << ", " << Muechk_tDiff[Muechk_nCand] << endl; // estimate background // double tWinBg; // Maybe this can be tweaked if (Muechk_tDiff[Muechk_nCand] <= 70) tWinBg = 20; else if (Muechk_tDiff[Muechk_nCand] <= 300) tWinBg = 30; else if (Muechk_tDiff[Muechk_nCand] <= 350) tWinBg = 50; else tWinBg = 100; if (Muechk_nCand > 0) { if (Muechk_tDiff[Muechk_nCand] - Muechk_tDiff[Muechk_nCand-1] <= tWinBg + Muechk_TimeWindowFine) { tWinBg = Muechk_tDiff[Muechk_nCand] - Muechk_tDiff[Muechk_nCand-1] - Muechk_TimeWindowFine - 10; // Maybe this can be tweaked if (tWinBg < 20) tWinBg = 20; // Maybe this can be tweaked } } Muechk_bg[Muechk_nCand] = 0; ///**************************** ///***************************** /// CRASH IN BELOW WHILE LOOP (in t_ind.at() overflow?) do { Muechk_bg[Muechk_nCand]++; //std::cout<<"Muechk nCand="< 0) { if (Muechk_tDiff[Muechk_nCand]-Muechk_tDiff[Muechk_nCand-1] < 1000) { // Maybe this can be tweaked if (Muechk_excess[Muechk_nCand] < 10) iflag = -1; // Maybe this can be tweaked iflag = 1; } } if (iflag != -1) { if ( (Muechk_tDiff[Muechk_nCand] > 600 && iflag == 0) // Maybe this can be tweaked || Muechk_excess[Muechk_nCand] >= Muechk_excessThr || Muechk_signif[Muechk_nCand] > Muechk_signifThr) { Muechk_nCand++; // Find candidates that are in the same 30 ns time window if (Muechk_nCand > 1) { if (Muechk_tDiff[Muechk_nCand-1]-Muechk_tDiff[Muechk_nCand-2] <= Muechk_TimeWindowFine) { Muechk_nCand--; // Probably the same decay-e // Set candidate to the lower of the two significances if (Muechk_signif[Muechk_nCand-1] < Muechk_signif[Muechk_nCand]) { Muechk_tDiff[Muechk_nCand-1] = Muechk_tDiff[Muechk_nCand]; Muechk_excess[Muechk_nCand-1] = Muechk_excess[Muechk_nCand]; Muechk_signif[Muechk_nCand-1] = Muechk_signif[Muechk_nCand]; } } } if (Muechk_nCand >= MAXCAND-1) break; } } // 30 continue (in muechk_gate.F) } i0 = i0 + h_tdiff[bin]; } if (!fQuiet) cout << endl; // Convert back to absolute time of TISKZ for (int i=0; i0) { for (int i=Muechk_nCand-1; i>=0; i--) { Muechk_bg[i+1] = Muechk_bg[i] ; Muechk_mean[i+1] = Muechk_mean[i] ; Muechk_tDiff[i+1] = Muechk_tDiff[i] ; Muechk_excess[i+1] = Muechk_excess[i]; Muechk_signif[i+1] = Muechk_signif[i]; } } // Add parent peak to beginning of array int i=0; Muechk_bg[i] = -1; Muechk_mean[i] = -1; Muechk_tDiff[i] = Muechk_tOya; Muechk_excess[i] = -1; Muechk_signif[i] = -1; Muechk_nCand++; if (!fQuiet) { cout << "spliTChan::Muechk_FindPeakCands(): Fine search results" << endl; cout << "Muechk_nCand = " << Muechk_nCand << endl; for (int i=0; i600) { ptime[n_sub] = Muechk_tDiff[imue]; n_sub++; } } //cout << "spliTChan: n_sub = " << n_sub << endl; if (!n_sub) return; int Muechk_nCand_inGate = Muechk_nCand - n_sub; // Muechk_nCand is now the number of "in-gate" decay-e for (int isub=0; isub1) // >1 to ignore parent peak // cout << "spliTChan: ptime[0] diffs = " << isub << " " << ptime[0]-Muechk_tDiff[Muechk_nCand_inGate-1] << endl; // //if (isub0) // cout << "spliTChan: ptime[isub-1] diffs = " << isub << " " << ptime[isub]-ptime[isub-1] << endl; if ( (isub==0 && Muechk_nCand_inGate>1 && ptime[0]-Muechk_tDiff[Muechk_nCand_inGate-1]<200) || //Time difference between this sub-event and next (isub0 && ptime[isub]-ptime[isub-1]<500) ) { //cout << "spliTChan: isub, ptime, excess = " << isub << " " << ptime[isub]-Muechk_tOya << " " << Muechk_excess[isub+1] << endl; if(isub Muechk_tOya ) h_tdiff.Fill(t[ihit]-Muechk_tOya); // Coarse search far away from parent peak // int itimer = 0; for (int bin=1; bin<=nBinMax-(Muechk_nBinsScanWin-1); bin++) { int n50 = 0; for (int i=0; i Muechk_n50Thr) { if (itimer == 0) { itimer = 1; n50max = n50; binmax = bin; binsta = bin; } else { if (n50 > n50max) { n50max = n50; binmax = bin; } } } else { if (itimer == 1) { //if (bin-binsta > 4) { (original from muechk_gate.F) if (bin-binsta >= Muechk_nBinsScanWin) { use_bin[binmax]=1; } } itimer = 0; } } // Do not use re-counted neighbouring bins that are probably part of the same peak for (int bin=1; bin<=nBinMax-1; bin++) { if (use_bin[bin] == 1) { if (use_bin[bin-2] == 1 && use_bin[bin-1] == 1 ) { use_bin[bin]=0; } } } for (int bin=1; bin<=nBinMax-1; bin++) { if (use_bin[bin] == 1) { if (use_bin[bin-1] == 1 ) { use_bin[bin]=0; } } } //cout << "spliTChan::Muechk_FindPeakCandsFine(): Candidate bins from coarse search" << endl; //cout << "bin bin_low_edge" << endl; //for (int bin=1; bin<=nBinMax; bin++) // if (use_bin[bin] == 1) // cout << bin << " " << h_tdiff.GetBinLowEdge(bin) << endl; //cout << endl; // Fine search // //cout << "spliTChan::Muechk_FindPeakCandsFine(): Starting fine search..." << endl; int i0 = i_oya; Muechk_nCand = 0; for (int bin=1; bin<=nBinMax-1; bin++) { if (use_bin[bin] == 1) { // find peak and count nhit in window // int n_peak = 0; int i_peak = -1; float t_peak; int i0_min = i0 - h_tdiff[bin-1]; int i0_max = i0 + h_tdiff[bin] + h_tdiff[bin+1]; if (i0_max >= nUse-1) i0_max = nUse-2; for (int i=i0_min; i<=i0_max; i++) { int n=1; do { n++; } while (t[t_ind[i+n]] - t[t_ind[i]] <= Muechk_TimeWindowFine ); if (n > n_peak) { n_peak = n; i_peak = i; t_peak = t[t_ind[i_peak]]; } } Muechk_tDiff[Muechk_nCand] = t_peak; //- Muechk_tOya; Muechk_nCand++; if (Muechk_nCand >= MAXCAND) break; } i0 = i0 + h_tdiff[bin]; } // Convert back to absolute time of TISKZ //for (int i=0; i=0; ipeak--) { Muechk_bg[ipeak+1] = Muechk_bg[ipeak] ; Muechk_mean[ipeak+1] = Muechk_mean[ipeak] ; Muechk_tDiff[ipeak+1] = Muechk_tDiff[ipeak] ; Muechk_excess[ipeak+1] = Muechk_excess[ipeak]; Muechk_signif[ipeak+1] = Muechk_signif[ipeak]; } // Add parent peak to beginning of array int ipeak=0; Muechk_bg[ipeak] = -1; Muechk_mean[ipeak] = -1; Muechk_tDiff[ipeak] = Muechk_tOya; Muechk_excess[ipeak] = -1; Muechk_signif[ipeak] = -1; Muechk_nCand++; } if (!fQuiet) { cout << "spliTChan::Muechk_FindPeakCandsFine(): Fine search results" << endl; cout << "Muechk_nCand = " << Muechk_nCand << endl; for (int i=0; iReset(); if (h_tisk_corr1[icand]) h_tisk_corr1[icand]->Reset(); } Cluster_timeOfPeak.clear(); Cluster_ipeak.clear(); } void spliTChan::Cluster_Search(double *vertex) { GetHitInfo(vertex); Cluster_Init(); const int nBinMax = 100000; float binWidth = 10; TH1I h_tdiff("h_tdiff","Time Difference from Parent Peak; #Deltat (ns)", nBinMax, 0, nBinMax*binWidth); int use_bin[nBinMax+2] = {0}; int i_oya = 0; float Cluster_tOya = t[t_ind[i_oya]]; // Fill histogram with time differences from parent peak // for (int ihit=0; ihit Cluster_tOya ) h_tdiff.Fill(t[ihit]-Cluster_tOya); //for (int ibin=1; ibin<=nBinMax; ibin++) //cout << "fitqun thist " << ibin << " " << h_tdiff.GetBinContent(ibin) << endl; if (h_tdiff[0]) { cout << "spliTChan::Cluster_Search() Error: h_tdiff underflow = " << h_tdiff[0] << endl; exit (-1); } if (h_tdiff[nBinMax+1]) { cout << "spliTChan::Cluster_Search() Error: h_tdiff overflow = " << h_tdiff[nBinMax+1] << endl; exit (-1); } int itimer = 0; vector use_binsta; vector use_binend; Cluster_nCand = 0; int binend; for (int bin=1; bin<=nBinMax-(Cluster_nBinsScanWin-1); bin++) { int nHit = (int)h_tdiff.Integral(bin,bin+Cluster_nBinsScanWin-1); if (itimer==0 && nHit > Cluster_nHitThr) { itimer = 1; use_binsta.push_back(bin); // Use bin at the end of scanning window (+1 for high edge) binend = bin+Cluster_nBinsScanWin+1; } else if (itimer==1 && nHit > Cluster_nHitThrFall) { // Use bin at the end of scanning window (+1 for high edge) binend = bin+Cluster_nBinsScanWin+1; } else { if (itimer == 1) { if (bin-use_binsta.back() >= Cluster_nBinsScanWin) { if (!fQuiet) cout << "SubEvent " << Cluster_nCand << " startBin, startTime = " << use_binsta.back() << ", " << h_tdiff.GetBinLowEdge(use_binsta.back())+Cluster_tOya << endl; // Extend end of time window to catch stray (reflected) hits // that may lie under noise (linear based on plot of furthest missed time // vs # of hits in the cluster, and each event weighted by % of missed hits) int nHitsInCluster = (int)h_tdiff.Integral(use_binsta.back(), binend-1); //float timeExtension = TMath::Max(0., (float)(-nHitsInCluster*300./500. + 300)); // 1st iteration //float timeExtension = TMath::Max(Cluster_tExtendMin, (float)(-nHitsInCluster*320./2000. + 320)); float timeExtension = TMath::Max(0., (-nHitsInCluster*320./800. + 320)); binend += (int)ceil(timeExtension/h_tdiff.GetBinWidth(binend)); // Extend low edge by 30 ns to make sure we collect all hits // (also FQ peak finder seems to be too early if low charge) use_binsta.at(use_binsta.size()-1) -= 3; if (timeExtension) if (!fQuiet) cout << "Extending time window by " << timeExtension << "(" << binend << ") for " << nHitsInCluster << " hit cluster." << endl; // Ignore clusters that start too close to previous one if ( (Cluster_nCand > 0) && (use_binsta.back()-use_binend[Cluster_nCand-1] <= Cluster_tBinSepThresh) ) { // Remove current cluster start time if (!fQuiet) cout << "Ignoring this SubEvent since it is too close to previous one." << endl; use_binsta.pop_back(); // Remove previous cluster start time if (!fQuiet) cout << "Extending previous SubEvent window to include this cluster." << endl; use_binend.pop_back(); if (!fQuiet) cout << "SubEvent " << Cluster_nCand-1 << " endBin, endTime = " << binend << ", " << h_tdiff.GetBinLowEdge(binend)+Cluster_tOya << endl; use_binend.push_back(binend); } else { // This is a good cluster if (!fQuiet) cout << "SubEvent " << Cluster_nCand << " endBin, endTime = " << binend << ", " << h_tdiff.GetBinLowEdge(binend)+Cluster_tOya << endl; use_binend.push_back(binend); Cluster_nCand++; } } else { use_binsta.pop_back(); } } itimer = 0; } } if (use_binsta.size() != Cluster_nCand) { cout << "binsta size != nCand " << use_binsta.size() << " != " << Cluster_nCand << endl; exit (-1); } if (use_binend.size() != Cluster_nCand) { cout << "binend size != nCand " << use_binend.size() << " != " << Cluster_nCand << endl; exit (-1); } for (int icluster=0; iclusterSetGate(this->Cluster_tStart[icluster],this->Cluster_tEnd[icluster],true,false); if (skq_nqisk<=0) { if (!fQuiet) cout << "runfiTQun Warning: skq_nqisk = " << skq_nqisk << " for icluster = " << icluster << ". Removing cluster [" << this->Cluster_tStart[icluster] << ", " << this->Cluster_tEnd[icluster] << "]" << endl; this->RemoveCluster(icluster); // This shifts Cluster_* array variables down by one and decrements Cluster_nCand icluster--; } } } void spliTChan::CalcClusterProperties() { for (int icluster=0; icluster < Cluster_nCand; icluster++) { Cluster_nHits[icluster] = 0; Cluster_totQ[icluster] = 0; for (int ihit=0; ihit > timeOfPeaksTempTemp; std::vector > ipeakTempTemp; for (int imethod=0; imethod timeOfPeaksTemp; std::vector ipeakTemp; for (int ipeak=0; ipeak timeOfPeaksTemp; //std::vector ipeakTemp; //for (int ipeak=0; ipeakMAXSE) { cout << "spliTChan::FillClusterCommon() Warning: Number of clusters exceeded " << MAXSE << endl; Cluster_nCand = MAXSE; } fitqunse_.cluster_ncand = Cluster_nCand; for (int icluster=0; iclusterMAXSE) { cout << "spliTChan::FillMuechkCommon() Warning: Number of peaks exceeded " << MAXSE << endl; Muechk_nCand = MAXSE; } fitqunse_.muechk_ncand[imethod] = Muechk_nCand; fitqunse_.muechk_toya[imethod] = Muechk_tOya; for (int ipeak=0; ipeakSetGate(Cluster_tStart[icluster],Cluster_tEnd[icluster],true,false); float *vertex=0; if (Cluster_vertex[icluster][0] && Cluster_vertex[icluster][1] && Cluster_vertex[icluster][2]) { vertex = Cluster_vertex[icluster]; if (!fQuiet) cout << "spliTChan::FillTQbanksAll(): Applying TOF correction with vertex = " << vertex[0] << " " << vertex[1] << " " << vertex[2] << endl; } //else //cout << "spliTChan::FillTQbanksAll(): No TOF correction." << endl; for (int icab=0; icabPMT_iHit[icab]==-1) continue; if (fQEventManager::Get()->PMT_q[icab]<=q_thresh) continue; double dist=0; if (vertex) { TVector3 d; d[0] = fiTQun_shared::Get()->PMTpos[icab][0]-vertex[0]; d[1] = fiTQun_shared::Get()->PMTpos[icab][1]-vertex[1]; d[2] = fiTQun_shared::Get()->PMTpos[icab][2]-vertex[2]; dist = d.Mag(); } chrg[icluster][icab] = fQEventManager::Get()->PMT_q[icab]; tHit[(vertex!=0)][icluster][icab] = fQEventManager::Get()->PMT_t[icab]-dist/cwt; if (!vertex) h_tisk_corr0[icluster]->Fill(fQEventManager::Get()->PMT_t[icab]); else h_tisk_corr1[icluster]->Fill(fQEventManager::Get()->PMT_t[icab]-dist/cwt); } } return 0; } TH1F* spliTChan::GetTiskzHisto() { if (!writeHistos) return 0; h_tiskz->Reset(); for (int ihit=0; ihitFill(t[ihit]); } return h_tiskz; } void spliTChan::SetClusterVertex(int icluster, double *vtxtmp) { for (int i=0; iReset(); for (int ihit=0; ihitFill( tHitz[ihit], chrgz[ihit]); } return h_qiskz_vs_tiskz; } //new from amis// int spliTChan::isValidHit(float thit, float trange){ //make sure there are cluster hits in nint 20ns intervals of a hit //loop over all hits in cluster and make sure // cout<<"called is Valid Hit"<=0){ if ((ttc[0][i]>thit)&&(ttc[0][i]thit+trange)) nhits++; } } if (nhits>=nhit_thresh){ return 1; } else { return 0; cout<<"is NOT a valid hit!!"<Cluster_tEnd[ncluster]){ return 0; } else { cout<<"merging cluster: "<RemoveCluster(ncluster+1); // Cluster_nCand--; return 1; } } //amis //Peak-to-cluster (P2C) cluster finding algorithm void spliTChan::MakeClusters(int npeaks, float* peak_t0, double* vertex, int nevt){ //set up fixed time window// // cout<<"called MakeClusters"<tmax[j]) continue; if (ttc[0][i]c_end_time){ if (isValidHit(ttc[0][i],trange2)==1){ c_end_time = ttc[0][i]; tof_end_time = ttc[1][i]; } } } // make sure time window is valid if (c_start_time>=c_end_time){ //repeat algorithm without valid checking for (int k=0;ktmax[j]) continue; if (ttc[0][k]c_end_time){ c_end_time = ttc[0][k]; } } } //set cluster properties Cluster_tStart[j] = c_start_time; Cluster_tEnd[j] = c_end_time; // tof_cluster_tstart[j] = tof_start_time; // tof_cluster_tend[j] = tof_end_time; Cluster_goodflag[j] = 1; } // cout<<"first cluster: "<n_Gate; // # of ATM gates for (int j=0;jt_Gate[j][0]; Cluster_tEnd[j] = fQEventManager::Get()->t_Gate[j][1]; Cluster_goodflag[j] = 1; } //calc cluster properties CalcClusterProperties(); //fill common blocs FillClusterCommon(); }