source: trunk/MagicSoft/Mars/mtools/MTFillMatrix.cc@ 7130

Last change on this file since 7130 was 7130, checked in by tbretz, 20 years ago
*** empty log message ***
File size: 9.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, 12/2003 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2003
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MTFillMatrix
28//
29// Use this tool to fill eg trainings and test-matrices, while the matrix
30// to be filled can be a real matrix (MHMatrix) or a file (MWriteRootFile)
31// or both.
32//
33// First create a reference histogram (MH3). For more details see
34// MFEventSelector2 which is used to select events according to the
35// reference histogram.
36//
37// If no reference histogram is available the number of events are
38// randomly choosen from the sample with a probability which fits
39// the total destination number of events.
40//
41// Here is an example of how to choose 1000 events somehow distributed in
42// size from a file.
43// -----------------------------------------------------------------------
44//
45// MH3 ref("MHillas.fSize"); // choose a predefined size distribution
46// // Now setup the distribution
47//
48// MHMatrix matrix1; // create matrix to fill
49// matrix.AddColumn("MHillas.fWidth"); // setup columns of your matrix
50//
51// MReadMarsFile read("myfile.root"); // Setup your 'reader'
52// read.DisableAutoScheme(); // make sure everything is read
53//
54// MTFillMatrix fill(&ref); // setup MTFillMatrix
55// fill.SetNumDestEvents1(1000); // setup number of events to select
56// fill.SetDestMatrix1(&matrix1); // setup destination matrix
57// if (!fill.Process()) // check if everything worked
58// return;
59// fill.WriteMatrix1("myoutput.root"); // write matrix to file
60//
61//
62// To get two matrices instead of one (splitted randomly) you can add
63// the following before calling Process():
64// ------------------------------------------------------------------------
65//
66// MHMatrix matrix2;
67// fill.SetNumDestEvents2(500); // setup number of events to select
68// fill.SetDestMatrix2(&matrix2); // setup destination matrix
69// [...]
70// fill.WriteMatrix2("myoutput2.root");
71//
72//
73// To write both matrices into a single file use:
74// ----------------------------------------------
75//
76// fill.WriteMatrices("myfile.root");
77//
78/////////////////////////////////////////////////////////////////////////////
79#include "MTFillMatrix.h"
80
81#include <TFile.h>
82
83#include "MHMatrix.h"
84
85#include "MLog.h"
86#include "MLogManip.h"
87
88#include "MParList.h"
89#include "MTaskList.h"
90#include "MEvtLoop.h"
91
92#include "MRead.h"
93#include "MFillH.h"
94#include "MContinue.h"
95#include "MFilterList.h"
96#include "MFEventSelector.h"
97#include "MFEventSelector2.h"
98
99ClassImp(MTFillMatrix);
100
101using namespace std;
102
103// --------------------------------------------------------------------------
104//
105// Print Size and contained columns.
106// Check whether the number of generated events is compatible with
107// the number of requested events.
108//
109Bool_t MTFillMatrix::CheckResult(MHMatrix *m, Int_t num) const
110{
111 if (!m || num==0)
112 return kTRUE;
113
114 m->Print("SizeCols");
115
116 const Int_t generated = m->GetM().GetNrows();
117 if (TMath::Abs(generated-num) <= TMath::Sqrt(9.0*num))
118 return kTRUE;
119
120 *fLog << warn << "WARNING - No. of generated events (";
121 *fLog << generated << ") incompatible with requested events (";
122 *fLog << num << ") for " << m->GetDescriptor() << endl;
123
124 return kFALSE;
125}
126
127// --------------------------------------------------------------------------
128//
129// Write the given MHMatrix with its name as default name to a
130// file fname.
131//
132Bool_t MTFillMatrix::WriteMatrix(MHMatrix *m, const TString &fname, Int_t i) const
133{
134 if (!m)
135 {
136 *fLog << "ERROR - Unable to write matrix #" << i << " (=NULL)... ignored." << endl;
137 return kFALSE;
138 }
139 if (fname.IsNull())
140 {
141 *fLog << "ERROR - Unable to write matrix, file name empty." << endl;
142 return kFALSE;
143 }
144
145 TFile file(fname, "RECREATE", m->GetTitle());
146 m->Write();
147 return kTRUE;
148}
149
150// --------------------------------------------------------------------------
151//
152// Constructor. Takes an MH3 as argument. This MH3 is the reference
153// distribution to fill the matrix. More information can be found
154// at MFEventSelector2 which is used to select the events.
155//
156// If no MH3 *ref is given the events are randomly selected from the
157// total sample - this may result in samples which don't have exactly
158// the predefined size, but it is much faster.
159//
160MTFillMatrix::MTFillMatrix(const MH3 *ref)
161: fReference(0), fReader(0), fDestMatrix1(0), fDestMatrix2(0),
162 fNumDestEvents1(0), fNumDestEvents2(0), fWriteFile1(0), fWriteFile2(0)
163{
164 fName = "MFillMatrix";
165 fTitle = "Tool to fill MHMatrix from file";
166
167 if (ref)
168 fReference = (MH3*)ref->Clone();
169}
170
171MTFillMatrix::~MTFillMatrix()
172{
173 if (fReference)
174 delete fReference;
175}
176
177// --------------------------------------------------------------------------
178//
179// Fill the matrix (FIXME: Flow diagram missing)
180//
181Bool_t MTFillMatrix::Process()
182{
183 if (!fReader)
184 {
185 *fLog << err << "ERROR - No task to read data was given... abort." << endl;
186 return kFALSE;
187 }
188
189 *fLog << inf;
190 fLog->Separator(GetDescriptor());
191 *fLog << "Fill " << fDestMatrix1->GetDescriptor() << " with " << fNumDestEvents1 << endl;
192 if (fDestMatrix2)
193 *fLog << "Fill " << fDestMatrix2->GetDescriptor() << " with " << fNumDestEvents2 << endl;
194 *fLog << "Distribution choosen ";
195 if (fReference && fReference->GetHist().GetEntries()>0)
196 *fLog << "from " << fReference->GetDescriptor();
197 else
198 *fLog << "randomly";
199 *fLog << endl;
200
201 //
202 // Create parameter list and task list, add tasklist to parlist
203 //
204 MParList plist;
205 MTaskList tlist;
206 plist.AddToList(&tlist);
207
208 //
209 // A selector to select a given number of events from a sample
210 //
211 // FIXME: Merge MFEventSelector and MFEventSelector2
212 MFilter *selector=0;
213 if (fNumDestEvents1>0 || fNumDestEvents2>0)
214 {
215 if (fReference)
216 {
217 // Case of a reference/nominal distribution
218 // The events must be read before selection
219 MFEventSelector2 *sel = new MFEventSelector2(*fReference);
220 sel->SetNumMax(fNumDestEvents1+fNumDestEvents2);
221 sel->SetInverted();
222
223 selector = sel;
224 }
225 else
226 {
227 // Case of a random distribution
228 // The events can be selected before reading
229 MFEventSelector *sel = new MFEventSelector;
230 sel->SetNumSelectEvts(fNumDestEvents1+fNumDestEvents2);
231 fReader->SetSelector(sel);
232
233 selector = sel;
234 }
235 }
236
237 //
238 // Continue for all events which are not (SetInverted())
239 // selected by the 'selector'
240 //
241 MContinue cont(selector);
242
243 //
244 // Create a filter doing a random split
245 //
246 const Double_t prob = (Double_t)fNumDestEvents1/(fNumDestEvents1+fNumDestEvents2);
247 MFEventSelector split;
248 split.SetSelectionRatio(prob);
249
250 //
251 // Create the logical inverted filter for 'split'
252 //
253 MFilterList invsplit;
254 invsplit.AddToList(&split);
255 invsplit.SetInverted();
256
257 //
258 // The two tasks filling the two matrices
259 //
260 MFillH fill1(fDestMatrix1);
261 MFillH fill2(fDestMatrix2);
262 if (selector)
263 {
264 fill1.SetFilter(&split);
265 fill2.SetFilter(&invsplit);
266 }
267
268 // entries in MTaskList
269 tlist.AddToList(fReader); // Read events
270 if (fReference && selector)
271 tlist.AddToList(&cont); // select a sample of events
272 tlist.AddToList(&invsplit); // process invsplit (which implicitly processes split)
273 if (fDestMatrix1)
274 tlist.AddToList(&fill1); // fill matrix 1
275 if (fDestMatrix2)
276 tlist.AddToList(&fill2); // fill matrix 2
277 if (fWriteFile1)
278 {
279 fWriteFile1->SetFilter(&split);
280 tlist.AddToList(fWriteFile1);
281 }
282 if (fWriteFile2)
283 {
284 fWriteFile2->SetFilter(&invsplit);
285 tlist.AddToList(fWriteFile2);
286 }
287
288 //
289 // Execute the eventloop
290 //
291 MEvtLoop evtloop(fName);
292 evtloop.SetParList(&plist);
293 evtloop.SetDisplay(fDisplay);
294 evtloop.SetLogStream(fLog);
295
296 const Bool_t rc = evtloop.Eventloop();
297
298 if (selector)
299 delete selector;
300
301 if (!rc)
302 {
303 *fLog << err << GetDescriptor() << ": Failed." << endl;
304 return kFALSE;
305 }
306
307 // Check the result of filling...
308 CheckResult(fDestMatrix1, fNumDestEvents1);
309 CheckResult(fDestMatrix2, fNumDestEvents2);
310
311 *fLog << inf << GetDescriptor() << ": Done." << endl;
312 return kTRUE;
313}
314
315// --------------------------------------------------------------------------
316//
317// Write both matrices to a file. Return kFALSE if writing one of them
318// failed or both have the same name.
319//
320Bool_t MTFillMatrix::WriteMatrices(const TString &fname) const
321{
322 if (fDestMatrix1 && fDestMatrix2 &&
323 (TString)fDestMatrix1->GetName()==(TString)fDestMatrix2->GetName())
324 {
325 *fLog << "ERROR - Cannot write matrices (both have the same name)... ignored." << endl;
326 return kFALSE;
327 }
328
329 return WriteMatrix1(fname) && WriteMatrix2(fname);
330}
Note: See TracBrowser for help on using the repository browser.