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

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