Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Fun4AllDstInputManager.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Fun4AllDstInputManager.cc
2 
3 #include "Fun4AllReturnCodes.h"
4 #include "Fun4AllServer.h"
5 
6 #include <ffaobjects/RunHeader.h>
7 #include <ffaobjects/SyncDefs.h>
9 
10 #include <frog/FROG.h>
11 
12 #include <phool/PHCompositeNode.h>
13 #include <phool/PHNodeIOManager.h>
14 #include <phool/PHNodeIntegrate.h>
15 #include <phool/PHNodeIterator.h> // for PHNodeIterator
16 #include <phool/PHObject.h> // for PHObject
17 #include <phool/getClass.h>
18 #include <phool/phool.h> // for PHWHERE, PHReadOnly, PHRunTree
19 #include <phool/phooldefs.h>
20 
21 #include <TSystem.h>
22 
23 #pragma GCC diagnostic push
24 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
25 #include <boost/algorithm/string.hpp>
26 #pragma GCC diagnostic pop
27 
28 #include <cassert>
29 #include <cstdlib>
30 #include <iostream> // for operator<<, basic_ostream, endl
31 #include <utility> // for pair
32 #include <vector> // for vector
33 
34 class TBranch;
35 
37  : Fun4AllInputManager(name, nodename, topnodename)
38 {
39  return;
40 }
41 
43 {
44  delete m_IManager;
45  delete m_RunNodeSum;
46  return;
47 }
48 
50 {
52  if (IsOpen())
53  {
54  std::cout << "Closing currently open file "
55  << FileName()
56  << " and opening " << filenam << std::endl;
57  fileclose();
58  }
59  FileName(filenam);
60  FROG frog;
61  fullfilename = frog.location(FileName());
62  if (Verbosity() > 0)
63  {
64  std::cout << Name() << ": opening file " << fullfilename << std::endl;
65  }
66  // sanity check - the IManager must be nullptr when this method is executed
67  // if not something is very very wrong and we must not continue
68  if (m_IManager)
69  {
70  std::cout << PHWHERE << " IManager pointer is not nullptr but " << m_IManager
71  << std::endl;
72  std::cout << "Send mail to off-l with this printout and the macro you used"
73  << std::endl;
74  std::cout << "Trying to execute IManager->print() to display more info"
75  << std::endl;
76  std::cout << "Code will probably segfault now" << std::endl;
77  m_IManager->print();
78  std::cout << "Have someone look into this problem - Exiting now" << std::endl;
79  exit(1);
80  }
81  // first read the runnode if not disabled
82  if (m_ReadRunTTree)
83  {
85  if (m_IManager->isFunctional())
86  {
89  // get the current run number
90  RunHeader *runheader = findNode::getClass<RunHeader>(m_RunNode, "RunHeader");
91  if (runheader)
92  {
93  SetRunNumber(runheader->get_RunNumber());
94  }
95  // delete our internal copy of the runnode when opening subsequent files
96  if (m_RunNodeCopy)
97  {
98  std::cout << PHWHERE
99  << " The impossible happened, we have a valid copy of the run node "
100  << m_RunNodeCopy->getName() << " which should be a nullptr"
101  << std::endl;
102  gSystem->Exit(1);
103  }
104  m_RunNodeCopy = new PHCompositeNode("RUNNODECOPY");
105  if (!m_RunNodeSum)
106  {
107  m_RunNodeSum = new PHCompositeNode("RUNNODESUM");
108  }
110  tmpIman->read(m_RunNodeCopy);
111  delete tmpIman;
112 
113  PHNodeIntegrate integrate;
114  integrate.RunNode(m_RunNode);
115  integrate.RunSumNode(m_RunNodeSum);
116  // run recursively over internal run node copy and integrate objects
117  PHNodeIterator mainIter(m_RunNodeCopy);
118  mainIter.forEach(integrate);
119  // we do not need to keep the internal copy, keeping it would crate
120  // problems in case a subsequent file does not contain all the
121  // runwise objects from the previous file. Keeping this copy would then
122  // integrate the missing object again with the old copy
123  delete m_RunNodeCopy;
124  m_RunNodeCopy = nullptr;
125  }
126  // DLW: move the delete outside the if block to cover the case where isFunctional() fails
127  delete m_IManager;
128  }
129  // now open the dst node
130  dstNode = se->getNode(InputNode(), TopNodeName());
132  if (m_IManager->isFunctional())
133  {
134  IsOpen(1);
135  events_thisfile = 0;
136  setBranches(); // set branch selections
137  AddToFileOpened(FileName()); // add file to the list of files which were opened
138  // check if our input file has a sync object or not
139  if (m_IManager->NodeExist(syncdefs::SYNCNODENAME))
140  {
141  m_HaveSyncObject = 1;
142  }
143  else
144  {
145  m_HaveSyncObject = -1;
146  }
147 
148  return 0;
149  }
150  else
151  {
152  std::cout << PHWHERE << ": " << Name() << " Could not open file "
153  << FileName() << std::endl;
154  delete m_IManager;
155  m_IManager = nullptr;
156  return -1;
157  }
158 }
159 
161 {
162  if (!IsOpen())
163  {
164  if (FileListEmpty())
165  {
166  if (Verbosity() > 0)
167  {
168  std::cout << Name() << ": No Input file open" << std::endl;
169  }
170  return -1;
171  }
172  else
173  {
174  if (OpenNextFile())
175  {
176  std::cout << Name() << ": No Input file from filelist opened" << std::endl;
177  return -1;
178  }
179  }
180  }
181  if (Verbosity() > 3)
182  {
183  std::cout << "Getting Event from " << Name() << std::endl;
184  }
185 readagain:
187  int ncount = 0;
188  dummy = m_IManager->read(dstNode);
189  while (dummy)
190  {
191  ncount++;
192  if (nevents > 0 && ncount >= nevents)
193  {
194  break;
195  }
196  dummy = m_IManager->read(dstNode);
197  }
198  if (!dummy)
199  {
200  fileclose();
201  if (!OpenNextFile())
202  {
203  // NOLINTNEXTLINE(hicpp-avoid-goto)
204  goto readagain;
205  }
206  return -1;
207  }
208  events_total += ncount;
209  events_thisfile += ncount;
210  // check if the local SubsysReco discards this event
212  {
213  // NOLINTNEXTLINE(hicpp-avoid-goto)
214  goto readagain;
215  }
216  syncobject = findNode::getClass<SyncObject>(dstNode, syncdefs::SYNCNODENAME);
217  return 0;
218 }
219 
221 {
222  if (!IsOpen())
223  {
224  std::cout << Name() << ": fileclose: No Input file open" << std::endl;
225  return -1;
226  }
227  delete m_IManager;
228  m_IManager = nullptr;
229  IsOpen(0);
230  UpdateFileList();
231  m_HaveSyncObject = 0;
232  return 0;
233 }
234 
236 {
237  // here we copy the sync object from the current file to the
238  // location pointed to by mastersync. If mastersync is a 0 pointer
239  // the syncobject is cloned. If mastersync allready exists the content
240  // of syncobject is copied
241  if (!(*mastersync))
242  {
243  if (syncobject)
244  {
245  *mastersync = dynamic_cast<SyncObject *>(syncobject->CloneMe());
246  assert(*mastersync);
247  }
248  }
249  else
250  {
251  *(*mastersync) = *syncobject; // copy syncobject content
252  }
254 }
255 
257 {
258  if (!mastersync)
259  {
260  std::cout << PHWHERE << Name() << " No MasterSync object, cannot perform synchronization" << std::endl;
261  std::cout << "Most likely your first file does not contain a SyncObject and the file" << std::endl;
262  std::cout << "opened by the Fun4AllDstInputManager with Name " << Name() << " has one" << std::endl;
263  std::cout << "Change your macro and use the file opened by this input manager as first input" << std::endl;
264  std::cout << "and you will be okay. Fun4All will not process the current configuration" << std::endl
265  << std::endl;
267  }
268  if (!syncobject)
269  {
270  std::cout << Name() << " no sync object found in this manager but synchronization needed" << std::endl;
271  std::cout << " Check if you have used an empty listfile. If this is not the case - please ask for help" << std::endl;
272  std::cout << "This may be a really bad internal problem and cannot continue, exiting now " << std::endl;
273  gSystem->Exit(1);
274  exit(1);
275  }
276  int iret = syncobject->Different(mastersync);
277  if (iret) // what to do if files are not in sync
278  {
279  if (mastersync->EventNumber() == -999999) // first file does not contain sync object
280  {
281  std::cout << PHWHERE << " Mastersync not filled, your first file does not contain a SyncObject" << std::endl;
282  std::cout << "This Event will not be processed further" << std::endl;
283  }
284  else // okay try to resync here
285  {
286  if (Verbosity() > 3)
287  {
288  std::cout << "Need to Resync, mastersync evt no: " << mastersync->EventNumber()
289  << ", this Event no: " << syncobject->EventNumber() << std::endl;
290  std::cout << "mastersync evt counter: " << mastersync->EventCounter()
291  << ", this Event counter: " << syncobject->EventCounter() << std::endl;
292  std::cout << "mastersync run number: " << mastersync->RunNumber()
293  << ", this run number: " << syncobject->RunNumber() << std::endl;
294  }
295 
296  while (syncobject->RunNumber() < mastersync->RunNumber())
297  {
299  if (Verbosity() > 2)
300  {
301  std::cout << Name() << " Run Number: " << syncobject->RunNumber()
302  << ", master: " << mastersync->RunNumber()
303  << std::endl;
304  }
305  iret = ReadNextEventSyncObject();
306  if (iret)
307  {
308  return iret;
309  }
310  }
311  int igood = 0;
312  if (syncobject->RunNumber() == mastersync->RunNumber())
313  {
314  igood = 1;
315  }
316  // only run up the Segment Number if run numbers are identical
317  while (syncobject->SegmentNumber() < mastersync->SegmentNumber() && igood)
318  {
320  if (Verbosity() > 2)
321  {
322  std::cout << Name() << " Segment Number: " << syncobject->SegmentNumber()
323  << ", master: " << mastersync->SegmentNumber()
324  << std::endl;
325  }
326  iret = ReadNextEventSyncObject();
327  if (iret)
328  {
329  return iret;
330  }
331  }
332  // only run up the Event Counter if run number and segment number are identical
333  if (syncobject->SegmentNumber() == mastersync->SegmentNumber() && syncobject->RunNumber() == mastersync->RunNumber())
334  {
335  igood = 1;
336  }
337  else
338  {
339  igood = 0;
340  }
341  while (syncobject->EventCounter() < mastersync->EventCounter() && igood)
342  {
344  if (Verbosity() > 2)
345  {
346  std::cout << Name()
347  << ", EventCounter: " << syncobject->EventCounter()
348  << ", master: " << mastersync->EventCounter()
349  << std::endl;
350  }
351  iret = ReadNextEventSyncObject();
352  if (iret)
353  {
354  return iret;
355  }
356  }
357  // Since up to here we only read the sync object we need to push
358  // the current event back inot the root file (subtract one from the
359  // local root file event counter) so we can read the full event
360  // if it syncs, if it does not sync we also read one event too many
361  // (otherwise we cannot determine that we are "too far")
362  // and also have to push this one back
363  PushBackEvents(1);
364  if (syncobject->RunNumber() > mastersync->RunNumber() || // check if run number too large
365  syncobject->EventCounter() > mastersync->EventCounter() || // check if event counter too large
366  syncobject->SegmentNumber() > mastersync->SegmentNumber()) // check segment number too large
367  {
368  // the event from first file which determines the mastersync
369  // and which we are trying to find on this file does not exist on this file
370  // so: return failure. This will cause the input managers to read
371  // the next event from the input files file
373  }
374  // Here the event counter and segment number and run number do agree - we found the right match
375  // now read the full event (previously we only read the sync object)
377  dummy = m_IManager->read(dstNode);
378  if (!dummy)
379  {
380  std::cout << PHWHERE << " " << Name() << " Could not read full Event" << std::endl;
381  std::cout << "PLEASE NOTIFY PHENIX-OFF-L and post the macro you used" << std::endl;
382  fileclose();
384  }
385  iret = syncobject->Different(mastersync); // final check if they really agree
386  if (iret) // if not things are severely wrong
387  {
388  std::cout << PHWHERE << " MasterSync and SyncObject of " << Name() << " are different" << std::endl;
389  std::cout << "This Event will not be processed further, here is some debugging info:" << std::endl;
390  std::cout << "PLEASE NOTIFY PHENIX-OFF-L and post the macro you used" << std::endl;
391  std::cout << "MasterSync->identify:" << std::endl;
392  mastersync->identify();
393  std::cout << Name() << ": SyncObject->identify:" << std::endl;
394  syncobject->identify();
396  }
397  else if (Verbosity() > 3)
398  {
399  std::cout << PHWHERE << " Resynchronization successfull for " << Name() << std::endl;
400  std::cout << "MasterSync->identify:" << std::endl;
401  mastersync->identify();
402  std::cout << Name() << ": SyncObject->identify:" << std::endl;
403  syncobject->identify();
404  }
405  }
406  }
407  // else
408  // {
409  // std::cout << "No Need to Resync" << std::endl;
410  // }
412 }
413 
415 {
416 readnextsync:
417  static int readfull = 0; // for some reason all the input managers need to see the same (I think, should look at this at some point)
418  if (!m_IManager) // in case the old file was exhausted and there is no new file opened
419  {
421  }
422  if (syncbranchname.empty())
423  {
424  readfull = 1; // we need to read a full event to set the root branches to phool nodes right when a new file has been opened
425  std::map<std::string, TBranch *>::const_iterator bIter;
426  for (bIter = m_IManager->GetBranchMap()->begin(); bIter != m_IManager->GetBranchMap()->end(); ++bIter)
427  {
428  if (Verbosity() > 2)
429  {
430  std::cout << Name() << ": branch: " << bIter->first << std::endl;
431  }
432  std::string delimeters = phooldefs::branchpathdelim; // + phooldefs::legacypathdelims;
433  std::vector<std::string> splitvec;
434  boost::split(splitvec, bIter->first, boost::is_any_of(delimeters));
435  for (auto &ia : splitvec) // -1 so we skip the node name
436  {
437  if (ia == syncdefs::SYNCNODENAME)
438  {
439  syncbranchname = bIter->first;
440  break;
441  }
442  }
443  if (!syncbranchname.empty())
444  {
445  break;
446  }
447  }
448  if (syncbranchname.empty())
449  {
450  std::cout << PHWHERE << "Could not locate Sync Branch" << std::endl;
451  std::cout << "Please check for it in the following list of branch names and" << std::endl;
452  std::cout << "PLEASE NOTIFY PHENIX-OFF-L and post the macro you used" << std::endl;
453  for (bIter = m_IManager->GetBranchMap()->begin(); bIter != m_IManager->GetBranchMap()->end(); ++bIter)
454  {
455  std::cout << bIter->first << std::endl;
456  }
458  }
459  }
460  size_t EventOnDst = 0;
461  int itest = 0;
462  if (!readfull)
463  {
464  // if all files are exhausted, the IManager is deleted and set to nullptr
465  // so check if IManager is valid before getting a new event
466  if (m_IManager)
467  {
468  EventOnDst = m_IManager->getEventNumber(); // this returns the next number of the event
469  itest = m_IManager->readSpecific(EventOnDst, syncbranchname.c_str());
470  }
471  else
472  {
473  if (Verbosity() > 2)
474  {
475  std::cout << Name() << ": File exhausted while resyncing" << std::endl;
476  }
478  }
479  }
480  else
481  {
482  if (m_IManager->read(dstNode))
483  {
484  itest = 1;
485  }
486  else
487  {
488  itest = 0;
489  }
490  }
491  if (!itest)
492  {
493  if (Verbosity() > 2)
494  {
495  std::cout << Name() << ": File exhausted while resyncing" << std::endl;
496  }
497  fileclose();
498  if (OpenNextFile())
499  {
501  }
502  syncbranchname.clear(); // clear the sync branch name, who knows - it might be different on new file
503  // NOLINTNEXTLINE(hicpp-avoid-goto)
504  goto readnextsync;
505  }
506  if (!readfull)
507  {
508  EventOnDst++;
509  m_IManager->setEventNumber(EventOnDst); // update event number in phool io manager
510  }
511  else
512  {
513  readfull = 0;
514  }
515  return 0;
516 }
517 
518 int Fun4AllDstInputManager::BranchSelect(const std::string &branch, const int iflag)
519 {
520  if (IsOpen())
521  {
522  std::cout << "BranchSelect(\"" << branch << "\", " << iflag
523  << ") : Input branches can only selected for reading before fileopen is called proceeding without input branch selection" << std::endl;
524  return -1;
525  }
526  // if iflag > 0 the branch is set to read
527  // if iflag = 0, the branch is set to NOT read
528  // if iflag < 0 the branchname is erased from our internal branch read map
529  // this does not have any effect on phool yet
530  if (iflag < 0)
531  {
532  std::map<const std::string, int>::iterator branchiter;
533  branchiter = branchread.find(branch);
534  if (branchiter != branchread.end())
535  {
536  branchread.erase(branchiter);
537  }
538  return 0;
539  }
540  int readit = 0;
541  if (iflag > 0)
542  {
543  if (Verbosity() > 1)
544  {
545  std::cout << "Setting Root Tree Branch: " << branch << " to read" << std::endl;
546  }
547  readit = 1;
548  }
549  else
550  {
551  if (Verbosity() > 1)
552  {
553  std::cout << "Setting Root Tree Branch: " << branch << " to NOT read" << std::endl;
554  }
555  }
556  branchread[branch] = readit;
557  return 0;
558 }
559 
561 {
562  if (m_IManager)
563  {
564  if (!branchread.empty())
565  {
566  std::map<const std::string, int>::const_iterator branchiter;
567  for (branchiter = branchread.begin(); branchiter != branchread.end(); ++branchiter)
568  {
569  m_IManager->selectObjectToRead(branchiter->first.c_str(), branchiter->second);
570  if (Verbosity() > 0)
571  {
572  std::cout << branchiter->first << " set to " << branchiter->second << std::endl;
573  }
574  }
575  // protection against switching off the sync variables
576  // only implemented in the Sync Manager
578  }
579  }
580  else
581  {
582  std::cout << PHWHERE << " " << Name() << ": You can only call this function after a file has been opened" << std::endl;
583  std::cout << "Do not worry, the branches will be set as soon as you open a file" << std::endl;
584  return -1;
585  }
586  return 0;
587 }
588 
590 {
591  // protection against switching off the sync variables
592  for (auto &i : syncdefs::SYNCVARS)
593  {
594  IMan->selectObjectToRead(i, true);
595  }
596  return 0;
597 }
598 
600 {
601  if (what == "ALL" || what == "BRANCH")
602  {
603  // loop over the map and print out the content (name and location in memory)
604  std::cout << "--------------------------------------" << std::endl
605  << std::endl;
606  std::cout << "List of selected branches in Fun4AllDstInputManager " << Name() << ":" << std::endl;
607 
608  std::map<const std::string, int>::const_iterator iter;
609  for (iter = branchread.begin(); iter != branchread.end(); ++iter)
610  {
611  std::cout << iter->first << " is switched ";
612  if (iter->second)
613  {
614  std::cout << "ON";
615  }
616  else
617  {
618  std::cout << "OFF";
619  }
620  std::cout << std::endl;
621  }
622  }
623  if ((what == "ALL" || what == "PHOOL") && m_IManager)
624  {
625  // loop over the map and print out the content (name and location in memory)
626  std::cout << "--------------------------------------" << std::endl
627  << std::endl;
628  std::cout << "PHNodeIOManager print in Fun4AllDstInputManager " << Name() << ":" << std::endl;
629  m_IManager->print();
630  }
632  return;
633 }
634 
636 {
637  if (m_IManager)
638  {
639  unsigned EventOnDst = m_IManager->getEventNumber();
640  EventOnDst -= static_cast<unsigned>(i);
641  m_IManager->setEventNumber(EventOnDst);
642  return 0;
643  }
644  std::cout << PHWHERE << Name() << ": could not push back events, Imanager is NULL"
645  << " probably the dst is not open yet (you need to call fileopen or run 1 event for lists)" << std::endl;
646  return -1;
647 }
648 
650 {
651  if (m_HaveSyncObject)
652  {
653  return m_HaveSyncObject;
654  }
655  if (IsOpen())
656  {
657  std::cout << PHWHERE << "HasSyncObject() not initialized check the calling order" << std::endl;
658  gSystem->Exit(1);
659  exit(1);
660  }
661  return 0;
662 }