source: trunk/MagicSoft/Mars/mbase/MWriteRootFile.cc@ 1115

Last change on this file since 1115 was 1108, checked in by tbretz, 23 years ago
*** empty log message ***
  • Property svn:executable set to *
File size: 12.5 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz 06/2001 <mailto:tbretz@uni-sw.gwdg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2001
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26// //
27// MWriteRootFile //
28// //
29// This is a writer to store several containers to a root file. //
30// The containers are added with AddContainer. //
31// To understand how it works, see base class MWriteFile //
32// //
33// Warning: Checkout the Warning in MTaskList. //
34// //
35/////////////////////////////////////////////////////////////////////////////
36
37#include "MWriteRootFile.h"
38
39#include <TFile.h>
40#include <TTree.h>
41
42#include "MLog.h"
43#include "MLogManip.h"
44
45#include "MParList.h"
46
47ClassImp(MRootFileBranch);
48ClassImp(MWriteRootFile);
49
50#define kFillTree BIT(14)
51
52// --------------------------------------------------------------------------
53//
54// Specify the name of the root file. You can also give an option ("UPDATE"
55// and "RECREATE" would make sense only) as well as the file title and
56// compression factor. To a more detaild description of the options see
57// TFile.
58//
59MWriteRootFile::MWriteRootFile(const char *fname,
60 const Option_t *opt,
61 const char *ftitle,
62 const Int_t comp,
63 const char *name,
64 const char *title)
65{
66 fName = name ? name : "MWriteRootFile";
67 fTitle = title ? title : "Task which writes a root-output file";
68
69 //
70 // Set the Arrays the owner of its entries. This means, that the
71 // destructor of the arrays will delete all its entries.
72 //
73 fBranches.SetOwner();
74
75 //
76 // Believing the root user guide, TTree instanced are owned by the
77 // directory (file) in which they are. This means we don't have to
78 // care about their destruction.
79 //
80 //fTrees.SetOwner();
81
82 //
83 // Open the rootfile
84 //
85 fOut = new TFile(fname, opt, ftitle, comp);
86}
87
88// --------------------------------------------------------------------------
89//
90// Prints some statistics about the file to the screen. And closes the file
91// properly.
92//
93MWriteRootFile::~MWriteRootFile()
94{
95 //
96 // Print some statistics to the looging out.
97 //
98 Print();
99
100 //
101 // If the file is still open (no error) write the keys. This is necessary
102 // for appearance of the all trees and branches.
103 //
104 if (IsFileOpen())
105 fOut->Write();
106
107 //
108 // Delete the file. This'll also close the file (if open)
109 //
110 delete fOut;
111
112 //
113 // Remark:
114 // - Trees are automatically deleted by the the file
115 // (unless file.SetDirectory(0) was called)
116 // - Branches are automatically deleted by the tree destructor
117 //
118}
119
120// --------------------------------------------------------------------------
121//
122// Prints all trees with the actually number of written entries to log-out.
123//
124void MWriteRootFile::Print(Option_t *) const
125{
126 *fLog << all << " File: " << GetFileName() << endl;
127 *fLog << setfill('-') << setw(strlen(GetFileName())+8) << "" << endl;
128 *fLog << setfill(' '); // FIXME: not resetting setfill results in strange output???
129
130 TTree *t = NULL;
131 TIter Next(&fTrees);
132 while ((t=(TTree*)Next()))
133 *fLog << t->GetName() << ": \t" << t->GetEntries() << " entries." << endl;
134}
135
136// --------------------------------------------------------------------------
137//
138// Add a new Container to list of containers which should be written to the
139// file. Give the name of the container which will identify the container
140// in the parameterlist. tname is the name of the tree to which the
141// container should be written (Remark: one tree can hold more than one
142// container). The default is the same name as the container name.
143// You can slso specify a title for the tree. This is only
144// used the first time this tree in 'mentioned'. As default the title
145// is the name of the tree.
146//
147void MWriteRootFile::AddContainer(const char *cname, const char *tname, const char *ttitle)
148{
149 //
150 // create a new entry in the list of branches to write and
151 // add the entry to the list.
152 //
153 MRootFileBranch *entry = new MRootFileBranch(cname, tname, ttitle);
154 fBranches.AddLast(entry);
155}
156
157// --------------------------------------------------------------------------
158//
159// Add a new Container to list of containers which should be written to the
160// file. Give the pointer to the container. tname is the name of the tree to
161// which the container should be written (Remark: one tree can hold more than
162// one container). The default is the same name as the container name.
163// You can slso specify a title for the tree. This is only
164// used the first time this tree in 'mentioned'. As default the title
165// is the name of the tree.
166//
167void MWriteRootFile::AddContainer(MParContainer *cont, const char *tname,
168 const char *ttitle)
169{
170 //
171 // create a new entry in the list of branches to write and
172 // add the entry to the list.
173 //
174 MRootFileBranch *entry = new MRootFileBranch(cont, tname, ttitle);
175 fBranches.AddLast(entry);
176}
177
178// --------------------------------------------------------------------------
179//
180// Add a new Container to list of containers which should be written to the
181// file. Give the pointer to the container. tname is the name of the tree to
182// which the container should be written (Remark: one tree can hold more than
183// one container). The default is the same name as the container name.
184// You can slso specify a title for the tree. This is only
185// used the first time this tree in 'mentioned'. As default the title
186// is the name of the tree.
187//
188Bool_t MWriteRootFile::GetContainer(MParList *pList)
189{
190 MRootFileBranch *entry;
191
192 //
193 // loop over all branches which are 'marked' as branches to get written.
194 //
195 TIter Next(&fBranches);
196 while ((entry=(MRootFileBranch*)Next()))
197 {
198 //
199 // Get the pointer to the container. If the pointer is NULL it seems,
200 // that the user identified the container by name.
201 //
202 MParContainer *cont = entry->GetContainer();
203 if (!cont)
204 {
205 //
206 // Get the name and try to find a container with this name
207 // in the parameter list.
208 //
209 const char *cname = entry->GetContName();
210 cont = (MParContainer*)pList->FindObject(cname);
211 if (!cont)
212 {
213 //
214 // No corresponding container is found
215 //
216 *fLog << dbginf << "Cannot find parameter container '" << cname << "'." << endl;
217 return kFALSE;
218 }
219 //
220 // The container is found. Put the pointer into the entry.
221 //
222 entry->SetContainer(cont);
223 }
224
225 //
226 // Get container name, tree name and tree title of this entry.
227 //
228 const char *cname = cont->GetName();
229 const char *tname = entry->GetName();
230 const char *ttitle = entry->GetTitle();
231
232 //
233 // if the tree name is NULL this idetifies it to use the default:
234 // the container name.
235 //
236 if (tname[0] == '\0')
237 tname = cname;
238
239 //
240 // Check if the tree is already existing (part of the file)
241 //
242 TTree *tree = (TTree*)fOut->Get(tname);
243 if (!tree)
244 {
245 //
246 // if the tree doesn't exist create a new tree. Use the tree
247 // name as title if title is NULL.
248 // And add the tree to the list of trees
249 //
250 tree = new TTree(tname, ttitle ? ttitle : tname);
251 fTrees.AddLast(tree);
252
253 *fLog << "Created Tree " << tname << "." << endl;
254 }
255
256 //
257 // Now we have a valid tree. Search the list of trees for this tree
258 // (either it is already there, or we created and add it previously)
259 // Add a pointer to the entry in the tree list to this branch-entry
260 //
261 TObject *obj;
262 TIter NextTree(&fTrees);
263 while ((obj=NextTree()))
264 {
265 if (obj == tree)
266 entry->SetTree((TTree*)obj);
267 }
268
269 //
270 // Try to get the branch from the file.
271 // If the branch already exists the user specified one branch twice.
272 //
273 TBranch *branch = tree->GetBranch(cname);
274 if (branch)
275 {
276 *fLog << dbginf << "Branch '" << cname << "' is already existing." << endl;
277 return kFALSE;
278 }
279
280 //
281 // Create a new branch in the actual tree. The branch has the name
282 // container name. The type of the container is given by the
283 // ClassName entry in the container. The Address is the address of a
284 // pointer to the container (gotten from the branch entry). As
285 // Basket size we specify a (more or less) common default value.
286 // The containers should be written in Splitlevel=1
287 //
288 TString branchname(cname);
289 branchname.Append(".");
290 branch = tree->Branch(branchname, cont->ClassName(), entry->GetAddress());
291
292 *fLog << "Created Branch " << cname << " of " << cont->ClassName() << "." << endl;
293
294 //
295 // If the branch couldn't be created we have a problem.
296 //
297 if (!branch)
298 {
299 *fLog << dbginf << "Unable to create branch '" << cname << "'." << endl;
300 return kFALSE;
301 }
302 }
303 return kTRUE;
304}
305
306// --------------------------------------------------------------------------
307//
308// Checks all given containers (branch entries) for the write flag.
309// If the write flag is set the corresponding Tree is marked to get filled.
310// All Trees which are marked to be filled are filled with the corresponding
311// branches.
312// Be carefull: If only one container (corresponding to a branch) of a tree
313// has the write flag, all containers in this tree are filled!
314//
315void MWriteRootFile::CheckAndWrite() const
316{
317 TObject *obj;
318
319 //
320 // Loop over all branch entries
321 //
322 TIter NextBranch(&fBranches);
323 while ((obj=NextBranch()))
324 {
325 MRootFileBranch *b = (MRootFileBranch*)obj;
326
327 //
328 // Check for the Write flag
329 //
330 if (!b->GetContainer()->IsReadyToSave())
331 continue;
332
333 //
334 // If the write flag of the branch entry is set, set the write flag of
335 // the corresponding tree entry.
336 //
337 b->GetTree()->SetBit(kFillTree);
338 }
339
340 //
341 // Loop over all tree entries
342 //
343 TIter NextTree(&fTrees);
344 while ((obj=NextTree()))
345 {
346 TTree *t = (TTree*)obj;
347
348 //
349 // Check the write flag of the tree
350 //
351 if (!t->TestBit(kFillTree))
352 continue;
353
354 //
355 // If the write flag is set, fill the tree (with the corresponding
356 // branches/containers), delete the write flag and increase the number
357 // of written/filled entries.
358 //
359 t->Fill();
360 t->ResetBit(kFillTree);
361 }
362}
363
364// --------------------------------------------------------------------------
365//
366// return open state of the root file.
367//
368Bool_t MWriteRootFile::IsFileOpen() const
369{
370 return fOut->IsOpen();
371}
372
373// --------------------------------------------------------------------------
374//
375// return name of the root-file
376//
377const char *MWriteRootFile::GetFileName() const
378{
379 return fOut->GetName();
380}
381
Note: See TracBrowser for help on using the repository browser.