Diana Software
MJitterByCoincidence.cc
Go to the documentation of this file.
2 #include "QBaseType.hh"
3 #include "QVector.hh"
4 #include "QError.hh"
5 #include "QEvent.hh"
6 #include "QRawEvent.hh"
7 #include "QEventList.hh"
8 #include "QCoincidenceData.hh"
9 #include "QDetChannelCollectionHandle.hh"
10 #include "QJitter.hh"
11 #include "QJitterHandle.hh"
12 #include <vector>
13 #include <math.h>
14 #include <algorithm>
15 #include <TH1D.h>
16 
17 using namespace std;
18 
20 
21 using std::vector;
22 using namespace Diana;
23 
25 {
26  fCoincidenceDataOwner = GetString("CoincidenceDataOwner", "Coincidence");
27  fOutput = GetString("Output", "jitter.txt");
28  fRefCh_IsSet = false;
29  fRefCh = GetInt("ReferenceChannel", Q_INT_DEFAULT, false);
30  fTower = GetInt("Tower", Q_INT_DEFAULT, false);
31  fJitterByDelaySource = GetString("JitterByDelaySource",Q_STRING_DEFAULT, false);
32 
33  Info("Tower is: %d", fTower);
34 
35  if (fRefCh!=Q_INT_DEFAULT) {
36  Info("Reference Channel set to: %d", fRefCh);
37  fRefCh_IsSet = true;
38  }
39 
40  fEnergyLabel = GetString("EnergyLabel","ApplyCalibration@Energy");
41  ev.RequireByLabel<QDouble>(fEnergyLabel);
42 
43  ev.Require<QPulseInfo>("DAQ","PulseInfo");
44  ev.Require<QHeader>("DAQ","Header");
45  ev.Require<QCoincidenceData>(fCoincidenceDataOwner,"CoincidenceData");
46  ev.Require<QDouble>(fCoincidenceDataOwner,"TotalEnergy");
47 
48  // clear quantities
49  fJitterSum = 0.;
50  fJitterErrorSum = 0.;
51  fDeltaT.clear();
52 }
53 
54 //void MJitterByCoincidence::Do(QEvent& ev, const QEventList& neighbours)
56 {
57  const QPulseInfo& pulseInfo = ev.Get<QPulseInfo>("DAQ","PulseInfo");
58  const int& channel = pulseInfo.GetChannelId();
59 
60  fGoodChannels.insert(channel);
61 
62  const QCoincidenceData& cd = ev.Get<QCoincidenceData>(fCoincidenceDataOwner.c_str(),"CoincidenceData");
63 
64  const QHeader& hdr = ev.Get<QHeader>("DAQ","Header");
65  fRun = hdr.GetRun();
66 
67  QDetChannelCollectionHandle dccHandle;
68  dccHandle.SetRun(fRun);
69  GlobalData().Get("",&dccHandle,"");
70  const QDetChannelCollection& DCC = dccHandle.Get();
71  const std::vector<int>& boloRelChan = DCC.GetRelativeChannels(channel);
72 
73  if(cd.fMultiplicity==2) {
74  // select multiplicity 2 event and order the coincident channels according to channel number
75  const int o_channel = cd.fCoincidentChannels[0].fChannelId;
76 
77  if(channel>o_channel) {
78  const int deltaTower = cd.fCoincidentChannels[0].fDeltaTower;
79  const int deltaFloor = cd.fCoincidentChannels[0].fDeltaFloor;
80  const int deltaPos = cd.fCoincidentChannels[0].fDeltaPosition;
81 
82  // if coincident channel is not on same bolometer (relative channel)
83  if (find(boloRelChan.begin(),boloRelChan.end(),o_channel)==boloRelChan.end()
84  // if coincident channel is in same tower
85  && deltaTower==0
86  // if coincident channel is in same floor OR in same column (+1 floor and same position)
87  && ((abs(deltaFloor)==1 && deltaPos==0)
88  || deltaFloor==0))
89  {
90  const double deltaT = cd.fCoincidentChannels[0].fDeltaT;
91  // fills the map fDeltaT with a vector of time differences for each couple of channels
92  fDeltaT[channel][o_channel].push_back(deltaT);
93  }
94  }
95  }
96 }
97 
99 {
100  // get dataset
101  GlobalHandle<QInt> dHandle("Dataset");
102  GlobalData().Get("",&dHandle,"");
103  fDataset = dHandle.Get();
104 
105  QDetChannelCollectionHandle dccHandle;
106  dccHandle.SetRun(fRun);
107  GlobalData().Get("",&dccHandle,"");
108  const QDetChannelCollection& DCC = dccHandle.Get();
109 
110  QVector vecDeltaT;
111  QVector vecDeltaT_red;
112 
113  double DeltaT = 0.;
114  double DeltaTRMS = 0.;
115 
116  std::map<int,std::map<int,std::vector<double> > >::const_iterator iter;
117  std::map<int,std::vector<double> > ::const_iterator mapIter;
118 
119  // calculates the mean value of vector fDeltaT for each couple of channels
120  // mean value is calculated after removing the outliers (cut on median +- 3*MAD)
121 
122  iter = fDeltaT.begin();
123  while(iter != fDeltaT.end()) {
124  int ch = iter->first;
125  mapIter = (iter->second).begin();
126  while(mapIter != (iter->second).end()) {
127  int o_ch = mapIter->first;
128  if(fDeltaT[ch][o_ch].size()>0) {
129  vecDeltaT.Resize(fDeltaT[ch][o_ch].size());
130  vecDeltaT_red.Resize(0);
131  for (size_t i=0; i<vecDeltaT.Size(); i++) {
132  vecDeltaT[i] = (fDeltaT[ch][o_ch])[i];
133  }
134  double medianDeltaT = vecDeltaT.GetMedian();
135  double MADDeltaT = vecDeltaT.GetMedianAbsoluteDeviation();
136  for (size_t j=0; j<vecDeltaT.Size(); j++) {
137  if(vecDeltaT[j]>(medianDeltaT-3.*MADDeltaT) && vecDeltaT[j]<(medianDeltaT+3.*MADDeltaT)) {
138  vecDeltaT_red.Append(vecDeltaT[j]);
139  }
140  }
141  if(vecDeltaT_red.Size()>0) {
142  DeltaT = vecDeltaT_red.Sum(vecDeltaT_red.Size(),0)/vecDeltaT_red.Size();
143  DeltaTRMS = vecDeltaT_red.GetRMS(vecDeltaT_red.Size())/sqrt(vecDeltaT_red.Size());
144  fJitter[ch][o_ch] = DeltaT;
145  fJitterRMS[ch][o_ch] = DeltaTRMS;
146  // debug printing
147  std::cout<< ch << " " << o_ch <<" "<<fJitter[ch][o_ch]<<" "<< fJitterRMS[ch][o_ch] << std::endl;
148  }
149  }
150  mapIter++;
151  }
152  iter++;
153  }
154 
155  // loop over detector geometry
156 
157  const std::vector<int>& towers = DCC.GetTowers();
158  fLastFloor = false;
159 
160  for (size_t j=0; j<towers.size(); j++) {
161  int tower = towers[j];
162  const std::vector<int>& floors = DCC.GetFloorsInTower(tower);
163 
164  // check if tower has floors
165  if (floors.size()>0)
166  Info("Processing tower: %d",tower);
167  if (tower!=fTower) {
168  // process by tower
169  Info("Skip tower %d",tower);
170  continue;
171  } else if (floors.size()==0) {
172  // problem if size = 0
173  Info("Tower %d has no floors",tower);
174  continue;
175  }
176 
177  int last_floor = floors[floors.size()-1];
178 
179  // identify reference channel as the first valid channel in the first floor of the current tower
180  // |
181  // 3 | 2
182  // ----|-----
183  // 4 | 1
184  // |
185 
186  int position=1;
187  int flfl = 1;
188  while (!fRefCh_IsSet) {
189  fRefCh = FindChanWithPosInTowerFloor(position,tower,flfl);
190  std::map<int,std::map<int,double > >::const_iterator riter = fJitter.find(fRefCh);
191  if (riter!=fJitter.end()) {
192  if(fJitterByDelaySource!=Q_STRING_DEFAULT) {
193  // get jitter by delay handle for this channel
194  QJitterHandle jdHandle(fRefCh,fDataset);
195  GlobalData().Get("JitterByDelay",&jdHandle,fJitterByDelaySource);
196 
197  if(jdHandle.IsValid()) {
198  fRefCh_IsSet=true;
199  } else {
200  Warn("Channel %d, has no jitter by delay: %s",fRefCh,jdHandle.GetError().GetDescription().c_str());
201  position = position+1;
202  }
203  } else {
204  fRefCh_IsSet=true;
205  }
206  } else {
207  position = position+1;
208  }
209  if (position>4) {
210  Warn("Tower %d has no valid reference channels in floor 1",tower);
211  position = 1;
212  flfl++;
213  }
214  if( flfl > last_floor )
215  Panic("Tower %d has no valid reference channels anywhere", tower);
216  }
217  Info("Reference Channel set to: %d", fRefCh);
218 
219  position = DCC.Get(fRefCh).fTd.fTdPos;
220 
221  // starts loop over floors
222  for (size_t i=0; i<floors.size(); i++) {
223  int floor = floors[i];
224  if (floor == last_floor)
225  fLastFloor = true;
226 
227  if( floor < flfl )
228  continue;
229 
230  Info("Processing floor: %d, position: %d",floor,position);
231  position = ProcessFloor(position,tower,floor);
232  }
233  }
234 }
235 
236 double MJitterByCoincidence::FindJitter(int ch, int o_ch)
237 {
238  double jitter = 0.;
239  if (ch>o_ch)
240  {
241  std::map<int,std::map<int,double > >::const_iterator miter = fJitter.find(ch);
242  if (miter!=fJitter.end()) jitter = fJitter[ch][o_ch];
243  }
244  else if (ch<o_ch)
245  {
246  std::map<int,std::map<int,double > >::const_iterator miter = fJitter.find(o_ch);
247  if (miter != fJitter.end()) {
248 std::map<int,double>::const_iterator viter = (miter->second).find(ch);
249 if (viter != (miter->second).end()) jitter = -fJitter[o_ch][ch];
250  }
251  }
252  return jitter;
253 }
254 
255 double MJitterByCoincidence::FindJitterRMS(int ch, int o_ch)
256 {
257  double jitterRMS = 0.;
258  if (ch>o_ch)
259  {
260  std::map<int,std::map<int,double > >::const_iterator miter = fJitterRMS.find(ch);
261  if (miter!=fJitterRMS.end()) jitterRMS = fJitterRMS[ch][o_ch];
262  }
263  else if (ch<o_ch)
264  {
265  std::map<int,std::map<int,double > >::const_iterator miter = fJitterRMS.find(o_ch);
266  if (miter != fJitterRMS.end()) {
267 std::map<int,double>::const_iterator viter = (miter->second).find(ch);
268 if (viter != (miter->second).end()) jitterRMS = fJitterRMS[o_ch][ch];
269  }
270  }
271  return jitterRMS;
272 }
273 
274 int MJitterByCoincidence::FindChanWithPosInTowerFloor(int pos, int tower, int floor)
275 {
276  int chan = Q_INT_DEFAULT;
277  std::vector<int> chans;
278 
279  QDetChannelCollectionHandle dccHandle;
280  dccHandle.SetRun(fRun);
281  GlobalData().Get("",&dccHandle,"");
282  const QDetChannelCollection& DCC = dccHandle.Get();
283 
284  const std::vector<int>& chTF = DCC.GetChannelsInTowerFloor(tower,floor);
285 
286  for (size_t i=0; i<chTF.size(); i++)
287  {
288  if (DCC.Get(chTF[i]).fTd.fTdPos == pos) chans.push_back(chTF[i]);
289  }
290 
291  for (size_t j=0; j<chans.size(); j++)
292  {
293  if (fGoodChannels.count(chans[j])>0) chan = chans[j];
294  }
295 
296  return chan;
297 }
298 
299 void MJitterByCoincidence::SaveJitter(int ch, double jitter, double jitter_error)
300 {
301  QJitter jitterObj;
302  jitterObj.Clear();
303 
304  // set the object jitterObj
305  jitterObj.fRefChannel = fRefCh;
306  jitterObj.fJitter = jitter;
307  jitterObj.fJitterError = jitter_error;
308 
309  QJitterHandle jitterHandle(ch,fDataset);
310  jitterHandle.SetCalibVersion(GetConfig().fVersionTag);
311 
312  GlobalHandle<QString> clabelh("CalibrationLabel");
313  clabelh.SetDataset(fDataset);
314  clabelh.SetChannel(ch);
315  GlobalData().Get(fEnergyLabel.owner,&clabelh,"CurrentReader");
316  if(clabelh.IsValid()) {
317  jitterHandle.SetCalibLabel(clabelh.Get());
318  } else {
319  jitterHandle.SetCalibLabel("");
320  }
321 
322  jitterHandle.Set(jitterObj);
323  GlobalData().Set(&jitterHandle,fOutput);
324 }
325 
326 int MJitterByCoincidence::ProcessFloor(int start_pos, int tower, int floor)
327 {
328 
329  int ndet = 4;
330  int pos[ndet];
331  int ch_pos[ndet];
332  int ch_pos_next_floor[ndet];
333  int best_pos = 1;
334  double best_jitter = 0.;
335  double best_jitterRMS = 0.;
336 
337  for (int i=0; i<ndet; i++)
338  {
339  pos[i] = start_pos+i;
340  if (pos[i]>4) pos[i]=pos[i]-4;
341 
342  ch_pos[i] = FindChanWithPosInTowerFloor(pos[i],tower,floor);
343  ch_pos_next_floor[i] = FindChanWithPosInTowerFloor(pos[i],tower,floor+1);
344 
345  double temp_jitterRMS = FindJitterRMS(ch_pos_next_floor[i],ch_pos[i]);
346  if (temp_jitterRMS>0.) best_jitterRMS = temp_jitterRMS;
347  }
348 
349  // finds path to next floor with lower error and calculates jitter (only if floor != last floor)
350  if (!fLastFloor) {
351  for (int i=0; i<ndet; i++)
352  {
353 double floor_jitterRMS = FindJitterRMS(ch_pos_next_floor[i],ch_pos[i]);
354 double floor_jitter = FindJitter(ch_pos_next_floor[i],ch_pos[i]);
355 
356 if(floor_jitterRMS!=0 && floor_jitterRMS<=best_jitterRMS)
357  {
358  best_jitterRMS = floor_jitterRMS;
359  best_jitter = floor_jitter;
360  best_pos=pos[i];
361  }
362  }
363  }
364 
365  // calculates jitter with respect to ref channel on this floor
366 
367  double jitter_rel[ndet];
368  double jitterRMS_rel[ndet];
369 
370  double jitter11,jitter21,jitter41,jitter32,jitter34,jitter31;
371  double jitter11RMS,jitter21RMS,jitter41RMS,jitter32RMS,jitter34RMS,jitter31RMS;
372  double error321, error341;
373 
374  jitter11 = FindJitter(ch_pos[0],ch_pos[0]);
375  jitter11RMS = FindJitterRMS(ch_pos[0],ch_pos[0]);
376 
377  jitter21 = FindJitter(ch_pos[1],ch_pos[0]);
378  jitter21RMS = FindJitterRMS(ch_pos[1],ch_pos[0]);
379 
380  jitter41 = FindJitter(ch_pos[3],ch_pos[0]);
381  jitter41RMS = FindJitterRMS(ch_pos[3],ch_pos[0]);
382 
383  jitter32 = FindJitter(ch_pos[2],ch_pos[1]);
384  jitter32RMS = FindJitterRMS(ch_pos[2],ch_pos[1]);
385 
386  jitter34 = FindJitter(ch_pos[2],ch_pos[3]);
387  jitter34RMS = FindJitterRMS(ch_pos[2],ch_pos[3]);
388 
389  jitter31 = FindJitter(ch_pos[2],ch_pos[0]);
390  jitter31RMS = FindJitterRMS(ch_pos[2],ch_pos[0]);
391 
392  if (jitter32RMS!=0. && jitter21RMS!=0.) {error321 = sqrt(pow(jitter32RMS,2)+pow(jitter21RMS,2));}
393  else error321 = 9999.;
394  if (jitter34RMS!=0. && jitter41RMS!=0.) {error341 = sqrt(pow(jitter34RMS,2)+pow(jitter41RMS,2));}
395  else error341 = 9999.;
396 
397  // position 3 (finds path with lower error)
398 
399  if (error321<error341) {
400  jitter_rel[2] = fJitterSum + jitter32 + jitter21;
401  jitterRMS_rel[2] = fJitterErrorSum + pow(error321,2);
402  // std::cout<< ch_pos[2]<<" "<<ch_pos[0]<<" "<<jitter_rel[2]<<" "<< sqrt(jitterRMS_rel[2])<<std::endl;
403  SaveJitter(ch_pos[2],jitter_rel[2],sqrt(jitterRMS_rel[2]));
404  }
405  else if (error341<error321) {
406  jitter_rel[2] = fJitterSum + jitter34 + jitter41;
407  jitterRMS_rel[2] = fJitterErrorSum + pow(error341,2);
408  // std::cout<< ch_pos[2]<<" "<<ch_pos[0]<<" "<<jitter_rel[2]<<" "<< sqrt(jitterRMS_rel[2])<<std::endl;
409  SaveJitter(ch_pos[2],jitter_rel[2],sqrt(jitterRMS_rel[2]));
410  }
411  else {
412  if (jitter31!=0.) {
413  jitter_rel[2] = fJitterSum + jitter31;
414  jitterRMS_rel[2] = fJitterErrorSum + pow(jitter31RMS,2);
415  // std::cout<< ch_pos[2]<<" "<<ch_pos[0]<<" "<<jitter_rel[2]<<" "<< sqrt(jitterRMS_rel[2])<<std::endl;
416  SaveJitter(ch_pos[2],jitter_rel[2],sqrt(jitterRMS_rel[2]));
417  }
418  }
419 
420  // position 2
421  if (jitter21!=0.) {
422  jitter_rel[1] = fJitterSum + jitter21;
423  jitterRMS_rel[1] = fJitterErrorSum + pow(jitter21RMS,2);
424  // std::cout<< ch_pos[1]<<" "<<ch_pos[0]<<" "<<jitter_rel[1]<<" "<< sqrt(jitterRMS_rel[1])<<std::endl;
425  SaveJitter(ch_pos[1],jitter_rel[1],sqrt(jitterRMS_rel[1]));
426  }
427 
428  // position 4
429  if (jitter41!=0.) {
430  jitter_rel[3] = fJitterSum + jitter41;
431  jitterRMS_rel[3] = fJitterErrorSum + pow(jitter41RMS,2);
432  // std::cout<< ch_pos[3]<<" "<<ch_pos[0]<<" "<<jitter_rel[3]<<" "<< sqrt(jitterRMS_rel[3])<<std::endl;
433  SaveJitter(ch_pos[3],jitter_rel[3],sqrt(jitterRMS_rel[3]));
434  }
435 
436  // position 1
437  jitter_rel[0] = fJitterSum + jitter11;
438  jitterRMS_rel[0] = fJitterErrorSum + pow(jitter11RMS,2);
439  // std::cout<< ch_pos[0]<<" "<<ch_pos[0]<<" "<<jitter_rel[0]<<" "<< sqrt(jitterRMS_rel[0])<<std::endl;
440  SaveJitter(ch_pos[0],jitter_rel[0],sqrt(jitterRMS_rel[0]));
441 
442  // calculates jitter of channel with best position (to go to lower floor) with respect to reference channel;
443  // increments fJitterSum and fJitterErrorSum
444 
445  if (!fLastFloor) {
446 
447  if (best_pos!=start_pos)
448  {
449 int ch = 0;
450 if (best_pos>start_pos){
451  ch = best_pos - start_pos;
452 }
453 if (best_pos<start_pos){
454  ch = 4 - (start_pos - best_pos);
455 }
456 
457 fJitterSum = jitter_rel[ch] + best_jitter;
458 fJitterErrorSum = fJitterErrorSum + pow(jitterRMS_rel[ch],2) + pow(best_jitterRMS,2);
459  }
460  else
461  {
462 fJitterSum = fJitterSum + best_jitter;
463 fJitterErrorSum = fJitterErrorSum + pow(best_jitterRMS,2);
464  }
465  }
466 
467  // return position of channel with lower error on jitter
468  return best_pos;
469 }
470 
c1 cd(1)
const int channel
Diana::QComplex pow(const Diana::QComplex &z, double a)
Raise a complex number to a real power.
Definition: QComplex.cc:246
#define Q_STRING_DEFAULT
Definition: QDiana.hh:38
#define Q_INT_DEFAULT
Definition: QDiana.hh:26
#define REGISTER_MODULE(clazz)
Definition: QDriver.hh:133
Diana::QVector abs(const Diana::QVector &v)
Definition: QVector.cc:811
Calculates time jitter between couples of channels using coincident events.
double FindJitter(int ch, int o_ch)
FindJitter function.
double FindJitterRMS(int ch, int o_ch)
FindJitterRMS function.
void Done()
Done method.
void Init(Diana::QEvent &ev)
Init method.
void Do(Diana::QEvent &ev)
Do method
void SaveJitter(int ch, double jitter, double jitter_error)
SaveJitter function.
int FindChanWithPosInTowerFloor(int pos, int tower, int floor)
FindPos function.
int ProcessFloor(int pos, int tower, int floor)
ProcessFloor function.
base types wrapped into a QObject. Currently implemented types are QInt QDouble and QFloat....
Definition: QBaseType.hh:17
coincidence data
diana event
Definition: QEvent.hh:46
void RequireByLabel(const QEventLabel &label) const
notify the QEvent that we need a QObject, if not found an exception is thrown
Definition: QEvent.hh:242
void Require(const std::string &owner, const std::string &name) const
notify the QEvent that we need a QObject, if not found an exception is thrown
Definition: QEvent.hh:232
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
global handle for jitter by coincidence
void SetCalibLabel(const std::string &calibl)
void SetCalibVersion(const std::string &calibv)
jitter by coincidence
Definition: QJitter.hh:17
void Clear()
Definition: QJitter.hh:21
int fRefChannel
Definition: QJitter.hh:28
double fJitterError
Definition: QJitter.hh:30
double fJitter
Definition: QJitter.hh:29
Raw event: bolometer channel, trigger positions and types.
Definition: QPulseInfo.hh:18
const int & GetChannelId() const
Get ChannelId.
Definition: QPulseInfo.hh:22
the Diana namespace is needed because sometimes we use Qt libraries, that use same class names of our...