From 1d76e83747dd263c4a0a8ef7fa9f013dbe4d9400 Mon Sep 17 00:00:00 2001 From: dkapukchyan Date: Wed, 27 Sep 2023 08:02:57 -0700 Subject: [PATCH] More additions and fixes to StFcsWaveformFitMaker and related classes (#579) Added and changed some options for PeakAnaPainter; made corresponding fixes of draw options in other parts of the code. Fixed an issue in the GetPossiblePeaks algorithm of PeakAna. Fix for StFcsWaveformFitMaker to prevent double calls to AnaPed() for pedestal determination. Added pedestal subtraction to sum methods. --- StRoot/StFcsWaveformFitMaker/PeakAna.cxx | 22 +++-- StRoot/StFcsWaveformFitMaker/PeakAna.h | 17 ++-- .../StFcsWaveformFitMaker/PeakAnaPainter.cxx | 86 ++++++++++--------- StRoot/StFcsWaveformFitMaker/PeakAnaPainter.h | 19 ++-- .../StFcsWaveformFitMaker.cxx | 70 ++++++++++----- .../StFcsWaveformFitMaker.h | 1 + 6 files changed, 134 insertions(+), 81 deletions(-) diff --git a/StRoot/StFcsWaveformFitMaker/PeakAna.cxx b/StRoot/StFcsWaveformFitMaker/PeakAna.cxx index 5d69cd7fadf..535a433f898 100644 --- a/StRoot/StFcsWaveformFitMaker/PeakAna.cxx +++ b/StRoot/StFcsWaveformFitMaker/PeakAna.cxx @@ -487,12 +487,14 @@ PeakAna* PeakAna::MeanFilter( Int_t sizeavgs, bool copy ) } } ynew[ipoint] = sumvalues/sumweights; + if( GetDebug()>2 ){ std::cout << " - |i:"<ForceInternal(); + if( GetDebug()>1 ){ std::cout << "PeakAna::MeanFilter:Copied PeakAna" << std::endl; } return ana; } if( mInternalSignal ){ @@ -501,11 +503,13 @@ PeakAna* PeakAna::MeanFilter( Int_t sizeavgs, bool copy ) //[July 3, 2022]>Taken from TGraph CtorAllocate(). Setting minimum and maximum to -1111 effectivley resets the minimum and maximum. GetData()->SetMinimum(-1111); GetData()->SetMaximum(-1111); + if( GetDebug()>1 ){ std::cout << "PeakAna::MeanFilter:Internal Graph Modified" << std::endl; } } else{ TGraph* graph = new TGraph(npoints,xdata,ynew ); SetData(graph); ForceInternal(); + if( GetDebug()>1 ){ std::cout << "PeakAna::MeanFilter:Created New Internal Graph" << std::endl; } } ResetPeak(); return this; @@ -578,6 +582,7 @@ PeakAna* PeakAna::GausFilter( Int_t sizeavgs, bool copy ) else{ sumweights += 2; } } ynew[ipoint] = sumvalues/sumweights; + if( GetDebug()>2 ){ std::cout << " - |i:"<ForceInternal(); + if( GetDebug()>1 ){ std::cout << "PeakAna::MeanFilter:Copied PeakAna" << std::endl; } return ana; } if( mInternalSignal ){ @@ -593,11 +599,13 @@ PeakAna* PeakAna::GausFilter( Int_t sizeavgs, bool copy ) //[July 3, 2022]>Taken from TGraph CtorAllocate(). Setting minimum and maximum to -1111 effectivley resets the minimum and maximum. GetData()->SetMinimum(-1111); GetData()->SetMaximum(-1111); + if( GetDebug()>1 ){ std::cout << "PeakAna::MeanFilter:Internal Graph Modified" << std::endl; } } else{ TGraph* graph = new TGraph(npoints,xdata,ynew ); SetData(graph); ForceInternal(); + if( GetDebug()>1 ){ std::cout << "PeakAna::MeanFilter:Created New Internal Graph" << std::endl; } } ResetPeak(); return this; @@ -673,12 +681,14 @@ void PeakAna::GetPossiblePeaks() //Check above will skip bad values if( peak.mStartX1 ){LOG_DEBUG << " + No StartTime" << endm;} - if( LY>baseline+slopecutoff && Slope>0 ){ - //Needs to be checked sequentially since we need to reject any points below the baseline+cutoff that may have a large slope - if( GetDebug()>1 ){LOG_DEBUG << " + Passed Slope and baselineCutoff setting as start time" << endm;} - peak.mStartX=LX;//Set start x-value - peak.mStartY=LY;//Set start y-value - LocalMax=LX;//Start checking local maximums + if( Slope>0){ + if( LY>baseline+slopecutoff || RY>baseline+slopecutoff ){ + //Needs to be checked sequentially since we need to reject any points below the baseline+cutoff that may have a large slope + if( GetDebug()>1 ){LOG_DEBUG << " + Passed Slope and baselineCutoff setting as start time" << endm;} + peak.mStartX=LX;//Set start x-value + peak.mStartY=LY;//Set start y-value + LocalMax=LX;//Start checking local maximums + } } //If didn't pass thresholds for start time then continue to next point } diff --git a/StRoot/StFcsWaveformFitMaker/PeakAna.h b/StRoot/StFcsWaveformFitMaker/PeakAna.h index db6f420e587..d1c66b93ba2 100644 --- a/StRoot/StFcsWaveformFitMaker/PeakAna.h +++ b/StRoot/StFcsWaveformFitMaker/PeakAna.h @@ -1,5 +1,8 @@ /* Author: David Kapukchyan +@[October 20, 2022] +> Added doxygen style comments + @[September 29, 2022] > Got rid of the virtual painter as it is no longer needed @@ -86,7 +89,6 @@ There is a helper data class #PeakWindow which holds the found peak data. //Custom Headers #include "PeakWindow.h" -//#include "PeakAnaVirtualPainter.h" class PeakAnaPainter; class PeakAna : public TObject @@ -192,13 +194,16 @@ class PeakAna : public TObject peak qa drawing options(case insensitive):\n - "R" for range\n - "B" for baselines\n - - "F" found peak qa\n - - "P" for full peak qa\n - - "A" for all, which combines "P" and "B"\n - stats drawing options(case insensitive):\n + - "F" found peak window\n + - "P" for all peak windows\n + - "M" for found peak marker\n + - "W" for all peak markers (upside down M)\n + - "E" combines "P" and "W"\n + - "A" for all, which combines "B", "P", and "W"\n + stats drawing options(case insensitive):\n - "S" is to show just the found peak\n - "A" is to show for all peaks\n - - "D" is whether to show detailed printout or not (works with option "S" or "A") + - "D" is whether to show detailed printout or not (works with option "S" or "A")\n Example1: "APL;FB;S" means draw graph using option "APL", draw only found peak qa and baselines, and create a stats box showing only basic information about the found peak. Example2: ";A;AD" means don't draw graph but draw all peaks and put detailed information of all peaks in a stats box diff --git a/StRoot/StFcsWaveformFitMaker/PeakAnaPainter.cxx b/StRoot/StFcsWaveformFitMaker/PeakAnaPainter.cxx index 91922437e12..74ceb97058c 100644 --- a/StRoot/StFcsWaveformFitMaker/PeakAnaPainter.cxx +++ b/StRoot/StFcsWaveformFitMaker/PeakAnaPainter.cxx @@ -80,8 +80,10 @@ void PeakAnaPainter::Paint(Option_t* opt) bool drawgraph = true; bool region = false; bool drawbaselines = false; - bool drawfoundpeakqa = false; - bool drawfullpeakqa = false; + bool drawfoundpeakrange = false; + bool drawallpeakranges = false; + bool drawfoundmarker = false; + bool drawallmarkers = false; std::size_t firstcolon = option.find(";"); if( firstcolon!=std::string::npos ){ @@ -99,19 +101,22 @@ void PeakAnaPainter::Paint(Option_t* opt) mPeakOption.ToLower(); if( mGraphOption.Length()==0 ){ drawgraph=false; } - //if( peakopts.Contains("e") ){ drawgraph=false; } if( mPeakOption.Contains("r") ){ region=true; } if( mPeakOption.Contains("b") ){ drawbaselines=true; } - if( mPeakOption.Contains("f") ){ drawfoundpeakqa=true; } - if( mPeakOption.Contains("p") ){ drawfullpeakqa=true; } - if( mPeakOption.Contains("a") ){ drawbaselines=true; drawfullpeakqa=true; } + if( mPeakOption.Contains("f") ){ drawfoundpeakrange=true; } + if( mPeakOption.Contains("p") ){ drawfoundpeakrange=true; drawallpeakranges=true; } + if( mPeakOption.Contains("m") ){ drawfoundmarker=true; } + if( mPeakOption.Contains("w") ){ drawfoundmarker=true; drawallmarkers=true; } + if( mPeakOption.Contains("e") ){ drawfoundpeakrange=true; drawallpeakranges=true; drawfoundmarker=true; drawallmarkers=true; } + if( mPeakOption.Contains("a") ){ drawbaselines=true; drawfoundpeakrange=true; drawallpeakranges=true; drawfoundmarker=true; drawallmarkers=true; } - if( drawfoundpeakqa && drawfullpeakqa ){ drawfoundpeakqa=false; }//Redundant to do both found and all peaks if( drawgraph ) { this->PaintRawData(); } if( region && drawgraph ) { this->PaintFoundPeak(); } //Doesn't make sense to restrict graph range if graph is not being drawn if( drawbaselines ) { this->PaintBaselines(); } - if( drawfoundpeakqa ) { this->PaintFoundPeakQa(); } - if( drawfullpeakqa ) { this->PaintPeakRanges(); } + if( drawfoundpeakrange ) { this->PaintFoundPeakRange(); } + if( drawallpeakranges ) { this->PaintPeakRanges(); } + if( drawfoundmarker ) { this->PaintFoundMarker(); } + if( drawallmarkers ) { this->PaintPeakMarkers(); } if( mStatsOption.Length()!=0 ) { this->PaintStats(); } } @@ -143,37 +148,11 @@ void PeakAnaPainter::PaintRawData( ) void PeakAnaPainter::PaintFoundPeak( ) { if( !ValidGraph()){return;} - Double_t Xmin = mPA->PeakStart(); Double_t Xmax = mPA->PeakEnd(); if( !(Xmin>mPA->MaxX() || Xmax>mPA->MaxX()) ){mPA->GetData()->GetXaxis()->SetRangeUser(Xmin-5,Xmax+5);} } -void PeakAnaPainter::PaintFoundPeakQa() -{ - if( !ValidGraph() ){return;} - - Int_t computedindex = mPA->FoundPeakIndex(); - if( computedindex<0 ){ computedindex = mPA->AnalyzeForPeak(); } - this->PaintBaselines(); - this->PaintFoundRange(); - - return; -} - -void PeakAnaPainter::PaintPeakQa( ) -{ - if( !ValidGraph() ){return;} - - Int_t computedindex = mPA->FoundPeakIndex(); - if( computedindex<0 ){computedindex = mPA->AnalyzeForPeak();} - - this->PaintBaselines(); - this->PaintPeakRanges(); - - return; -} - void PeakAnaPainter::PaintBaselines() { Double_t base = mPA->Baseline(); @@ -189,8 +168,9 @@ void PeakAnaPainter::PaintBaselines() mTheHitLine->Paint(); } -void PeakAnaPainter::PaintFoundRange() +void PeakAnaPainter::PaintFoundPeakRange() { + if( !ValidGraph() ){return;} Int_t computedindex = mPA->FoundPeakIndex(); if( computedindex<0 ){computedindex = mPA->AnalyzeForPeak();} if( computedindex == mPA->NPeaks() ){return;}//If no peak found then computed index is equal to number of peaks in peak vector @@ -198,17 +178,15 @@ void PeakAnaPainter::PaintFoundRange() TLine* sl = mPA->GetPeak(computedindex).GetStartLine(mPA->MinY(),mPA->MaxY()); sl->SetLineColor(kRed); sl->Paint(); - TMarker* mp = mPA->GetPeak(computedindex).GetPeakMarker(); - mp->SetMarkerColor(kViolet); - mp->SetMarkerSize(mPA->GetMarkerSize()*2.0); - mp->Paint(); TLine* el = mPA->GetPeak(computedindex).GetEndLine(mPA->MinY(),mPA->MaxY()); el->SetLineColor(kOrange); el->Paint(); } + void PeakAnaPainter::PaintPeakRanges( ) { + if( !ValidGraph() ){return;} Int_t computedindex = mPA->FoundPeakIndex(); if(computedindex<0 ){computedindex = mPA->AnalyzeForPeak();} @@ -226,11 +204,37 @@ void PeakAnaPainter::PaintPeakRanges( ) mp->Paint(); mPA->GetPeak(ipeak).GetEndLine( mPA->MinY(), mPA->MaxY() )->Paint(); } - this->PaintFoundRange(); return; } +void PeakAnaPainter::PaintFoundMarker() +{ + if( !ValidGraph() ){return;} + Int_t computedindex = mPA->FoundPeakIndex(); + if( computedindex<0 ){computedindex = mPA->AnalyzeForPeak();} + if( computedindex == mPA->NPeaks() ){return;}//If no peak found then computed index is equal to number of peaks in peak vector + + TMarker* mp = mPA->GetPeak(computedindex).GetPeakMarker(); + mp->SetMarkerColor(kViolet); + mp->SetMarkerSize(mPA->GetMarkerSize()*2.0); + mp->Paint(); +} + +void PeakAnaPainter::PaintPeakMarkers() +{ + if( !ValidGraph() ){return;} + Int_t computedindex = mPA->FoundPeakIndex(); + if(computedindex<0 ){computedindex = mPA->AnalyzeForPeak();} + + for( UShort_t ipeak = 0; ipeakNPeaks(); ++ipeak ){ + if( ipeak==computedindex ){continue;} + TMarker* mp = mPA->GetPeak(ipeak).GetPeakMarker(); + mp->SetMarkerSize(mPA->GetMarkerSize()*2.0); + mp->Paint(); + } +} + void PeakAnaPainter::PaintStats() { //@[April 8, 2022]>Need a way to determine size of pavetext from number of peaks as well as information to be added for each peak (this could be as simple as counting the number of lines and scaling the size accordingly) diff --git a/StRoot/StFcsWaveformFitMaker/PeakAnaPainter.h b/StRoot/StFcsWaveformFitMaker/PeakAnaPainter.h index 44ddd21e182..8ae820aedfa 100644 --- a/StRoot/StFcsWaveformFitMaker/PeakAnaPainter.h +++ b/StRoot/StFcsWaveformFitMaker/PeakAnaPainter.h @@ -1,5 +1,8 @@ /* Author: David Kapukchyan +@[July 5, 2023] +> Modified paint functions to only paint certain things and added options to select what to paint + @[October 20, 2022] > Added doxygen style comments @@ -53,14 +56,14 @@ class PeakAnaPainter : public TObject virtual ~PeakAnaPainter(); virtual void Paint(Option_t *opt=""); - virtual void PaintRawData(); //!< Raw data with no modifications - virtual void PaintFoundPeak(); //!< Raw data inside zoomed in on found signal region - virtual void PaintFoundPeakQa(); //!< Draw signal and found signal window - virtual void PaintPeakQa(); //!< Show all found signal windows and signal - virtual void PaintBaselines(); //!< Just draw the baseline and hitlines - virtual void PaintFoundRange(); //!< Just draw the found peak on the current pad - virtual void PaintPeakRanges(); //!< Draw all found peaks on the current pad - virtual void PaintStats(); //!< Draw Stats box for peak finding + virtual void PaintRawData(); //!< Raw data with no modifications + virtual void PaintFoundPeak(); //!< Raw data inside zoomed in on found signal region + virtual void PaintBaselines(); //!< Just draw the baseline and hitlines + virtual void PaintFoundPeakRange(); //!< Just draw the found peak on the current pad + virtual void PaintPeakRanges(); //!< Draw all found peaks on the current pad except the found peak + virtual void PaintFoundMarker(); //!< Draw the marker indicating the found peak + virtual void PaintPeakMarkers(); //!< Draw markers indicating all peaks except the found peak marker + virtual void PaintStats(); //!< Draw Stats box for peak finding virtual void CleanPainter(); //!< Clean up internal objects diff --git a/StRoot/StFcsWaveformFitMaker/StFcsWaveformFitMaker.cxx b/StRoot/StFcsWaveformFitMaker/StFcsWaveformFitMaker.cxx index 1673eb92e0c..d2e01307dd0 100644 --- a/StRoot/StFcsWaveformFitMaker/StFcsWaveformFitMaker.cxx +++ b/StRoot/StFcsWaveformFitMaker/StFcsWaveformFitMaker.cxx @@ -510,8 +510,8 @@ int StFcsWaveformFitMaker::Make() { float gain = mDb->getGain(hits[i]); float gaincorr = mDb->getGainCorrection(hits[i]); hits[i]->setEnergy(integral*gain*gaincorr); - if(GetDebug()>0) printf("det=%1d id=%3d integ=%10.2f peak=%8.2f, sig=%8.4f chi2=%8.2f npeak=%2d\n", - det,hits[i]->id(),integral,res[2],res[3],res[4],int(res[5])); + if(GetDebug()>0){ printf("det=%1d id=%3d integ=%10.2f peak=%8.2f, sig=%8.4f chi2=%8.2f npeak=%2d ped=%8.2f pedrms=%4.2f\n", + det,hits[i]->id(),integral,res[2],res[3],res[4],int(res[5]),res[6],res[7]); } if(mMeasureTime){ auto stop=std::chrono::high_resolution_clock::now(); long long usec = chrono::duration_cast(stop-start).count(); @@ -780,6 +780,7 @@ float StFcsWaveformFitMaker::sum8(TGraphAsymmErrors* g, float* res){ } } //res[0]/=1.226; //Compensate for fitting sum in ECal. Only turn on for testing comparisons + if( fabs(res[7]) > 0.000001 ){ sum -= res[6]*8; }//pedestal subtraction for sum8. 8 timebi sum, so pedestal*8 is integrated sum of pedestal. res[0]=sum; if(sum>0) res[2]=tsum/sum; return sum; @@ -800,6 +801,7 @@ float StFcsWaveformFitMaker::sum16(TGraphAsymmErrors* g, float* res){ tsum += a[i] * tb; } } + if( fabs(res[7]) > 0.000001 ){ sum -= res[6]*16; }//pedestal subtraction for sum16. 16 timebin sum, so pedestal*16 is integrated sum of pedestal. res[0]=sum; if(sum>0) res[2]=tsum/sum; return sum; @@ -824,12 +826,14 @@ float StFcsWaveformFitMaker::highest(TGraphAsymmErrors* g, float* res){ } } //! https://www.star.bnl.gov/protected/spin/akio/fcs/pulse/waveformRes.png + if( fabs(res[7]) > 0.000001 ){ maxadc -= res[6]; }//pedestal subtraction for highest. res[0]=maxadc / 0.2; //this is estimated "full integral" res[1]=maxadc; //this is peak height res[2]=maxtb; //this is peak position [timebin] //res[3]=0.0; //no width from this method //res[4]=0.0; //no chi2 from this - //res[5]=0.0; //no # of peaks + //res[5]=0.0; //no # of peaks + return maxadc; //this is the highest } @@ -859,6 +863,7 @@ float StFcsWaveformFitMaker::highest3(TGraphAsymmErrors* g, float* res){ } } //! https://www.star.bnl.gov/protected/spin/akio/fcs/pulse/waveformRes.png + if( fabs(res[7]) > 0.000001 ){ sum -= res[6]*3; }//pedestal subtraction for highest3. Since 3 timebin sum pedestal*3 is integrated pedestal res[0]= sum / 0.555; //this is estimated "full integral" res[1]= maxadc; //this is peak height if(sum>0) res[2]= tsum/sum; //this is averaged peak position [timebin] @@ -927,14 +932,15 @@ float StFcsWaveformFitMaker::gausFit(TGraphAsymmErrors* g, float* res, TF1*& fun } } - //For comparing with pulse fit analysis class - if( mPulseFit==0 ){mPulseFit = new StFcsPulseAna(g); SetupDavidFitterMay2022(); }//Setup only needs to be called once as those values will not get reset when data changes. - else{ mPulseFit->SetData(g); } - Int_t compidx = mPulseFit->FoundPeakIndex(); + Int_t compidx = -1; int myNpeaks = -1; int npeakidx = -1; int mypeakidx = -1; if( mTest==2 || mTest==8 ){ + //For comparing with pulse fit analysis class + if( mPulseFit==0 ){mPulseFit = new StFcsPulseAna(g); SetupDavidFitterMay2022(); }//Setup only needs to be called once as those values will not get reset when data changes. + else{ mPulseFit->SetData(g); } + compidx = mPulseFit->FoundPeakIndex(); mH1_NPeaksAkio->Fill(npeak); if( trgx>=0 ){ mH1_NPeaksFilteredAkio->Fill(npeak); }//peaks inside triggered crossing if( mTest==2 ){ @@ -1050,10 +1056,10 @@ void StFcsWaveformFitMaker::drawFit(TGraphAsymmErrors* gg, TF1* func){ char post[50]; sprintf(post,"_D%dC%d",det,ch); StFcsPulseAna* ana = (StFcsPulseAna*)mPulseFit->DrawCopy("LP;A",post,gg);//Sets 'kCanDelete' so canvas will delete the copy - ana->GetData()->SetLineColor(kBlue); - ana->GetData()->SetMarkerStyle(kBlue); - ana->GetData()->SetMarkerStyle(4); - ana->GetData()->SetMarkerSize(0.5); + ana->SetLineColor(kBlue); + ana->SetMarkerColor(kBlue); + ana->SetMarkerStyle(4); + ana->SetMarkerSize(0.5); } if(mPad==MAXPAD){ @@ -1085,7 +1091,7 @@ void StFcsWaveformFitMaker::drawCh(UInt_t detid, UInt_t ch) const if( id>=0 && id==static_cast(ch) ){ ggdraw->Draw("APL"); ggdraw->SetLineColor(kBlack); - ggdraw->SetMarkerStyle(kBlack); + ggdraw->SetMarkerColor(kBlack); ggdraw->SetMarkerStyle(4); ggdraw->SetMarkerSize(0.5); ggdraw->GetXaxis()->SetTitle("timebin"); @@ -1096,9 +1102,9 @@ void StFcsWaveformFitMaker::drawCh(UInt_t detid, UInt_t ch) const StFcsDb::getFromName(ggdraw->GetName(),det,ch); char post[50]; sprintf(post,"_D%dC%d",det,ch); - StFcsPulseAna* ana = mPulseFit->DrawCopy("LP;P",post,ggdraw);//Sets 'kCanDelete' so an external canvas will delete this object when "Clear" is called + StFcsPulseAna* ana = mPulseFit->DrawCopy("LP;E",post,ggdraw);//Sets 'kCanDelete' so an external canvas will delete this object when "Clear" is called ana->GetData()->SetLineColor(kBlue); - ana->GetData()->SetMarkerStyle(kBlue); + ana->GetData()->SetMarkerColor(kBlue); ana->GetData()->SetMarkerStyle(4); ana->GetData()->SetMarkerSize(0.5); //ana->ResetPeak(); @@ -1125,15 +1131,15 @@ void StFcsWaveformFitMaker::drawDualFit(UInt_t detid, UInt_t ch) ggdraw->SetTitle(post); ggdraw->Draw("APL"); ggdraw->SetLineColor(kBlack); - ggdraw->SetMarkerStyle(kBlack); + ggdraw->SetMarkerColor(kBlack); ggdraw->SetMarkerStyle(4); ggdraw->SetMarkerSize(0.5); ggdraw->GetXaxis()->SetTitle("timebin"); ggdraw->GetYaxis()->SetTitle("ADC"); if( mPulseFit!=0 ){ - StFcsPulseAna* ana = mPulseFit->DrawCopy("LP;P",post,ggdraw);//Sets 'kCanDelete' so an external canvas will delete this object when "Clear" is called + StFcsPulseAna* ana = mPulseFit->DrawCopy("LP;E",post,ggdraw);//Sets 'kCanDelete' so an external canvas will delete this object when "Clear" is called ana->GetData()->SetLineColor(kBlue); - ana->GetData()->SetMarkerStyle(kBlue); + ana->GetData()->SetMarkerColor(kBlue); ana->GetData()->SetMarkerStyle(4); ana->GetData()->SetMarkerSize(0.5); Int_t compidx = ana->FoundPeakIndex(); @@ -1194,7 +1200,7 @@ void StFcsWaveformFitMaker::drawDualFit(UInt_t detid, UInt_t ch) } float StFcsWaveformFitMaker::gausFitWithPed(TGraphAsymmErrors* g, float* res, TF1*& func){ - AnaPed( g, res[6], res[7] ); + if( fabs(res[7]) < 0.000001 ){AnaPed( g, res[6], res[7] ); } //Only call AnaPed if pedestal hasn't already been calculated and stored in res. res[7] will be nonzero only if AnaPed was already called. LOG_DEBUG << "Pedestal ("<