Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:19:34

0001 #include "Fun4AllDstInputManager.h"
0002 
0003 #include "DBInterface.h"
0004 #include "Fun4AllReturnCodes.h"
0005 #include "Fun4AllServer.h"
0006 
0007 #include <ffaobjects/RunHeader.h>
0008 #include <ffaobjects/SyncDefs.h>
0009 #include <ffaobjects/SyncObject.h>
0010 
0011 #include <phool/PHCompositeNode.h>
0012 #include <phool/PHNodeIOManager.h>
0013 #include <phool/PHNodeIntegrate.h>
0014 #include <phool/PHNodeIterator.h>  // for PHNodeIterator
0015 #include <phool/PHObject.h>        // for PHObject
0016 #include <phool/getClass.h>
0017 #include <phool/phool.h>  // for PHWHERE, PHReadOnly, PHRunTree
0018 #include <phool/phooldefs.h>
0019 
0020 #include <TSystem.h>
0021 
0022 #pragma GCC diagnostic push
0023 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
0024 #include <boost/algorithm/string.hpp>
0025 #pragma GCC diagnostic pop
0026 
0027 #include <cassert>
0028 #include <cstdlib>
0029 #include <iostream>  // for operator<<, basic_ostream, endl
0030 #include <utility>   // for pair
0031 #include <vector>    // for vector
0032 
0033 class TBranch;
0034 
0035 Fun4AllDstInputManager::Fun4AllDstInputManager(const std::string &name, const std::string &nodename, const std::string &topnodename)
0036   : Fun4AllInputManager(name, nodename, topnodename)
0037 {
0038   return;
0039 }
0040 
0041 Fun4AllDstInputManager::~Fun4AllDstInputManager()
0042 {
0043   delete m_IManager;
0044   delete m_RunNodeSum;
0045   return;
0046 }
0047 
0048 int Fun4AllDstInputManager::fileopen(const std::string &filenam)
0049 {
0050   Fun4AllServer *se = Fun4AllServer::instance();
0051   if (IsOpen())
0052   {
0053     std::cout << "Closing currently open file "
0054               << FileName()
0055               << " and opening " << filenam << std::endl;
0056     fileclose();
0057   }
0058   FileName(filenam);
0059   fullfilename = DBInterface::instance()->location(FileName());
0060   if (Verbosity() > 0)
0061   {
0062     std::cout << Name() << ": opening file " << fullfilename << std::endl;
0063   }
0064   // sanity check - the IManager must be nullptr when this method is executed
0065   // if not something is very very wrong and we must not continue
0066   if (m_IManager)
0067   {
0068     std::cout << PHWHERE << " IManager pointer is not nullptr but " << m_IManager
0069               << std::endl;
0070     std::cout << "Send mail to off-l with this printout and the macro you used"
0071               << std::endl;
0072     std::cout << "Trying to execute IManager->print() to display more info"
0073               << std::endl;
0074     std::cout << "Code will probably segfault now" << std::endl;
0075     m_IManager->print();
0076     std::cout << "Have someone look into this problem - Exiting now" << std::endl;
0077     exit(1);
0078   }
0079   // first read the runnode if not disabled
0080   if (m_ReadRunTTree)
0081   {
0082     m_IManager = new PHNodeIOManager(fullfilename, PHReadOnly, PHRunTree);
0083     if (m_IManager->isFunctional())
0084     {
0085       m_RunNode = se->getNode(RunNode, TopNodeName());
0086       m_IManager->read(m_RunNode);
0087       // get the current run number
0088       RunHeader *runheader = findNode::getClass<RunHeader>(m_RunNode, "RunHeader");
0089       if (runheader)
0090       {
0091         SetRunNumber(runheader->get_RunNumber());
0092       }
0093       // delete our internal copy of the runnode when opening subsequent files
0094       if (m_RunNodeCopy)
0095       {
0096         std::cout << PHWHERE
0097                   << " The impossible happened, we have a valid copy of the run node "
0098                   << m_RunNodeCopy->getName() << " which should be a nullptr"
0099                   << std::endl;
0100         gSystem->Exit(1);
0101       }
0102       m_RunNodeCopy = new PHCompositeNode("RUNNODECOPY");
0103       if (!m_RunNodeSum)
0104       {
0105         m_RunNodeSum = new PHCompositeNode("RUNNODESUM");
0106       }
0107       PHNodeIOManager *tmpIman = new PHNodeIOManager(fullfilename, PHReadOnly, PHRunTree);
0108       tmpIman->read(m_RunNodeCopy);
0109       delete tmpIman;
0110 
0111       PHNodeIntegrate integrate;
0112       integrate.RunNode(m_RunNode);
0113       integrate.RunSumNode(m_RunNodeSum);
0114       // run recursively over internal run node copy and integrate objects
0115       PHNodeIterator mainIter(m_RunNodeCopy);
0116       mainIter.forEach(integrate);
0117       // we do not need to keep the internal copy, keeping it would crate
0118       // problems in case a subsequent file does not contain all the
0119       // runwise objects from the previous file. Keeping this copy would then
0120       // integrate the missing object again with the old copy
0121       delete m_RunNodeCopy;
0122       m_RunNodeCopy = nullptr;
0123     }
0124     // DLW: move the delete outside the if block to cover the case where isFunctional() fails
0125     delete m_IManager;
0126   }
0127   // now open the dst node
0128   dstNode = se->getNode(InputNode(), TopNodeName());
0129   m_IManager = new PHNodeIOManager(fullfilename, PHReadOnly);
0130   if (m_IManager->isFunctional())
0131   {
0132     IsOpen(1);
0133     events_thisfile = 0;
0134     setBranches();                // set branch selections
0135     AddToFileOpened(FileName());  // add file to the list of files which were opened
0136                                   // check if our input file has a sync object or not
0137     if (ReadCacheDisabled())
0138     {
0139       m_IManager->DisableReadCache();
0140     }
0141     if (m_IManager->NodeExist(syncdefs::SYNCNODENAME))
0142     {
0143       m_HaveSyncObject = 1;
0144     }
0145     else
0146     {
0147       m_HaveSyncObject = -1;
0148     }
0149 
0150     return 0;
0151   }
0152 
0153   std::cout << PHWHERE << ": " << Name() << " Could not open file "
0154             << FileName() << std::endl;
0155   delete m_IManager;
0156   m_IManager = nullptr;
0157   return -1;
0158 }
0159 
0160 int Fun4AllDstInputManager::run(const int nevents)
0161 {
0162   if (!IsOpen())
0163   {
0164     if (FileListEmpty())
0165     {
0166       if (Verbosity() > 0)
0167       {
0168         std::cout << Name() << ": No Input file open" << std::endl;
0169       }
0170       return -1;
0171     }
0172 
0173     if (OpenNextFile())
0174     {
0175       std::cout << Name() << ": No Input file from filelist opened" << std::endl;
0176       return -1;
0177     }
0178   }
0179   if (Verbosity() > 3)
0180   {
0181     std::cout << "Getting Event from " << Name() << std::endl;
0182   }
0183 readagain:
0184   PHCompositeNode *dummy;
0185   int ncount = 0;
0186   dummy = m_IManager->read(dstNode);
0187   while (dummy)
0188   {
0189     ncount++;
0190     if (nevents > 0 && ncount >= nevents)
0191     {
0192       break;
0193     }
0194     dummy = m_IManager->read(dstNode);
0195   }
0196   if (!dummy)
0197   {
0198     fileclose();
0199     if (!OpenNextFile())
0200     {
0201       // NOLINTNEXTLINE(hicpp-avoid-goto)
0202       goto readagain;
0203     }
0204     return -1;
0205   }
0206   events_total += ncount;
0207   events_thisfile += ncount;
0208   // check if the local SubsysReco discards this event
0209   if (RejectEvent() != Fun4AllReturnCodes::EVENT_OK)
0210   {
0211     // NOLINTNEXTLINE(hicpp-avoid-goto)
0212     goto readagain;
0213   }
0214   syncobject = findNode::getClass<SyncObject>(dstNode, syncdefs::SYNCNODENAME);
0215   return 0;
0216 }
0217 
0218 int Fun4AllDstInputManager::fileclose()
0219 {
0220   if (!IsOpen())
0221   {
0222     std::cout << Name() << ": fileclose: No Input file open" << std::endl;
0223     return -1;
0224   }
0225   delete m_IManager;
0226   m_IManager = nullptr;
0227   IsOpen(0);
0228   UpdateFileList();
0229   m_HaveSyncObject = 0;
0230   return 0;
0231 }
0232 
0233 int Fun4AllDstInputManager::GetSyncObject(SyncObject **mastersync)
0234 {
0235   // here we copy the sync object from the current file to the
0236   // location pointed to by mastersync. If mastersync is a 0 pointer
0237   // the syncobject is cloned. If mastersync allready exists the content
0238   // of syncobject is copied
0239   if (!(*mastersync))
0240   {
0241     if (syncobject)
0242     {
0243       *mastersync = dynamic_cast<SyncObject *>(syncobject->CloneMe());
0244       assert(*mastersync);
0245     }
0246   }
0247   else
0248   {
0249     *(*mastersync) = *syncobject;  // copy syncobject content
0250   }
0251   return Fun4AllReturnCodes::SYNC_OK;
0252 }
0253 
0254 int Fun4AllDstInputManager::SyncIt(const SyncObject *mastersync)
0255 {
0256   if (!mastersync)
0257   {
0258     std::cout << PHWHERE << Name() << " No MasterSync object, cannot perform synchronization" << std::endl;
0259     std::cout << "Most likely your first file does not contain a SyncObject and the file" << std::endl;
0260     std::cout << "opened by the Fun4AllDstInputManager with Name " << Name() << " has one" << std::endl;
0261     std::cout << "Change your macro and use the file opened by this input manager as first input" << std::endl;
0262     std::cout << "and you will be okay. Fun4All will not process the current configuration" << std::endl
0263               << std::endl;
0264     return Fun4AllReturnCodes::SYNC_FAIL;
0265   }
0266   if (!syncobject)
0267   {
0268     std::cout << Name() << " no sync object found in this manager but synchronization needed" << std::endl;
0269     std::cout << "  Check if you have used an empty listfile. If this is not the case - please ask for help" << std::endl;
0270     std::cout << "This may be a really bad internal problem and cannot continue, exiting now " << std::endl;
0271     gSystem->Exit(1);
0272     exit(1);
0273   }
0274   int iret = syncobject->Different(mastersync);
0275   if (iret)  // what to do if files are not in sync
0276   {
0277     if (mastersync->EventNumber() == -999999)  // first file does not contain sync object
0278     {
0279       std::cout << PHWHERE << " Mastersync not filled, your first file does not contain a SyncObject" << std::endl;
0280       std::cout << "This Event will not be processed further" << std::endl;
0281     }
0282     else  // okay try to resync here
0283     {
0284       if (Verbosity() > 3)
0285       {
0286         std::cout << "Need to Resync, mastersync evt no: " << mastersync->EventNumber()
0287                   << ", this Event no: " << syncobject->EventNumber() << std::endl;
0288         std::cout << "mastersync evt counter: " << mastersync->EventNumber()
0289                   << ", this Event counter: " << syncobject->EventNumber() << std::endl;
0290         std::cout << "mastersync run number: " << mastersync->RunNumber()
0291                   << ", this run number: " << syncobject->RunNumber() << std::endl;
0292       }
0293 
0294       while (syncobject->RunNumber() < mastersync->RunNumber())
0295       {
0296         events_skipped_during_sync++;
0297         if (Verbosity() > 2)
0298         {
0299           std::cout << Name() << " Run Number: " << syncobject->RunNumber()
0300                     << ", master: " << mastersync->RunNumber()
0301                     << std::endl;
0302         }
0303         iret = ReadNextEventSyncObject();
0304         if (iret)
0305         {
0306           return iret;
0307         }
0308       }
0309       int igood = 0;
0310       if (syncobject->RunNumber() == mastersync->RunNumber())
0311       {
0312         igood = 1;
0313       }
0314       // only run up the Segment Number if run numbers are identical
0315       while (syncobject->SegmentNumber() < mastersync->SegmentNumber() && igood)
0316       {
0317         events_skipped_during_sync++;
0318         if (Verbosity() > 2)
0319         {
0320           std::cout << Name() << " Segment Number: " << syncobject->SegmentNumber()
0321                     << ", master: " << mastersync->SegmentNumber()
0322                     << std::endl;
0323         }
0324         iret = ReadNextEventSyncObject();
0325         if (iret)
0326         {
0327           return iret;
0328         }
0329       }
0330       // only run up the Event Counter if run number and segment number are identical
0331       if (syncobject->SegmentNumber() == mastersync->SegmentNumber() && syncobject->RunNumber() == mastersync->RunNumber())
0332       {
0333         igood = 1;
0334       }
0335       else
0336       {
0337         igood = 0;
0338       }
0339       while (syncobject->EventNumber() < mastersync->EventNumber() && igood)
0340       {
0341         events_skipped_during_sync++;
0342         if (Verbosity() > 2)
0343         {
0344           std::cout << Name()
0345                     << ", EventNumber: " << syncobject->EventNumber()
0346                     << ", master: " << mastersync->EventNumber()
0347                     << std::endl;
0348         }
0349         iret = ReadNextEventSyncObject();
0350         if (iret)
0351         {
0352           return iret;
0353         }
0354       }
0355       // Since up to here we only read the sync object we need to push
0356       // the current event back into the root file (subtract one from the
0357       // local root file event counter) so we can read the full event
0358       // if it syncs, if it does not sync we also read one event too many
0359       // (otherwise we cannot determine that we are "too far")
0360       // and also have to push this one back
0361       PushBackEvents(1);
0362       if (syncobject->RunNumber() > mastersync->RunNumber() ||        // check if run number too large
0363           syncobject->EventNumber() > mastersync->EventNumber() ||    // check if event counter too large
0364           syncobject->SegmentNumber() > mastersync->SegmentNumber())  // check segment number too large
0365       {
0366         // the event from first file which determines the mastersync
0367         // and which we are trying to find on this file does not exist on this file
0368         // so: return failure. This will cause the input managers to read
0369         // the next event from the input files file
0370         return Fun4AllReturnCodes::SYNC_FAIL;
0371       }
0372       // Here the event counter and segment number and run number do agree - we found the right match
0373       // now read the full event (previously we only read the sync object)
0374       PHCompositeNode *dummy;
0375       dummy = m_IManager->read(dstNode);
0376       if (!dummy)
0377       {
0378         std::cout << PHWHERE << " " << Name() << " Could not read full Event" << std::endl;
0379         std::cout << "PLEASE NOTIFY PHENIX-OFF-L and post the macro you used" << std::endl;
0380         fileclose();
0381         return Fun4AllReturnCodes::SYNC_FAIL;
0382       }
0383       iret = syncobject->Different(mastersync);  // final check if they really agree
0384       if (iret)                                  // if not things are severely wrong
0385       {
0386         std::cout << PHWHERE << " MasterSync and SyncObject of " << Name() << " are different" << std::endl;
0387         std::cout << "This Event will not be processed further, here is some debugging info:" << std::endl;
0388         std::cout << "PLEASE NOTIFY PHENIX-OFF-L and post the macro you used" << std::endl;
0389         std::cout << "MasterSync->identify:" << std::endl;
0390         mastersync->identify();
0391         std::cout << Name() << ": SyncObject->identify:" << std::endl;
0392         syncobject->identify();
0393         return Fun4AllReturnCodes::SYNC_FAIL;
0394       }
0395       if (Verbosity() > 3)
0396       {
0397         std::cout << PHWHERE << " Resynchronization successfull for " << Name() << std::endl;
0398         std::cout << "MasterSync->identify:" << std::endl;
0399         mastersync->identify();
0400         std::cout << Name() << ": SyncObject->identify:" << std::endl;
0401         syncobject->identify();
0402       }
0403     }
0404   }
0405   //    else
0406   //        {
0407   //            std::cout << "No Need to Resync" << std::endl;
0408   //        }
0409   return Fun4AllReturnCodes::SYNC_OK;
0410 }
0411 
0412 int Fun4AllDstInputManager::ReadNextEventSyncObject()
0413 {
0414 readnextsync:
0415   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)
0416   if (!m_IManager)          // in case the old file was exhausted and there is no new file opened
0417   {
0418     return Fun4AllReturnCodes::SYNC_FAIL;
0419   }
0420   if (syncbranchname.empty())
0421   {
0422     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
0423     std::map<std::string, TBranch *>::const_iterator bIter;
0424     for (bIter = m_IManager->GetBranchMap()->begin(); bIter != m_IManager->GetBranchMap()->end(); ++bIter)
0425     {
0426       if (Verbosity() > 2)
0427       {
0428         std::cout << Name() << ": branch: " << bIter->first << std::endl;
0429       }
0430       std::string delimeters = phooldefs::branchpathdelim;  // + phooldefs::legacypathdelims;
0431       std::vector<std::string> splitvec;
0432       boost::split(splitvec, bIter->first, boost::is_any_of(delimeters));
0433       for (auto &ia : splitvec)  // -1 so we skip the node name
0434       {
0435         if (ia == syncdefs::SYNCNODENAME)
0436         {
0437           syncbranchname = bIter->first;
0438           break;
0439         }
0440       }
0441       if (!syncbranchname.empty())
0442       {
0443         break;
0444       }
0445     }
0446     if (syncbranchname.empty())
0447     {
0448       std::cout << PHWHERE << "Could not locate Sync Branch" << std::endl;
0449       std::cout << "Please check for it in the following list of branch names and" << std::endl;
0450       std::cout << "PLEASE NOTIFY PHENIX-OFF-L and post the macro you used" << std::endl;
0451       for (bIter = m_IManager->GetBranchMap()->begin(); bIter != m_IManager->GetBranchMap()->end(); ++bIter)
0452       {
0453         std::cout << bIter->first << std::endl;
0454       }
0455       return Fun4AllReturnCodes::SYNC_FAIL;
0456     }
0457   }
0458   size_t EventOnDst = 0;
0459   int itest = 0;
0460   if (!readfull)
0461   {
0462     // if all files are exhausted, the IManager is deleted and set to nullptr
0463     // so check if IManager is valid before getting a new event
0464     if (m_IManager)
0465     {
0466       EventOnDst = m_IManager->getEventNumber();  // this returns the next number of the event
0467       itest = m_IManager->readSpecific(EventOnDst, syncbranchname);
0468     }
0469     else
0470     {
0471       if (Verbosity() > 2)
0472       {
0473         std::cout << Name() << ": File exhausted while resyncing" << std::endl;
0474       }
0475       return Fun4AllReturnCodes::SYNC_FAIL;
0476     }
0477   }
0478   else
0479   {
0480     if (m_IManager->read(dstNode))
0481     {
0482       itest = 1;
0483     }
0484     else
0485     {
0486       itest = 0;
0487     }
0488   }
0489   if (!itest)
0490   {
0491     if (Verbosity() > 2)
0492     {
0493       std::cout << Name() << ": File exhausted while resyncing" << std::endl;
0494     }
0495     fileclose();
0496     if (OpenNextFile())
0497     {
0498       return Fun4AllReturnCodes::SYNC_FAIL;
0499     }
0500     syncbranchname.clear();  // clear the sync branch name, who knows - it might be different on new file
0501     // NOLINTNEXTLINE(hicpp-avoid-goto)
0502     goto readnextsync;
0503   }
0504   if (!readfull)
0505   {
0506     EventOnDst++;
0507     m_IManager->setEventNumber(EventOnDst);  // update event number in phool io manager
0508   }
0509   else
0510   {
0511     readfull = 0;
0512   }
0513   return 0;
0514 }
0515 
0516 int Fun4AllDstInputManager::BranchSelect(const std::string &branch, const int iflag)
0517 {
0518   if (IsOpen())
0519   {
0520     std::cout << "BranchSelect(\"" << branch << "\", " << iflag
0521               << ") : Input branches can only selected for reading before fileopen is called proceeding without input branch selection" << std::endl;
0522     return -1;
0523   }
0524   // if iflag > 0 the branch is set to read
0525   // if iflag = 0, the branch is set to NOT read
0526   // if iflag < 0 the branchname is erased from our internal branch read map
0527   // this does not have any effect on phool yet
0528   if (iflag < 0)
0529   {
0530     std::map<const std::string, int>::iterator branchiter;
0531     branchiter = branchread.find(branch);
0532     if (branchiter != branchread.end())
0533     {
0534       branchread.erase(branchiter);
0535     }
0536     return 0;
0537   }
0538   int readit = 0;
0539   if (iflag > 0)
0540   {
0541     if (Verbosity() > 1)
0542     {
0543       std::cout << "Setting Root Tree Branch: " << branch << " to read" << std::endl;
0544     }
0545     readit = 1;
0546   }
0547   else
0548   {
0549     if (Verbosity() > 1)
0550     {
0551       std::cout << "Setting Root Tree Branch: " << branch << " to NOT read" << std::endl;
0552     }
0553   }
0554   branchread[branch] = readit;
0555   return 0;
0556 }
0557 
0558 int Fun4AllDstInputManager::setBranches()
0559 {
0560   if (m_IManager)
0561   {
0562     if (!branchread.empty())
0563     {
0564       std::map<const std::string, int>::const_iterator branchiter;
0565       for (branchiter = branchread.begin(); branchiter != branchread.end(); ++branchiter)
0566       {
0567         m_IManager->selectObjectToRead(branchiter->first, branchiter->second);
0568         if (Verbosity() > 0)
0569         {
0570           std::cout << branchiter->first << " set to " << branchiter->second << std::endl;
0571         }
0572       }
0573       // protection against switching off the sync variables
0574       // only implemented in the Sync Manager
0575       setSyncBranches(m_IManager);
0576     }
0577   }
0578   else
0579   {
0580     std::cout << PHWHERE << " " << Name() << ": You can only call this function after a file has been opened" << std::endl;
0581     std::cout << "Do not worry, the branches will be set as soon as you open a file" << std::endl;
0582     return -1;
0583   }
0584   return 0;
0585 }
0586 
0587 int Fun4AllDstInputManager::setSyncBranches(PHNodeIOManager *IMan)
0588 {
0589   // protection against switching off the sync variables
0590   for (auto &i : syncdefs::SYNCVARS)
0591   {
0592     IMan->selectObjectToRead(i, true);
0593   }
0594   return 0;
0595 }
0596 
0597 void Fun4AllDstInputManager::Print(const std::string &what) const
0598 {
0599   if (what == "ALL" || what == "BRANCH")
0600   {
0601     // loop over the map and print out the content (name and location in memory)
0602     std::cout << "--------------------------------------" << std::endl
0603               << std::endl;
0604     std::cout << "List of selected branches in Fun4AllDstInputManager " << Name() << ":" << std::endl;
0605 
0606     std::map<const std::string, int>::const_iterator iter;
0607     for (iter = branchread.begin(); iter != branchread.end(); ++iter)
0608     {
0609       std::cout << iter->first << " is switched ";
0610       if (iter->second)
0611       {
0612         std::cout << "ON";
0613       }
0614       else
0615       {
0616         std::cout << "OFF";
0617       }
0618       std::cout << std::endl;
0619     }
0620   }
0621   if ((what == "ALL" || what == "PHOOL") && m_IManager)
0622   {
0623     // loop over the map and print out the content (name and location in memory)
0624     std::cout << "--------------------------------------" << std::endl
0625               << std::endl;
0626     std::cout << "PHNodeIOManager print in Fun4AllDstInputManager " << Name() << ":" << std::endl;
0627     m_IManager->print();
0628   }
0629   Fun4AllInputManager::Print(what);
0630   return;
0631 }
0632 
0633 int Fun4AllDstInputManager::PushBackEvents(const int i)
0634 {
0635   if (m_IManager)
0636   {
0637     unsigned EventOnDst = m_IManager->getEventNumber();
0638     EventOnDst -= static_cast<unsigned>(i);
0639     m_IManager->setEventNumber(EventOnDst);
0640     return 0;
0641   }
0642   std::cout << PHWHERE << Name() << ": could not push back events, Imanager is NULL"
0643             << " probably the dst is not open yet (you need to call fileopen or run 1 event for lists)" << std::endl;
0644   return -1;
0645 }
0646 
0647 int Fun4AllDstInputManager::HasSyncObject() const
0648 {
0649   if (m_HaveSyncObject)
0650   {
0651     return m_HaveSyncObject;
0652   }
0653   if (IsOpen())
0654   {
0655     std::cout << PHWHERE << "HasSyncObject() not initialized check the calling order" << std::endl;
0656     gSystem->Exit(1);
0657     exit(1);
0658   }
0659   return 0;
0660 }