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

Last change on this file since 1788 was 1772, checked in by wittek, 22 years ago
*** empty log message ***
File size: 26.0 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! Rudy Boeck 2003 <mailto:
20! Wolfgang Wittek2003 <mailto:wittek@mppmu.mpg.de>
21!
22! Copyright: MAGIC Software Development, 2000-2003
23!
24!
25\* ======================================================================== */
26
27/////////////////////////////////////////////////////////////////////////////
28//
29// MHMatrix
30//
31// This is a histogram container which holds a matrix with one column per
32// data variable. The data variable can be a complex rule (MDataChain).
33// Each event for wich Fill is called (by MFillH) is added as a new
34// row to the matrix.
35//
36// For example:
37// MHMatrix m;
38// m.AddColumn("MHillas.fSize");
39// m.AddColumn("MMcEvt.fImpact/100");
40// m.AddColumn("HillasSource.fDist*MGeomCam.fConvMm2Deg");
41// MFillH fillm(&m);
42// taskliost.AddToList(&fillm);
43// [...]
44// m.Print();
45//
46/////////////////////////////////////////////////////////////////////////////
47#include "MHMatrix.h"
48
49#include <fstream.h>
50
51#include <TList.h>
52#include <TArrayF.h>
53#include <TArrayD.h>
54#include <TArrayI.h>
55
56#include <TH1.h>
57#include <TCanvas.h>
58#include <TRandom3.h>
59
60#include "MLog.h"
61#include "MLogManip.h"
62
63#include "MFillH.h"
64#include "MEvtLoop.h"
65#include "MParList.h"
66#include "MTaskList.h"
67
68#include "MData.h"
69#include "MDataArray.h"
70
71ClassImp(MHMatrix);
72
73const TString MHMatrix::gsDefName = "MHMatrix";
74const TString MHMatrix::gsDefTitle = "Multidimensional Matrix";
75
76// --------------------------------------------------------------------------
77//
78// Default Constructor
79//
80MHMatrix::MHMatrix(const char *name, const char *title)
81 : fNumRow(0), fData(NULL)
82{
83 fName = name ? name : gsDefName.Data();
84 fTitle = title ? title : gsDefTitle.Data();
85}
86
87// --------------------------------------------------------------------------
88//
89// Constructor. Initializes the columns of the matrix with the entries
90// from a MDataArray
91//
92MHMatrix::MHMatrix(MDataArray *mat, const char *name, const char *title)
93 : fNumRow(0), fData(mat)
94{
95 fName = name ? name : gsDefName.Data();
96 fTitle = title ? title : gsDefTitle.Data();
97}
98
99// --------------------------------------------------------------------------
100//
101// Destructor. Does not deleted a user given MDataArray, except IsOwner
102// was called.
103//
104MHMatrix::~MHMatrix()
105{
106 if (TestBit(kIsOwner) && fData)
107 delete fData;
108}
109
110// --------------------------------------------------------------------------
111//
112// Add a new column to the matrix. This can only be done before the first
113// event (row) was filled into the matrix. For the syntax of the rule
114// see MDataChain.
115// Returns the index of the new column, -1 in case of failure.
116// (0, 1, 2, ... for the 1st, 2nd, 3rd, ...)
117//
118Int_t MHMatrix::AddColumn(const char *rule)
119{
120 if (fM.IsValid())
121 {
122 *fLog << warn << "Warning - matrix is already in use. Can't add a new column... skipped." << endl;
123 return -1;
124 }
125
126 if (TestBit(kIsLocked))
127 {
128 *fLog << warn << "Warning - matrix is locked. Can't add new column... skipped." << endl;
129 return -1;
130 }
131
132 if (!fData)
133 {
134 fData = new MDataArray;
135 SetBit(kIsOwner);
136 }
137
138 fData->AddEntry(rule);
139 return fData->GetNumEntries()-1;
140}
141
142// --------------------------------------------------------------------------
143//
144void MHMatrix::AddColumns(MDataArray *matrix)
145{
146 if (fM.IsValid())
147 {
148 *fLog << warn << "Warning - matrix is already in use. Can't add new columns... skipped." << endl;
149 return;
150 }
151
152 if (TestBit(kIsLocked))
153 {
154 *fLog << warn << "Warning - matrix is locked. Can't add new columns... skipped." << endl;
155 return;
156 }
157
158 if (fData)
159 *fLog << warn << "Warning - columns already added... replacing." << endl;
160
161 if (fData && TestBit(kIsOwner))
162 {
163 delete fData;
164 ResetBit(kIsOwner);
165 }
166
167 fData = matrix;
168}
169
170// --------------------------------------------------------------------------
171//
172// Checks whether at least one column is available and PreProcesses all
173// data chains.
174//
175Bool_t MHMatrix::SetupFill(const MParList *plist)
176{
177 if (!fData)
178 {
179 *fLog << err << "Error - No Columns initialized... aborting." << endl;
180 return kFALSE;
181 }
182
183 return fData->PreProcess(plist);
184}
185
186// --------------------------------------------------------------------------
187//
188// If the matrix has not enough rows double the number of available rows.
189//
190void MHMatrix::AddRow()
191{
192 fNumRow++;
193
194 if (fM.GetNrows() > fNumRow)
195 return;
196
197 if (!fM.IsValid())
198 {
199 fM.ResizeTo(1, fData->GetNumEntries());
200 return;
201 }
202
203 TMatrix m(fM);
204
205 fM.ResizeTo(fM.GetNrows()*2, fData->GetNumEntries());
206
207 for (int x=0; x<m.GetNcols(); x++)
208 for (int y=0; y<m.GetNrows(); y++)
209 fM(y, x) = m(y, x);
210}
211
212// --------------------------------------------------------------------------
213//
214// Add the values correspoding to the columns to the new row
215//
216Bool_t MHMatrix::Fill(const MParContainer *par)
217{
218 AddRow();
219
220 for (int col=0; col<fData->GetNumEntries(); col++)
221 fM(fNumRow-1, col) = (*fData)(col);
222
223 return kTRUE;
224}
225
226// --------------------------------------------------------------------------
227//
228// Resize the matrix to a number of rows which corresponds to the number of
229// rows which have really been filled with values.
230//
231Bool_t MHMatrix::Finalize()
232{
233 //
234 // It's not a fatal error so we don't need to stop PostProcessing...
235 //
236 if (fData->GetNumEntries()==0 || fNumRow<1)
237 return kTRUE;
238
239 TMatrix m(fM);
240
241 fM.ResizeTo(fNumRow, fData->GetNumEntries());
242
243 for (int x=0; x<fM.GetNcols(); x++)
244 for (int y=0; y<fM.GetNrows(); y++)
245 fM(y, x) = m(y, x);
246
247 return kTRUE;
248}
249/*
250// --------------------------------------------------------------------------
251//
252// Draw clone of histogram. So that the object can be deleted
253// and the histogram is still visible in the canvas.
254// The cloned object are deleted together with the canvas if the canvas is
255// destroyed. If you want to handle destroying the canvas you can get a
256// pointer to it from this function
257//
258TObject *MHMatrix::DrawClone(Option_t *opt) const
259{
260 TCanvas &c = *MH::MakeDefCanvas(fHist);
261
262 //
263 // This is necessary to get the expected bahviour of DrawClone
264 //
265 gROOT->SetSelectedPad(NULL);
266
267 fHist->DrawCopy(opt);
268
269 TString str(opt);
270 if (str.Contains("PROFX", TString::kIgnoreCase) && fDimension==2)
271 {
272 TProfile *p = ((TH2*)fHist)->ProfileX();
273 p->Draw("same");
274 p->SetBit(kCanDelete);
275 }
276 if (str.Contains("PROFY", TString::kIgnoreCase) && fDimension==2)
277 {
278 TProfile *p = ((TH2*)fHist)->ProfileY();
279 p->Draw("same");
280 p->SetBit(kCanDelete);
281 }
282
283 c.Modified();
284 c.Update();
285
286 return &c;
287}
288
289// --------------------------------------------------------------------------
290//
291// Creates a new canvas and draws the histogram into it.
292// Be careful: The histogram belongs to this object and won't get deleted
293// together with the canvas.
294//
295void MHMatrix::Draw(Option_t *opt)
296{
297 if (!gPad)
298 MH::MakeDefCanvas(fHist);
299
300 fHist->Draw(opt);
301
302 TString str(opt);
303 if (str.Contains("PROFX", TString::kIgnoreCase) && fDimension==2)
304 {
305 TProfile *p = ((TH2*)fHist)->ProfileX();
306 p->Draw("same");
307 p->SetBit(kCanDelete);
308 }
309 if (str.Contains("PROFY", TString::kIgnoreCase) && fDimension==2)
310 {
311 TProfile *p = ((TH2*)fHist)->ProfileY();
312 p->Draw("same");
313 p->SetBit(kCanDelete);
314 }
315
316 gPad->Modified();
317 gPad->Update();
318}
319*/
320
321// --------------------------------------------------------------------------
322//
323// Prints the meaning of the columns and the contents of the matrix.
324// Becareful, this can take a long time for matrices with many rows.
325// Use the option 'size' to print the size of the matrix.
326// Use the option 'cols' to print the culumns
327// Use the option 'data' to print the contents
328//
329void MHMatrix::Print(Option_t *o) const
330{
331 TString str(o);
332
333 *fLog << all << flush;
334
335 if (str.Contains("size", TString::kIgnoreCase))
336 {
337 *fLog << GetDescriptor() << ": NumColumns=" << fM.GetNcols();
338 *fLog << " NumRows=" << fM.GetNrows() << endl;
339 }
340
341 if (!fData && str.Contains("cols", TString::kIgnoreCase))
342 *fLog << "Sorry, no column information available." << endl;
343
344 if (fData && str.Contains("cols", TString::kIgnoreCase))
345 fData->Print();
346
347 if (str.Contains("data", TString::kIgnoreCase))
348 fM.Print();
349}
350
351// --------------------------------------------------------------------------
352//
353const TMatrix *MHMatrix::InvertPosDef()
354{
355 TMatrix m(fM);
356
357 const Int_t rows = m.GetNrows();
358 const Int_t cols = m.GetNcols();
359
360 for (int x=0; x<cols; x++)
361 {
362 Double_t avg = 0;
363 for (int y=0; y<rows; y++)
364 avg += fM(y, x);
365
366 avg /= rows;
367
368 for (int y=0; y<rows; y++)
369 m(y, x) -= avg;
370 }
371
372 TMatrix *m2 = new TMatrix(m, TMatrix::kTransposeMult, m);
373
374 Double_t det;
375 m2->Invert(&det);
376 if (det==0)
377 {
378 *fLog << err << "ERROR - MHMatrix::InvertPosDef failed (Matrix is singular)." << endl;
379 delete m2;
380 return NULL;
381 }
382
383 // m2->Print();
384
385 return m2;
386}
387
388// --------------------------------------------------------------------------
389//
390// Calculated the distance of vector evt from the reference sample
391// represented by the covariance metrix m.
392// - If n<0 the kernel method is applied and
393// -log(sum(epx(-d/h))/n) is returned.
394// - For n>0 the n nearest neighbors are summed and
395// sqrt(sum(d)/n) is returned.
396// - if n==0 all distances are summed
397//
398Double_t MHMatrix::CalcDist(const TMatrix &m, const TVector &evt, Int_t num) const
399{
400 if (num==0) // may later be used for another method
401 {
402 TVector d = evt;
403 d *= m;
404 return TMath::Sqrt(d*evt);
405 }
406
407 const Int_t rows = fM.GetNrows();
408 const Int_t cols = fM.GetNcols();
409
410 TArrayD dists(rows);
411
412 //
413 // Calculate: v^T * M * v
414 //
415 for (int i=0; i<rows; i++)
416 {
417 TVector col(cols);
418 col = TMatrixRow(fM, i);
419
420 TVector d = evt;
421 d -= col;
422
423 TVector d2 = d;
424 d2 *= m;
425
426 dists[i] = d2*d; // square of distance
427
428 //
429 // This corrects for numerical uncertanties in cases of very
430 // small distances...
431 //
432 if (dists[i]<0)
433 dists[i]=0;
434 }
435
436 TArrayI idx(rows);
437 TMath::Sort(dists.GetSize(), dists.GetArray(), idx.GetArray(), kFALSE);
438
439 Int_t from = 0;
440 Int_t to = TMath::Abs(num)<rows ? TMath::Abs(num) : rows;
441 //
442 // This is a zero-suppression for the case a test- and trainings
443 // sample is identical. This would result in an unwanted leading
444 // zero in the array. To suppress also numerical uncertanties of
445 // zero we cut at 1e-5. Due to Rudy this should be enough. If
446 // you encounter problems we can also use (eg) 1e-25
447 //
448 if (dists[idx[0]]<1e-5)
449 {
450 from++;
451 to ++;
452 if (to>rows)
453 to = rows;
454 }
455
456 if (num<0)
457 {
458 //
459 // Kernel function sum (window size h set according to literature)
460 //
461 const Double_t h = TMath::Power(rows, -1./(cols+4));
462 const Double_t hwin = h*h*2;
463
464 Double_t res = 0;
465 for (int i=from; i<to; i++)
466 res += TMath::Exp(-dists[idx[i]]/hwin);
467
468 return -TMath::Log(res/(to-from));
469 }
470 else
471 {
472 //
473 // Nearest Neighbor sum
474 //
475 Double_t res = 0;
476 for (int i=from; i<to; i++)
477 res += dists[idx[i]];
478
479 return TMath::Sqrt(res/(to-from));
480 }
481}
482
483// --------------------------------------------------------------------------
484//
485// Calls calc dist. In the case of the first call the covariance matrix
486// fM2 is calculated.
487// - If n<0 it is divided by (nrows-1)/h while h is the kernel factor.
488//
489Double_t MHMatrix::CalcDist(const TVector &evt, Int_t num)
490{
491 if (!fM2.IsValid())
492 {
493 const TMatrix *m = InvertPosDef();
494 if (!m)
495 return -1;
496
497 fM2.ResizeTo(*m);
498 fM2 = *m;
499 fM2 *= fM.GetNrows()-1;
500 delete m;
501 }
502
503 return CalcDist(fM2, evt, num);
504}
505
506void MHMatrix::Reassign()
507{
508 TMatrix m = fM;
509 fM.ResizeTo(1,1);
510 fM.ResizeTo(m);
511 fM = m;
512}
513
514// --------------------------------------------------------------------------
515//
516// Implementation of SavePrimitive. Used to write the call to a constructor
517// to a macro. In the original root implementation it is used to write
518// gui elements to a macro-file.
519//
520void MHMatrix::StreamPrimitive(ofstream &out) const
521{
522 Bool_t data = fData && !TestBit(kIsOwner);
523
524 if (data)
525 {
526 fData->SavePrimitive(out);
527 out << endl;
528 }
529
530 out << " MHMatrix " << GetUniqueName();
531
532 if (data || fName!=gsDefName || fTitle!=gsDefTitle)
533 {
534 out << "(";
535 if (data)
536 out << "&" << fData->GetUniqueName();
537 if (fName!=gsDefName || fTitle!=gsDefTitle)
538 {
539 if (data)
540 out << ", ";
541 out << "\"" << fName << "\"";
542 if (fTitle!=gsDefTitle)
543 out << ", \"" << fTitle << "\"";
544 }
545 }
546 out << ");" << endl;
547
548 if (fData && TestBit(kIsOwner))
549 for (int i=0; i<fData->GetNumEntries(); i++)
550 out << " " << GetUniqueName() << ".AddColumn(\"" << (*fData)[i].GetRule() << "\");" << endl;
551}
552
553// --------------------------------------------------------------------------
554//
555const TArrayI MHMatrix::GetIndexOfSortedColumn(Int_t ncol, Bool_t desc) const
556{
557 TMatrixColumn col(fM, ncol);
558
559 const Int_t n = fM.GetNrows();
560
561 TArrayF array(n);
562
563 for (int i=0; i<n; i++)
564 array[i] = col(i);
565
566 TArrayI idx(n);
567 TMath::Sort(n, array.GetArray(), idx.GetArray(), desc);
568
569 return idx;
570}
571
572// --------------------------------------------------------------------------
573//
574void MHMatrix::SortMatrixByColumn(Int_t ncol, Bool_t desc)
575{
576 TArrayI idx = GetIndexOfSortedColumn(ncol, desc);
577
578 const Int_t n = fM.GetNrows();
579
580 TMatrix m(n, fM.GetNcols());
581 for (int i=0; i<n; i++)
582 {
583 TVector vold(n);
584 vold = TMatrixRow(fM, idx[i]);
585
586 TMatrixRow rownew(m, i);
587 rownew = vold;
588 }
589
590 fM = m;
591}
592
593// --------------------------------------------------------------------------
594//
595Bool_t MHMatrix::Fill(MParList *plist, MTask *read)
596{
597 //
598 // Read data into Matrix
599 //
600 const Bool_t is = plist->IsOwner();
601 plist->SetOwner(kFALSE);
602
603 MTaskList tlist;
604 plist->Replace(&tlist);
605
606 MFillH fillh(this);
607
608 tlist.AddToList(read);
609 tlist.AddToList(&fillh);
610
611 MEvtLoop evtloop;
612 evtloop.SetParList(plist);
613
614 if (!evtloop.Eventloop())
615 return kFALSE;
616
617 plist->Remove(&tlist);
618 plist->SetOwner(is);
619
620 return kTRUE;
621}
622
623// --------------------------------------------------------------------------
624//
625// Return a comma seperated list of all data members used in the matrix.
626// This is mainly used in MTask::AddToBranchList
627//
628TString MHMatrix::GetDataMember() const
629{
630 return fData ? fData->GetDataMember() : TString("");
631}
632
633// --------------------------------------------------------------------------
634//
635//
636void MHMatrix::ReduceNumberOfRows(UInt_t numrows, const TString opt)
637{
638 UInt_t rows = fM.GetNrows();
639
640 if (rows==numrows)
641 {
642 *fLog << warn << "Matrix has already the correct number of rows..." << endl;
643 return;
644 }
645
646 Float_t ratio = (Float_t)numrows/fM.GetNrows();
647
648 if (ratio>=1)
649 {
650 *fLog << warn << "Matrix cannot be enlarged..." << endl;
651 return;
652 }
653
654 Double_t sum = 0;
655
656 UInt_t oldrow = 0;
657 UInt_t newrow = 0;
658
659 while (oldrow<rows)
660 {
661 sum += ratio;
662
663 if (newrow<=(unsigned int)sum)
664 {
665 TVector vold(fM.GetNcols());
666 vold = TMatrixRow(fM, oldrow);
667
668 TMatrixRow rownew(fM, newrow);
669 rownew = vold;
670 newrow++;
671 }
672
673 oldrow++;
674 }
675
676/*
677
678 TMatrix m(n, fM.GetNcols());
679 for (int i=0; i<n; i++)
680 {
681 TVector vold(n);
682 vold = TMatrixRow(fM, idx[i]);
683
684 TMatrixRow rownew(m, i);
685 rownew = vold;
686 }
687*/
688}
689
690// ------------------------------------------------------------------------
691//
692// Define the reference matrix
693// refcolumn number of the column containing the variable, for which a
694// target distribution may be given;
695// if refcolumn is negative the target distribution will be set
696// equal to the real distribution; the events in the reference
697// matrix will then be simply a random selection of the events
698// in the original matrix.
699// thsh histogram containing the target distribution of the variable
700// nmaxevts maximum number of events in the reference matrix
701//
702Bool_t MHMatrix::DefRefMatrix(const Int_t refcolumn, const TH1F *thsh,
703 const Int_t nmaxevts)
704{
705 if (!fM.IsValid())
706 {
707 *fLog << "MHMatrix::DefRefMatrix; matrix not initialized" << endl;
708 return kFALSE;
709 }
710
711 const TH1F *fHthsh; // target distribution
712 TH1F *fHthd; // normalization factors
713 TH1F *fHth; // distribution before
714 TH1F *fHthaft; // distribution after renormalization
715
716 Int_t frefcol; // number of the column (count from 0) containing
717 // the variable for which the target distribution is given
718 Int_t fnbins; // histogram parameters for thsh
719 Float_t ffrombin; //
720 Float_t ftobin; //
721 Float_t fdbin; //
722
723 TArrayF fnormfac; // array of normalization factors
724 TMatrix fMnew; // matrix fM having the requested distribution
725 // and the requested number of rows;
726 // this is the matrix to be used in the g/h separation
727
728
729 //===================================================================
730 //---------------------------------------------------------
731 // Calculate normalization factors
732 //
733
734 fHthsh = thsh;
735
736 Int_t fNrows = fM.GetNrows();
737 Int_t fNcols = fM.GetNcols();
738
739 // print characteristics
740 //
741 //Int_t fColLwb = fM.GetColLwb();
742 //Int_t fRowLwb = fM.GetRowLwb();
743 //*fLog << "MHMatrix::CalcNormFactors; Event matrix (input): " << endl;
744 //*fLog << " fNrows, fNcols, fColLwb, fRowLwb = " << fNrows << ", "
745 // << fNcols << ", " << fColLwb << ", " << fRowLwb << endl;
746
747
748 //---------------------------------------------------------
749 //
750 // if refcol < 0 : select reference events randomly
751 // i.e. set the normaliztion factotrs equal to 1.0
752
753 if (refcolumn<0)
754 {
755 frefcol = -refcolumn;
756 }
757 else
758 {
759 frefcol = refcolumn;
760 }
761
762
763 //---------------------------------------------------------
764
765 if (fHthsh == NULL)
766 {
767 *fLog << "MHMatrix::DefRefMatrix; target distribution has to be defined"
768 << endl;
769 return kFALSE;
770 }
771
772 fnbins = fHthsh->GetNbinsX();
773 ffrombin = fHthsh->GetBinLowEdge(1);
774 ftobin = fHthsh->GetBinLowEdge(fnbins+1);
775 fdbin = (ftobin-ffrombin)/fnbins;
776 //*fLog << "CalcNormFactors; Reference column (count from 0) = "
777 // << frefcol << endl;
778 //*fLog << "CalcNormFactors; Histo params : " << fnbins << ", " << ffrombin
779 // <<", "<< ftobin << endl;
780
781
782 //---------------------------------------------------------
783 // ===== set up the real histogram
784 //
785 fHth = new TH1F("th", "data at input", fnbins, ffrombin, ftobin);
786 for (Int_t j=1; j<=fNrows; j++)
787 {
788 fHth->Fill(fM(j-1,frefcol));
789 //*fLog << "j, frefcol, fM(j-1,frefcol) = " << j << ", " << frefcol
790 // << ", " << fM(j-1,frefcol) << endl;
791 }
792
793 // if refcolumn<0 set target distribution equal to the real distribution
794 // in order to obtain normalization factors = 1.0
795 //if (refcolumn<0)
796 //{
797 // for (Int_t j=1; j<=fnbins; j++)
798 // {
799 // float cont = fHth-> GetBinContent(j);
800 // fHthsh->SetBinContent(j, cont);
801 // }
802 //}
803
804 //---------------------------------------------------------
805 // ===== obtain correction factors
806 //
807 fHthd = new TH1F ("thd", "correction factors", fnbins, ffrombin, ftobin);
808
809 Double_t cmax = 0.;
810 Float_t a;
811 Float_t b;
812 Float_t c;
813 for (Int_t j=1; j<=fnbins; j++)
814 {
815 a = fHth->GetBinContent(j);
816
817 // if refcolumn < 0 set the correction factors equal to 1
818 if ( refcolumn>=0.0 )
819 b = fHthsh->GetBinContent(j);
820 else
821 b = a;
822
823 if ( a<0.0 || b<0.0 )
824 {
825 *fLog << "MHMatrix::DefRefMatrix; renormalization of input matrix is not possible" << endl;
826 *fLog << " a, b = " << a << ", " << b << endl;
827 return kFALSE;
828 }
829
830 if (a == 0.0)
831 c = 0.0;
832 else
833 c = b/a;
834
835 fHthd->SetBinContent(j, c);
836 if (cmax < c) cmax = c;
837 //*fLog << j << ", " << a << ", " << b << ", " << c << endl;
838 }
839
840 //*fLog << "MHMatrix::CalcNormFactors; maximum ratio between histogram and target "
841 // << cmax << endl;
842
843 if (cmax <= 0.0)
844 {
845 *fLog << "MHMatrix::CalcNormFactors; maximum ratio is LE zero" << endl;
846 return kFALSE;
847 }
848
849 fnormfac.Set(fnbins);
850 Float_t minbin = 1.0;
851 for (Int_t j=1; j<=fnbins; j++)
852 {
853 float c = (fHthd->GetBinContent(j)) / cmax;
854 fnormfac[j-1] = c;
855 if (minbin > c && c>0) minbin = c;
856 fHthd->SetBinContent(j, c);
857 }
858 //*fLog << "MHMatrix::CalcNormFactors; maximum weight = 1, minimum non-zero weight = "
859 // << minbin <<endl;
860
861
862 //---------------------------------------------------------
863 //===================================================================
864
865
866 // ==== compress matrix fM into Mnew
867 //
868 // get random access
869 TArrayF ranx(fNrows);
870 TRandom3 *fRnd = new TRandom3(0);
871
872 for (Int_t i=0;i<fNrows;i++) ranx[i] = fRnd->Rndm(i);
873
874 TArrayI ind(fNrows);
875 TMath::Sort(fNrows, ranx.GetArray(), ind.GetArray(),kTRUE);
876
877 //*fLog << "MHMatrix::DefRefMatrix; permuting array " <<endl;
878 //for (Int_t i=0; i<10; i++) cout << ind[i] << " ";
879 //*fLog << endl;
880
881 //---------------------------------------------------------
882 // go through matrix and keep events depending on content of
883 // reference column
884 //
885 //*fLog << "MHMatrix::DefRefMatrix; pass at most " << nmaxevts
886 // << " events, in random order " << endl;
887
888
889 //---------------------------------------------------------
890 // define new matrix
891 Int_t evtcount = 0;
892 TMatrix Mnew_tmp (fNrows,fNcols);
893
894 TArrayF cumul_weight(fNrows); // keep track for each bin how many events
895
896 for (Int_t ir=0; ir<fNrows; ir++) cumul_weight[ir]=0;
897
898 //--------------------------------
899 // select events
900 //
901 fHthaft = new TH1F ("thaft","data after selection", fnbins, ffrombin, ftobin);
902 for (Int_t ir=0; ir<fNrows; ir++)
903 {
904 Int_t indref = (Int_t) ((fM(ind[ir],frefcol)-ffrombin)/fdbin);
905 cumul_weight[indref] += fnormfac[indref];
906 if (cumul_weight[indref]>0.5)
907 {
908 cumul_weight[indref] -= 1.;
909 if (evtcount++ < nmaxevts)
910 {
911 fHthaft->Fill(fM(ind[ir],frefcol));
912 for (Int_t ic=0; ic<fNcols; ic++)
913 Mnew_tmp(evtcount-1,ic) = fM(ind[ir],ic);
914 }
915 else break;
916 }
917 }
918 evtcount--;
919 //*fLog << "MHMatrix::DefRefMatrix; passed " << evtcount
920 // << " events" << endl;
921
922 //--------------------------------
923 // reduce size
924
925 TMatrix Mnew(evtcount, fNcols);
926 fM.ResizeTo (evtcount, fNcols);
927 fNumRow = evtcount;
928
929 for (Int_t ir=0;ir<evtcount; ir++)
930 for (Int_t ic=0;ic<fNcols;ic++)
931 {
932 Mnew(ir,ic) = Mnew_tmp(ir,ic);
933 fM(ir,ic) = Mnew_tmp(ir,ic);
934 }
935
936 if (evtcount < nmaxevts)
937 {
938 *fLog << "MHMatrix::DefRefMatrix; Warning : The reference sample contains less events (" << evtcount << ") than required (" << nmaxevts << ")" << endl;
939 }
940
941
942 //---------------------------------------------------------
943 // test: print new matrix (part)
944 *fLog << "MHMatrix::DefRefMatrix; Event matrix (output) :" << endl;
945 *fLog << "MHMatrix::DefRefMatrix; Nrows, Ncols = " << Mnew.GetNrows()
946 << " " << Mnew.GetNcols() << endl;
947 for (Int_t ir=0;ir<10; ir++)
948 {
949 *fLog <<ir <<" ";
950 for (Int_t ic=0;ic<13;ic++) cout<<Mnew(ir,ic)<<" ";
951 *fLog <<endl;
952 }
953
954 // test print new bin contents
955 *fLog << "MHMatrix::DefRefMatrix; new histogram: " << endl;
956 for (Int_t j=1; j<=fnbins; j++)
957 {
958 float a = fHthaft->GetBinContent(j);
959 if (a>0) *fLog << j << " "<< a << " ";
960 }
961 *fLog <<endl;
962
963 //---------------------------------------------------------
964 // ==== plot four histograms
965 TCanvas *th1 = new TCanvas (fName, fName, 1);
966 th1->Divide(2,2);
967
968 th1->cd(1);
969 ((TH1F*)fHthsh)->Draw(); // target
970
971 th1->cd(2);
972 ((TH1F*)fHth)->Draw(); // real histogram before
973
974 th1->cd(3);
975 ((TH1F*)fHthd) -> Draw(); // correction factors
976
977 th1->cd(4);
978 ((TH1F*)fHthaft) -> Draw(); // histogram after
979
980 //---------------------------------------------------------
981 // --- write onto output file
982 //
983 //TFile *outfile = new TFile(fileNameout, "RECREATE", "");
984 //Mnew.Write(fileNameout);
985 //outfile->Close();
986
987 return kTRUE;
988}
989
990// --------------------------------------------------------------------------
991//
992// overload TOject member function read
993// in order to reset the name of the object read
994//
995Int_t MHMatrix::Read(const char *name)
996{
997 Int_t ret = TObject::Read(name);
998 SetName(name);
999
1000 return ret;
1001}
1002
1003// --------------------------------------------------------------------------
1004
1005
1006
1007
1008
1009
1010
Note: See TracBrowser for help on using the repository browser.