File indexing completed on 2025-12-16 09:19:34
0001 #include "Fun4AllDstOutputManager.h"
0002
0003 #include "Fun4AllServer.h"
0004
0005 #include <phool/PHCompositeNode.h>
0006 #include <phool/PHNode.h>
0007 #include <phool/PHNodeIOManager.h>
0008 #include <phool/PHNodeIterator.h>
0009 #include <phool/phool.h> // for PHWHERE, PHReadOnly, PHRunTree
0010 #include <phool/recoConsts.h>
0011
0012 #include <TSystem.h>
0013
0014 #include <cstdlib>
0015 #include <filesystem>
0016 #include <format>
0017 #include <iostream>
0018 #include <string>
0019
0020 Fun4AllDstOutputManager::Fun4AllDstOutputManager(const std::string &myname, const std::string &filename)
0021 : Fun4AllOutputManager(myname, filename)
0022 {
0023 return;
0024 }
0025
0026 Fun4AllDstOutputManager::~Fun4AllDstOutputManager()
0027 {
0028 delete dstOut;
0029 return;
0030 }
0031
0032 int Fun4AllDstOutputManager::AddNode(const std::string &nodename)
0033 {
0034 savenodes.insert(nodename);
0035 return 0;
0036 }
0037
0038 int Fun4AllDstOutputManager::AddRunNode(const std::string &nodename)
0039 {
0040 saverunnodes.insert(nodename);
0041 return 0;
0042 }
0043
0044 int Fun4AllDstOutputManager::StripCompositeNode(const std::string &nodename)
0045 {
0046 m_StripCompositeNodes.insert(nodename);
0047 return 0;
0048 }
0049
0050 int Fun4AllDstOutputManager::StripNode(const std::string &nodename)
0051 {
0052 stripnodes.insert(nodename);
0053 return 0;
0054 }
0055
0056 int Fun4AllDstOutputManager::StripRunNode(const std::string &nodename)
0057 {
0058 striprunnodes.insert(nodename);
0059 return 0;
0060 }
0061
0062 int Fun4AllDstOutputManager::outfileopen(const std::string &fname)
0063 {
0064 OutFileName(fname);
0065 return 0;
0066 }
0067
0068 void Fun4AllDstOutputManager::Print(const std::string &what) const
0069 {
0070 if (what == "ALL" || what == "WRITENODES")
0071 {
0072 std::cout << Name() << " writes " << OutFileName() << std::endl;
0073 if (savenodes.empty())
0074 {
0075 if (stripnodes.empty())
0076 {
0077 std::cout << Name() << ": All Nodes will be written out" << std::endl;
0078 }
0079 else
0080 {
0081 for (const auto &nodename : stripnodes)
0082 {
0083 std::cout << Name() << ": Node " << nodename << " will be stripped" << std::endl;
0084 }
0085 }
0086 }
0087 else
0088 {
0089 for (const auto &nodename : savenodes)
0090 {
0091 std::cout << Name() << ": Node " << nodename << " is written out" << std::endl;
0092 }
0093 }
0094 }
0095
0096 Fun4AllOutputManager::Print(what);
0097
0098 return;
0099 }
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109 int Fun4AllDstOutputManager::Write(PHCompositeNode *startNode)
0110 {
0111 if (!m_SaveDstNodeFlag)
0112 {
0113 return 0;
0114 }
0115 if (!dstOut)
0116 {
0117 outfile_open_first_write();
0118 }
0119 PHNodeIterator nodeiter(startNode);
0120 if (savenodes.empty())
0121 {
0122 Fun4AllServer *se = Fun4AllServer::instance();
0123 se->MakeNodesPersistent(startNode);
0124 if (!m_StripCompositeNodes.empty())
0125 {
0126 for (const auto &compnodename : m_StripCompositeNodes)
0127 {
0128 PHCompositeNode *stripcomp = dynamic_cast<PHCompositeNode *>(nodeiter.findFirst("PHCompositeNode", compnodename));
0129 if (stripcomp)
0130 {
0131 se->MakeNodesTransient(stripcomp);
0132 }
0133 }
0134 }
0135 if (!stripnodes.empty())
0136 {
0137 for (const auto &nodename : stripnodes)
0138 {
0139 PHNode *ChosenNode = nodeiter.findFirst("PHIODataNode", nodename);
0140 if (ChosenNode)
0141 {
0142 ChosenNode->makeTransient();
0143 }
0144 else
0145 {
0146 if (Verbosity() > 0)
0147 {
0148 std::cout << PHWHERE << Name() << ": Node " << nodename
0149 << " does not exist" << std::endl;
0150 }
0151 }
0152 }
0153 }
0154 }
0155 else
0156 {
0157 for (const auto &nodename : savenodes)
0158 {
0159 PHNode *ChosenNode = nodeiter.findFirst("PHIODataNode", nodename);
0160 if (ChosenNode)
0161 {
0162 ChosenNode->makePersistent();
0163 }
0164 else
0165 {
0166 if (Verbosity() > 0)
0167 {
0168 std::cout << PHWHERE << Name() << ": Node " << nodename
0169 << " does not exist" << std::endl;
0170 }
0171 }
0172 }
0173 }
0174 dstOut->write(startNode);
0175
0176
0177
0178
0179 if (savenodes.empty())
0180 {
0181 Fun4AllServer *se = Fun4AllServer::instance();
0182 se->MakeNodesTransient(startNode);
0183 }
0184 else
0185 {
0186 for (const auto &nodename : savenodes)
0187 {
0188 PHNode *ChosenNode = nodeiter.findFirst("PHIODataNode", nodename);
0189 if (ChosenNode)
0190 {
0191 ChosenNode->makeTransient();
0192 }
0193 }
0194 }
0195 return 0;
0196 }
0197
0198 int Fun4AllDstOutputManager::WriteNode(PHCompositeNode *thisNode)
0199 {
0200 if (!m_SaveRunNodeFlag)
0201 {
0202 dstOut = nullptr;
0203 return 0;
0204 }
0205 PHAccessType access_type = PHUpdate;
0206 if (!m_SaveDstNodeFlag)
0207 {
0208 access_type = PHWrite;
0209 }
0210 else
0211 {
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221 if (!dstOut)
0222 {
0223 if (Verbosity() > 0)
0224 {
0225 std::cout << PHWHERE << " DST file has not been written to yet, not saving the RunNode by itself" << std::endl;
0226 }
0227 return 0;
0228 }
0229 }
0230 delete dstOut;
0231
0232 if (UsedOutFileName().empty())
0233 {
0234 std::filesystem::path p = OutFileName();
0235 if (m_FileNameStem.empty())
0236 {
0237 m_FileNameStem = p.stem();
0238 }
0239 m_UsedOutFileName = OutFileName() + std::string("?reproducible=") + std::string(p.filename());
0240 }
0241 dstOut = new PHNodeIOManager(UsedOutFileName(), access_type, PHRunTree);
0242 if (SplitLevel() != std::numeric_limits<int>::min())
0243 {
0244 dstOut->SplitLevel(SplitLevel());
0245 }
0246 if (BufferSize() != std::numeric_limits<int>::min())
0247 {
0248 dstOut->BufferSize(BufferSize());
0249 }
0250 Fun4AllServer *se = Fun4AllServer::instance();
0251 PHNodeIterator nodeiter(thisNode);
0252 if (saverunnodes.empty())
0253 {
0254 se->MakeNodesPersistent(thisNode);
0255 if (!m_StripCompositeNodes.empty())
0256 {
0257 for (const auto &compnodename : m_StripCompositeNodes)
0258 {
0259 PHCompositeNode *stripcomp = dynamic_cast<PHCompositeNode *>(nodeiter.findFirst("PHCompositeNode", compnodename));
0260 if (stripcomp)
0261 {
0262 se->MakeNodesTransient(stripcomp);
0263 }
0264 }
0265 }
0266 if (!striprunnodes.empty())
0267 {
0268 for (const auto &nodename : striprunnodes)
0269 {
0270 PHNode *ChosenNode = nodeiter.findFirst("PHIODataNode", nodename);
0271 if (ChosenNode)
0272 {
0273 ChosenNode->makeTransient();
0274 }
0275 else
0276 {
0277 if (Verbosity() > 0)
0278 {
0279 std::cout << PHWHERE << Name() << ": Node " << nodename
0280 << " does not exist" << std::endl;
0281 }
0282 }
0283 }
0284 }
0285 }
0286 else
0287 {
0288 for (const auto &nodename : saverunnodes)
0289 {
0290 PHNode *ChosenNode = nodeiter.findFirst("PHIODataNode", nodename);
0291 if (ChosenNode)
0292 {
0293 ChosenNode->makePersistent();
0294 }
0295 else
0296 {
0297 if (Verbosity() > 0)
0298 {
0299 std::cout << PHWHERE << Name() << ": Node " << nodename
0300 << " does not exist" << std::endl;
0301 }
0302 }
0303 }
0304 }
0305 dstOut->write(thisNode);
0306 se->MakeNodesTransient(thisNode);
0307 delete dstOut;
0308 dstOut = nullptr;
0309 return 0;
0310 }
0311
0312 int Fun4AllDstOutputManager::outfile_open_first_write()
0313 {
0314 delete dstOut;
0315 SetEventsWritten(1);
0316 std::filesystem::path p = OutFileName();
0317 if (m_FileNameStem.empty())
0318 {
0319 m_FileNameStem = p.stem();
0320 }
0321 if (ApplyFileRule())
0322 {
0323 recoConsts *rc = recoConsts::instance();
0324 int runnumber = 0;
0325 if (rc->FlagExist("RUNNUMBER"))
0326 {
0327 runnumber = rc->get_IntFlag("RUNNUMBER");
0328 }
0329 std::string fullpath = ".";
0330 if (p.has_parent_path())
0331 {
0332 fullpath = p.parent_path();
0333 }
0334 std::string runseg = std::format("-{:08}-{:05}", runnumber, m_CurrentSegment);
0335 std::string newfile = fullpath + std::string("/") + m_FileNameStem + runseg + std::string(p.extension());
0336 OutFileName(newfile);
0337 m_CurrentSegment++;
0338 }
0339 m_UsedOutFileName = OutFileName() + std::string("?reproducible=") + std::string(p.filename());
0340 dstOut = new PHNodeIOManager(UsedOutFileName(), PHWrite);
0341 if (SplitLevel() != std::numeric_limits<int>::min())
0342 {
0343 dstOut->SplitLevel(SplitLevel());
0344 }
0345 if (BufferSize() != std::numeric_limits<int>::min())
0346 {
0347 dstOut->BufferSize(BufferSize());
0348 }
0349 if (!dstOut->isFunctional())
0350 {
0351 delete dstOut;
0352 dstOut = nullptr;
0353 std::cout << PHWHERE << " Could not open " << OutFileName() << std::endl;
0354 return -1;
0355 }
0356
0357 dstOut->SetCompressionSetting(m_CompressionSetting);
0358 return 0;
0359 }
0360
0361
0362
0363
0364
0365
0366
0367 void Fun4AllDstOutputManager::InitializeLastEvent(int eventnumber)
0368 {
0369 if (GetEventNumberRollover() == 0 || m_LastEventInitialized || eventnumber < 0)
0370 {
0371 return;
0372 }
0373 m_LastEventInitialized = true;
0374 unsigned int firstevent = eventnumber / GetEventNumberRollover();
0375 unsigned int newlastevent = firstevent * GetEventNumberRollover() + GetEventNumberRollover() - 1;
0376 if (Verbosity() > 1)
0377 {
0378 std::cout << "event number: " << eventnumber << ", rollover: " << GetEventNumberRollover() << ", multiple: "
0379 << eventnumber / GetEventNumberRollover() << ", new last event number "
0380 << newlastevent << std::endl;
0381 }
0382 SetLastEventNumber(firstevent * GetEventNumberRollover() + GetEventNumberRollover() - 1);
0383 return;
0384 }