source: trunk/MagicSoft/Mars/mmuon/MHSingleMuon.cc@ 8625

Last change on this file since 8625 was 8625, checked in by tbretz, 17 years ago
*** empty log message ***
File size: 17.0 KB
Line 
1/* ======================================================================== *\
2! $Name: not supported by cvs2svn $:$Id: MHSingleMuon.cc,v 1.15 2007-06-29 12:29:47 tbretz Exp $
3! --------------------------------------------------------------------------
4!
5! *
6! * This file is part of MARS, the MAGIC Analysis and Reconstruction
7! * Software. It is distributed to you in the hope that it can be a useful
8! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
9! * It is distributed WITHOUT ANY WARRANTY.
10! *
11! * Permission to use, copy, modify and distribute this software and its
12! * documentation for any purpose is hereby granted without fee,
13! * provided that the above copyright notice appear in all copies and
14! * that both that copyright notice and this permission notice appear
15! * in supporting documentation. It is provided "as is" without express
16! * or implied warranty.
17! *
18!
19!
20! Author(s): Keiichi Mase, 10/2004
21! Author(s): Markus Meyer, 02/2005 <mailto:meyer@astro.uni-wuerzburg.de>
22! Author(s): Thomas Bretz, 04/2005 <mailto:tbretz@astro.uni-wuerzburg.de>
23!
24! Copyright: MAGIC Software Development, 2000-2005
25!
26!
27\* ======================================================================== */
28
29/////////////////////////////////////////////////////////////////////////////
30//
31// MHSingleMuon
32//
33// This class is a histogram class for displaying the radial (fHistWidth)
34// and the azimuthal (fHistPhi) intensity distribution for one muon.
35// You can retrieve the histogram (TH1F) using the function GetHistPhi()
36// or GetHistWidth().
37// From these histograms the fraction of the ring segment (ArcPhi) and the
38// Width of the muon ring (ArcWidth) is calculated.
39//
40// First, the radius and center of the ring has to be calculted by
41// MMuonSearchParCalc
42// After that the histograms has to be filled in the following way:
43//
44// MFillH fillmuon("MHSingleMuon", "", "FillMuon");
45//
46// The allowed region to estimate ArcPhi is a certain margin around the
47// radius. The default value is 0.2 deg (60mm). If the estimated radius
48// of the arc is 1.0 deg, the pixel contents in the radius range from
49// 0.8 deg to 1.2 deg are fill in the histogram.
50//
51// For ArcPhi only bins over a certain threshold are supposed to be part
52// of the ring.
53// For ArcWidth, the same algorithm is used to determine the fit region
54// for a gaussian fit to the radial intensity distribution. The ArcWidth
55// is defined as the sigma value of the gaussian fit.
56//
57// The binning of the histograms can be changed in the following way:
58//
59// MBinning bins1("BinningMuonWidth");
60// MBinning bins2("BinningArcPhi");
61// bins1.SetEdges(28, 0.3, 1.7);
62// bins2.SetEdges(20, -180,180);
63// plist.AddToList(&bins1);
64// plist.AddToList(&bins2);
65//
66// The values for the thresholds and the margin are saved in MMuonSetup.
67// They can be easily changed in star.rc.
68//
69// Please have in mind, that changes in this basic parameters will change
70// your results!!
71//
72// Inputcontainer:
73// - MGeomCam
74// - MMuonSearchPar
75//
76//
77////////////////////////////////////////////////////////////////////////////
78#include "MHSingleMuon.h"
79
80#include <TF1.h>
81#include <TMinuit.h>
82#include <TPad.h>
83#include <TCanvas.h>
84
85#include "MLog.h"
86#include "MLogManip.h"
87
88#include "MBinning.h"
89#include "MParList.h"
90
91#include "MGeomCam.h"
92#include "MGeomPix.h"
93
94#include "MSignalCam.h"
95#include "MSignalPix.h"
96
97#include "MMuonSetup.h"
98#include "MMuonCalibPar.h"
99#include "MMuonSearchPar.h"
100
101ClassImp(MHSingleMuon);
102
103using namespace std;
104
105// --------------------------------------------------------------------------
106//
107// Setup histograms
108//
109MHSingleMuon::MHSingleMuon(const char *name, const char *title) :
110 fSignalCam(0), fMuonSearchPar(0), fGeomCam(0), fMargin(0)
111{
112 fName = name ? name : "MHSingleMuon";
113 fTitle = title ? title : "Histograms of muon parameters";
114
115 fHistPhi.SetName("HistPhi");
116 fHistPhi.SetTitle("HistPhi");
117 fHistPhi.SetXTitle("\\phi [\\circ]");
118 fHistPhi.SetYTitle("sum of ADC");
119 fHistPhi.SetDirectory(NULL);
120 fHistPhi.SetFillStyle(4000);
121 fHistPhi.UseCurrentStyle();
122
123 fHistWidth.SetName("HistWidth");
124 fHistWidth.SetTitle("HistWidth");
125 fHistWidth.SetXTitle("distance from the ring center [\\circ]");
126 fHistWidth.SetYTitle("sum of ADC");
127 fHistWidth.SetDirectory(NULL);
128 fHistWidth.SetFillStyle(4000);
129 fHistWidth.UseCurrentStyle();
130
131 fHistTime.SetName("HistTime");
132 fHistTime.SetTitle("HistTime");
133 fHistTime.SetXTitle("timing difference");
134 fHistTime.SetYTitle("Counts");
135 fHistTime.SetDirectory(NULL);
136 fHistTime.SetFillStyle(4000);
137 fHistTime.UseCurrentStyle();
138
139 MBinning bins;
140 bins.SetEdges(20, -180, 180);
141 bins.Apply(fHistPhi);
142
143 bins.SetEdges(28, 0.3, 1.7);
144 bins.Apply(fHistWidth);
145
146 bins.SetEdges(101, -33, 33); // +/- 33ns
147 bins.Apply(fHistTime);
148}
149
150// --------------------------------------------------------------------------
151//
152// Setup the Binning for the histograms automatically if the correct
153// instances of MBinning
154//
155Bool_t MHSingleMuon::SetupFill(const MParList *plist)
156{
157 fGeomCam = (MGeomCam*)plist->FindObject("MGeomCam");
158 if (!fGeomCam)
159 {
160 *fLog << warn << "MGeomCam not found... abort." << endl;
161 return kFALSE;
162 }
163 fMuonSearchPar = (MMuonSearchPar*)plist->FindObject("MMuonSearchPar");
164 if (!fMuonSearchPar)
165 {
166 *fLog << warn << "MMuonSearchPar not found... abort." << endl;
167 return kFALSE;
168 }
169 fSignalCam = (MSignalCam*)plist->FindObject("MSignalCam");
170 if (!fSignalCam)
171 {
172 *fLog << warn << "MSignalCam not found... abort." << endl;
173 return kFALSE;
174 }
175
176 MMuonSetup *setup = (MMuonSetup*)const_cast<MParList*>(plist)->FindCreateObj("MMuonSetup");
177 if (!setup)
178 return kFALSE;
179
180 fMargin = setup->GetMargin()/fGeomCam->GetConvMm2Deg();
181
182 ApplyBinning(*plist, "ArcPhi", &fHistPhi);
183 ApplyBinning(*plist, "MuonWidth", &fHistWidth);
184 ApplyBinning(*plist, "MuonTime", &fHistTime);
185
186 return kTRUE;
187}
188
189// --------------------------------------------------------------------------
190//
191// Fill the histograms with data from a MMuonCalibPar and
192// MMuonSearchPar container.
193//
194Bool_t MHSingleMuon::Fill(const MParContainer *par, const Stat_t w)
195{
196 fHistPhi.Reset();
197 fHistWidth.Reset();
198 fHistTime.Reset();
199
200 const Int_t entries = fSignalCam->GetNumPixels();
201
202 // the position of the center of a muon ring
203 const Float_t cenx = fMuonSearchPar->GetCenterX();
204 const Float_t ceny = fMuonSearchPar->GetCenterY();
205
206 for (Int_t i=0; i<entries; i++)
207 {
208 const MSignalPix &pix = (*fSignalCam)[i];
209 const MGeomPix &gpix = (*fGeomCam)[i];
210
211 const Float_t dx = gpix.GetX() - cenx;
212 const Float_t dy = gpix.GetY() - ceny;
213
214 const Float_t dist = TMath::Hypot(dx, dy);
215
216 // if the signal is not near the estimated circle, it is ignored.
217 if (TMath::Abs(dist-fMuonSearchPar->GetRadius())<fMargin)
218 {
219 fHistTime.Fill(pix.GetArrivalTime()-fMuonSearchPar->GetTime());
220 }
221
222 // use only the inner pixles. FIXME: This is geometry dependent
223 if(gpix.GetAidx()>0)
224 continue;
225
226 fHistWidth.Fill(dist*fGeomCam->GetConvMm2Deg(), pix.GetNumPhotons());
227 }
228 // Setup the function and perform the fit
229 TF1 g1("g1", "gaus");//, -fHistTime.GetXmin(), fHistTime.GetXmax());
230
231 // Choose starting values as accurate as possible
232 g1.SetParameter(0, fHistTime.GetMaximum());
233 g1.SetParameter(1, 0);
234 g1.SetParameter(2, 0.7); // FIXME! GetRMS instead???
235
236 // According to fMuonSearchPar->GetTimeRMS() identified muons
237 // do not have an arrival time rms>3
238 g1.SetParLimits(1, -1.7, 1.7);
239 g1.SetParLimits(2, 0, 3.4);
240
241 // options : N do not store the function, do not draw
242 // I use integral of function in bin rather than value at bin center
243 // R use the range specified in the function range
244 // Q quiet mode
245 fHistTime.Fit(&g1, "QNB");
246
247 // Double_t err;
248 Double_t sig, mean, dummy;
249 gMinuit->GetParameter(1, mean, dummy); // get the mean value
250 gMinuit->GetParameter(2, sig, dummy); // get the sigma value
251
252 for (Int_t i=0; i<entries; i++)
253 {
254 const MSignalPix &pix = (*fSignalCam)[i];
255 const MGeomPix &gpix = (*fGeomCam)[i];
256
257 const Float_t dx = gpix.GetX() - cenx;
258 const Float_t dy = gpix.GetY() - ceny;
259
260 const Float_t dist = TMath::Hypot(dx, dy);
261
262 // if the signal is not near the estimated circle, it is ignored.
263 if (TMath::Abs(dist-fMuonSearchPar->GetRadius())<fMargin &&
264 TMath::Abs(pix.GetArrivalTime()-fMuonSearchPar->GetTime()-mean) < 2*sig)
265 {
266 fHistPhi.Fill(TMath::ATan2(dx, dy)*TMath::RadToDeg(), pix.GetNumPhotons());
267 }
268 }
269
270 // error estimation (temporaly)
271 // The error is estimated from the signal. In order to do so, we have to
272 // once convert the signal from ADC to photo-electron. Then we can get
273 // the fluctuation such as F-factor*sqrt(phe).
274 // Up to now, the error of pedestal is not taken into accout. This is not
275 // of course correct. We will include this soon.
276 const Double_t Ffactor = 1.4;
277 for (Int_t i=0; i<fHistPhi.GetNbinsX()+1; i++)
278 {
279 const Float_t abs = TMath::Abs(fHistPhi.GetBinContent(i));
280 const Float_t rougherr = TMath::Sqrt(abs)*Ffactor;
281
282 fHistPhi.SetBinError(i, rougherr);
283 }
284
285 for (Int_t i=0; i<fHistWidth.GetNbinsX()+1; i++)
286 {
287 const Float_t abs = TMath::Abs(fHistWidth.GetBinContent(i));
288 const Float_t rougherr = TMath::Sqrt(abs)*Ffactor;
289
290 fHistWidth.SetBinError(i, rougherr);
291 }
292
293 return kTRUE;
294}
295
296// --------------------------------------------------------------------------
297//
298// Find the first bins starting at the bin with maximum content in both
299// directions which are below threshold.
300// If in a range of half the histogram size in both directions no bin
301// below the threshold is found, kFALSE is returned.
302//
303Bool_t MHSingleMuon::FindRangeAboveThreshold(const TProfile &h, Float_t thres, Int_t &first, Int_t &last) const
304{
305 const Int_t n = h.GetNbinsX();
306 const Int_t maxbin = h.GetMaximumBin();
307 const Int_t edge = maxbin+n/2;
308
309 // Search from the peak to the right
310 last = -1;
311 for (Int_t i=maxbin; i<edge; i++)
312 {
313 const Float_t val = h.GetBinContent(i%n + 1);
314 if (val<thres)
315 {
316 last = i%n+1;
317 break;
318 }
319 }
320
321 // Search from the peak to the left
322 first = -1;
323 for (Int_t i=maxbin+n-1; i>=edge; i--)
324 {
325 const Float_t val = h.GetBinContent(i%n + 1);
326 if (val<thres)
327 {
328 first = i%n+1;
329 break;
330 }
331 }
332
333 return first>=0 && last>=0;
334}
335
336// --------------------------------------------------------------------------
337//
338// Photon distribution along the estimated circle is fitted with theoritical
339// function in order to get some more information such as Arc Phi and Arc
340// Length.
341//
342Bool_t MHSingleMuon::CalcPhi(Double_t thres, Double_t &peakphi, Double_t &arcphi) const
343{
344 if (fHistPhi.GetMaximum()<thres)
345 return kFALSE;
346
347 peakphi = 180.-fHistPhi.GetBinCenter(fHistPhi.GetMaximumBin());
348
349 // Now find the position at which the peak edges crosses the threshold
350 Int_t first, last;
351
352 FindRangeAboveThreshold(fHistPhi, thres, first, last);
353
354 const Int_t n = fHistPhi.GetNbinsX();
355 const Int_t edge = fHistPhi.GetMaximumBin()+n/2;
356 if (first<0)
357 first = (edge-1)%n+1;
358 if (last<0)
359 last = edge%n+1;;
360
361 const Float_t startfitval = fHistPhi.GetBinLowEdge(first+1);
362 const Float_t endfitval = fHistPhi.GetBinLowEdge(last);
363
364 arcphi = last-1<first ? 360+(endfitval-startfitval) : endfitval-startfitval;
365
366 //if (fEnableImpactCalc)
367 // CalcImpact(effbinnum, startfitval, endfitval);
368
369 return kTRUE;
370}
371
372// --------------------------------------------------------------------------
373//
374// Photon distribution of distance from the center of estimated ring is
375// fitted in order to get some more information such as ARC WIDTH which
376// can represent to the PSF of our reflector.
377//
378// thres: Threshold above zero to determin the edges of the peak which
379// is used as fit range
380// width: ArcWidth returned in deg
381// chi: Chi^2/NDF of the fit
382//
383Bool_t MHSingleMuon::CalcWidth(Double_t thres, Double_t &width, Double_t &chi)
384{
385 Int_t first, last;
386
387 if (!FindRangeAboveThreshold(fHistWidth, thres, first, last))
388 return kFALSE;
389
390 // This happens in some cases
391 const Int_t n = fHistWidth.GetNbinsX()/2;
392 const Int_t m = fHistWidth.GetMaximumBin();
393 if (first>last)
394 if (m>n) // If maximum is on the right side of histogram
395 last = n;
396 else
397 first = 0; // If maximum is on the left side of histogram
398
399 if (last-first<=3)
400 return kFALSE;
401
402 // Now get the fit range
403 const Float_t startfitval = fHistWidth.GetBinLowEdge(first+1);
404 const Float_t endfitval = fHistWidth.GetBinLowEdge(last);
405
406 // Setup the function and perform the fit
407 TF1 f1("f1", "gaus + [3]", startfitval, endfitval);
408 f1.SetLineColor(kBlue);
409
410 // Choose starting values as accurate as possible
411 f1.SetParameter(0, fHistWidth.GetMaximum());
412 f1.SetParameter(1, fHistWidth.GetBinCenter(m));
413// f1.SetParameter(2, (endfitval-startfitval)/2);
414 f1.SetParameter(2, 0.1);
415 f1.SetParameter(3, 1.8);
416
417 // options : N do not store the function, do not draw
418 // I use integral of function in bin rather than value at bin center
419 // R use the range specified in the function range
420 // Q quiet mode
421// fHistWidth.Fit(&f1, "QRO");
422 fHistWidth.Fit(&f1, "QRN");
423
424 chi = f1.GetChisquare()/f1.GetNDF();
425
426 Double_t ferr;
427 gMinuit->GetParameter(2, width, ferr); // get the sigma value
428
429 return kTRUE;
430}
431
432/*
433// --------------------------------------------------------------------------
434//
435// An impact parameter is calculated by fitting the histogram of photon
436// distribution along the circle with a theoritical model.
437// (See G. Vacanti et. al., Astroparticle Physics 2, 1994, 1-11.
438// The function (6) is used here.)
439//
440// By default this calculation is suppressed because this calculation is
441// very time consuming. If you want to calculate an impact parameter,
442// you can call the function of EnableImpactCalc().
443//
444void MMuonCalibParCalc::CalcImpact(Int_t effbinnum, Float_t startfitval, Float_t endfitval)
445{
446 // Fit the distribution with Vacanti function. The function is different
447 // for the impact parameter of inside or outside of our reflector.
448 // Then two different functions are applied to the photon distribution,
449 // and the one which give us smaller chisquare value is taken as a
450 // proper one.
451
452 Double_t val1,err1,val2,err2;
453 // impact parameter inside mirror radius (8.5m)
454 TString func1;
455 Float_t tmpval = (*fMuonSearchPar).GetRadius()*(*fGeomCam).GetConvMm2Deg()*TMath::DegToRad();
456 tmpval = sin(2.*tmpval)*8.5;
457 func1 += "[0]*";
458 func1 += tmpval;
459 func1 += "*(sqrt(1.-([1]/8.5)**2*sin((x-[2])*3.1415926/180.)**2)+([1]/8.5)*cos((x-[2])*3.1415926/180.))";
460
461 TF1 f1("f1",func1,startfitval,endfitval);
462 f1.SetParameters(2000,3,0);
463 f1.SetParLimits(1,0,8.5);
464 f1.SetParLimits(2,-180.,180.);
465
466 fMuonCalibPar->fHistPhi->Fit("f1","RQEM");
467
468 Float_t chi1 = -1;
469 Float_t chi2 = -1;
470 if(effbinnum>3)
471 chi1 = f1.GetChisquare()/((Float_t)(effbinnum-3));
472
473 gMinuit->GetParameter(1,val1,err1); // get the estimated IP
474 Float_t estip1 = val1;
475
476 // impact parameter beyond mirror area (8.5m)
477 TString func2;
478 Float_t tmpval2 = (*fMuonSearchPar).GetRadius()*(*fGeomCam).GetConvMm2Deg()*TMath::DegToRad();
479 tmpval2 = sin(2.*tmpval2)*8.5*2.;
480 func2 += "[0]*";
481 func2 += tmpval2;
482 func2 += "*sqrt(1.-(([1]/8.5)*sin((x-[2])*3.1415926/180.))**2)";
483
484 TF1 f2("f2",func2,startfitval,endfitval);
485 f2.SetParameters(2000,20,0);
486 f2.SetParLimits(1,8.5,300.);
487 f2.SetParLimits(2,-180.,180.);
488
489 fMuonCalibPar->fHistPhi->Fit("f2","RQEM+");
490
491 if(effbinnum>3)
492 chi2 = f2.GetChisquare()/((Float_t)(effbinnum-3));
493
494 gMinuit->GetParameter(1,val2,err2); // get the estimated IP
495 Float_t estip2 = val2;
496
497 if(effbinnum<=3)
498 {
499 fMuonCalibPar->SetEstImpact(-1.);
500 }
501 if(chi2 > chi1)
502 {
503 fMuonCalibPar->SetEstImpact(estip1);
504 fMuonCalibPar->SetChiArcPhi(chi1);
505 }
506 else
507 {
508 fMuonCalibPar->SetEstImpact(estip2);
509 fMuonCalibPar->SetChiArcPhi(chi2);
510 }
511}
512*/
513
514Float_t MHSingleMuon::CalcSize() const
515{
516 const Int_t n = fHistPhi.GetNbinsX();
517
518 Double_t sz=0;
519 for (Int_t i=1; i<=n; i++)
520 sz += fHistPhi.GetBinContent(i)*fHistPhi.GetBinEntries(i);
521
522 return sz;
523}
524
525void MHSingleMuon::Paint(Option_t *o)
526{
527 TF1 *f = fHistWidth.GetFunction("f1");
528 if (f)
529 f->ResetBit(1<<9);
530}
531
532void MHSingleMuon::Draw(Option_t *o)
533{
534 TVirtualPad *pad = gPad ? gPad : MakeDefCanvas(this);
535 pad->SetBorderMode(0);
536
537 AppendPad("");
538
539 pad->Divide(1,2);
540
541 pad->cd(1);
542 gPad->SetBorderMode(0);
543 fHistPhi.Draw();
544
545 pad->cd(2);
546 gPad->SetBorderMode(0);
547 fHistWidth.Draw();
548}
Note: See TracBrowser for help on using the repository browser.