File indexing completed on 2025-08-05 08:16:10
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 (!striprunnodes.empty())
0256 {
0257 for (const auto &nodename : striprunnodes)
0258 {
0259 PHNode *ChosenNode = nodeiter.findFirst("PHIODataNode", nodename);
0260 if (ChosenNode)
0261 {
0262 ChosenNode->makeTransient();
0263 }
0264 else
0265 {
0266 if (Verbosity() > 0)
0267 {
0268 std::cout << PHWHERE << Name() << ": Node " << nodename
0269 << " does not exist" << std::endl;
0270 }
0271 }
0272 }
0273 }
0274 }
0275 else
0276 {
0277 for (const auto &nodename : saverunnodes)
0278 {
0279 PHNode *ChosenNode = nodeiter.findFirst("PHIODataNode", nodename);
0280 if (ChosenNode)
0281 {
0282 ChosenNode->makePersistent();
0283 }
0284 else
0285 {
0286 if (Verbosity() > 0)
0287 {
0288 std::cout << PHWHERE << Name() << ": Node " << nodename
0289 << " does not exist" << std::endl;
0290 }
0291 }
0292 }
0293 }
0294 dstOut->write(thisNode);
0295 se->MakeNodesTransient(thisNode);
0296 delete dstOut;
0297 dstOut = nullptr;
0298 return 0;
0299 }
0300
0301 int Fun4AllDstOutputManager::outfile_open_first_write()
0302 {
0303 delete dstOut;
0304 SetEventsWritten(1);
0305 std::filesystem::path p = OutFileName();
0306 if (m_FileNameStem.empty())
0307 {
0308 m_FileNameStem = p.stem();
0309 }
0310 if (ApplyFileRule())
0311 {
0312 recoConsts *rc = recoConsts::instance();
0313 int runnumber = 0;
0314 if (rc->FlagExist("RUNNUMBER"))
0315 {
0316 runnumber = rc->get_IntFlag("RUNNUMBER");
0317 }
0318 std::string fullpath = ".";
0319 if (p.has_parent_path())
0320 {
0321 fullpath = p.parent_path();
0322 }
0323 std::string runseg = std::format("-{:08}-{:05}",runnumber,m_CurrentSegment);
0324 std::string newfile = fullpath + std::string("/") + m_FileNameStem + runseg + std::string(p.extension());
0325 OutFileName(newfile);
0326 m_CurrentSegment++;
0327 }
0328 m_UsedOutFileName = OutFileName() + std::string("?reproducible=") + std::string(p.filename());
0329 dstOut = new PHNodeIOManager(UsedOutFileName(), PHWrite);
0330 if (SplitLevel() != std::numeric_limits<int>::min())
0331 {
0332 dstOut->SplitLevel(SplitLevel());
0333 }
0334 if (BufferSize() != std::numeric_limits<int>::min())
0335 {
0336 dstOut->BufferSize(BufferSize());
0337 }
0338 if (!dstOut->isFunctional())
0339 {
0340 delete dstOut;
0341 dstOut = nullptr;
0342 std::cout << PHWHERE << " Could not open " << OutFileName() << std::endl;
0343 return -1;
0344 }
0345
0346 dstOut->SetCompressionSetting(m_CompressionSetting);
0347 return 0;
0348 }