source: trunk/MagicSoft/Mars/mfileio/MWriteRootFile.cc@ 1583

Last change on this file since 1583 was 1583, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 14.4 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@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2002
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#include "MWriteRootFile.h"
37
38#include <fstream.h>
39
40#include <TFile.h>
41#include <TTree.h>
42
43#include "MLog.h"
44#include "MLogManip.h"
45
46#include "MParList.h"
47
48ClassImp(MRootFileBranch);
49ClassImp(MWriteRootFile);
50
51static const TString gsDefName = "MWriteRootFile";
52static const TString gsDefTitle = "Task which writes a root-output file";
53// --------------------------------------------------------------------------
54//
55// Default constructor. It is there to support some root stuff.
56// Don't use it.
57//
58MWriteRootFile::MWriteRootFile() : fOut(NULL)
59{
60 fName = gsDefName;
61 fTitle = gsDefTitle;
62
63 fBranches.SetOwner();
64}
65
66// --------------------------------------------------------------------------
67//
68// Specify the name of the root file. You can also give an option ("UPDATE"
69// and "RECREATE" would make sense only) as well as the file title and
70// compression factor. To a more detaild description of the options see
71// TFile.
72//
73MWriteRootFile::MWriteRootFile(const char *fname,
74 const Option_t *opt,
75 const char *ftitle,
76 const Int_t comp,
77 const char *name,
78 const char *title)
79{
80 fName = name ? name : gsDefName.Data();
81 fTitle = title ? title : gsDefTitle.Data();
82
83 //
84 // Set the Arrays the owner of its entries. This means, that the
85 // destructor of the arrays will delete all its entries.
86 //
87 fBranches.SetOwner();
88
89 //
90 // Believing the root user guide, TTree instanced are owned by the
91 // directory (file) in which they are. This means we don't have to
92 // care about their destruction.
93 //
94 //fTrees.SetOwner();
95
96 //
97 // Open the rootfile
98 //
99 fOut = new TFile(fname, opt, ftitle, comp);
100}
101
102// --------------------------------------------------------------------------
103//
104// Prints some statistics about the file to the screen. And closes the file
105// properly.
106//
107MWriteRootFile::~MWriteRootFile()
108{
109 //
110 // Print some statistics to the looging out.
111 //
112 Print();
113
114 //
115 // If the file is still open (no error) write the keys. This is necessary
116 // for appearance of the all trees and branches.
117 //
118 if (IsFileOpen())
119 fOut->Write();
120
121 //
122 // Delete the file. This'll also close the file (if open)
123 //
124 delete fOut;
125
126 //
127 // Remark:
128 // - Trees are automatically deleted by the the file
129 // (unless file.SetDirectory(0) was called)
130 // - Branches are automatically deleted by the tree destructor
131 //
132}
133
134// --------------------------------------------------------------------------
135//
136// Prints all trees with the actually number of written entries to log-out.
137//
138void MWriteRootFile::Print(Option_t *) const
139{
140 *fLog << all << " File: " << GetFileName() << endl;
141 *fLog << setfill('-') << setw(strlen(GetFileName())+8) << "" << endl;
142 *fLog << setfill(' '); // FIXME: not resetting setfill results in strange output???
143
144 TTree *t = NULL;
145 TIter Next(&fTrees);
146 while ((t=(TTree*)Next()))
147 *fLog << t->GetName() << ": \t" << t->GetEntries() << " entries." << endl;
148 *fLog << endl;
149}
150
151// --------------------------------------------------------------------------
152//
153// Add a new Container to list of containers which should be written to the
154// file. Give the name of the container which will identify the container
155// in the parameterlist. tname is the name of the tree to which the
156// container should be written (Remark: one tree can hold more than one
157// container). The default is the same name as the container name.
158// You can slso specify a title for the tree. This is only
159// used the first time this tree in 'mentioned'. As default the title
160// is the name of the tree.
161//
162void MWriteRootFile::AddContainer(const char *cname, const char *tname, const char *ttitle)
163{
164 //
165 // create a new entry in the list of branches to write and
166 // add the entry to the list.
167 //
168 MRootFileBranch *entry = new MRootFileBranch(cname, tname, ttitle);
169 fBranches.AddLast(entry);
170
171 if (tname && tname[0])
172 AddToBranchList(Form("%s.%s", cname, tname));
173}
174
175// --------------------------------------------------------------------------
176//
177// Add a new Container to list of containers which should be written to the
178// file. Give the pointer to the container. tname is the name of the tree to
179// which the container should be written (Remark: one tree can hold more than
180// one container). The default is the same name as the container name.
181// You can slso specify a title for the tree. This is only
182// used the first time this tree in 'mentioned'. As default the title
183// is the name of the tree.
184//
185void MWriteRootFile::AddContainer(MParContainer *cont, const char *tname,
186 const char *ttitle)
187{
188 //
189 // create a new entry in the list of branches to write and
190 // add the entry to the list.
191 //
192 MRootFileBranch *entry = new MRootFileBranch(cont, tname, ttitle);
193 fBranches.AddLast(entry);
194}
195
196// --------------------------------------------------------------------------
197//
198// Add a new Container to list of containers which should be written to the
199// file. Give the pointer to the container. tname is the name of the tree to
200// which the container should be written (Remark: one tree can hold more than
201// one container). The default is the same name as the container name.
202// You can slso specify a title for the tree. This is only
203// used the first time this tree in 'mentioned'. As default the title
204// is the name of the tree.
205//
206Bool_t MWriteRootFile::GetContainer(MParList *pList)
207{
208 MRootFileBranch *entry;
209
210 //
211 // loop over all branches which are 'marked' as branches to get written.
212 //
213 TIter Next(&fBranches);
214 while ((entry=(MRootFileBranch*)Next()))
215 {
216 //
217 // Get the pointer to the container. If the pointer is NULL it seems,
218 // that the user identified the container by name.
219 //
220 MParContainer *cont = entry->GetContainer();
221 if (!cont)
222 {
223 //
224 // Get the name and try to find a container with this name
225 // in the parameter list.
226 //
227 const char *cname = entry->GetContName();
228 cont = (MParContainer*)pList->FindObject(cname);
229 if (!cont)
230 {
231 //
232 // No corresponding container is found
233 //
234 *fLog << dbginf << "Cannot find parameter container '" << cname << "'." << endl;
235 return kFALSE;
236 }
237 //
238 // The container is found. Put the pointer into the entry.
239 //
240 entry->SetContainer(cont);
241 }
242
243 //
244 // Get container name, tree name and tree title of this entry.
245 //
246 const char *cname = cont->GetName();
247 const char *tname = entry->GetName();
248 const char *ttitle = entry->GetTitle();
249
250 //
251 // if the tree name is NULL this idetifies it to use the default:
252 // the container name.
253 //
254 if (tname[0] == '\0')
255 tname = cname;
256
257 //
258 // Check if the tree is already existing (part of the file)
259 //
260 TTree *tree = (TTree*)fOut->Get(tname);
261 if (!tree)
262 {
263 //
264 // if the tree doesn't exist create a new tree. Use the tree
265 // name as title if title is NULL.
266 // And add the tree to the list of trees
267 //
268 TDirectory *save = gDirectory;
269 fOut->cd();
270
271 tree = new TTree(tname, ttitle ? ttitle : tname);
272 fTrees.AddLast(tree);
273
274 gDirectory = save;
275
276 *fLog << "Created Tree " << tname << "." << endl;
277 }
278
279 //
280 // Now we have a valid tree. Search the list of trees for this tree
281 // (either it is already there, or we created and add it previously)
282 // Add a pointer to the entry in the tree list to this branch-entry
283 //
284 TObject *obj;
285 TIter NextTree(&fTrees);
286 while ((obj=NextTree()))
287 {
288 if (obj == tree)
289 entry->SetTree((TTree*)obj);
290 }
291
292 //
293 // Try to get the branch from the file.
294 // If the branch already exists the user specified one branch twice.
295 //
296 TBranch *branch = tree->GetBranch(cname);
297 if (branch)
298 {
299 *fLog << dbginf << "Branch '" << cname << "' is already existing." << endl;
300 return kFALSE;
301 }
302
303 //
304 // Create a new branch in the actual tree. The branch has the name
305 // container name. The type of the container is given by the
306 // ClassName entry in the container. The Address is the address of a
307 // pointer to the container (gotten from the branch entry). As
308 // Basket size we specify a (more or less) common default value.
309 // The containers should be written in Splitlevel=1
310 //
311 TString branchname(cname);
312 branchname.Append(".");
313 branch = tree->Branch(branchname, cont->ClassName(), entry->GetAddress());
314
315 *fLog << "Created Branch " << cname << " of " << cont->ClassName() << "." << endl;
316
317 //
318 // If the branch couldn't be created we have a problem.
319 //
320 if (!branch)
321 {
322 *fLog << dbginf << "Unable to create branch '" << cname << "'." << endl;
323 return kFALSE;
324 }
325 }
326 return kTRUE;
327}
328
329// --------------------------------------------------------------------------
330//
331// Checks all given containers (branch entries) for the write flag.
332// If the write flag is set the corresponding Tree is marked to get filled.
333// All Trees which are marked to be filled are filled with the corresponding
334// branches.
335// Be carefull: If only one container (corresponding to a branch) of a tree
336// has the write flag, all containers in this tree are filled!
337//
338void MWriteRootFile::CheckAndWrite() const
339{
340 const Int_t kFillTree = BIT(14);
341
342 TObject *obj;
343
344 //
345 // Loop over all branch entries
346 //
347 TIter NextBranch(&fBranches);
348 while ((obj=NextBranch()))
349 {
350 MRootFileBranch *b = (MRootFileBranch*)obj;
351
352 //
353 // Check for the Write flag
354 //
355 if (!b->GetContainer()->IsReadyToSave())
356 continue;
357
358 //
359 // If the write flag of the branch entry is set, set the write flag of
360 // the corresponding tree entry.
361 //
362 b->GetTree()->SetBit(kFillTree);
363 }
364
365 //
366 // Loop over all tree entries
367 //
368 TIter NextTree(&fTrees);
369 while ((obj=NextTree()))
370 {
371 TTree *t = (TTree*)obj;
372
373 //
374 // Check the write flag of the tree
375 //
376 if (!t->TestBit(kFillTree))
377 continue;
378
379 //
380 // If the write flag is set, fill the tree (with the corresponding
381 // branches/containers), delete the write flag and increase the number
382 // of written/filled entries.
383 //
384 t->Fill();
385 t->ResetBit(kFillTree);
386 }
387}
388
389// --------------------------------------------------------------------------
390//
391// return open state of the root file.
392//
393Bool_t MWriteRootFile::IsFileOpen() const
394{
395 return fOut->IsOpen();
396}
397
398// --------------------------------------------------------------------------
399//
400// return name of the root-file
401//
402const char *MWriteRootFile::GetFileName() const
403{
404 return fOut->GetName();
405}
406
407// --------------------------------------------------------------------------
408//
409// Implementation of SavePrimitive. Used to write the call to a constructor
410// to a macro. In the original root implementation it is used to write
411// gui elements to a macro-file.
412//
413void MWriteRootFile::StreamPrimitive(ofstream &out) const
414{
415 out << " MWriteRootFile " << GetUniqueName() << "(\"";
416 out << fOut->GetName() << "\", \"";
417 out << fOut->GetOption() << "\", \"";
418 out << fOut->GetTitle() << "\", ";
419 out << fOut->GetCompressionLevel();
420
421 if (fName!=gsDefName || fTitle!=gsDefTitle)
422 {
423 out << ", \"" << fName << "\"";
424 if (fTitle!=gsDefTitle)
425 out << ", \"" << fTitle << "\"";
426 }
427 out << ");" << endl;
428
429
430 MRootFileBranch *entry;
431 TIter Next(&fBranches);
432 while ((entry=(MRootFileBranch*)Next()))
433 {
434 out << " " << GetUniqueName() << ".AddContainer(";
435
436 if (entry->GetContainer())
437 {
438 entry->GetContainer()->SavePrimitive(out);
439 out << "&" << entry->GetContainer()->GetUniqueName();
440 }
441 else
442 out << "\"" << entry->GetContName() << "\"";
443
444 out << ", \"" << entry->GetName() << "\"";
445 if ((TString)entry->GetTitle()!="")
446 out << ", \"" << entry->GetTitle() << "\"";
447
448 out <<");" << endl;
449 }
450}
Note: See TracBrowser for help on using the repository browser.