source: trunk/MagicSoft/Mars/mhist/MHMatrix.cc@ 1353

Last change on this file since 1353 was 1348, checked in by tbretz, 23 years ago
*** empty log message ***
File size: 9.3 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 2002 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2002
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MHMatrix
28//
29// This is a histogram container which holds a matrix with one column per
30// data variable. The data variable can be a complex rule (MDataChain).
31// Each event for wich Fill is called (by MFillH) is added as a new
32// row to the matrix.
33//
34// For example:
35// MHMatrix m;
36// m.AddColumn("MHillas.fSize");
37// m.AddColumn("MMcEvt.fImpact/100");
38// m.AddColumn("HillasSource.fDist*MGeomCam.fConvMm2Deg");
39// MFillH fillm(&m);
40// taskliost.AddToList(&fillm);
41// [...]
42// m.Print();
43//
44/////////////////////////////////////////////////////////////////////////////
45#include "MHMatrix.h"
46
47#include <math.h> // fabs on Alpha
48
49#include <TList.h>
50#include <TArrayD.h>
51#include <TArrayI.h>
52
53#include "MLog.h"
54#include "MLogManip.h"
55
56#include "MParList.h"
57
58#include "MDataChain.h"
59
60ClassImp(MHMatrix);
61
62// --------------------------------------------------------------------------
63//
64// Default Constructor
65//
66MHMatrix::MHMatrix(const char *name, const char *title)
67 : fNumRow(0)
68{
69 fName = name ? name : "MHMatrix";
70 fTitle = title ? title : "Multidimensional Matrix";
71
72 fData = new TList;
73 fData->SetOwner();
74
75 fRules = new TList;
76 fRules->SetOwner();
77}
78
79// --------------------------------------------------------------------------
80//
81// Destructor
82//
83MHMatrix::~MHMatrix()
84{
85 delete fData;
86 delete fRules;
87}
88
89// --------------------------------------------------------------------------
90//
91// Add a new column to the matrix. This can only be done before the first
92// event (row) was filled into the matrix. For the syntax of the rule
93// see MDataChain.
94//
95void MHMatrix::AddColumn(const char *rule)
96{
97 if (fM.IsValid())
98 {
99 *fLog << warn << "Warning - matrix is already in use. Can't add a new column... skipped." << endl;
100 return;
101 }
102
103 MDataChain &chain = *new MDataChain(rule);
104 if (!chain.IsValid())
105 {
106 *fLog << err << "Error - Rule cannot be translated... ignored." << endl;
107 delete &chain;
108 return;
109 }
110 fData->Add(&chain);
111
112 TNamed *name = new TNamed(rule, rule); // Fimxe, in 3.02/07 the title can't be "", why?
113 fRules->Add(name);
114}
115
116void MHMatrix::AddColumns(const MHMatrix *matrix)
117{
118 TIter Next(matrix->fRules);
119 TObject *rule=NULL;
120 while ((rule=Next()))
121 AddColumn(rule->GetName());
122}
123
124// --------------------------------------------------------------------------
125//
126// Checks whether at least one column is available and PreProcesses all
127// data chains.
128//
129Bool_t MHMatrix::SetupFill(const MParList *plist)
130{
131 if (fData->GetSize()==0)
132 {
133 *fLog << err << "Error - No Column specified... aborting." << endl;
134 return kFALSE;
135 }
136
137 TIter Next(fData);
138 MData *data = NULL;
139 while ((data=(MData*)Next()))
140 if (!data->PreProcess(plist))
141 return kFALSE;
142
143 return kTRUE;
144}
145
146// --------------------------------------------------------------------------
147//
148// If the matrix has not enough rows double the number of available rows.
149//
150void MHMatrix::AddRow()
151{
152 fNumRow++;
153
154 if (fM.GetNrows() > fNumRow)
155 return;
156
157 if (!fM.IsValid())
158 {
159 fM.ResizeTo(1, fData->GetSize());
160 return;
161 }
162
163 TMatrix m(fM);
164
165 fM.ResizeTo(fM.GetNrows()*2, fData->GetSize());
166
167 for (int x=0; x<m.GetNcols(); x++)
168 for (int y=0; y<m.GetNrows(); y++)
169 fM(y, x) = m(y, x);
170}
171
172// --------------------------------------------------------------------------
173//
174// Add the values correspoding to the columns to the new row
175//
176Bool_t MHMatrix::Fill(const MParContainer *par)
177{
178 AddRow();
179
180 int col=0;
181 TIter Next(fData);
182 MData *data = NULL;
183 while ((data=(MData*)Next()))
184 fM(fNumRow-1, col++) = data->GetValue();
185
186 return kTRUE;
187}
188
189// --------------------------------------------------------------------------
190//
191// Resize the matrix to a number of rows which corresponds to the number of
192// rows which have really been filled with values.
193//
194Bool_t MHMatrix::Finalize()
195{
196 TMatrix m(fM);
197
198 fM.ResizeTo(fNumRow, fData->GetSize());
199
200 for (int x=0; x<fM.GetNcols(); x++)
201 for (int y=0; y<fM.GetNrows(); y++)
202 fM(y, x) = m(y, x);
203
204 return kTRUE;
205}
206/*
207// --------------------------------------------------------------------------
208//
209// Draw clone of histogram. So that the object can be deleted
210// and the histogram is still visible in the canvas.
211// The cloned object are deleted together with the canvas if the canvas is
212// destroyed. If you want to handle destroying the canvas you can get a
213// pointer to it from this function
214//
215TObject *MHMatrix::DrawClone(Option_t *opt) const
216{
217 TCanvas &c = *MH::MakeDefCanvas(fHist);
218
219 //
220 // This is necessary to get the expected bahviour of DrawClone
221 //
222 gROOT->SetSelectedPad(NULL);
223
224 fHist->DrawCopy(opt);
225
226 TString str(opt);
227 if (str.Contains("PROFX", TString::kIgnoreCase) && fDimension==2)
228 {
229 TProfile *p = ((TH2*)fHist)->ProfileX();
230 p->Draw("same");
231 p->SetBit(kCanDelete);
232 }
233 if (str.Contains("PROFY", TString::kIgnoreCase) && fDimension==2)
234 {
235 TProfile *p = ((TH2*)fHist)->ProfileY();
236 p->Draw("same");
237 p->SetBit(kCanDelete);
238 }
239
240 c.Modified();
241 c.Update();
242
243 return &c;
244}
245
246// --------------------------------------------------------------------------
247//
248// Creates a new canvas and draws the histogram into it.
249// Be careful: The histogram belongs to this object and won't get deleted
250// together with the canvas.
251//
252void MHMatrix::Draw(Option_t *opt)
253{
254 if (!gPad)
255 MH::MakeDefCanvas(fHist);
256
257 fHist->Draw(opt);
258
259 TString str(opt);
260 if (str.Contains("PROFX", TString::kIgnoreCase) && fDimension==2)
261 {
262 TProfile *p = ((TH2*)fHist)->ProfileX();
263 p->Draw("same");
264 p->SetBit(kCanDelete);
265 }
266 if (str.Contains("PROFY", TString::kIgnoreCase) && fDimension==2)
267 {
268 TProfile *p = ((TH2*)fHist)->ProfileY();
269 p->Draw("same");
270 p->SetBit(kCanDelete);
271 }
272
273 gPad->Modified();
274 gPad->Update();
275}
276*/
277
278// --------------------------------------------------------------------------
279//
280// Prints the meaning of the columns and the contents of the matrix.
281// Becareful, this can take a long time for matrices with many rows.
282//
283void MHMatrix::Print(Option_t *) const
284{
285 int n=0;
286
287 TIter Next(fData->GetSize() ? fData : fRules);
288 MData *data = NULL;
289 while ((data=(MData*)Next()))
290 {
291 *fLog << all << " Column " << setw(3) << n++ << ": " << flush;
292 data->Print();
293 *fLog << endl;
294 }
295
296 fM.Print();
297}
298
299const TMatrix *MHMatrix::InvertPosDef()
300{
301 TMatrix m(fM);
302
303 const Int_t rows = m.GetNrows();
304 const Int_t cols = m.GetNcols();
305
306 for (int i=0; i<cols; i++)
307 {
308 Double_t avg = 0;
309 for (int j=0; j<rows; j++)
310 avg += fM(j, i);
311
312 avg /= rows;
313
314 for (int j=0; j<rows; j++)
315 m(j, i) -= avg;
316 }
317
318 TMatrix *m2 = new TMatrix(m, TMatrix::kTransposeMult, m);
319
320 Double_t det;
321 m2->Invert(&det);
322 if (det==0)
323 {
324 *fLog << err << "ERROR - MHMatrix::InvertPosDef failed (Matrix is sigular)." << endl;
325 delete m2;
326 return NULL;
327 }
328
329 // m2->Print();
330
331 return m2;
332}
333
334Double_t MHMatrix::CalcDist(const TMatrix &m, const TVector &evt, Int_t num) const
335{
336 const Int_t rows = fM.GetNrows();
337 const Int_t cols = fM.GetNcols();
338
339 TArrayD dists(rows);
340
341 //
342 // Calculate: v^T * M * v
343 //
344 for (int i=0; i<rows; i++)
345 {
346 TVector col(cols);
347 col = TMatrixRow(fM, i);
348
349 TVector d = evt;
350 d -= col;
351
352 TVector d2 = d;
353 d2 *= m;
354
355 dists[i] = fabs(d2*d);
356 }
357
358 TArrayI idx(rows);
359 TMath::Sort(dists.GetSize(), dists.GetArray(), idx.GetArray(), kFALSE);
360
361 const Int_t n = num<rows ? num : rows;
362
363 Double_t res = 0;
364 for (int i=0; i<n; i++)
365 res += dists[idx[i]];
366
367 return res/n;
368}
369
370Double_t MHMatrix::CalcDist(const TVector &evt, Int_t num)
371{
372 if (!fM2.IsValid())
373 {
374 const TMatrix &m = *InvertPosDef();
375 fM2.ResizeTo(m);
376 fM2 = m;
377 delete &m;
378 }
379
380 return CalcDist(fM2, evt, num);
381}
382
383void MHMatrix::Reassign()
384{
385 TMatrix m = fM;
386 fM.ResizeTo(1,1);
387 fM.ResizeTo(m);
388 fM = m;
389
390 TIter Next(fRules);
391 TObject *obj = NULL;
392 while ((obj=Next()))
393 fData->Add(new MDataChain(obj->GetName()));
394}
Note: See TracBrowser for help on using the repository browser.