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