source: trunk/Mars/mfileio/MReadReports.cc@ 16823

Last change on this file since 16823 was 10130, checked in by tbretz, 14 years ago
Fixed a bug in MreadReports which caused the reading to get corrupted as soon as the first event tree was fully read.
File size: 13.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, 11/2003 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2006
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MReadReports
28//
29// Read from a file events from different trees ordered in time, eg:
30//
31// Having a file with:
32//
33// Tree1 Tree2 Tree3
34// ------------ ------------ -----------
35// (0) MTime[0]
36// (0) MTime[1]
37// (1) MTime[2]
38// (2) MTime[3]
39// (0) MTime[1]
40// (3) MTime[4]
41//
42// MReadReports will read the events in the tree in the following order:
43// <0> (0) from Tree1
44// <1> (0) from Tree2
45// <2> (1) from Tree1
46// <3> (2) from Tree1
47// <4> (0) from Tree3
48// <5> (3) from Tree1
49// ...
50//
51// To tell MReadReports which Trees to read use: MReadReports::AddTree()
52// To schedule a file for reading use MReadReports::AddFile()
53//
54// All calls to AddTree _must_ be before the calls to AddFile!
55//
56// After reading from a tree with the name 'TreeName' the stream id of
57// the main tasklist ('MTaskList' found in MParList in PreProcess) is
58// set to this name. This means that only tasks having this stream id
59// are executed.
60//
61/////////////////////////////////////////////////////////////////////////////
62#include "MReadReports.h"
63
64#include <TChain.h>
65#include <TChainElement.h>
66
67#include "MLog.h"
68#include "MLogManip.h"
69
70#include "MTime.h"
71#include "MParList.h"
72#include "MTaskList.h"
73
74#include "MReadMarsFile.h"
75
76ClassImp(MReadReports);
77
78using namespace std;
79
80// --------------------------------------------------------------------------
81//
82// Default constructor. Set fName and fTitle. Instatiate fTrees and fChains.
83// Call SetOwner for fTrees and fChains
84//
85MReadReports::MReadReports() : fEnableAutoScheme(kFALSE)
86{
87 fName = "MRead";
88 fTitle = "Reads events and reports from a root file ordered in time";
89
90 fTrees = new MTaskList("MReadReports");
91 fChains = new TList;
92
93 fTrees->SetOwner();
94 fChains->SetOwner();
95}
96
97// --------------------------------------------------------------------------
98//
99// Destructor, delete everything which was allocated by this task...
100//
101MReadReports::~MReadReports()
102{
103 TObject *o=0;
104 TIter NextC(fChains);
105 while ((o=NextC()))
106 delete *GetTime((TChain*)o);
107
108 delete fTrees;
109 delete fChains;
110}
111
112// --------------------------------------------------------------------------
113//
114// Return the number of entries in all trees.
115//
116UInt_t MReadReports::GetEntries()
117{
118 UInt_t n=0;
119
120 TIter NextT(fTrees->GetList());
121 MReadTree *tree=0;
122 while ((tree=(MReadTree*)NextT()))
123 n += tree->GetEntries();
124
125 return n;
126}
127
128// --------------------------------------------------------------------------
129//
130// In case of a Master Tree GetFileName() of the MReadMarsFile is returned.
131// If no master is available "<MReadReports>" is returned.
132//
133TString MReadReports::GetFullFileName() const
134{
135 if (!TestBit(kHasMaster))
136 return "<MReadReports>";
137
138 TIter NextT(fTrees->GetList());
139 MReadTree *tree=0;
140 while ((tree=(MReadTree*)NextT()))
141 if (tree->InheritsFrom("MReadMarsFile"))
142 return tree->GetFileName();
143
144 return "<n/a>";
145
146}
147
148void MReadReports::AddToBranchList(const char *name)
149{
150 MTask::AddToBranchList(name);
151}
152
153// --------------------------------------------------------------------------
154//
155// Schedule the contents of this tree for reading. As a default the time
156// branch which is used for the ordering is assumed to by "MTime"+tree.
157// If this is not the case you can overwrite the default specifying the
158// name in time.
159//
160// All calls to AddTree _must_ be BEFORE the calls to AddFile!
161//
162// To be done: A flag(?) telling whether the headers can be skipped.
163//
164void MReadReports::AddTree(const char *tree, const char *time, Type_t master)
165{
166 /*
167 if (fTrees->GetNumTasks()>0)
168 {
169 *fLog << warn << "WARNING - AddTree must be called before AddFile... ignored." << endl;
170 *fLog << dbg << fTrees->GetNumTasks() << endl;
171 return kFALSE;
172 }
173 */
174
175 if (master==kMaster && TestBit(kHasMaster))
176 {
177 *fLog << warn << GetDescriptor() << " already has a master tree... ignored." << endl;
178 master = kStandard;
179 }
180
181 MReadTree *t = master==kMaster ? new MReadMarsFile(tree) : new MReadTree(tree);
182 t->SetName(tree);
183 t->SetTitle(time?time:"");
184 if (master==kMaster)
185 SetBit(kHasMaster);
186 if (master==kRequired)
187 t->SetBit(kIsRequired);
188
189 if (!fEnableAutoScheme)
190 t->DisableAutoScheme();
191
192 //FIXME!
193 //t->DisableAutoScheme();
194
195 fTrees->AddToList(t);
196 // return kTRUE;
197}
198
199MReadTree *MReadReports::GetReader(const char *tree) const
200{
201 return (MReadTree*)fTrees->FindObject(tree);
202}
203
204// --------------------------------------------------------------------------
205//
206// Schedule a file or several files (using widcards) for reading.
207//
208// All calls to AddTree _must_ be BEFORE the calls to AddFile!
209//
210Int_t MReadReports::AddFile(const char *fname, Int_t entries)
211{
212 Int_t n=0;
213
214 TIter NextT(fTrees->GetList());
215 MReadTree *tree=0;
216 while ((tree=(MReadTree*)NextT()))
217 n += tree->AddFile(fname, entries);
218
219 return n;
220}
221
222// --------------------------------------------------------------------------
223//
224// Count the number of required trees and store the number if fNumRequired.
225// Reset the kIsProcessed bit.
226//
227void MReadReports::ForceRequired()
228{
229 fNumRequired = 0;
230
231 TIter Next(fTrees->GetList());
232 TObject *o=0;
233 while ((o=Next()))
234 if (o->TestBit(kIsRequired))
235 {
236 o->ResetBit(kIsProcessed);
237 fNumRequired++;
238 }
239
240 *fLog << dbg << "Number of required trees: " << fNumRequired << endl;
241}
242
243// --------------------------------------------------------------------------
244//
245// Find MTaskList and store a pointer to it in fList.
246// Delete all entries in fChains.
247// Create all chains to read the time in the trees in advance.
248// Enable only the time-branch in this chains.
249// PreProcess fTrees (a MTaskList storing MReadTree tasks for reading)
250//
251Int_t MReadReports::PreProcess(MParList *plist)
252{
253 fChains->Delete();
254
255 Int_t i=0;
256
257 TIter NextT(fTrees->GetList());
258 MReadTree *tree=0;
259 while ((tree=(MReadTree*)NextT()))
260 {
261 if (!((TChain*)tree->fChain)->GetFile())
262 {
263 *fLog << warn << "No files or no tree '" << tree->GetName() << "'... skipped." << endl;
264 fTrees->RemoveFromList(tree);
265 continue;
266 }
267
268 if (tree->GetEntries()==0)
269 {
270 *fLog << warn << "No events in tree '" << tree->GetName() << "'... skipped." << endl;
271 fTrees->RemoveFromList(tree);
272 continue;
273 }
274
275 TString tn(tree->GetTitle());
276 if (tn.IsNull())
277 {
278 tn += "MTime";
279 tn += tree->GetName();
280 tn += ".";
281 }
282
283 TString tn2(tn);
284 tn2 += "*";
285
286 // FIXME: Should be tree->AddToBranchList such that
287 // each run a new 'table' is created, but
288 // MRead is searching for MTaskList in the
289 // parameter list.
290 //AddToBranchList((const char*)tn2);
291
292 //
293 // SetBranchStatus wants to have a pointer to a pointer
294 //
295 MTime **tx = new MTime*;
296 *tx = 0;//new MTime;
297
298 TChain *c=new TChain(tree->GetName());
299
300 c->SetBranchStatus("*", 0);
301 c->SetBranchAddress(tn, tx);
302 c->SetBranchStatus(tn2, 1);
303
304 c->Add((TChain*)tree->fChain);
305 c->GetEntry(0);
306
307 fChains->Add(c);
308
309 i++;
310 }
311
312 if (i==0)
313 {
314 *fLog << err << "Files do not contain any valid tree... abort." << endl;
315 return kFALSE;
316 }
317
318 fPosEntry.Set(i);
319 fPosEntry.Reset();
320
321 // Force that with the next call to Process the required events are read
322 ForceRequired();
323 //fFirstReInit=kTRUE;
324
325 // Preprocess all tasks in fTrees
326 return fTrees->CallPreProcess(plist);
327}
328
329// --------------------------------------------------------------------------
330//
331// If this is not the first ReInit after PreProcess force the required
332// trees to be read first (call FirstRequired())
333//
334/*
335Bool_t MReadReports::ReInit(MParList *plist)
336{
337 if (!fFirstReInit)
338 ForceRequired();
339 fFirstReInit=kFALSE;
340 return kTRUE;
341}
342*/
343
344// --------------------------------------------------------------------------
345//
346// Return the number of the tree which is the next one to be read.
347// The condition for this decision is the time-stamp.
348//
349Int_t MReadReports::FindNextTime()
350{
351 TIter NextC(fChains);
352 TChain *c=0;
353
354 Int_t nmin=0;
355 MTime tmin(**GetTime((TChain*)NextC()));
356
357 Int_t i=0;
358
359 while ((c=(TChain*)NextC()))
360 {
361 MTime &t = **GetTime(c);
362 i++;
363
364 if (t >= tmin)
365 continue;
366
367 tmin = t;
368 nmin = i;
369 }
370 return nmin;
371}
372
373// --------------------------------------------------------------------------
374//
375// Return the number of the tree which is the next one to be read.
376// The condition for this decision kIsRequired but not kIsProcessed is set.
377//
378Int_t MReadReports::FindNextRequired()
379{
380 Int_t n = 0;
381
382 TIter Next(fTrees->GetList());
383 TObject *o=0;
384 while ((o=Next()))
385 {
386 if (o->TestBit(kIsRequired) && !o->TestBit(kIsProcessed))
387 {
388 o->SetBit(kIsProcessed);
389 fNumRequired--;
390 *fLog << dbg << "Reading from tree " << n << " " << o->GetName() << endl;
391 return n;
392 }
393 n++;
394 }
395
396 return -1;
397}
398
399// --------------------------------------------------------------------------
400//
401// Return the MTime corresponding to this TChain...
402//
403MTime** MReadReports::GetTime(TChain *c) const
404{
405 TChainElement *e=(TChainElement*)c->GetStatus()->At(1);
406 return (MTime**)e->GetBaddress();
407}
408
409// --------------------------------------------------------------------------
410//
411// Check which is the next tree to read from. Read an event from this tree.
412// Sets the StreamId accordingly.
413//
414Int_t MReadReports::Process()
415{
416 while (fChains->GetSize())
417 {
418 // Find the next tree to read from checking the time-stamps
419 // of the next events which would be read
420 const Int_t nmin=FindNext();
421 if (nmin<0)
422 {
423 *fLog << err << "MReadReports::Process: ERROR - Determination of next tree failed... abort." << endl;
424 return kERROR;
425 }
426
427 // Read the event from this tree
428 MTask *task = static_cast<MTask*>(fTrees->GetList()->At(nmin));
429 const Int_t rc = task->CallProcess();
430
431 // Read the time-stamp of the next event
432 TChain *chain = static_cast<TChain*>(fChains->At(nmin));
433 const Int_t cnt = chain->GetEntry(++fPosEntry[nmin]);
434
435 // In case there is no further time-stamp of an error reading the
436 // event we remove this time-stamp from the list of time-stamps to
437 // be checked for reading the next events, because there is none.
438 if (cnt<=0 || rc==kFALSE)
439 {
440 *fLog << inf << "Removing chain " << chain->GetName() << " from list" << flush;
441
442 // Find index of chain to be removed
443 const Int_t idx = fChains->IndexOf(chain);
444 *fLog << " (" << idx << ")" << flush;
445
446 delete *GetTime(chain); // Delete MTime*
447 *fLog << "." << flush;
448 delete fChains->Remove(chain); // Remove chain from TList
449 *fLog << "." << flush;
450
451 // Change array accordingly
452 if (fPosEntry.GetSize()>1)
453 {
454 for (int i=idx; i<fPosEntry.GetSize()-1; i++)
455 fPosEntry[i] = fPosEntry[i+1];
456 fPosEntry[fPosEntry.GetSize()-1] = 0;
457 }
458
459 // FIXME: Maybe MTaskList should have a member function to
460 // reorder the tasks?
461
462 // Move this task to the end of the list so that nmin still
463 // corresponds to the correct task in the list.
464 const_cast<TList*>(fTrees->GetList())->Remove(task);
465 *fLog << "." << flush;
466 const_cast<TList*>(fTrees->GetList())->AddLast(task);
467 *fLog << "done." << endl;
468 }
469
470 // If something else than kFALSE (means: stop reading from this
471 // tree) has happened we return the return code of the processing
472 if (rc!=kFALSE)
473 return rc;
474 }
475
476 return kFALSE;
477}
478
479// --------------------------------------------------------------------------
480//
481// PostProcess all MReadTree tasks in fTrees.
482//
483Int_t MReadReports::PostProcess()
484{
485 return fTrees->CallPostProcess();
486}
487
488// --------------------------------------------------------------------------
489//
490// PrintStatistics of this task and of the MReadTree tasks in fTress
491//
492void MReadReports::PrintStatistics(const Int_t lvl, Bool_t title, Double_t time) const
493{
494 MRead::PrintStatistics(lvl, title, time);
495 fTrees->PrintStatistics(lvl+1, title, GetCpuTime());
496}
Note: See TracBrowser for help on using the repository browser.