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

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