Diana Software
MAveragePulses.cc
Go to the documentation of this file.
1 #include "MAveragePulses.hh"
2 #include "QEvent.hh"
3 #include "QRawEvent.hh"
4 #include "QVector.hh"
5 #include "QGlobalHandle.hh"
6 #include "QAveragePulseHandle.hh"
7 #include "QAverageVector.hh"
8 #include "QBaseType.hh"
9 #include "QRunDataHandle.hh"
10 #include <math.h>
11 
12 using std::cout;
13 using std::endl;
14 
15 using namespace Diana;
17 
18 // Init method is called before event loop
19 void MAveragePulses::Init(QEvent& ev)
20 {
21  // get parameters from config file
22 
23  fPulseLabel = GetString("PulseLabel","DAQ@Pulse",false);
24  ev.RequireByLabel<QPulse>(fPulseLabel);
25 
26 
27  fValidityKind = GetString("ValidityKind","dataset",false);
28  if(fValidityKind != "dataset" && fValidityKind != "run") {
29  Panic("ValidityKind must be set to dataset or run");
30  }
31 
32  fValidityStart = GetInt("ValidityStart",Q_INT_DEFAULT,false);
33  fValidityEnd = GetInt("ValidityEnd",Q_INT_DEFAULT,false);
34 
35  fAlignmentOn = GetBool("AlignmentOn",false);
36  fOutput = GetString("Output","avgpulses.root");
37  fSubtractBaseline = GetBool("SubtractBaseline",false);
38  if(fSubtractBaseline) fNumBaselinePoints = GetInt("BaselineNumPoints",0);
39  if(fAlignmentOn) {
40  fMaxShift = GetInt("MaxShift",10);
41  fFractionalShift = GetBool("FractionalShift",true);
42  }
43 
44  fCurrentRun = -1;
45  ev.Require<QHeader>("DAQ","Header");
46  ev.Require<QPulseInfo>("DAQ","PulseInfo");
47  ev.RequireByLabel<QPulse>(fPulseLabel);
48 }
49 
50 // Do method is called for each event, getting the event as argument
52 {
53  const QHeader& header = ev.Get<QHeader>("DAQ","Header");
54  const QVector& pulse = ev.GetByLabel<QPulse>(fPulseLabel).GetSamples();
55  const int run = header.GetRun();
56 
57  int chanId = ev.Get<QPulseInfo>("DAQ","PulseInfo").GetChannelId();
58 
59  if (run != fCurrentRun)
60  {
61  fCurrentRun = run;
62  // store run number into SourceRuns vector
63  if(GetIteration()== 1) fSRuns.push_back(fCurrentRun);
64  }
65 
66  if( GetIteration() == 1 && fChannelData.find(chanId) == fChannelData.end()) {
67  //const QVector& pulse = ev.GetByLabel<QPulse>(fPulseLabel).GetSamples();
68  size_t fNumSamples = pulse.Size();
69  ChannelData thisChanData;
70  thisChanData.fAvgPulse.Resize(fNumSamples);
71  thisChanData.fAvgPulse.Initialize(0.);
72  thisChanData.fNumPulses = 0;
73  if(fAlignmentOn) {
74  thisChanData.fPeakPositions.Resize(fNumSamples);
75  thisChanData.fPeakPositions.Initialize(0.);
76  thisChanData.fAlignPos = -1.;
77  }
78  fChannelData[chanId] = thisChanData;
79  }
80 
81 
82  ChannelData& thisChanData = fChannelData[chanId];
83  if(fAlignmentOn)
84  {
85  //Alignment on
86  double maxPos = pulse.GetMaxIndex();
87  if(GetIteration() == 1)
88  {
89  thisChanData.fPeakPositions[(int)maxPos] += 1;
90  thisChanData.fNumPulses++;
91  }
92  else
93  {
94  // use maxPos to align pulses: standard procedure
95  float delay = maxPos;
96 
97  // integer shift & fractional shift
98  float stepreal = delay - thisChanData.fAlignPos;
99  int stepint = (int) stepreal;
100  stepreal = stepreal - stepint;
101 
102  QVector shifted = pulse;
103 
104  // first integer shift
105  // maximum shift allowed. If exceeded, event is discarded.
106 
107  if(stepint < fMaxShift && stepint > -fMaxShift)
108  {
109  // differentiate
110  shifted.Differentiate();
111 
112  // mean derivative
113  int derivMeanSize = int(0.02*pulse.Size());
114  QVector beginDeriv(derivMeanSize);
115  QVector endDeriv(derivMeanSize);
116 
117  for(int i = 0; i < derivMeanSize; i++)
118  {
119  beginDeriv[i] = shifted[i];
120  endDeriv[i] = shifted[shifted.Size() - 1 -i];
121  }
122  double derivMeanBegin = beginDeriv.Sum(derivMeanSize)/derivMeanSize;
123  double derivMeanEnd = endDeriv.Sum(derivMeanSize)/derivMeanSize;
124 
125  // shift vector and sum mean derivative to the end or subtract mean derivative to the beginning
126  shifted.Shift(-stepint);
127  if (stepint >0)
128  {
129  for(int i = 0; i < stepint; i++)
130  {
131  shifted[shifted.Size() - stepint +i] += derivMeanEnd;
132  }
133  }
134  else if (stepint <0)
135  {
136  for(int i = 0; i < stepint; i++)
137  {
138  shifted[i] -= derivMeanBegin;
139  }
140  }
141 
142  // integrate
143  shifted.Integrate(pulse[0]);
144  if (fFractionalShift)
145  {
146  shifted.ShiftReal(-stepreal);
147  if (stepreal >0) shifted[shifted.Size() - 1] = shifted[shifted.Size() - 2] + derivMeanEnd;
148  else if (stepreal <0) shifted[0] = shifted[1] - derivMeanBegin;
149  }
150  thisChanData.fAvgPulse += shifted;
151  thisChanData.fNumPulses++;
152  }
153  }
154  }
155  else
156  {
157  // fAlignmentOn = false
158  thisChanData.fAvgPulse += pulse;
159  thisChanData.fNumPulses++;
160  }
161 
162  return;
163 }
164 
165 // Done method is called after event loop
167 {
168  std::map<int,ChannelData>::iterator chanIter = fChannelData.begin();
169  while(chanIter != fChannelData.end()) {
170  ChannelData& thisChanData = chanIter->second;
171  int chanId = chanIter->first;
172 
173  if(chanIter!=fChannelData.begin()){
174  --chanIter;
175  int prevChan = (chanId-1);
176  int prevEntry = (chanIter->first);
177  ++chanIter;
178  if(prevEntry != (prevChan)) {
179  Error("Missing channel %d - Could not build AP",(prevChan));}
180  }
181  if(chanIter!= --fChannelData.end()){
182  ++chanIter;
183  int nextChan = (chanId+1);
184  int nextEntry = (chanIter->first);
185  --chanIter;
186  if(nextEntry != (nextChan)) {
187  Error("Missing channel %d - Could not build AP",(nextChan));}
188  }
189 
190 
191 
192  if (thisChanData.fNumPulses != 0) {
193  if(fAlignmentOn && GetIteration() == 1) {
194  // alignment positions is the mode of the distribution peak distribution
195  thisChanData.fAlignPos = thisChanData.fPeakPositions.GetMaxIndex() ;
196  Debug("Channel[%d]: Number of events: %d, PeakMode %f",
197  chanId,thisChanData.fNumPulses, thisChanData.fAlignPos);
198  thisChanData.fNumPulses = 0;
199  } else {
200  Debug("Channel[%d]: Number of events: %d", chanId, thisChanData.fNumPulses);
201  thisChanData.fAvgPulse /= thisChanData.fNumPulses;
202 
203  // dump
204  std::string algo;
205  if(fAlignmentOn) algo = "Aligned";
206  else algo = "Normal";
207  // Calculate and subtract baseline from average pulse
208  if (fSubtractBaseline)
209  {
210  double AvgBaseline = 0;
211  QVector AvgBaselineVector;
212  int nbsamples;
213  if(fNumBaselinePoints <=0) {
214  nbsamples = int (thisChanData.fAvgPulse.GetMaxIndex()*3./4);
215  } else {
216  nbsamples = fNumBaselinePoints;
217  }
218  for (int k = 0; k < nbsamples; ++k)
219  {
220  AvgBaseline += thisChanData.fAvgPulse[k];
221  }
222  AvgBaseline /= nbsamples;
223  AvgBaselineVector.Resize(thisChanData.fAvgPulse.Size());
224  AvgBaselineVector.Initialize(AvgBaseline);
225  thisChanData.fAvgPulse-= AvgBaselineVector;
226  char buf[128]; snprintf(buf,128,"_%.2d",chanId);
227  }
228 
229  // set number of events and source runs of QAverageVector
230 
231  thisChanData.fAvgPulse.SetSourceRuns(fSRuns);
232  thisChanData.fAvgPulse.SetNumEvents(thisChanData.fNumPulses);
233 
234  // Fill Output
235 
236  QAveragePulseHandle aphandle(chanId);
237  if(fValidityKind=="dataset"){
238  // get dataset
239  GlobalHandle<QInt> dHandle("Dataset");
240  GlobalData().Get("",&dHandle,"");
241  int dataset = dHandle.Get();
242  aphandle.SetDataset(dataset);
243  }
244  else if (fValidityKind=="run"){
245  if (fSRuns.size()==1){
246  aphandle.SetRun(fSRuns[0]);
247  }
248  else Error("ValidityKind set to run is not permitted when reading multiple runs.");
249  }
250  else Error("ValidityKind can be set only to run or dataset. Check cfg.");
251 
252  aphandle.Set(thisChanData.fAvgPulse);
253  GlobalData().Set(&aphandle, fOutput);
254  }
255  }
256  else {
257  Error("Could not build average pulse for channel %i: , 0 events passing the selection cuts",chanId);
258  }
259  chanIter++;
260  }
261 
262  if(fAlignmentOn && GetIteration() == 1) SetRunAgain(true);
263  else SetRunAgain(false);
264 
265 }
266 
267 
#define Q_INT_DEFAULT
Definition: QDiana.hh:26
#define REGISTER_MODULE(clazz)
Definition: QDriver.hh:133
Module to form idealized pulses by averaging.
virtual void Do(Diana::QEvent &ev)
virtual void Done()
global handle for average pulse
void SetSourceRuns(const std::vector< int > &sourceRuns)
Set the list of source runs.
void SetNumEvents(int nEvents)
Set the number of events in the average.
diana event
Definition: QEvent.hh:46
const Q & GetByLabel(const QEventLabel &label) const
Get a QObject in read mode by label.
Definition: QEvent.hh:135
void Get(const char *owner, ReadHandle< Q > &handle) const
Get a QObject Handle in read mode.
Definition: QEvent.hh:74
Raw event: basic information like run number and time.
Definition: QHeader.hh:16
int GetRun() const
destructor
Definition: QHeader.hh:22
Raw event: bolometer channel, trigger positions and types.
Definition: QPulseInfo.hh:18
Raw event: sampled waveform.
Definition: QPulse.hh:22
the Diana namespace is needed because sometimes we use Qt libraries, that use same class names of our...