FilterAnalyzer_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: FilterAnalyzer
3 // Module Type: analyser
4 // File: FilterAnalyzer_module.cc
5 // Author: Karl Warburton (k.warburton@sheffield.ac.uk), April 2016
6 //
7 // A quick analysis module for looking at the filter.
8 //
9 // Runs over an artdaq-formatted file and produces a tree or histogram,
10 // filled for each channel combination and the respective correlation.
11 ////////////////////////////////////////////////////////////////////////
12 
13 // framework
20 #include "art_root_io/TFileService.h"
21 #include "art_root_io/TFileDirectory.h"
23 #include "fhiclcpp/ParameterSet.h"
25 
26 // lbne-artdaq
27 #include "lbne-raw-data/Overlays/TpcMilliSliceFragment.hh"
28 #include "artdaq-core/Data/Fragment.hh"
29 
30 // larsoft
32 #include "lardataobj/RawData/raw.h"
34 #include "tpcFragmentToRawDigits.h"
41 #include "cetlib/getenv.h"
42 
43 // c++
44 #include <memory>
45 #include <array>
46 #include <iostream>
47 #include <fstream>
48 #include <sstream>
49 
50 // ROOT
51 #include "TMath.h"
52 #include "TTree.h"
53 #include "TF1.h"
54 #include "TH1.h"
55 #include "TH2.h"
56 #include "TVirtualFFT.h"
57 #include "TStyle.h"
58 
59 namespace DAQToOffline {
60  class FilterAnalyzer;
61 }
62 
64 public:
65 
66  explicit FilterAnalyzer(fhicl::ParameterSet const & pset);
67  // The destructor generated by the compiler is fine for classes
68  // without bare pointers or other resource use.
69 
70  // Plugins should not be copied or assigned.
71  FilterAnalyzer(FilterAnalyzer const &) = delete;
72  FilterAnalyzer(FilterAnalyzer &&) = delete;
73  FilterAnalyzer & operator = (FilterAnalyzer const &) = delete;
75 
76  void analyze(art::Event const& evt) override;
77  void reconfigure(const fhicl::ParameterSet &pset);
78 
79 private:
80 
84 
85  TF1* fColFilterFunc; ///< Parameterized collection filter function.
86  TF1* fIndUFilterFunc; ///< Parameterized induction filter function.
87  TF1* fIndVFilterFunc; ///< Parameterized induction filter function.
88 
89  const lariov::DetPedestalProvider& fPedestalRetrievalAlg = *(lar::providerFrom<lariov::DetPedestalService>());
90 
91  TH1F* RawDigitHistos[2048];
92  TH1F* RawDigitFFT[2048];
93  TH1F* RawDigitFFTCorrect[2048];
94  TH1F* RawDigitFFTChannel[2048];
96  TH1F* RawDigitInvFFT[2048];
97 
102 };
103 
105 
106  this->reconfigure(pset);
107  gStyle->SetOptStat(0);
108 
110  RawFFT_100KHz = tfs->make<TH2F>("RawFFT_100KHz" , "Raw FFT for all channels less than 100 KHz; Channel Number; Frequency (KHz)" , 2048, 0, 2048, 100, 0, 100 );
111  FixFFT_100KHz = tfs->make<TH2F>("FixFFT_100KHz" , "FFT for all channels less than 100 KHz after filtering; Channel Number; Frequency (KHz)" , 2048, 0, 2048, 100, 0, 100 );
112  RawFFT_1000KHz = tfs->make<TH2F>("RawFFT_1000KHz", "Raw FFT for all channels less than 1000 KHz; Channel Number; Frequency (KHz)" , 2048, 0, 2048, 1000, 0, 1000);
113  FixFFT_1000KHz = tfs->make<TH2F>("FixFFT_1000KHz", "FFT for all channels less than 1000 KHz after filtering; Channel Number; Frequency (KHz)", 2048, 0, 2048, 1000, 0, 1000);
114 
115  int NumBins = 15000;
116  for (int HistoChan=0; HistoChan<2048; HistoChan++) {
117 
118  // Make the RawDigit Histograms....
119  std::stringstream oss1, oss2;
120  oss1 << "RawDigit_"<<HistoChan;
121  oss2 << "Raw Digit for Channel "<<HistoChan<<"; Time (us); ADC";
122  std::string Name1 = oss1.str();
123  std::string Title1= oss2.str();
124  if (fMakeADCPlots) RawDigitHistos[HistoChan] = tfs->make<TH1F>(Name1.c_str(), Title1.c_str(), NumBins, 0, NumBins/2);
125  else RawDigitHistos[HistoChan] = new TH1F(Name1.c_str(), Title1.c_str(), NumBins, 0, NumBins/2);
126 
127  // Make the FFT Histograms....
128  std::stringstream oss3, oss3a, oss4;
129  oss3 << "FFT_"<<HistoChan;
130  oss3a << "FFT_"<<HistoChan<<"_correct";
131  oss4 << "FFT of Raw Digit for Channel "<<HistoChan<< " in frequency domain";
132  std::string Name2 = oss3.str();
133  std::string Name2a= oss3a.str();
134  std::string Title2= oss4.str();
135  RawDigitFFT[HistoChan] = new TH1F(Name2.c_str(), Title2.c_str(), NumBins, 0, NumBins);
136  RawDigitFFTCorrect[HistoChan] = new TH1F(Name2a.c_str(),Title2.c_str(), NumBins, 0, NumBins);
137 
138  // Make the FFT Channel Histograms....
139  std::stringstream oss5, oss5a, oss6;
140  oss5 << "ChanFFT_"<<HistoChan;
141  oss6 << "FFT of Raw Digit for Channel "<<HistoChan<<"; Frequency (KHz); Number";
142  std::string Name3 = oss5.str();
143  std::string Title3= oss6.str();
144  RawDigitFFTChannel[HistoChan] = new TH1F(Name3.c_str(), Title3.c_str(), NumBins, 0, 2000);
145 
146  // Make the FFT Channel after filter Histograms....
147  std::stringstream oss9, oss10;
148  oss9 << "ChanFFT_"<<HistoChan<<"_Filter";
149  oss10 << "FFT of Raw Digit for Channel "<<HistoChan<<" after filter is applied; Frequency (KHz); Number";
150  std::string Name5 = oss9.str();
151  std::string Title5= oss10.str();
152  RawDigitFFTChannelFilter[HistoChan] = new TH1F(Name5.c_str(), Title5.c_str(), NumBins, 0, 2000);
153 
154  // Make the Inverse FFT Histograms....
155  std::stringstream oss7, oss8;
156  oss5 << "InvFFT_"<<HistoChan;
157  oss6 << "Inverse FFT of the FFT Channel "<<HistoChan<<" histogram; Time (us); ADC";
158  std::string Name4 = oss5.str();
159  std::string Title4= oss6.str();
160  RawDigitInvFFT[HistoChan] = new TH1F(Name4.c_str(), Title4.c_str(), NumBins, 0, NumBins/2);
161  }
162 }
163 
165  fDigitModuleLabel = pset.get<std::string>("DigitModuleLabel");
166  fDigitModuleInstance = pset.get<std::string>("DigitModuleInstance");
167  fMakeADCPlots = pset.get<bool> ("MakeADCPlots");
168  // Make the filter functions.
169  std::string colFilt = pset.get<std::string>("ColFilter");
170  std::vector<double> colFiltParams = pset.get<std::vector<double> >("ColFilterParams");
171  fColFilterFunc = new TF1("colFilter", colFilt.c_str());
172  for(unsigned int i=0; i<colFiltParams.size(); ++i)
173  fColFilterFunc->SetParameter(i, colFiltParams[i]);
174 
175  std::string indUFilt = pset.get<std::string>("IndUFilter");
176  std::vector<double> indUFiltParams = pset.get<std::vector<double> >("IndUFilterParams");
177  fIndUFilterFunc = new TF1("indUFilter", indUFilt.c_str());
178  for(unsigned int i=0; i<indUFiltParams.size(); ++i)
179  fIndUFilterFunc->SetParameter(i, indUFiltParams[i]);
180 
181  std::string indVFilt = pset.get<std::string>("IndVFilter");
182  std::vector<double> indVFiltParams = pset.get<std::vector<double> >("IndVFilterParams");
183  fIndVFilterFunc = new TF1("indVFilter", indVFilt.c_str());
184  for(unsigned int i=0; i<indVFiltParams.size(); ++i)
185  fIndVFilterFunc->SetParameter(i, indVFiltParams[i]);
186 }
187 
189 
191 
193  evt.getByLabel(fDigitModuleLabel, fDigitModuleInstance, rawDigitHandle);
194  std::vector<raw::RawDigit> const& rawDigitVector(*rawDigitHandle);
195 
196  std::vector< std::pair<int,int> > ZeroFreq;
197  //ZeroFreq.push_back( std::make_pair(276 , 285 ) );
198  //ZeroFreq.push_back( std::make_pair(558 , 568 ) );
199  //ZeroFreq.push_back( std::make_pair(837 , 849 ) );
200  //ZeroFreq.push_back( std::make_pair(1116, 1127) );
201  //ZeroFreq.push_back( std::make_pair(4340, 5205) );
202 
203  for (size_t DigLoop=0; DigLoop < rawDigitVector.size(); ++DigLoop) {
204 
205  int Channel = rawDigitVector[DigLoop].Channel();
206  size_t NADC = rawDigitVector[DigLoop].NADC();
207  double Pedestal = rawDigitVector[DigLoop].GetPedestal();
208  const geo::View_t view = geo->View(Channel);
209  //std::cout << "Looking at rawDigitVector["<<DigLoop<<"] it was on channel " << rawDigitVector[DigLoop].Channel() << "("<<Channel<<") it is in View " << view
210  // << ", NADC is " << rawDigitVector[DigLoop].NADC() << " ("<<NADC<<")"
211  // << ", pedestal is " << rawDigitVector[DigLoop].GetPedestal() << " ("<<Pedestal<<")"
212  // << std::endl;
213 
214  // Fill the RawDigit histogram for this histogram.
215  for (size_t ADCs=0; ADCs < NADC; ++ADCs) {
216  RawDigitHistos[Channel] -> SetBinContent( ADCs+1, rawDigitVector[DigLoop].ADC(ADCs)-Pedestal );
217  }
218  for (int ww=NADC; ww<16384; ++ww)
219  RawDigitHistos[Channel] -> SetBinContent( ww, 0 );
220  // Make the FFT for this channel.
221  RawDigitHistos[Channel] -> FFT( RawDigitFFT[Channel] ,"MAG");
222  for (int bin = 0; bin < RawDigitFFTCorrect[Channel]->GetNbinsX(); ++bin) {
223  double BinVal = RawDigitFFT[Channel]->GetBinContent(bin+1);
224  RawDigitFFTCorrect[Channel] -> SetBinContent(bin+1, BinVal );
225  double freq = 2000. * bin / (double)RawDigitFFTCorrect[Channel]->GetNbinsX();
226  if (freq < 1000 && BinVal < 1e5) {
227  RawFFT_1000KHz -> Fill( Channel,freq, BinVal);
228  if (freq < 100) {
229  RawFFT_100KHz-> Fill( Channel,freq, BinVal);
230  }
231  }
232  }
233 
234  // I want to do an inverse FFT, so need to convert the tranformed FFT into an array....
235  int NBins = RawDigitFFT[Channel]->GetNbinsX();
236  //double Re[NADC], Im[NADC];
237  std::unique_ptr<double[]> Re( new double[NADC]);
238  std::unique_ptr<double[]> Im( new double[NADC]);
239  TVirtualFFT *fft = TVirtualFFT::GetCurrentTransform();
240  fft->GetPointsComplex(Re.get(),Im.get());
241 
242  // Set the noisy frequency range bins to zero.
243  for (size_t aa=0; aa<ZeroFreq.size(); ++aa) {
244  for (int bb=ZeroFreq[aa].first; bb<ZeroFreq[aa].second; ++bb) {
245  double ReMeanVal=0;
246  double ImMeanVal=0;
247  int Range = 50;
248  for (int cc=0; cc<Range; ++cc) {
249  ReMeanVal += Re[ZeroFreq[aa].first-cc] + Re[ZeroFreq[aa].second+cc];
250  ImMeanVal += Im[ZeroFreq[aa].first-cc] + Im[ZeroFreq[aa].second+cc];
251  }
252  ReMeanVal = ReMeanVal / Range;
253  Re[bb] = Re[1500-bb] = ReMeanVal;
254  ImMeanVal = ImMeanVal / Range;
255  Im[bb] = Im[1500-bb] = ImMeanVal;
256  double MagVal = pow ( Re[bb]*Re[bb] + Im[bb]*Im[bb], 0.5);
257  RawDigitFFTCorrect[Channel] -> SetBinContent(bb+1 , MagVal );
258  RawDigitFFTCorrect[Channel] -> SetBinContent(15000-bb+1, MagVal );
259  }
260  }
261 
262  // Renormalise the X axis, so it is in frequency.
263  for (int bin = 0; bin < RawDigitFFTCorrect[Channel]->GetNbinsX(); ++bin){
264  RawDigitFFTChannel[Channel] -> SetBinContent( bin+1, RawDigitFFTCorrect[Channel]->GetBinContent(bin+1) );
265  }
266  // Apply the filter...
267  for (int bin = 0; bin < NBins; ++bin) {
268  double freq = 2000. * bin / NBins;
269  if (view == geo::kU) { // U plane
270  Re[bin] = Re[bin]*fIndUFilterFunc->Eval(freq);
271  Im[bin] = Im[bin]*fIndUFilterFunc->Eval(freq);
272  } else if ( view == geo::kV) { // V plane
273  Re[bin] = Re[bin]*fIndVFilterFunc->Eval(freq);
274  Im[bin] = Im[bin]*fIndVFilterFunc->Eval(freq);
275  } else if ( view == geo::kZ) { // Collection plane
276  Re[bin] = Re[bin]*fColFilterFunc->Eval(freq);
277  Im[bin] = Im[bin]*fColFilterFunc->Eval(freq);
278  }
279  double MagVal = pow ( Re[bin]*Re[bin] + Im[bin]*Im[bin], 0.5);
280  if (TMath::IsNaN(MagVal)) MagVal = 0;
281  RawDigitFFTChannelFilter[Channel] -> SetBinContent( bin+1, MagVal );
282 
283  // Now do the big histograms...
284  if (freq < 1000 && RawDigitFFTChannelFilter[Channel]->GetBinContent(bin+1) < 1e5) {
285  FixFFT_1000KHz -> Fill( Channel,freq, MagVal );
286  if (freq < 100) {
287  FixFFT_100KHz-> Fill( Channel,freq, MagVal );
288  }
289  }
290  }
291 
292  // I have applied the filter so now transform back....
293  TVirtualFFT *fft_back = TVirtualFFT::FFT(1, &NBins, "C2R");
294  fft_back->SetPointsComplex(Re.get(),Im.get());
295  fft_back->Transform();
296  TH1 *hb=0;
297  hb = TH1::TransformHisto(fft_back, hb, "Re");
298  for (int BinNum=0; BinNum<NBins; ++BinNum) {
299  //if (TMath::IsNaN(hb->GetBinContent(BinNum+1))) {
300  ////std::cout << "A bin entry is NaN." << std::endl;
301  //RawDigitInvFFT[Channel] -> Fill( BinNum, 0 );
302  //} else {
303  RawDigitInvFFT[Channel] -> Fill( BinNum, hb->GetBinContent(BinNum+1) / NBins );
304  //}
305  }
306  RawDigitInvFFT[Channel] -> SetXTitle("Time (us)");
307  RawDigitInvFFT[Channel] -> SetYTitle("ADC");
308  }
309  return;
310 }
311 
void analyze(art::Event const &evt) override
FilterAnalyzer & operator=(FilterAnalyzer const &)=delete
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
std::string string
Definition: nybbler.cc:12
Planes which measure V.
Definition: geo_types.h:126
constexpr T pow(T x)
Definition: pow.h:72
Definition of basic raw digits.
Planes which measure Z direction.
Definition: geo_types.h:128
EDAnalyzer(fhicl::ParameterSet const &pset)
Definition: EDAnalyzer.h:27
TF1 * fColFilterFunc
Parameterized collection filter function.
TF1 * fIndVFilterFunc
Parameterized induction filter function.
Planes which measure U.
Definition: geo_types.h:125
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
Definition: DataViewImpl.h:446
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:69
FilterAnalyzer(fhicl::ParameterSet const &pset)
Collect all the RawData header files together.
T get(std::string const &key) const
Definition: ParameterSet.h:231
View_t View(geo::PlaneID const &pid) const
Returns the view (wire orientation) on the channels of specified TPC plane.
TF1 * fIndUFilterFunc
Parameterized induction filter function.
void reconfigure(const fhicl::ParameterSet &pset)
ChannelMappingService::Channel Channel
QTextStream & bin(QTextStream &s)
Interface for experiment-specific channel quality info provider.
TCEvent evt
Definition: DataStructs.cxx:7
Interface for experiment-specific service for channel quality info.
Namespace collecting geometry-related classes utilities.
const lariov::DetPedestalProvider & fPedestalRetrievalAlg