Diana Software
MMultipletValidation.cc
Go to the documentation of this file.
1 // this will be a module that checks for coherence in coincidence multiplets
2 // and selects just the ones that exist, symmetric, after a given set of cuts
3 // meaning that both MAIN <-> COINCIDENT pass the cuts
4 
6 #include "QEvent.hh"
7 #include "QRawEvent.hh"
8 #include "QBaseType.hh"
9 #include "QCoincidenceData.hh"
10 #include "QBool.hh"
11 
12 #include <string>
13 #include <map>
14 #include <set>
15 
16 using namespace std;
17 using namespace Diana;
18 
20 
22  fValid = true; // if no-one comes to set this multiplet invalid, assume it OK
23  fTag = _tag;
24 }
25 
26 bool LightMultiplet::Insert( ULong64_t _tag ){
27  if( fCoincidentTag.count( _tag ) != 0 )
28  return false;
29  fCoincidentTag.insert( _tag );
30  return true;
31 }
32 
34  fValid = false;
35 }
36 
38  return fValid;
39 }
40 void MMultipletValidation::Init( Diana::QEvent& ev ){
41  fCoincidenceLabel = GetString("CoincidenceLabel","FastCoincidence@CoincidenceData");
42  // need to read EventNumber and Channel
43  ev.Require<QHeader>("DAQ", "Header");
44  ev.Require<QPulseInfo>("DAQ", "PulseInfo");
45  ev.RequireByLabel<QCoincidenceData>( fCoincidenceLabel );
46  ev.Add<QBool>("Valid");
47  ev.Add<QBool>("Selected");
48 }
49 
50 void MMultipletValidation::Do( Diana::QEvent& ev ){
51  const QHeader& header = ev.Get<QHeader>("DAQ", "Header");
52  const QPulseInfo& pulseinfo = ev.Get<QPulseInfo>("DAQ", "PulseInfo");
53  const QCoincidenceData& coindata = ev.GetByLabel<QCoincidenceData>( fCoincidenceLabel );
54  const int channel = pulseinfo.GetChannelId();
55  const int tower = ( (channel-1)/52 ) + 1;
56  const int EventNumber = header.GetEventNumber();
57  ULong64_t tag = 100*EventNumber + tower; // unique tag for event
58  // 1st iteration: build "graph" in RAM of multiplets
59  if( GetIteration() == 1 ){
60  if( fMultiplets.count( tag ) != 0 )
61  Panic("Something impossible happened: unique tag %llu found twice!",tag);
62  fMultiplets[ tag ] = new LightMultiplet( tag );
63  // loop over coincident event data
64  for(unsigned int j=0; j < coindata.fCoincidentChannels.size(); j++){
65  QCoincidentChannel IT = coindata.fCoincidentChannels[j];
66  int cointower = ((IT.fChannelId - 1)/52) + 1;
67  ULong64_t thistag = 100*IT.fEventNumber + cointower;
68  if( !(fMultiplets.at(tag))->Insert( thistag ) )
69  Panic("Current tag: %llu. Found duplicate tag %llu in coincident tag-list.",tag,thistag);
70  }
71  }else{// 2nd iteration: perform selection
72  ev.Get<QBool>("Valid") = (fMultiplets.at( tag ))->GetIsValid();
73  ev.Get<QBool>("Selected") = true;
74  }
75 }
76 
78  if( GetIteration() == 1 ){
79  SetRunAgain(true);
80  // 1st part: assuming the coincidences are built correctly
81  // and mismatches are due just to different selections
82  /* perform all kind of checks and prepare bool flags for next iteration
83  * 1. loop over the primary keys (both valid and invalid).
84  * if valid..
85  * a. check that each coincident key exists as primary (was selected)
86  * b. if yes, go ahead with next coincident key.
87  * c. if no, mark the main key as invalid and go to 2.
88  * 2. if invalid, loop over its coincidents and set them all invalid
89  */
90  std::map< ULong64_t, LightMultiplet* >::iterator mainIT;
91  for( mainIT = fMultiplets.begin(); mainIT != fMultiplets.end(); ++mainIT )
92  {// loop over multiplets (main event tags)
93  if( (mainIT->second)->GetIsValid() ){
94  std::set<ULong64_t>::iterator coinIT;
95  for(coinIT = ((mainIT->second)->fCoincidentTag).begin(); coinIT != ((mainIT->second)->fCoincidentTag).end(); ++coinIT )
96  {// loop over coincident keys
97  if( fMultiplets.count( *coinIT ) <= 0 ){// coincident key not found as main
98  (mainIT->second)->SetInvalid();// set main invalid
99  break;// stop checking other coincidents
100  }
101  }
102  }
103  // if main is invalid at this point, set invalid all the existing coincidents
104  if( false == (mainIT->second)->GetIsValid() ){
105  std::set<ULong64_t>::iterator coinIT;
106  std::map<ULong64_t, LightMultiplet*>::iterator mainIT2;
107  for(coinIT = ((mainIT->second)->fCoincidentTag).begin(); coinIT != ((mainIT->second)->fCoincidentTag).end(); ++coinIT )
108  {// loop over coincident keys
109  mainIT2 = fMultiplets.find( *coinIT );
110  if( mainIT2 != fMultiplets.end() ){// if exists in the main key list...
111  (mainIT2->second)->SetInvalid();// ... set it invalid
112  }
113  }
114  }
115  }
116  // 2nd part: check coherence and remove iteratively mismatched multiplets
117  bool myRunAgain;
118  int myRunCounter = 0;
119  do{
120  myRunCounter++;
121  Info("Running 2nd level check of coincident multiplets. Iteration %d", myRunCounter);
122  if( myRunCounter > 1 )
123  Warn("The 2nd level check had to modify multiplet validity at least once. This means multiplets were NOT symmetric in the first place.");
124  myRunAgain = false;
125  for( mainIT = fMultiplets.begin(); mainIT != fMultiplets.end(); ++mainIT )
126  {// loop over multiplets (main event tags)
127  if( (mainIT->second)->GetIsValid() )
128  { // if main valid go ahead
129  std::set<ULong64_t>::iterator coinIT;
130  std::map<ULong64_t, LightMultiplet*>::iterator mainIT2;
131  for(coinIT = ((mainIT->second)->fCoincidentTag).begin(); coinIT != ((mainIT->second)->fCoincidentTag).end(); ++coinIT )
132  {// loop over coincident keys...
133  if( fMultiplets.count( *coinIT ) <= 0 )
134  Panic("Event tag %llu, coincident of valid main event tag %llu not found.", *coinIT, mainIT->first);
135  mainIT2 = fMultiplets.find( *coinIT ); // find it in the main event list...
136  if( (mainIT2->second)->GetIsValid() && ((mainIT2->second)->fCoincidentTag).count( mainIT->first ) )
137  continue; // if from there you can come back to the main, everything is fine.
138  (mainIT->second)->SetInvalid(); // otherwise the main is invalid ...
139  if( !myRunAgain )
140  myRunAgain = true; // run another iteration later
141  Info("Event tag %llu found as coincident of valid main event tag %llu, either is invalid or does not list the main tag among its coincidents. Set main invalid.", mainIT2->first, mainIT->first);
142  Info("Setting invalid all coincident events of main event tag %llu", mainIT->first);
143  --mainIT; // and also its coincidents! (this loops back on the same event -> finds it invalid -> invalidates all the coincidents
144  break;
145  }
146  }else{ // if main invalid check that ALL coincidents are invalid!
147  std::set<ULong64_t>::iterator coinIT;
148  std::map<ULong64_t, LightMultiplet*>::iterator mainIT2;
149  for(coinIT = ((mainIT->second)->fCoincidentTag).begin(); coinIT != ((mainIT->second)->fCoincidentTag).end(); ++coinIT )
150  {// loop over coincidents
151  mainIT2 = fMultiplets.find( *coinIT );
152  if( mainIT2 != fMultiplets.end() ){ // if the coincident exists in the main key list...
153  if( (mainIT2->second)->GetIsValid() ){ // ... and is valid ...
154  (mainIT2->second)->SetInvalid(); // ... set it invalid!
155  if( !myRunAgain )
156  myRunAgain = true; // run another iteration later
157  Info("Event tag %llu found as coincident of invalid main event tag %llu, was set valid. Set invalid.", mainIT2->first, mainIT->first); // and inform the user.
158  }
159  }
160  }
161  }
162  }
163  }while( myRunAgain );
164  }else{
165  SetRunAgain(false);
166  std::map< ULong64_t, LightMultiplet*>::iterator it;
167  for( it = fMultiplets.begin(); it != fMultiplets.end(); ++it)
168  delete it->second;
169  }
170 }
const int channel
REGISTER_MODULE(MMultipletValidation)
LightMultiplet(ULong64_t _tag)
bool Insert(ULong64_t _tag)
void Init(Diana::QEvent &ev)
void Do(Diana::QEvent &ev)
bool wrapped into a QObject
Definition: QBool.hh:17
coincidence data
data of coincident channel
Raw event: basic information like run number and time.
Definition: QHeader.hh:16
int GetEventNumber() const
get EventNumber
Definition: QHeader.hh:25
Raw event: bolometer channel, trigger positions and types.
Definition: QPulseInfo.hh:18
the Diana namespace is needed because sometimes we use Qt libraries, that use same class names of our...