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

Last change on this file since 1809 was 1809, checked in by wittek, 22 years ago
*** empty log message ***
File size: 25.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 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
506// --------------------------------------------------------------------------
507//
508void MHMatrix::Reassign()
509{
510 TMatrix m = fM;
511 fM.ResizeTo(1,1);
512 fM.ResizeTo(m);
513 fM = m;
514}
515
516// --------------------------------------------------------------------------
517//
518// Implementation of SavePrimitive. Used to write the call to a constructor
519// to a macro. In the original root implementation it is used to write
520// gui elements to a macro-file.
521//
522void MHMatrix::StreamPrimitive(ofstream &out) const
523{
524 Bool_t data = fData && !TestBit(kIsOwner);
525
526 if (data)
527 {
528 fData->SavePrimitive(out);
529 out << endl;
530 }
531
532 out << " MHMatrix " << GetUniqueName();
533
534 if (data || fName!=gsDefName || fTitle!=gsDefTitle)
535 {
536 out << "(";
537 if (data)
538 out << "&" << fData->GetUniqueName();
539 if (fName!=gsDefName || fTitle!=gsDefTitle)
540 {
541 if (data)
542 out << ", ";
543 out << "\"" << fName << "\"";
544 if (fTitle!=gsDefTitle)
545 out << ", \"" << fTitle << "\"";
546 }
547 }
548 out << ");" << endl;
549
550 if (fData && TestBit(kIsOwner))
551 for (int i=0; i<fData->GetNumEntries(); i++)
552 out << " " << GetUniqueName() << ".AddColumn(\"" << (*fData)[i].GetRule() << "\");" << endl;
553}
554
555// --------------------------------------------------------------------------
556//
557const TArrayI MHMatrix::GetIndexOfSortedColumn(Int_t ncol, Bool_t desc) const
558{
559 TMatrixColumn col(fM, ncol);
560
561 const Int_t n = fM.GetNrows();
562
563 TArrayF array(n);
564
565 for (int i=0; i<n; i++)
566 array[i] = col(i);
567
568 TArrayI idx(n);
569 TMath::Sort(n, array.GetArray(), idx.GetArray(), desc);
570
571 return idx;
572}
573
574// --------------------------------------------------------------------------
575//
576void MHMatrix::SortMatrixByColumn(Int_t ncol, Bool_t desc)
577{
578 TArrayI idx = GetIndexOfSortedColumn(ncol, desc);
579
580 const Int_t n = fM.GetNrows();
581
582 TMatrix m(n, fM.GetNcols());
583 for (int i=0; i<n; i++)
584 {
585 TVector vold(n);
586 vold = TMatrixRow(fM, idx[i]);
587
588 TMatrixRow rownew(m, i);
589 rownew = vold;
590 }
591
592 fM = m;
593}
594
595// --------------------------------------------------------------------------
596//
597Bool_t MHMatrix::Fill(MParList *plist, MTask *read)
598{
599 //
600 // Read data into Matrix
601 //
602 const Bool_t is = plist->IsOwner();
603 plist->SetOwner(kFALSE);
604
605 MTaskList tlist;
606 plist->Replace(&tlist);
607
608 MFillH fillh(this);
609
610 tlist.AddToList(read);
611 tlist.AddToList(&fillh);
612
613 MEvtLoop evtloop;
614 evtloop.SetParList(plist);
615
616 if (!evtloop.Eventloop())
617 return kFALSE;
618
619 plist->Remove(&tlist);
620 plist->SetOwner(is);
621
622 return kTRUE;
623}
624
625// --------------------------------------------------------------------------
626//
627// Return a comma seperated list of all data members used in the matrix.
628// This is mainly used in MTask::AddToBranchList
629//
630TString MHMatrix::GetDataMember() const
631{
632 return fData ? fData->GetDataMember() : TString("");
633}
634
635// --------------------------------------------------------------------------
636//
637//
638void MHMatrix::ReduceNumberOfRows(UInt_t numrows, const TString opt)
639{
640 UInt_t rows = fM.GetNrows();
641
642 if (rows==numrows)
643 {
644 *fLog << warn << "Matrix has already the correct number of rows..." << endl;
645 return;
646 }
647
648 Float_t ratio = (Float_t)numrows/fM.GetNrows();
649
650 if (ratio>=1)
651 {
652 *fLog << warn << "Matrix cannot be enlarged..." << endl;
653 return;
654 }
655
656 Double_t sum = 0;
657
658 UInt_t oldrow = 0;
659 UInt_t newrow = 0;
660
661 while (oldrow<rows)
662 {
663 sum += ratio;
664
665 if (newrow<=(unsigned int)sum)
666 {
667 TVector vold(fM.GetNcols());
668 vold = TMatrixRow(fM, oldrow);
669
670 TMatrixRow rownew(fM, newrow);
671 rownew = vold;
672 newrow++;
673 }
674
675 oldrow++;
676 }
677
678/*
679
680 TMatrix m(n, fM.GetNcols());
681 for (int i=0; i<n; i++)
682 {
683 TVector vold(n);
684 vold = TMatrixRow(fM, idx[i]);
685
686 TMatrixRow rownew(m, i);
687 rownew = vold;
688 }
689*/
690}
691
692// ------------------------------------------------------------------------
693//
694// Define the reference matrix
695// refcolumn number of the column (starting at 1)containing the variable,
696// for which a target distribution may be given;
697// if refcolumn is negative the target distribution will be set
698// equal to the real distribution; the events in the reference
699// matrix will then be simply a random selection of the events
700// in the original matrix.
701// thsh histogram containing the target distribution of the variable
702// nmaxevts maximum number of events in the reference matrix
703//
704Bool_t MHMatrix::DefRefMatrix(const Int_t refcolumn, const TH1F *thsh,
705 const Int_t nmaxevts)
706{
707 if (!fM.IsValid())
708 {
709 *fLog << "MHMatrix::DefRefMatrix; matrix not initialized" << endl;
710 return kFALSE;
711 }
712
713 const TH1F *fHthsh; // target distribution
714 TH1F *fHthd; // normalization factors
715 TH1F *fHth; // distribution before
716 TH1F *fHthaft; // distribution after renormalization
717
718 Int_t frefcol; // number of the column (count from 0) containing
719 // the variable for which the target distribution is given
720 Int_t fnbins; // histogram parameters for thsh
721 Float_t ffrombin; //
722 Float_t ftobin; //
723 Float_t fdbin; //
724
725 TArrayF fnormfac; // array of normalization factors
726 TMatrix fMnew; // matrix fM having the requested distribution
727 // and the requested number of rows;
728 // this is the matrix to be used in the g/h separation
729
730
731 //===================================================================
732 //---------------------------------------------------------
733 // Calculate normalization factors
734 //
735
736 fHthsh = thsh;
737
738 Int_t fNrows = fM.GetNrows();
739 Int_t fNcols = fM.GetNcols();
740
741 // print characteristics
742 //
743 //Int_t fColLwb = fM.GetColLwb();
744 //Int_t fRowLwb = fM.GetRowLwb();
745 //*fLog << "MHMatrix::CalcNormFactors; Event matrix (input): " << endl;
746 //*fLog << " fNrows, fNcols, fColLwb, fRowLwb = " << fNrows << ", "
747 // << fNcols << ", " << fColLwb << ", " << fRowLwb << endl;
748
749
750 //---------------------------------------------------------
751 //
752 // if refcolumn < 0 : select reference events randomly
753 // i.e. set the normaliztion factotrs equal to 1.0
754 // refcol is the column number starting at 0; it is >= 0
755
756 if (refcolumn<0)
757 {
758 frefcol = -refcolumn - 1;
759 }
760 else
761 {
762 frefcol = refcolumn - 1;
763 }
764
765
766 //---------------------------------------------------------
767
768 if (fHthsh == NULL)
769 {
770 *fLog << "MHMatrix::DefRefMatrix; target distribution has to be defined"
771 << endl;
772 return kFALSE;
773 }
774
775 fnbins = fHthsh->GetNbinsX();
776 ffrombin = fHthsh->GetBinLowEdge(1);
777 ftobin = fHthsh->GetBinLowEdge(fnbins+1);
778 fdbin = (ftobin-ffrombin)/fnbins;
779 //*fLog << "CalcNormFactors; Reference column (count from 0) = "
780 // << frefcol << endl;
781 //*fLog << "CalcNormFactors; Histo params : " << fnbins << ", " << ffrombin
782 // <<", "<< ftobin << endl;
783
784
785 //---------------------------------------------------------
786 // ===== set up the real histogram
787 //
788 fHth = new TH1F("th", "data at input", fnbins, ffrombin, ftobin);
789 for (Int_t j=1; j<=fNrows; j++)
790 {
791 fHth->Fill(fM(j-1,frefcol));
792 //*fLog << "j, frefcol, fM(j-1,frefcol) = " << j << ", " << frefcol
793 // << ", " << fM(j-1,frefcol) << endl;
794 }
795
796 //---------------------------------------------------------
797 // ===== obtain correction factors
798 //
799 fHthd = new TH1F ("thd", "correction factors", fnbins, ffrombin, ftobin);
800
801 Double_t cmax = 0.;
802 Float_t a;
803 Float_t b;
804 Float_t c;
805 for (Int_t j=1; j<=fnbins; j++)
806 {
807 a = fHth->GetBinContent(j);
808
809 // if refcolumn < 0 set the correction factors equal to 1
810 if ( refcolumn>=0 )
811 b = fHthsh->GetBinContent(j);
812 else
813 b = a;
814
815 if ( a<0.0 || b<0.0 )
816 {
817 *fLog << "MHMatrix::DefRefMatrix; renormalization of input matrix is not possible" << endl;
818 *fLog << " a, b = " << a << ", " << b << endl;
819 return kFALSE;
820 }
821
822 if (a == 0.0)
823 c = 0.0;
824 else
825 c = b/a;
826
827 fHthd->SetBinContent(j, c);
828 if (cmax < c) cmax = c;
829 //*fLog << j << ", " << a << ", " << b << ", " << c << endl;
830 }
831
832 //*fLog << "MHMatrix::CalcNormFactors; maximum ratio between histogram and target "
833 // << cmax << endl;
834
835 if (cmax <= 0.0)
836 {
837 *fLog << "MHMatrix::CalcNormFactors; maximum ratio is LE zero" << endl;
838 return kFALSE;
839 }
840
841 fnormfac.Set(fnbins);
842 Float_t minbin = 1.0;
843 for (Int_t j=1; j<=fnbins; j++)
844 {
845 float c = (fHthd->GetBinContent(j)) / cmax;
846 fnormfac[j-1] = c;
847 if (minbin > c && c>0) minbin = c;
848 fHthd->SetBinContent(j, c);
849 }
850 //*fLog << "MHMatrix::CalcNormFactors; maximum weight = 1, minimum non-zero weight = "
851 // << minbin <<endl;
852
853
854 //---------------------------------------------------------
855 //===================================================================
856
857
858 // ==== compress matrix fM into Mnew
859 //
860 // get random access
861 TArrayF ranx(fNrows);
862 TRandom3 *fRnd = new TRandom3(0);
863
864 for (Int_t i=0;i<fNrows;i++) ranx[i] = fRnd->Rndm(i);
865
866 TArrayI ind(fNrows);
867 TMath::Sort(fNrows, ranx.GetArray(), ind.GetArray(),kTRUE);
868
869 //*fLog << "MHMatrix::DefRefMatrix; permuting array " <<endl;
870 //for (Int_t i=0; i<10; i++) cout << ind[i] << " ";
871 //*fLog << endl;
872
873 //---------------------------------------------------------
874 // go through matrix and keep events depending on content of
875 // reference column
876 //
877 //*fLog << "MHMatrix::DefRefMatrix; pass at most " << nmaxevts
878 // << " events, in random order " << endl;
879
880
881 //---------------------------------------------------------
882 // define new matrix
883 Int_t evtcount = 0;
884 TMatrix Mnew_tmp (fNrows,fNcols);
885
886 TArrayF cumul_weight(fNrows); // keep track for each bin how many events
887
888 for (Int_t ir=0; ir<fNrows; ir++) cumul_weight[ir]=0;
889
890 //--------------------------------
891 // select events
892 //
893 fHthaft = new TH1F ("thaft","data after selection", fnbins, ffrombin, ftobin);
894 for (Int_t ir=0; ir<fNrows; ir++)
895 {
896 Int_t indref = (Int_t) ((fM(ind[ir],frefcol)-ffrombin)/fdbin);
897 cumul_weight[indref] += fnormfac[indref];
898 if (cumul_weight[indref]>0.5)
899 {
900 cumul_weight[indref] -= 1.;
901 if (evtcount++ < nmaxevts)
902 {
903 fHthaft->Fill(fM(ind[ir],frefcol));
904 for (Int_t ic=0; ic<fNcols; ic++)
905 Mnew_tmp(evtcount-1,ic) = fM(ind[ir],ic);
906 }
907 else break;
908 }
909 }
910 evtcount--;
911 //*fLog << "MHMatrix::DefRefMatrix; passed " << evtcount
912 // << " events" << endl;
913
914 //--------------------------------
915 // reduce size
916
917 TMatrix Mnew(evtcount, fNcols);
918 fM.ResizeTo (evtcount, fNcols);
919 fNumRow = evtcount;
920
921 for (Int_t ir=0;ir<evtcount; ir++)
922 for (Int_t ic=0;ic<fNcols;ic++)
923 {
924 Mnew(ir,ic) = Mnew_tmp(ir,ic);
925 fM(ir,ic) = Mnew_tmp(ir,ic);
926 }
927
928 if (evtcount < nmaxevts)
929 {
930 *fLog << "MHMatrix::DefRefMatrix; Warning : The reference sample contains less events (" << evtcount << ") than required (" << nmaxevts << ")" << endl;
931 }
932
933
934 //---------------------------------------------------------
935 // test: print new matrix (part)
936 *fLog << "MHMatrix::DefRefMatrix; Event matrix (output) :" << endl;
937 *fLog << "MHMatrix::DefRefMatrix; Nrows, Ncols = " << Mnew.GetNrows()
938 << " " << Mnew.GetNcols() << endl;
939 for (Int_t ir=0;ir<10; ir++)
940 {
941 *fLog <<ir <<" ";
942 for (Int_t ic=0; ic<Mnew.GetNcols(); ic++) cout<<Mnew(ir,ic)<<" ";
943 *fLog <<endl;
944 }
945
946 // test print new bin contents
947 *fLog << "MHMatrix::DefRefMatrix; new histogram: " << endl;
948 for (Int_t j=1; j<=fnbins; j++)
949 {
950 float a = fHthaft->GetBinContent(j);
951 *fLog << j << " "<< a << " ";
952 }
953 *fLog <<endl;
954
955 //---------------------------------------------------------
956 // ==== plot four histograms
957 TCanvas *th1 = new TCanvas (fName, fName, 1);
958 th1->Divide(2,2);
959
960 th1->cd(1);
961 ((TH1F*)fHthsh)->DrawCopy(); // target
962
963 th1->cd(2);
964 ((TH1F*)fHth)->DrawCopy(); // real histogram before
965
966 th1->cd(3);
967 ((TH1F*)fHthd)->DrawCopy(); // correction factors
968
969 th1->cd(4);
970 ((TH1F*)fHthaft)->DrawCopy(); // histogram after
971
972 //---------------------------------------------------------
973
974 return kTRUE;
975}
976
977// --------------------------------------------------------------------------
978//
979// overload TOject member function read
980// in order to reset the name of the object read
981//
982Int_t MHMatrix::Read(const char *name)
983{
984 Int_t ret = TObject::Read(name);
985 SetName(name);
986
987 return ret;
988}
989
990// --------------------------------------------------------------------------
991
992
993
994
995
996
997
Note: See TracBrowser for help on using the repository browser.