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

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