Diana Software
QNeighboursFiller.cc
Go to the documentation of this file.
1 #include "QNeighboursFiller.hh"
2 #include "QEventAssembler.hh"
3 #include "QEventList.hh"
4 #include "QReader.hh"
5 #include "QReaderNeighbour.hh"
7 
8 
10 
12  fReader = reader;
13  fReaderNeighbour = 0;
14 }
15 
18 }
19 
20 
22  std::string rnname = fReader->GetString("NeighbourAlgorithm","");
24  if(!fReaderNeighbour) fReader->Panic("NeighbourAlgorithm %s not known",rnname.c_str());
25  fNeighboursReloading=fReader->GetBool("NeighboursReloading",true,true);
26  fMaxEventIndex = (size_t)fReader->GetInt("MaximumEventIndexInBuffer",1000,false);
28  fEventIndex = 0;
29  fEventList.Clear();
30  fEvalNeighbours.clear();
31 
32  fEva.Assign(eva.GetEvent());
33  fEndOfEvents = false;
34  fReader->Init(fEva);
35  eva.Assign(fEva.GetEvent());
36  eva.GetAliases() = fEva.GetAliases();
37 
38  fFillStrategy = fReader->GetInt("NeighbourFillStrategy",fReaderNeighbour->GetFillStrategy(),false);
39 
40 }
41 
43 {
44  if(fEndOfEvents && fEventIndex == fEventList.Size()) return false;
45  if(fEventIndex == 0) {
46  fEva.Assign(evao.GetEvent());
47  fEva.Consolidate();
48  }
49  // At this point fEventIndex corresponds to the event that will be
50  // read out at the end of Do. But evao, contains the data from the
51  // last event.
52  bool EnterMainLoop=true;
54  std::cout<<"AOOOOOO "<<EnterMainLoop<<std::endl;
56  EnterMainLoop=AssociativeFillNeighbours(evao,neighbours);
58  EnterMainLoop=FilterFillNeighbours(evao,neighbours);
59  else
60  EnterMainLoop=ExhaustiveFillNeighbours(evao,neighbours);
61  std::cout<<"AOOOOOO2 "<<EnterMainLoop<<std::endl;
62  if(!EnterMainLoop) return false;
63 
64  // Fill the data from the event in the cached list into the event assembler
65  evao.Assign(fEventList[fEventIndex].GetEvent());
66 
68 
69  fEventIndex++; // Increment fEventIndex for the next call
70 
71  return true;
72 }
73 
75  // For this method, we are going to assume that fIsInWindow and
76  // fIsNeighbour are interchangable. Because of that, we dont need
77  // to check if each event in the fEventList belongs in
78  // neighbours. Instead, we simply do quick searches for the first
79  // InWindow in EventList, and know that the last event in
80  // fEventList is not a neighbour of the previous event. So, things
81  // are a lot faster.
82 
83  neighbours.Clear();
84  const QEvent* currEv = 0;
85  if(!fEventList.Empty()) currEv = &(fEventList[fEventIndex].GetEvent());
86 
88 
89 
90  // Start with two most likely places that the first neighbour
91  // could be (e.g. the first event in fEventList, and the event
92  // before fEventIndex).
93  int firstNeighbour = -1;
94  if(fEventIndex>0) {
95  nInfo = GetNeighbourInfo(*currEv,fEventList[0].GetEvent());
96  if(nInfo.fIsInWindow) // Maybe the first event in fEventList is a neighbour?
97  firstNeighbour = 0;
98  if(firstNeighbour < 0) { // Maybe fEventIndex is not a neighbour?
99  nInfo = GetNeighbourInfo(*currEv,fEventList[fEventIndex-1].GetEvent());
100  if(!nInfo.fIsInWindow)
101  firstNeighbour = fEventIndex;
102  }
103  if(firstNeighbour < 0) { // Otherwise, do a binary search for the first neighbour
104  int start = 0;
105  int end = fEventIndex - 1;
106  firstNeighbour = fEventIndex - 1;
107  while(start<=end) {
108  int mid = (start+end)/2;
109  nInfo = GetNeighbourInfo(*currEv,fEventList[mid].GetEvent());
110  if(nInfo.fIsInWindow) {
111  firstNeighbour = mid;
112  end = mid - 1;
113  }else {
114  start = mid + 1;
115  }
116  }
117  }
118  }
119  // Pop all the things that are behind and can be dropped from
120  // consideration.
121  for(int i=0;i<firstNeighbour;i++) {
122  fEventList.Pop();
123  fEventIndex--;
124  }
125 
126  // Fill all the past events from 0 to fEventIndex-1
127  for(size_t iev=0;iev<fEventIndex;iev++) {
128  if(iev == fEventIndex - 1)
129  fEventList[iev].Assign(evao.GetEvent());
130  neighbours.Push(&(fEventList[iev].GetEvent()));
131  }
132 
133 
134  // Test the last event in fEventList, if its a neighbour we'll
135  // need to read more, if its not a neighbour, don't read
136  // anymore. Eitherway, we are going to fill all of the events from
137  // fEventIndex up to fEventList.Size()-1 into neighbours.
138  bool futureEventLeft = false;
139  if(fEventList.Size()>1) {
140  nInfo = GetNeighbourInfo(*currEv,fEventList[fEventList.Size()-1].GetEvent());
141  futureEventLeft = !nInfo.fIsInWindow;
142 
143  for(size_t iev=fEventIndex+1;iev < fEventList.Size()-futureEventLeft;iev++)
144  neighbours.Push(&(fEventList[iev].GetEvent()));
145  }
146 
147 
148  // get new events
149  if(!futureEventLeft && !fEndOfEvents) {
150  bool isInWindow = false;
151  do {
152  fEva.Clear();
154  if(fEndOfEvents) break;
155 
157  if(fEventList.Size() == 1) {
158  currEv = &(fEventList[0].GetEvent());
159  isInWindow = true;
160  } else {
161  const QEvent& otherEv = fEventList.Back().GetEvent();
162  nInfo = GetNeighbourInfo(*currEv,otherEv);
163  isInWindow = nInfo.fIsInWindow;
164  if(nInfo.fIsNeighbour) neighbours.Push(&otherEv);
165  }
166  } while (isInWindow && !fEndOfEvents);
167  }
168 
169  return true;
170 }
171 
173  // fReader->Warn("EventList size %d",fEventList.Size());
174  neighbours.Clear();
175  const QEvent* currEv = 0;
176  if(!fEventList.Empty()) currEv = &(fEventList[fEventIndex].GetEvent());
177 
178 
180 
181  // Start from the beginning of the cached event list. And test
182  // whether each of the events before fEventIndex is in window and
183  // a neighbour.
184  for(int iev = 0; iev < (int)fEventIndex; iev++) {
185  QEvent& otherEv = fEventList[iev].GetEvent();
186  nInfo = GetNeighbourInfo(*currEv,otherEv);
187  if(!nInfo.fIsInWindow) {
188  fEventList.Pop(); // If the event is not in the window, drop it from cache
189  fEventIndex--;
190  iev--;
191  } else {
192  if(iev == int(fEventIndex -1)) {
193  // What we are doing here, is assigning the data in
194  // evao (some of which was calculated in the last
195  // round of Do's) to the cached data in the list.
196  fEventList[iev].Assign(evao.GetEvent());
197  }
198  if(nInfo.fIsNeighbour)
199  // If its a neighbour, add it to the list of neighbours.
200  neighbours.Push(&otherEv);
201  }
202  }
203  evao.Clear(); // Clear the data from the last event (fEventIndex-1).
204 
205  // forward events in list
206  bool futureEventLeft = false;
207  for(size_t iev = fEventIndex+1; iev < fEventList.Size(); iev++) {
208  const QEvent& otherEv = fEventList[iev].GetEvent();
209  nInfo = GetNeighbourInfo(*currEv,otherEv);
210  if(nInfo.fIsInWindow && nInfo.fIsNeighbour)
211  neighbours.Push(&otherEv);
212  else if(!nInfo.fIsInWindow)
213  futureEventLeft = true;
214  }
215 
216  // get new events
217  std::cout<<"ExhaustiveFillNeighbours"<<std::endl;
218  if(!futureEventLeft && !fEndOfEvents) {
219  bool isInWindow = false;
220  do {
221  fEva.Clear();
223  if(fEndOfEvents) break;
224 
226  if(fEventList.Size() == 1) {
227  currEv = &(fEventList[0].GetEvent());
228  isInWindow = true;
229  } else {
230  const QEvent& otherEv = fEventList.Back().GetEvent();
231  nInfo = GetNeighbourInfo(*currEv,otherEv);
232  isInWindow = nInfo.fIsInWindow;
233  if(nInfo.fIsNeighbour) neighbours.Push(&otherEv);
234  }
235  } while (isInWindow && !fEndOfEvents);
236  }
237 
238  return true;
239 }
240 
241 
243 
244  neighbours.Clear(); //clear neighbours
245  const QEvent* currEv = 0; //pointer to data of current event being evaled
246  bool eval_neigh = false; //<- tells us if we want to enter in the event loop
247  QReaderNeighbour::NeighbourInfo nInfo; //initialize info
248 
249  //Loop until you find the main event that wants neighbours
250  do{
251  //If list is not empty then assign current event
252  if(!fEventList.Empty()){
253  currEv = &(fEventList[fEventIndex].GetEvent());
254  eval_neigh=fEvalNeighbours[fEventIndex];
255  }
256 
257  //Quickly empty the fEventList every now and then in order to not make
258  //cache diverge. Only do this for events that don't want the neighbours,
259  //since the cache is correctly emptied when the neighbour algo is called.
260  if(!eval_neigh and fEventIndex>fMaxEventIndex){
261  size_t other_evidx=fEventIndex/2;
262  nInfo = GetNeighbourInfo(*currEv,fEventList[other_evidx].GetEvent());
263  if(!nInfo.fIsInWindow){
264  for(size_t iev = 0; iev <other_evidx; iev++){
265  fEventList.Pop();
266  fEvalNeighbours.pop_front();
267  fEventIndex--;
268  other_evidx--;
269  iev--;
270  }
271  }
272  }
273  //Reload past event if we want (very slow, deprecated).
274  //Since we only enter the main diana event loop there is no need to add events
275  //that don't want neighbours since they remain unchanged.
277  // What we are doing here, is assigning the data in
278  // evao (some of which was calculated in the last
279  // round of Do's) to the cached data in the list.
280  if(fEvalNeighbours[fEventIndex-1]) fEventList[fEventIndex-1].Assign(evao.GetEvent());
281  }
282 
283  //if we are not in presence of a master event but we have finished
284  //the fEventList then we must read 1 new event from the file. If we
285  //are in the presence of a master event then it will be taken care of
286  //after.
287  if((!eval_neigh and !fEndOfEvents) and (fEventIndex+1 == fEventList.Size() or (fEventIndex==fEventList.Size() and fEventList.Size()==0))){
288  fEva.Clear();
290  if(!fEndOfEvents){
291  fEventList.Push(fEva.GetEvent());//<- this is a costly operation
293  }
294  }
295 
296  //Move to next event in cache if not a master event, otherwise the main loop
297  //takes care of it
298  if(!eval_neigh and fEventList.Size()>1){
299  fEventIndex++;
300  }
301  }while(!eval_neigh and !(fEndOfEvents and fEventIndex==fEventList.Size())); //exit if we have master event or if we finished the events
302 
303  //If it is not a master event and we are at the end of the cache and at the end of
304  //the file the event must not be processed
305  if(!eval_neigh and fEventIndex==fEventList.Size() and fEndOfEvents) return false;
306 
307  //From this point on we are sure that we have an event that wants neighbours.
308  //So we assume eval_neigh=true (and all that it implies :3 ).
309 
310  // Start from the beginning of the cached event list. And test
311  // whether each of the events before fEventIndex is in window and
312  // a neighbour.
313  for(int iev = 0; iev < (int)fEventIndex; iev++) {
314  QEvent& otherEv = fEventList[iev].GetEvent();
315  nInfo = GetNeighbourInfo(*currEv,otherEv);
316  if(!nInfo.fIsInWindow) {
317  // If the event is not in the window, drop it from cache
318  fEventList.Pop();
319  fEvalNeighbours.pop_front();
320  fEventIndex--;
321  iev--;
322  } else {
323  if(nInfo.fIsNeighbour)
324  // If its a neighbour, add it to the list of neighbours.
325  neighbours.Push(&otherEv);
326  }
327  }
328 
329  evao.Clear(); // Clear the data from the last event (fEventIndex-1).
330 
331  bool futureEventLeft = false;
332  // forward events in list
333  for(size_t iev = fEventIndex+1; iev < fEventList.Size(); iev++) {
334  const QEvent& otherEv = fEventList[iev].GetEvent();
335  nInfo = GetNeighbourInfo(*currEv,otherEv);
336  if(nInfo.fIsInWindow && nInfo.fIsNeighbour)
337  neighbours.Push(&otherEv);
338  else if(!nInfo.fIsInWindow)
339  futureEventLeft = true;
340  }
341 
342  // get new events
343  if(!futureEventLeft && !fEndOfEvents) {
344  bool isInWindow = false;
345  do {
346  fEva.Clear();
348  if(fEndOfEvents) break;
349 
350  fEventList.Push(fEva.GetEvent());//<- this is a costly operation
351 
353  if(fEventList.Size() == 1) {
354  currEv = &(fEventList[0].GetEvent());
355  eval_neigh=fEvalNeighbours[0];
356  }
357 
358  if(fEventList.Size() == 1) {
359  isInWindow = true;
360  } else{
361  const QEvent& otherEv = fEventList.Back().GetEvent();
362  nInfo = GetNeighbourInfo(*currEv,otherEv);
363  isInWindow = nInfo.fIsInWindow;
364  if(nInfo.fIsNeighbour) neighbours.Push(&otherEv);
365  }
366  } while (isInWindow && !fEndOfEvents);
367  }
368 
369  return true;
370 }
371 
373  return fReaderNeighbour->GetNeighbourInfoBase(thisEvent,otherEvent);
374 }
375 
377  return fReaderNeighbour->GetWantsNeighbours(thisEvent);
378 }
379 
#define Q_END_NAMESPACE
Definition: QDiana.hh:22
#define Q_BEGIN_NAMESPACE
Definition: QDiana.hh:20
Q_BEGIN_NAMESPACE QReaderNeighbour * QReaderNeighbourFactory(const std::string &name)
factory for neighbour algorithms.
const std::string & GetString(const std::string &parname, const std::string &defVal, bool warnCfg=true) const
Get a string parameter from config file ( see GetDouble() )
Definition: QBaseModule.cc:297
void Panic(const char *descr,...) const
Send a panic message (stops the framework) with printf syntax.
Definition: QBaseModule.hh:248
int GetInt(const std::string &parname, int defVal, bool warnCfg=true) const
Get an int parameter from config file ( see GetDouble() )
Definition: QBaseModule.cc:219
bool GetBool(const std::string &parname, bool defVal, bool warnCfg=true) const
Get a bool parameter from config file ( see GetDouble() )
Definition: QBaseModule.cc:256
void Push(const QEvent &obj)
bool Empty() const
const QEventAssembler & Back() const
size_t Size() const
Visitor class of QEvent that provides full handling of QEvent.
QEvent & GetEvent()
Get the QEvent.
void Consolidate()
Consolidate QEvent.
void Assign(const QEvent &ev)
copies the underlying QEvent (calls QEvent::operator=)
const QAliases & GetAliases() const
get aliases (const version)
void Clear()
clear the underlying QEvent (calls QEvent::Clear())
list of references to const QEvent (s)
Definition: QEventList.hh:21
void Clear()
reset list to 0 elements
Definition: QEventList.hh:42
void Push(const QEvent *obj)
add a QEvent
Definition: QEventList.cc:17
diana event
Definition: QEvent.hh:46
virtual void EndProcessCall()
End a process call and increment time and calls.
virtual void StartProcessCall()
Start of a process call.
bool FilterFillNeighbours(QEventAssembler &evao, QEventList &neighbours)
Only enters in Diana's main loop when the event requires neighbours.
QEventAssembler fEva
QNeighboursFiller(QReader *reader)
bool GetWantsNeighbours(const QEvent &thisEvent)
QReaderNeighbour::NeighbourInfo GetNeighbourInfo(const QEvent &thisEvent, const QEvent &otherEvent)
bool ExhaustiveFillNeighbours(QEventAssembler &evao, QEventList &neighbours)
void Init(QEventAssembler &eva)
QCachedEventList fEventList
QReaderNeighbour * fReaderNeighbour
std::deque< bool > fEvalNeighbours
bool Do(QEventAssembler &evao, QEventList &neighbours)
bool AssociativeFillNeighbours(QEventAssembler &evao, QEventList &neighbours)
A faster version that makes assumptions.
int GetFillStrategy() const
virtual bool GetWantsNeighbours(const QEvent &thisEvent)
virtual NeighbourInfo GetNeighbourInfoBase(const QEvent &thisEvent, const QEvent &otherEvent)
void InitBase(const QReader &reader)
Base class for diana event readers.
Definition: QReader.hh:50
virtual void Init(QEventAssembler &eva)=0
Init method is called before event loop, getting the QEventAssembler as argument This method must be ...
bool DoBase(QEventAssembler &eva)
DoBase executes Do, and is called by QNeighboursFiller.
Definition: QReader.cc:85