Belle II Software development
HistoManager2.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include "daq/dqm/HistoManager2.h"
10#include <TROOT.h>
11#include <TFile.h>
12#include <filesystem>
13#include <unistd.h>
14
15using namespace Belle2;
16using namespace std;
17
18// Constructor / Destructor
19
20HistoManager2::HistoManager2(std::string name)
21{
22 m_name = name;
23 clear();
24 merge();
25}
26
27HistoManager2::~HistoManager2()
28{
29}
30
31bool HistoManager2::add(const string& subdir, const string& name, int pid, TH1* histo)
32{
33 // printf ( "HistoManager2: adding %s to subdir %s from id %d\n",
34 // name.c_str(), subdir.c_str(), pid );
35
36 // Check for subdirectory
37 if (m_subdir.find(subdir) == m_subdir.end()) {
38 // Work dir and hist
39 map<string, map<int, TH1*>>* newsubdir = new map<string, map<int, TH1*>>;
40 map<int, TH1*>* newhlist = new map<int, TH1*> ;
41 (*newsubdir)[name] = *newhlist;
42 m_subdir[subdir] = *newsubdir;
43 // Merge dir and hist
44 map<string, TH1*>* newmergedir = new map<string, TH1*>;
45 (*newmergedir)[name] = NULL; // TH1 is not yet created
46 m_mergedir[subdir] = *newmergedir;
47 printf("HistoManager2: new list created for subdir %s\n", subdir.c_str());
48 delete newsubdir;
49 delete newhlist;
50 delete newmergedir;
51 }
52
53 // Get histogram map of subdir
54 map<string, map<int, TH1*>>& dirlist = m_subdir[subdir];
55 map<int, TH1*>& hlist = dirlist[name];
56 if (hlist.find(pid) == hlist.end()) {
57 hlist[pid] = histo;
58 // printf("HistoManager2: histogram %s from %d registered in %s\n",
59 // histo->GetName(), pid, subdir.c_str());
60 // histo->Print();
61 return true;
62 }
63 return false;
64}
65
66bool HistoManager2::update(const string& subdir, const string& name, int pid, TH1* histo)
67{
68 // Register the histogram if not yet done
69 if (add(subdir, name, pid, histo)) return true;
70
71
72 // Retrieve the histogram list for the name
73 map<string, map<int, TH1*>>& dirlist = m_subdir[subdir];
74 map<int, TH1*>& hlist = dirlist[name];
75
76 // Replace histogram
77 TH1* prevhisto = hlist[pid];
78 if (prevhisto != NULL) delete prevhisto;
79 hlist[pid] = histo;
80 // printf ( "HistoManager2: histogram %s replaced in subdir %s, entry = %f\n",
81 // name.c_str(), subdir.c_str(), histo->GetEntries());
82 // hlist[pid]->Print();
83 // Return
84 return true;
85}
86
87TH1* HistoManager2::get(const string& subdir, const string& name, int pid)
88{
89 const map<string, map<int, TH1*>>& dirlist = m_subdir[subdir];
90 const map<int, TH1*>& hlist = dirlist.at(name);
91 TH1* hist = hlist.at(pid);
92 return hist;
93}
94
95bool HistoManager2::merge()
96{
97 {
98 // Loop over subdir list
99 string subdir;
100 for (map<string, map<string, map<int, TH1*>>>::iterator is =
101 m_subdir.begin(); is != m_subdir.end(); ++is) {
102 map<string, map<int, TH1*>>& dirlist = is->second;
103 map<string, TH1*>& mergelist = m_mergedir[is->first];
104 // Move to the root directory
105 gROOT->cd();
106
107 // cd to subdirectory if defined
108 subdir = is->first;
109 /*
110 if ( is->first != "root" ) {
111 TDirectory* fdir = (m_memfile->GetmemFile())->GetDirectory();
112 fdir->mkdir ( (is->first).c_str() );
113 fdir->cd ( (is->first).c_str() );
114 printf ( "TMemFile: subdir set to %s\n", (is->first).c_str() );
115 fdir->ls();
116 }
117 */
118 // Loop over histogram list
119 for (map<string, std::map<int, TH1*> >::iterator it = dirlist.begin();
120 it != dirlist.end(); ++it) {
121 string name = it->first;
122 map<int, TH1*>& hmap = it->second;
123 if (mergelist[name] != NULL) {
124 TH1* merge_hist = mergelist[name];
125 merge_hist->Reset();
126
127 }
128 // Loop over pid list
129 for (map<int, TH1*>::iterator ih = hmap.begin(); ih != hmap.end();
130 ++ih) {
131 // int pid = ih->first;
132 TH1* hist = ih->second;
133 // printf ( "Retrieving histo %s from pid = %d\n", hist->GetName(), pid );
134 // hist->Print();
135 // Create new histogram in merge list if not exist yet
136 if (mergelist[name] == NULL) {
137 // printf ( "HistoManager2: adding %s (class %s) to mergelist\n",
138 // hist->GetName(), hist->ClassName() );
139 string newname;
140 if (subdir != "")
141 newname = subdir + "/" + string(hist->GetName());
142 else
143 newname = string(hist->GetName());
144 hist->SetName(newname.c_str());
145 TH1* mhist = (TH1*)hist->Clone();
146 mergelist[name] = mhist;
147 // mergelist[name] = (TH1*)hist->Clone();
148 // m_mapfile->Add(mergelist[name]);
149 // delete hist;
150 }
151 // Add histogram if exist
152 else {
153 TH1* merge_hist = mergelist[name];
154 merge_hist->Add(hist);
155 merge_hist->SetTitle(hist->GetTitle());
156 }
157 }
158 }
159 }
160 }
161 TFile* fh;
162 fh = new TFile(("/dev/shm/tmp_" + m_name).c_str(), "RECREATE");
163 if (fh) {
164 if (!fh->IsOpen()) {
165 printf("HistoManager2 cannot open file : %s\n", ("/dev/shm/tmp_" + m_name).c_str());
166 return false;
167 }
168
169 // Loop over subdir list
170 for (map<string, map<string, map<int, TH1*>>>::iterator is =
171 m_subdir.begin(); is != m_subdir.end(); ++is) {
172 map<string, map<int, TH1*>>& dirlist = is->second;
173 map<string, TH1*>& mergelist = m_mergedir[is->first];
174 // No directories, all Hist are in root dir but with a dir prefix in its name
175 for (map<string, std::map<int, TH1*> >::iterator it = dirlist.begin();
176 it != dirlist.end(); ++it) {
177 string name = it->first;
178 TH1* merge_hist = mergelist[name];
179 if (merge_hist) merge_hist->Write();
180 }
181 }
182 fh->Close();
183 delete fh;
184 }
185
186 if (rename(("/dev/shm/tmp_" + m_name).c_str(), ("/dev/shm/" + m_name).c_str())) {
187 perror("Rename dhm file failed ");
188 return false;
189 }
190
191 return true;
192}
193
194void HistoManager2::clear()
195{
196 for (map<string, map<string, map<int, TH1*>>>::iterator is = m_subdir.begin(); is != m_subdir.end(); ++is) {
197 map<string, map<int, TH1*>>& dirlist = is->second;
198
199 for (map<string, std::map<int, TH1*> >::iterator it = dirlist.begin(); it != dirlist.end(); ++it) {
200 map<int, TH1*>& hmap = it->second;
201
202 for (map<int, TH1*>::iterator ih = hmap.begin(); ih != hmap.end(); ++ih) {
203 TH1* hist = ih->second;
204 if (hist != NULL) delete hist;
205 //if (hist != NULL) hist->Reset();
206 }
207 hmap.clear();
208 }
209 dirlist.clear();
210 }
211 m_subdir.clear();
212
213 for (map<string, map<string, TH1*> >::iterator is = m_mergedir.begin(); is != m_mergedir.end(); ++is) {
214 map<string, TH1*>& dirlist = is->second;
215
216 for (map<string, TH1*>::iterator it = dirlist.begin(); it != dirlist.end(); ++it) {
217 TH1* hist = it->second;
218 if (hist != NULL) delete hist;
219 //it->second = NULL;
220 //if (hist != NULL) hist->Reset();
221 }
222 dirlist.clear();
223 }
224 m_mergedir.clear();
225
226 // we delete the outfile(s)
227 unlink(("/dev/shm/tmp_" + m_name).c_str());
228 unlink(("/dev/shm/" + m_name).c_str());
229 printf("HistoManager2: clear\n");
230}
231
232
233void HistoManager2::filedump(std::string outfile)
234{
235 printf("dump to dqm file = %s\n", outfile.c_str());
236 merge(); // Smart move to first merge, but necessary?
237 // update/overwrite existing. we could be faster with sendfile, but more code to write
238 filesystem::copy_file("/dev/shm/" + m_name, outfile, filesystem::copy_options::overwrite_existing);
239}
Abstract base class for different kinds of events.
STL namespace.