/** @file * $Author: kusanagi $ * $Date: 2004/12/03 22:04:04 $ * $Revision: 2.3 $ * * Implementation of the PamelaRun class. */ #include #include #include #include #include #include #include #include //Substituted by Maurizio 05 Feb 2004 #include //Substituted by Maurizio 05 Feb 2004 #include //Substituted by Maurizio 05 Feb 2004 #include //Substituted by Maurizio 05 Feb 2004 #include //Substituted by Maurizio 05 Feb 2004 #include "PamelaRun.h" #include "EventHeader.h" #include "Algorithm.h" #include "AlgorithmInfo.h" #include "Exception.h" #include extern "C" { #include #include "DirectoryStructure.h" } using namespace pamela; static log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger(_T("pamela.PamelaRun")); static std::stringstream oss; /** * Get the run name according to a certain run number. * @param run Run number. * @return a string with the run name. */ std::string PamelaRun::GetRunName(int run) { std::ostringstream t_Stream; t_Stream << std::setw( 4 ) << std::setfill( '0' ) << run; return "Run" + t_Stream.str(); } /** * Check if the run number is already assigned * @param int run - Number of the run to check * @return int */ /*int PamelaRun::RunExists(int run) throw (std::exception){ int res; DIR *dirp; std::string pathDir((char*)getenv("YODA_DATA")); pathDir = pathDir + "/"; pathDir = pathDir + GetRunName(run); // Open the directory if ((dirp = opendir(pathDir.c_str())) == NULL) { res = 0; } else { closedir(dirp); res = 1; } return res; }*/ /** * Check if the run number is already assigned * @param int run - Number of the run to check * @return int */ std::string PamelaRun::RunExists(std::string input) throw (std::exception){ int res; DIR *dirp; std::string fileName; std::string pathDir((char*)getenv("YODA_DATA")); std::string tempName; std::string::size_type pos; std::ostringstream t_Stream; pos = input.find_last_of("/"); //if ((pos == std::string::npos) && !input.empty()) ;//throw Exception("Directories not allowed...."); fileName = input.substr(pos+1); pos = fileName.find_last_of("."); fileName = fileName.substr(0,pos); pathDir = pathDir + "/"; tempName = pathDir + fileName; int i = 0; while (res){ if ((dirp = opendir(tempName.c_str())) == NULL) { res = 0; } else { closedir(dirp); t_Stream.str(""); t_Stream << std::setw( 2 ) << std::setfill( '0' ) << ++i; tempName = pathDir + fileName + t_Stream.str() ; res = 1; } } return (fileName + t_Stream.str()); } /** * Create a new Pamela run. * @param run Run number * @param path Base path name to the data */ PamelaRun::PamelaRun(std::string fileName, std::string path): Path(path), RunNumber(1){ //veirificare se รจ possibilie eliminare questa variabile logger->debug(_T("Constructor")); Run = RunExists(fileName); info = RunInfo(this); } /** * Get the directory name that contains the files of a certain event * type for this run. * @param type the packet type. * @return the complete path for this event type. */ std::string PamelaRun::GetDirName(PacketType const * type) const { std::string EventType = type->GetName(); return Path + "/" + Run + "/" + EventType; } /** * Get the file name for a certain event type. * @param type subpacket type. * @param name subpacket name. * @return the complete path and file name. */ std::string PamelaRun::GetFileName(const SubPacket* type, std::string name) const { if (type->IsDetectorSpecific()) { return GetDirName(type->GetPacketType()) + "/" + type->GetSubDetector()->GetName() + "/" + Run + "." + type->GetPacketType()->GetName() + "." + type->GetSubDetector()->GetName() + "." + name + ".root"; } else { return GetDirName(type->GetPacketType()) + "/" + Run + "." + type->GetPacketType()->GetName() + "." + name + ".root"; } } /** * Get the file name for a certain event type. * @param type subpacket type. * @return the complete path and file name. */ std::string PamelaRun::GetFileName(const SubPacket* type) const { return GetFileName(type, type->GetSubPacketName()); } /** * Get the branch name that corresponds to a certain * subpacket. Usually, this is the name of the subpacket. * @param type subpacket type. * @return the corresponding branch name. */ static std::string GetDefaultBranchName(const SubPacket* type) { return type->GetSubPacketName(); } /** * Get the tree name for a certain subpacket. This is the name of the * subdetector for detector specific subpackets, and the packet name * ("Physics" etc.) for common packets. * @param type the packet type. * @return the corresponding tree name. */ static std::string GetTreeName(const SubPacket* type) { if (type->IsDetectorSpecific()) { return type->GetSubDetector()->GetName(); } else { return type->GetPacketType()->GetName(); } } /** * Get a list of all root files from a certain path. * @param path Path name to start the search. * @return A list of all file names. */ static std::list GetRootFiles(std::string path) throw (std::exception) { std::list files; DIR *dir = opendir(path.c_str()); if (dir == 0) { oss.str(""); oss << "Could not open " << path; logger->debug(oss.str().c_str()); //throw Exception("Could not open " + path); } for (struct dirent *d = readdir(dir); d != NULL; d = readdir(dir)) { if ((strcmp(".",d->d_name) == 0) || (strcmp("..",d->d_name) == 0)) continue; std::string filename = path + "/" + d->d_name; struct stat buf; stat(filename.c_str(), &buf); if S_ISDIR(buf.st_mode) { std::listtoAdd = GetRootFiles(filename); files.insert(files.end(), toAdd.begin(), toAdd.end()); } else if ((filename.substr(filename.size()-5, filename.size()) == ".root") // correct suffix && (!isdigit(filename[filename.size()-6]))) { // base file std::string nextfilename = filename; nextfilename.insert(filename.size()-5, "_1"); if (stat(nextfilename.c_str(), &buf) == 0) { filename.insert(filename.size()-5, "*"); } oss.str(""); oss << "Using " << filename; logger->debug(oss.str().c_str()); files.push_back(filename); } } return files; } /** * Helper function to open the ROOT TTree of the header within the run * framework. * @param type The packet type. * @return the ROOT TTree. */ TChain* PamelaRun::ReadHeaderTree(const PacketType *type) throw (std::exception) { EventHeader header(type); std::string FileName = GetFileName(&header); std::string TreeName = GetTreeName(&header); TChain *tree = new TChain(TreeName.c_str()); tree->Add(FileName.c_str()); return tree; } /** * All add trees of a file as friend to a given tree. The tree name of * each tree found in the file is used as the name of the friend alias. * @param tree The base tree to add all other as friends. * @param FileName The name of the file with other trees. */ static void AddAllAsFriend(TChain* tree, std::string FileName) { std::string BaseFileName = FileName; bool HaveChain = false; if (BaseFileName[BaseFileName.size()-6] == '*') { BaseFileName.erase(BaseFileName.size()-6, 1); HaveChain = true; } TFile* File = new TFile(BaseFileName.c_str(), "read"); if (!File->IsOpen()) { oss.str(""); oss << "Could not open file " << BaseFileName << " for reading."; logger->warn(oss.str().c_str()); return; } TList* list = File->GetListOfKeys(); if (HaveChain) { for (TIter i(list); TKey* k = (TKey*)i();) { if (std::string(TTree::Class()->GetName()) == k->GetClassName()) { std::string TreeName = k->GetName(); TChain* FriendChain = new TChain(TreeName.c_str()); FriendChain->Add(FileName.c_str()); tree->AddFriend(FriendChain, TreeName.c_str()); oss.str(""); oss << "Adding chain " << TreeName << " with " << FriendChain->GetEntries() << " entries as Friend"; logger->warn(oss.str().c_str()); } } File->Close(); } else { for (TIter i(list); TKey* k = (TKey*)i();) { if (std::string(TTree::Class()->GetName()) == k->GetClassName()) { std::string TreeName = k->GetName(); TTree* FriendTree = (TTree *)File->Get(TreeName.c_str()); tree->AddFriend(FriendTree, TreeName.c_str()); oss.str(""); oss << "Adding tree " << TreeName << " with " << FriendTree->GetEntries() << " entries as Friend"; logger->debug(oss.str().c_str()); } } } } /** * Read all Root TTrees which belong to a certain event type and mount them * together as "friends". * @param type The packet type. * @return The root trees with the friends. */ TTree* PamelaRun::ReadTTree(const PacketType* type) { oss.str(""); oss << "Getting root files of " << type->GetName(); logger->debug(oss.str().c_str()); RootTreeMap::iterator t = TTreeMap.find(type); if (t != TTreeMap.end()) { return t->second; } else { oss.str(""); oss << "Reading root files of " << type->GetName(); logger->debug(oss.str().c_str()); EventHeader header(type); std::string HeaderFileName = GetFileName(&header); TChain* HeaderTree = ReadHeaderTree(type); std::list rootfiles = GetRootFiles(GetDirName(type)); for (std::list::iterator i = rootfiles.begin(); i != rootfiles.end(); i++){ if (*i == HeaderFileName) continue; // dont add the header tree itself. AddAllAsFriend(HeaderTree, *i); } TTreeMap.insert(RootTreeMap::value_type(type, HeaderTree)); return HeaderTree; } } /** * Register a certain SubPacket, identified by its name, to be read * from the repository. This function is made for interactive work. * @param subpacket A pointer to the pointer of the packet. * @param name The name of the subpacket */ void PamelaRun::ReadSubPacket(void* subpacket, std::string name) { SubPacket *packet = *(SubPacket**)subpacket; // look into the map of subpackets if we already read it. std::string FullName = packet->GetPacketType()->GetName() + "." + name; SubPacketMap::iterator i = SubPacketAddresses.find(FullName); if (i != SubPacketAddresses.end()) { // it is in the map *(SubPacket**)subpacket = i->second; return; } else { // not found in the map of used subpackets TTree* tree = ReadTTree(packet->GetPacketType()); TBranch* branch = tree->GetBranch(name.c_str()); if (branch != 0) { branch->SetAddress(subpacket); SubPacketAddresses.insert(SubPacketMap::value_type(FullName, packet)); } else { oss.str(""); oss << "Could not find data for " << packet->GetPacketType()->GetName() << "/" << name ; logger->error(oss.str().c_str()); } } } /** * Register a certain SubPacket, identified by its default name, to be * read from the repository. This function is made for * interactive work. * @param subpacket A pointer to the pointer of the packet. */ void PamelaRun::ReadSubPacket(void* subpacket) { SubPacket *packet = *(SubPacket**)subpacket; ReadSubPacket(subpacket, GetDefaultBranchName(packet)); } /** * Register a certain SubPacket with its default name, to be read from * the repository. This functions is for use from the algorithm. * @param algo Algorithm that needs this SubPacket. * @param subpacket A pointer to the pointer of the packet. */ void PamelaRun::ReadSubPacket(const Algorithm* algo, void* subpacket) { //:TODO: store the request of the algorithm here. ReadSubPacket(subpacket); } /** * Register a certain SubPacket, with a custom name, to * be read from the repository. This functions is for use from * the algorithm. * @param algo Algorithm that needs this SubPacket. * @param subpacket A pointer to the pointer of the packet. * @param name The name of the subpacket */ void PamelaRun::ReadSubPacket(const Algorithm* algo, void* subpacket, std::string name) { //:TODO: store the request of the algorithm here. ReadSubPacket(subpacket, name); } /** * Helper function to create a ROOT TTree within the run framework. * @param algo Algorithm that creates this SubPacket. * @param packet subpacket type * @param name the name of the subpacket * @return the ROOT TTree. */ TTree* PamelaRun::CreateTTree(Algorithm* algo, const SubPacket* packet, std::string name) throw (std::exception) { std::string FileName = GetFileName(packet, name); std::string EventType = packet->GetPacketType()->GetName(); CreateDirectoryStructure(FileName.c_str()); TFile* File = new TFile(FileName.c_str(), "create"); File->SetCompressionLevel(5); if (!File->IsOpen()) { oss.str(""); oss << "Could not open file " << FileName ; logger->error(oss.str().c_str()); //throw Exception("Could not open file " + FileName); } std::string TreeName = GetTreeName(packet); TTree *tree = new TTree(TreeName.c_str(), algo->GetAlgorithmName().c_str()); WritingRootTrees[packet->GetPacketType()].push_back(tree); tree->GetCurrentFile()->cd(); AlgorithmInfo ai(algo); ai.Write(); info.Write(); oss.str(""); oss << "Creating file " << FileName << " with Tree " << TreeName; logger->info(oss.str().c_str()); return tree; } /** * Register a certain SubPacket to be written to the repository. A * usual call sequence for this function ist * MyEvent *event = new MyEvent(); * run->WriteSubPacket(this, &event, event->Class() * @param algo Algorithm that produces this SubPacket. * @param subpacket A pointer to the pointer of the subpacket. * @param c The class the subpacket belongs to. * @param name The name of the packet. */ void PamelaRun::WriteSubPacket(Algorithm *algo, void* subpacket, const TClass *c, std::string name) { SubPacket *packet = *(SubPacket **)subpacket; oss.str(""); oss << "Register: " << name << " for " << algo->GetAlgorithmName() << " (writing)"; logger->debug(oss.str().c_str()); TTree* HeaderTree = ReadTTree(packet->GetPacketType()); TTree* tree = CreateTTree(algo, packet, name); oss.str(""); oss << "Branch: " << name << " Class: " << c->GetName(); logger->debug(oss.str().c_str()); tree->Branch(name.c_str(), c->GetName(), subpacket); HeaderTree->AddFriend(tree, tree->GetName()); std::string FullName = packet->GetPacketType()->GetName() + "." + name; SubPacketAddresses.insert(SubPacketMap::value_type(FullName, packet)); } /** * Register a certain SubPacket with its default name to be written to * the repository. A usual call sequence for this function ist * MyEvent *event = new MyEvent(); * run->WriteSubPacket(this, &event, event->Class() * @param algo Algorithm that produces this SubPacket. * @param subpacket A pointer to the pointer of the subpacket. * @param c The class the subpacket belongs to. */ void PamelaRun::WriteSubPacket(Algorithm *algo, void* subpacket, const TClass *c) { SubPacket *packet = *(SubPacket **)subpacket; WriteSubPacket(algo, subpacket, c, GetDefaultBranchName(packet)); } /** * Write the header packet of a specified packet type. This is mainly used * for the raw reader to create the base for the event structure. * @param algo Algorithm that produces this SubPacket. * @param subpacket A pointer to the pointer of the packet. * @param type The packet type. */ void PamelaRun::WriteHeader(Algorithm* algo, EventHeader** subpacket, const PacketType* type) { EventHeader header(type); std::string FileName = GetFileName(&header, GetDefaultBranchName(&header)); std::string EventType = (&header)->GetPacketType()->GetName(); CreateDirectoryStructure(FileName.c_str()); TFile* File = new TFile(FileName.c_str(), "create"); if (!File->IsOpen()) { oss.str(""); oss << "Could not open file " << FileName ; logger->error(oss.str().c_str()); //throw Exception("Could not open file " + FileName); } //std::string TreeName = GetTreeName(packet); TTree *tree = new TTree("Pscu", algo->GetAlgorithmName().c_str()); WritingRootTrees[(&header)->GetPacketType()].push_back(tree); tree->GetCurrentFile()->cd(); AlgorithmInfo ai(algo); ai.Write(); info.Write(); oss.str(""); oss << "Created file " << FileName << " with Tree Pscu"; logger->info(oss.str().c_str()); tree->Branch(GetDefaultBranchName(&header).c_str(), (*subpacket)->Class()->GetName(), subpacket); TTreeMap.insert(RootTreeMap::value_type(type, tree)); } /** * Write the header packet to all ROOT files in the tree. Intended to * be used for raw data readers that create the initial event structure. * @param algo Algorithm that produces this SubPacket. * @param subpacket A pointer to the pointer of the header packet. */ void PamelaRun::WriteHeaders(Algorithm* algo, EventHeader** subpacket) { WriteHeader(algo, subpacket, PacketType::PhysEndRun); WriteHeader(algo, subpacket, PacketType::CalibCalPulse1); WriteHeader(algo, subpacket, PacketType::CalibCalPulse2); WriteHeader(algo, subpacket, PacketType::Physics); WriteHeader(algo, subpacket, PacketType::CalibTrkBoth); WriteHeader(algo, subpacket, PacketType::CalibTrk1); WriteHeader(algo, subpacket, PacketType::CalibTrk2); WriteHeader(algo, subpacket, PacketType::CalibTrd); WriteHeader(algo, subpacket, PacketType::CalibTof); WriteHeader(algo, subpacket, PacketType::CalibS4); WriteHeader(algo, subpacket, PacketType::CalibCalPed); WriteHeader(algo, subpacket, PacketType::CalibAc); WriteHeader(algo, subpacket, PacketType::RunHeader); WriteHeader(algo, subpacket, PacketType::RunTrailer); WriteHeader(algo, subpacket, PacketType::CalibHeader); WriteHeader(algo, subpacket, PacketType::CalibTrailer); WriteHeader(algo, subpacket, PacketType::InitHeader); WriteHeader(algo, subpacket, PacketType::InitTrailer); WriteHeader(algo, subpacket, PacketType::EventTrk); WriteHeader(algo, subpacket, PacketType::TestTrk); WriteHeader(algo, subpacket, PacketType::TestTof); WriteHeader(algo, subpacket, PacketType::Log); WriteHeader(algo, subpacket, PacketType::VarDump); WriteHeader(algo, subpacket, PacketType::ArrDump); WriteHeader(algo, subpacket, PacketType::TabDump); WriteHeader(algo, subpacket, PacketType::Tmtc); WriteHeader(algo, subpacket, PacketType::Mcmd); WriteHeader(algo, subpacket, PacketType::ForcedFECmd); WriteHeader(algo, subpacket, PacketType::AcInit); WriteHeader(algo, subpacket, PacketType::CalInit); WriteHeader(algo, subpacket, PacketType::TrkInit); WriteHeader(algo, subpacket, PacketType::TofInit); WriteHeader(algo, subpacket, PacketType::TrgInit); WriteHeader(algo, subpacket, PacketType::NdInit); WriteHeader(algo, subpacket, PacketType::S4Init); WriteHeader(algo, subpacket, PacketType::CalAlarm); WriteHeader(algo, subpacket, PacketType::AcAlarm); WriteHeader(algo, subpacket, PacketType::TrkAlarm); WriteHeader(algo, subpacket, PacketType::TrgAlarm); WriteHeader(algo, subpacket, PacketType::TofAlarm); WriteHeader(algo, subpacket, PacketType::S4Alarm); } /** * Write the ROOT files to disk. */ void PamelaRun::WriteFiles(void) { // Workaround: unlink all friend trees first top avoid to store // the links in the header tree file. for (RootTreeMap::iterator i = TTreeMap.begin(); i != TTreeMap.end(); i++) { if (i->second->GetListOfFriends() != 0) { i->second->GetListOfFriends()->Delete(); } } for (TTreeListMap::iterator i = WritingRootTrees.begin(); i != WritingRootTrees.end(); i++) { for (TTreeList::iterator j = i->second.begin(); j != i->second.end(); j++) { (*j)->GetCurrentFile()->Write(); } } } /** * Fill all ROOT trees of a certain type that were opened for writing. * @param type the package type of the trees to fill. */ void PamelaRun::FillTrees(const PacketType* type) { for (TTreeList::iterator j = WritingRootTrees[type].begin(); j != WritingRootTrees[type].end(); j++) { (*j)->Fill(); ; } }