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

Last change on this file since 1081 was 1080, checked in by tbretz, 25 years ago
*** empty log message ***
  • Property svn:executable set to *
File size: 12.1 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 fTrees.SetOwner();
75
76 //
77 // Open the rootfile
78 //
79 fOut = new TFile(fname, opt, ftitle, comp);
80}
81
82// --------------------------------------------------------------------------
83//
84// Prints some statistics about the file to the screen. And closes the file
85// properly.
86//
87MWriteRootFile::~MWriteRootFile()
88{
89 //
90 // Print some statistics to the looging out.
91 //
92 Print();
93
94 //
95 // If the file is still open (no error) write the keys. This is necessary
96 // for appearance of the all trees and branches.
97 //
98 if (IsFileOpen())
99 fOut->Write();
100
101 //
102 // Delete the file. This'll also close the file (if open)
103 //
104 delete fOut;
105
106 //
107 // Remark:
108 // - Trees are automatically deleted by the the file
109 // (unless file.SetDirectory(0) was called)
110 // - Branches are automatically deleted by the tree destructor
111 //
112}
113
114// --------------------------------------------------------------------------
115//
116// Prints all trees with the actually number of written entries to log-out.
117//
118void MWriteRootFile::Print(Option_t *) const
119{
120 cout << all << " File: " << GetFileName() << endl;
121 cout << setfill('-') << setw(strlen(GetFileName())+8) << "" << endl;
122
123 TTree *t;
124 TIter Next(&fTrees);
125 while ((t=(TTree*)Next()))
126 cout << t->GetName() << ": \t" << t->GetEntries() << " entries." << endl;
127}
128
129// --------------------------------------------------------------------------
130//
131// Add a new Container to list of containers which should be written to the
132// file. Give the name of the container which will identify the container
133// in the parameterlist. tname is the name of the tree to which the
134// container should be written (Remark: one tree can hold more than one
135// container). The default is the same name as the container name.
136// You can slso specify a title for the tree. This is only
137// used the first time this tree in 'mentioned'. As default the title
138// is the name of the tree.
139//
140void MWriteRootFile::AddContainer(const char *cname, const char *tname, const char *ttitle)
141{
142 //
143 // create a new entry in the list of branches to write and
144 // add the entry to the list.
145 //
146 MRootFileBranch *entry = new MRootFileBranch(cname, tname, ttitle);
147 fBranches.AddLast(entry);
148}
149
150// --------------------------------------------------------------------------
151//
152// Add a new Container to list of containers which should be written to the
153// file. Give the pointer to the container. tname is the name of the tree to
154// which the container should be written (Remark: one tree can hold more than
155// one container). The default is the same name as the container name.
156// You can slso specify a title for the tree. This is only
157// used the first time this tree in 'mentioned'. As default the title
158// is the name of the tree.
159//
160void MWriteRootFile::AddContainer(MParContainer *cont, const char *tname,
161 const char *ttitle)
162{
163 //
164 // create a new entry in the list of branches to write and
165 // add the entry to the list.
166 //
167 MRootFileBranch *entry = new MRootFileBranch(cont, tname, ttitle);
168 fBranches.AddLast(entry);
169}
170
171// --------------------------------------------------------------------------
172//
173// Add a new Container to list of containers which should be written to the
174// file. Give the pointer to the container. tname is the name of the tree to
175// which the container should be written (Remark: one tree can hold more than
176// one container). The default is the same name as the container name.
177// You can slso specify a title for the tree. This is only
178// used the first time this tree in 'mentioned'. As default the title
179// is the name of the tree.
180//
181Bool_t MWriteRootFile::GetContainer(MParList *pList)
182{
183 MRootFileBranch *entry;
184
185 //
186 // loop over all branches which are 'marked' as branches to get written.
187 //
188 TIter Next(&fBranches);
189 while ((entry=(MRootFileBranch*)Next()))
190 {
191 //
192 // Get the pointer to the container. If the pointer is NULL it seems,
193 // that the user identified the container by name.
194 //
195 MParContainer *cont = entry->GetContainer();
196 if (!cont)
197 {
198 //
199 // Get the name and try to find a container with this name
200 // in the parameter list.
201 //
202 const char *cname = entry->GetContName();
203 cont = (MParContainer*)pList->FindObject(cname);
204 if (!cont)
205 {
206 //
207 // No corresponding container is found
208 //
209 *fLog << dbginf << "Cannot find parameter container '" << cname << "'." << endl;
210 return kFALSE;
211 }
212 //
213 // The container is found. Put the pointer into the entry.
214 //
215 entry->SetContainer(cont);
216 }
217
218 //
219 // Get container name, tree name and tree title of this entry.
220 //
221 const char *cname = cont->GetName();
222 const char *tname = entry->GetName();
223 const char *ttitle = entry->GetTitle();
224
225 //
226 // if the tree name is NULL this idetifies it to use the default:
227 // the container name.
228 //
229 if (tname[0] == '\0')
230 tname = cname;
231
232 //
233 // Check if the tree is already existing (part of the file)
234 //
235 TTree *tree = (TTree*)fOut->Get(tname);
236 if (!tree)
237 {
238 //
239 // if the tree doesn't exist create a new tree. Use the tree
240 // name as title if title is NULL.
241 // And add the tree to the list of trees
242 //
243 tree = new TTree(tname, ttitle ? ttitle : tname);
244 fTrees.AddLast(tree);
245
246 *fLog << "Created Tree " << tname << "." << endl;
247 }
248
249 //
250 // Now we have a valid tree. Search the list of trees for this tree
251 // (either it is already there, or we created and add it previously)
252 // Add a pointer to the entry in the tree list to this branch-entry
253 //
254 TObject *obj;
255 TIter NextTree(&fTrees);
256 while ((obj=NextTree()))
257 {
258 if (obj == tree)
259 entry->SetTree((TTree*)obj);
260 }
261
262 //
263 // Try to get the branch from the file.
264 // If the branch already exists the user specified one branch twice.
265 //
266 TBranch *branch = tree->GetBranch(cname);
267 if (branch)
268 {
269 *fLog << dbginf << "Branch '" << cname << "' is already existing." << endl;
270 return kFALSE;
271 }
272
273 //
274 // Create a new branch in the actual tree. The branch has the name
275 // container name. The type of the container is given by the
276 // ClassName entry in the container. The Address is the address of a
277 // pointer to the container (gotten from the branch entry). As
278 // Basket size we specify a (more or less) common default value.
279 // The containers should be written in Splitlevel=1
280 //
281 branch = tree->Branch(cname, cont->ClassName(), entry->GetAddress());
282
283 *fLog << "Created Branch " << cname << " of " << cont->ClassName() << "." << endl;
284
285 //
286 // If the branch couldn't be created we have a problem.
287 //
288 if (!branch)
289 {
290 *fLog << dbginf << "Unable to create branch '" << cname << "'." << endl;
291 return kFALSE;
292 }
293 }
294 return kTRUE;
295}
296
297// --------------------------------------------------------------------------
298//
299// Checks all given containers (branch entries) for the write flag.
300// If the write flag is set the corresponding Tree is marked to get filled.
301// All Trees which are marked to be filled are filled with the corresponding
302// branches.
303// Be carefull: If only one container (corresponding to a branch) of a tree
304// has the write flag, all containers in this tree are filled!
305//
306void MWriteRootFile::CheckAndWrite() const
307{
308 TObject *obj;
309
310 //
311 // Loop over all branch entries
312 //
313 TIter NextBranch(&fBranches);
314 while ((obj=NextBranch()))
315 {
316 MRootFileBranch *b = (MRootFileBranch*)obj;
317
318 //
319 // Check for the Write flag
320 //
321 if (!b->GetContainer()->IsReadyToSave())
322 continue;
323
324 //
325 // If the write flag of the branch entry is set, set the write flag of
326 // the corresponding tree entry.
327 //
328 b->GetTree()->SetBit(kFillTree);
329 }
330
331 //
332 // Loop over all tree entries
333 //
334 TIter NextTree(&fTrees);
335 while ((obj=NextTree()))
336 {
337 TTree *t = (TTree*)obj;
338
339 //
340 // Check the write flag of the tree
341 //
342 if (!t->TestBit(kFillTree))
343 continue;
344
345 //
346 // If the write flag is set, fill the tree (with the corresponding
347 // branches/containers), delete the write flag and increase the number
348 // of written/filled entries.
349 //
350 t->Fill();
351 t->ResetBit(kFillTree);
352 }
353}
354
355// --------------------------------------------------------------------------
356//
357// return open state of the root file.
358//
359Bool_t MWriteRootFile::IsFileOpen() const
360{
361 return fOut->IsOpen();
362}
363
364// --------------------------------------------------------------------------
365//
366// return name of the root-file
367//
368const char *MWriteRootFile::GetFileName() const
369{
370 return fOut->GetName();
371}
372
Note: See TracBrowser for help on using the repository browser.