CompressedHitFinder_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: CompressedHitFinder
3 // Plugin Type: producer (art v2_11_02)
4 // File: CompressedHitFinder_module.cc
5 //
6 // Generated at Wed Jun 13 15:27:13 2018 by Thomas Junk using cetskelgen
7 // from cetlib version v3_03_01.
8 // Report the compressed raw digit blocks as hits -- just a threshold
9 ////////////////////////////////////////////////////////////////////////
10 
19 #include "fhiclcpp/ParameterSet.h"
22 #include "art_root_io/TFileService.h"
23 
25 #include "RawDataProducts/raw.h"
27 #include "Geometry/GeometryGAr.h"
30 
31 #include <memory>
32 
33 #include "TMath.h"
34 #include "TH1D.h"
35 
36 namespace gar {
37  namespace rec {
38 
40  public:
41  explicit CompressedHitFinder(fhicl::ParameterSet const & p);
42  // The compiler-generated destructor is fine for non-base
43  // classes without bare pointers or other resource use.
44 
45  // Plugins should not be copied or assigned.
46  CompressedHitFinder(CompressedHitFinder const &) = delete;
50 
51  // Required functions.
52  void produce(art::Event & e) override;
53 
54  private:
55 
56  // Declare member data here.
57 
58  int fADCThreshold; ///< zero-suppression threshold (in case the raw digits need to be zero-suppressed)
59  int fTicksBefore; ///< zero-suppression ticks before. Only used if raw waveforms are not zero-suppressed and we must do it
60  int fTicksAfter; ///< zero-suppression ticks after. Only used if raw waveforms are not zero-suppressed and we must do it
61 
62  float fMinRMS; ///< minimum RMS to report in case only one tick has signal on it
63  float fHitMaxLen; ///< maximum length of a hit in X, in cm
64  float fHitFracADCNewHit; ///< threshold below which if the ADC falls below multiplied by adcmax, to start a new hit
65  float fHitFracADCRise; ///< fraction ADC must rise back from the minimum to start a new hit
66 
67  std::string fRawDigitLabel; ///< label to find the right raw digits
68  const detinfo::DetectorProperties* fDetProp; ///< detector properties
69  const geo::GeometryCore* fGeo; ///< pointer to the geometry
70  const gar::detinfo::DetectorClocks* fTime; ///< electronics clock
71 
74  };
75 
76 
78  : EDProducer{p}
79  {
80  fADCThreshold = p.get<int>("ADCThreshold",5);
81  fTicksBefore = p.get<int>("TicksBefore",5);
82  fTicksAfter = p.get<int>("TicksAfter",5);
83  fMinRMS = p.get<float>("MinRMS",3);
84  fRawDigitLabel = p.get<std::string>("RawDigitLabel","daq");
85  fHitMaxLen = p.get<float>("HitMaxLen",1.0);
86  fHitFracADCNewHit = p.get<float>("HitFracADCNewHit",0.5);
87  fHitFracADCRise = p.get<float>("HitFracADCRise",1.3);
88 
89  fTime = gar::providerFrom<detinfo::DetectorClocksServiceGAr>();
90  fGeo = gar::providerFrom<geo::GeometryGAr>();
91  fDetProp = gar::providerFrom<detinfo::DetectorPropertiesService>();
92 
93  consumes< std::vector<raw::RawDigit> >(fRawDigitLabel);
94  produces< std::vector<rec::Hit> >();
95  produces< art::Assns<rec::Hit, raw::RawDigit> >();
96 
98  fAvgPulseLongHist = tfs->make<TH1D>("garAvgPulseLongHist","Pulse ADC Average;tick;ADC Sum",1000,-0.5,999.5);
99  fAvgPulseShortHist = tfs->make<TH1D>("garAvgPulseShortHist","Pulse ADC Average;tick;ADC Sum",200,-0.5,199.5);
100  }
101 
103  {
104  // create an emtpy output hit collection -- to add to.
105  std::unique_ptr<std::vector<Hit> > hitCol (new std::vector<Hit> );
106 
107  // create art::Assns between (multiple) rec::Hit and a raw::RawDigit
108  std::unique_ptr< art::Assns<rec::Hit, raw::RawDigit> >
109  hitDigAssns(new::art::Assns<rec::Hit, raw::RawDigit>);
110 
111  auto const hitPtrMaker = art::PtrMaker<rec::Hit>(e);
112 
113  // the input raw digits
114  auto rdCol = e.getValidHandle< std::vector<raw::RawDigit> >(fRawDigitLabel);
115 
116  for (size_t ird = 0; ird < rdCol->size(); ++ ird)
117  {
118  auto const& rd = (*rdCol)[ird];
119  auto channel = rd.Channel();
120  raw::ADCvector_t adc = rd.ADCs();
121  if (rd.Compression() == raw::kNone)
122  {
124  }
125  else if (rd.Compression() == raw::kZeroSuppression)
126  {
127  // we already have what we want
128  }
129  else
130  {
131  MF_LOG_WARNING("CompressedHitFinder") << " Ununderstood compression mode: " << rd.Compression() << " Not making hits.";
132  e.put(std::move(hitCol));
133  e.put(std::move(hitDigAssns));
134  return;
135  }
136  // use the format of the compressed raw digits -- a table of contents of the number of blocks, then all the block sizes, and then all the
137  // block start locations
138  if (adc.size() < 2)
139  {
140  //MF_LOG_WARNING("CompressedHitFinder") << " adc vector size < 2, skipping channel";
141  continue;
142  }
143 
144  // walk through the zero-suppressed raw digits and call each block a hit
145 
146  int nBlocks = adc[1];
147  int zerosuppressedindex = nBlocks*2 + 2;
148  float pos[3] = {0,0,0};
150  float chanposx = pos[0];
151 
152  int t0adcblockhist = 0;
153 
154  for (int iBlock=0; iBlock<nBlocks; ++iBlock)
155  {
156  double hitSig = 0;
157  double hitTime = 0;
158  double hitSumSq = 0;
159  double hitRMS = 0;
160  unsigned int begT = adc[2+iBlock];
161  int blocksize = adc[2+nBlocks+iBlock];
162  if (blocksize<1)
163  {
164  throw cet::exception("CompressedHitFinder") << "Negative or zero block size in compressed data.";
165  }
166  unsigned int endT = begT + blocksize; // will update this as need be.
167 
168  // divide the hits up into smaller hits
169 
170  int adcmax = 0;
171  int jhl = 0;
172 
173  double distonetick = fDetProp->DriftVelocity() * (fTime->TPCTick2Time(1) - fTime->TPCTick2Time(0)) ;
174 
175  for(int jInBlock = 0; jInBlock < blocksize; ++jInBlock) // loop over time samples in each block
176  {
177  ULong64_t t = adc[2+iBlock]+jInBlock;
178  int a = adc[zerosuppressedindex];
179  zerosuppressedindex++;
180 
181  fAvgPulseShortHist->Fill(jInBlock,a);
182  if (t0adcblockhist == 0)
183  {
184  t0adcblockhist = t;
185  }
186  int deltat = t - t0adcblockhist;
187  if (deltat < fAvgPulseLongHist->GetNbinsX())
188  {
189  fAvgPulseLongHist->Fill(deltat,a);
190  }
191  else
192  {
193  t0adcblockhist = 0;
194  }
195  endT = begT + jhl;
196  ++jhl;
197 
198  hitSig += a;
199  hitTime += a*t;
200  hitSumSq += a*t*t;
201  //std::cout << " In hit calc: " << t << " " << a << " " << hitSig << " " << hitTime << " " << hitSumSq << std::endl;
202 
203  // make a new hit if the ADC value drops below a fraction of the max value or if we have exceeded the length limit
204  // add a check to make sure the ADC value goes back up after the dip, otherwise keep adding to the same hit.
205 
206  bool splithit = jhl*distonetick > fHitMaxLen;
207  if (!splithit) // only do this calc if we need to
208  {
209  if (a < adcmax*fHitFracADCNewHit)
210  {
211  int zsi2 = zerosuppressedindex;
212  for (int kInBlock=jInBlock+1; kInBlock<blocksize; ++kInBlock)
213  {
214  int a2 = adc[zsi2];
215  zsi2++;
216  if (a2 > a*fHitFracADCRise)
217  {
218  splithit = true;
219  break;
220  }
221  }
222  }
223  }
224  adcmax = TMath::Max(adcmax,a);
225 
226  // create a hit if we have split a hit or if we are out of waveforms
227 
228  if ( splithit || jInBlock == (blocksize - 1))
229  {
230  if (hitSig > 0) // otherwise leave the values at zero
231  {
232  hitTime /= hitSig;
233  hitRMS = TMath::Sqrt(hitSumSq/hitSig - hitTime*hitTime);
234  }
235  else
236  {
237  hitTime = 0.5*(begT + endT);
238  hitRMS = 0;
239  }
240  if (hitRMS == 0) hitRMS = fMinRMS;
241  //std::cout << " hit RMS calc: " << hitSumSq << " " << hitSig << " " << hitTime << " " << hitRMS << std::endl;
242 
243  double driftdistance = fDetProp->DriftVelocity() * fTime->TPCTick2Time(hitTime);
244  if (chanposx < fGeo->TPCXCent())
245  {
246  pos[0] = chanposx + driftdistance;
247  }
248  else
249  {
250  pos[0] = chanposx - driftdistance;
251  }
252 
253  // noise hits are plentiful
254  //if (hitSig < 0)
255  // {
256  // MF_LOG_WARNING("CompressedHitFinder") << "Negative Signal in hit finder" << std::endl;
257  // }
258  if (hitSig>0)
259  {
260  rec::Hit newHit(channel,hitSig,pos,begT,endT,hitTime,hitRMS);
261  hitCol->emplace_back(newHit);
262 
263  // Make art::Assn<Hit,RawDigit>
264  art::Ptr<rec::Hit> hitPtr = hitPtrMaker(hitCol->size()-1);
266  hitDigAssns->addSingle(hitPtr,digPtr);
267  }
268  jhl = 0; // reset accumulators so we can make the next hit
269  hitSig = 0;
270  hitTime = 0;
271  hitSumSq = 0;
272  begT = endT + 1;
273  endT = begT;
274  adcmax = 0;
275  }
276  }
277  }
278  }
279 
280  // cluster hits if requested
281 
282  e.put(std::move(hitCol));
283  e.put(std::move(hitDigAssns));
284  return;
285 
286  }
287 
289 
290  } // namespace rec
291 } // namespace gar
std::vector< ADC_t > ADCvector_t
Definition: RawTypes.h:13
rec
Definition: tracks.py:88
int ZeroSuppression(gar::raw::ADCvector_t &adc, gar::raw::ADC_t zerothreshold, size_t ticksbefore_in, size_t ticksafter_in)
Definition: raw.cxx:66
float fHitFracADCNewHit
threshold below which if the ADC falls below multiplied by adcmax, to start a new hit ...
std::string string
Definition: nybbler.cc:12
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.h:20
float fHitFracADCRise
fraction ADC must rise back from the minimum to start a new hit
int16_t adc
Definition: CRTFragment.hh:202
CompressedHitFinder(fhicl::ParameterSet const &p)
Description of geometry of one entire detector.
Definition: GeometryCore.h:436
uint8_t channel
Definition: CRTFragment.hh:201
std::string fRawDigitLabel
label to find the right raw digits
#define a2
const double e
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
CompressedHitFinder & operator=(CompressedHitFinder const &)=delete
const double a
def move(depos, offset)
Definition: depos.py:107
Zero Suppression algorithm.
Definition: RawTypes.h:18
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
Definition: DataViewImpl.h:441
p
Definition: test.py:223
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: DataViewImpl.h:686
no compression
Definition: RawTypes.h:16
General GArSoft Utilities.
void produce(art::Event &e) override
float fMinRMS
minimum RMS to report in case only one tick has signal on it
int fTicksBefore
zero-suppression ticks before. Only used if raw waveforms are not zero-suppressed and we must do it ...
int fTicksAfter
zero-suppression ticks after. Only used if raw waveforms are not zero-suppressed and we must do it ...
const detinfo::DetectorProperties * fDetProp
detector properties
#define MF_LOG_WARNING(category)
int fADCThreshold
zero-suppression threshold (in case the raw digits need to be zero-suppressed)
float fHitMaxLen
maximum length of a hit in X, in cm
virtual double DriftVelocity(double efield=0., double temperature=0., bool cmPerns=true) const =0
art framework interface to geometry description
void ChannelToPosition(unsigned int const channel, float *const worldLoc) const
const geo::GeometryCore * fGeo
pointer to the geometry
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
virtual double TPCTick2Time(double tick) const =0
Given TPC time-tick (waveform index), returns electronics clock [ns].
const gar::detinfo::DetectorClocks * fTime
electronics clock