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

Last change on this file since 8590 was 8117, checked in by tbretz, 18 years ago
*** empty log message ***
File size: 16.8 KB
Line 
1/* ======================================================================== *\
2! $Name: not supported by cvs2svn $:$Id: MHSingleMuon.cc,v 1.14 2006-10-18 10:35:52 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, -10, 10);
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(i>397)
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", -10, 10);
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.2);
235
236 g1.SetParLimits(1, -0.5, 0.5);
237 g1.SetParLimits(2, 0, 1);
238 // options : N do not store the function, do not draw
239 // I use integral of function in bin rather than value at bin center
240 // R use the range specified in the function range
241 // Q quiet mode
242 fHistTime.Fit(&g1, "QNRB");
243
244 // Double_t err;
245 Double_t sig, mean, dummy;
246 gMinuit->GetParameter(1, mean, dummy); // get the mean value
247 gMinuit->GetParameter(2, sig, dummy); // get the sigma value
248
249 for (Int_t i=0; i<entries; i++)
250 {
251 const MSignalPix &pix = (*fSignalCam)[i];
252 const MGeomPix &gpix = (*fGeomCam)[i];
253
254 const Float_t dx = gpix.GetX() - cenx;
255 const Float_t dy = gpix.GetY() - ceny;
256
257 const Float_t dist = TMath::Hypot(dx, dy);
258
259 // if the signal is not near the estimated circle, it is ignored.
260 if (TMath::Abs(dist-fMuonSearchPar->GetRadius())<fMargin &&
261 TMath::Abs(pix.GetArrivalTime()-fMuonSearchPar->GetTime()-mean) < 2*sig)
262 {
263 fHistPhi.Fill(TMath::ATan2(dx, dy)*TMath::RadToDeg(), pix.GetNumPhotons());
264 }
265 }
266
267 // error estimation (temporaly)
268 // The error is estimated from the signal. In order to do so, we have to
269 // once convert the signal from ADC to photo-electron. Then we can get
270 // the fluctuation such as F-factor*sqrt(phe).
271 // Up to now, the error of pedestal is not taken into accout. This is not
272 // of course correct. We will include this soon.
273 const Double_t Ffactor = 1.4;
274 for (Int_t i=0; i<fHistPhi.GetNbinsX()+1; i++)
275 {
276 const Float_t abs = TMath::Abs(fHistPhi.GetBinContent(i));
277 const Float_t rougherr = TMath::Sqrt(abs)*Ffactor;
278
279 fHistPhi.SetBinError(i, rougherr);
280 }
281
282 for (Int_t i=0; i<fHistWidth.GetNbinsX()+1; i++)
283 {
284 const Float_t abs = TMath::Abs(fHistWidth.GetBinContent(i));
285 const Float_t rougherr = TMath::Sqrt(abs)*Ffactor;
286
287 fHistWidth.SetBinError(i, rougherr);
288 }
289
290 return kTRUE;
291}
292
293// --------------------------------------------------------------------------
294//
295// Find the first bins starting at the bin with maximum content in both
296// directions which are below threshold.
297// If in a range of half the histogram size in both directions no bin
298// below the threshold is found, kFALSE is returned.
299//
300Bool_t MHSingleMuon::FindRangeAboveThreshold(const TProfile &h, Float_t thres, Int_t &first, Int_t &last) const
301{
302 const Int_t n = h.GetNbinsX();
303 const Int_t maxbin = h.GetMaximumBin();
304 const Int_t edge = maxbin+n/2;
305
306 // Search from the peak to the right
307 last = -1;
308 for (Int_t i=maxbin; i<edge; i++)
309 {
310 const Float_t val = h.GetBinContent(i%n + 1);
311 if (val<thres)
312 {
313 last = i%n+1;
314 break;
315 }
316 }
317
318 // Search from the peak to the left
319 first = -1;
320 for (Int_t i=maxbin+n-1; i>=edge; i--)
321 {
322 const Float_t val = h.GetBinContent(i%n + 1);
323 if (val<thres)
324 {
325 first = i%n+1;
326 break;
327 }
328 }
329
330 return first>=0 && last>=0;
331}
332
333// --------------------------------------------------------------------------
334//
335// Photon distribution along the estimated circle is fitted with theoritical
336// function in order to get some more information such as Arc Phi and Arc
337// Length.
338//
339Bool_t MHSingleMuon::CalcPhi(Double_t thres, Double_t &peakphi, Double_t &arcphi) const
340{
341 if (fHistPhi.GetMaximum()<thres)
342 return kFALSE;
343
344 peakphi = 180.-fHistPhi.GetBinCenter(fHistPhi.GetMaximumBin());
345
346 // Now find the position at which the peak edges crosses the threshold
347 Int_t first, last;
348
349 FindRangeAboveThreshold(fHistPhi, thres, first, last);
350
351 const Int_t n = fHistPhi.GetNbinsX();
352 const Int_t edge = fHistPhi.GetMaximumBin()+n/2;
353 if (first<0)
354 first = (edge-1)%n+1;
355 if (last<0)
356 last = edge%n+1;;
357
358 const Float_t startfitval = fHistPhi.GetBinLowEdge(first+1);
359 const Float_t endfitval = fHistPhi.GetBinLowEdge(last);
360
361 arcphi = last-1<first ? 360+(endfitval-startfitval) : endfitval-startfitval;
362
363 //if (fEnableImpactCalc)
364 // CalcImpact(effbinnum, startfitval, endfitval);
365
366 return kTRUE;
367}
368
369// --------------------------------------------------------------------------
370//
371// Photon distribution of distance from the center of estimated ring is
372// fitted in order to get some more information such as ARC WIDTH which
373// can represent to the PSF of our reflector.
374//
375// thres: Threshold above zero to determin the edges of the peak which
376// is used as fit range
377// width: ArcWidth returned in deg
378// chi: Chi^2/NDF of the fit
379//
380Bool_t MHSingleMuon::CalcWidth(Double_t thres, Double_t &width, Double_t &chi)
381{
382 Int_t first, last;
383
384 if (!FindRangeAboveThreshold(fHistWidth, thres, first, last))
385 return kFALSE;
386
387 // This happens in some cases
388 const Int_t n = fHistWidth.GetNbinsX()/2;
389 const Int_t m = fHistWidth.GetMaximumBin();
390 if (first>last)
391 if (m>n) // If maximum is on the right side of histogram
392 last = n;
393 else
394 first = 0; // If maximum is on the left side of histogram
395
396 if (last-first<=3)
397 return kFALSE;
398
399 // Now get the fit range
400 const Float_t startfitval = fHistWidth.GetBinLowEdge(first+1);
401 const Float_t endfitval = fHistWidth.GetBinLowEdge(last);
402
403 // Setup the function and perform the fit
404 TF1 f1("f1", "gaus + [3]", startfitval, endfitval);
405 f1.SetLineColor(kBlue);
406
407 // Choose starting values as accurate as possible
408 f1.SetParameter(0, fHistWidth.GetMaximum());
409 f1.SetParameter(1, fHistWidth.GetBinCenter(m));
410// f1.SetParameter(2, (endfitval-startfitval)/2);
411 f1.SetParameter(2, 0.1);
412 f1.SetParameter(3, 1.8);
413
414 // options : N do not store the function, do not draw
415 // I use integral of function in bin rather than value at bin center
416 // R use the range specified in the function range
417 // Q quiet mode
418// fHistWidth.Fit(&f1, "QRO");
419 fHistWidth.Fit(&f1, "QRN");
420
421 chi = f1.GetChisquare()/f1.GetNDF();
422
423 Double_t ferr;
424 gMinuit->GetParameter(2, width, ferr); // get the sigma value
425
426 return kTRUE;
427}
428
429/*
430// --------------------------------------------------------------------------
431//
432// An impact parameter is calculated by fitting the histogram of photon
433// distribution along the circle with a theoritical model.
434// (See G. Vacanti et. al., Astroparticle Physics 2, 1994, 1-11.
435// The function (6) is used here.)
436//
437// By default this calculation is suppressed because this calculation is
438// very time consuming. If you want to calculate an impact parameter,
439// you can call the function of EnableImpactCalc().
440//
441void MMuonCalibParCalc::CalcImpact(Int_t effbinnum, Float_t startfitval, Float_t endfitval)
442{
443 // Fit the distribution with Vacanti function. The function is different
444 // for the impact parameter of inside or outside of our reflector.
445 // Then two different functions are applied to the photon distribution,
446 // and the one which give us smaller chisquare value is taken as a
447 // proper one.
448
449 Double_t val1,err1,val2,err2;
450 // impact parameter inside mirror radius (8.5m)
451 TString func1;
452 Float_t tmpval = (*fMuonSearchPar).GetRadius()*(*fGeomCam).GetConvMm2Deg()*TMath::DegToRad();
453 tmpval = sin(2.*tmpval)*8.5;
454 func1 += "[0]*";
455 func1 += tmpval;
456 func1 += "*(sqrt(1.-([1]/8.5)**2*sin((x-[2])*3.1415926/180.)**2)+([1]/8.5)*cos((x-[2])*3.1415926/180.))";
457
458 TF1 f1("f1",func1,startfitval,endfitval);
459 f1.SetParameters(2000,3,0);
460 f1.SetParLimits(1,0,8.5);
461 f1.SetParLimits(2,-180.,180.);
462
463 fMuonCalibPar->fHistPhi->Fit("f1","RQEM");
464
465 Float_t chi1 = -1;
466 Float_t chi2 = -1;
467 if(effbinnum>3)
468 chi1 = f1.GetChisquare()/((Float_t)(effbinnum-3));
469
470 gMinuit->GetParameter(1,val1,err1); // get the estimated IP
471 Float_t estip1 = val1;
472
473 // impact parameter beyond mirror area (8.5m)
474 TString func2;
475 Float_t tmpval2 = (*fMuonSearchPar).GetRadius()*(*fGeomCam).GetConvMm2Deg()*TMath::DegToRad();
476 tmpval2 = sin(2.*tmpval2)*8.5*2.;
477 func2 += "[0]*";
478 func2 += tmpval2;
479 func2 += "*sqrt(1.-(([1]/8.5)*sin((x-[2])*3.1415926/180.))**2)";
480
481 TF1 f2("f2",func2,startfitval,endfitval);
482 f2.SetParameters(2000,20,0);
483 f2.SetParLimits(1,8.5,300.);
484 f2.SetParLimits(2,-180.,180.);
485
486 fMuonCalibPar->fHistPhi->Fit("f2","RQEM+");
487
488 if(effbinnum>3)
489 chi2 = f2.GetChisquare()/((Float_t)(effbinnum-3));
490
491 gMinuit->GetParameter(1,val2,err2); // get the estimated IP
492 Float_t estip2 = val2;
493
494 if(effbinnum<=3)
495 {
496 fMuonCalibPar->SetEstImpact(-1.);
497 }
498 if(chi2 > chi1)
499 {
500 fMuonCalibPar->SetEstImpact(estip1);
501 fMuonCalibPar->SetChiArcPhi(chi1);
502 }
503 else
504 {
505 fMuonCalibPar->SetEstImpact(estip2);
506 fMuonCalibPar->SetChiArcPhi(chi2);
507 }
508}
509*/
510
511Float_t MHSingleMuon::CalcSize() const
512{
513 const Int_t n = fHistPhi.GetNbinsX();
514
515 Double_t sz=0;
516 for (Int_t i=1; i<=n; i++)
517 sz += fHistPhi.GetBinContent(i)*fHistPhi.GetBinEntries(i);
518
519 return sz;
520}
521
522void MHSingleMuon::Paint(Option_t *o)
523{
524 TF1 *f = fHistWidth.GetFunction("f1");
525 if (f)
526 f->ResetBit(1<<9);
527}
528
529void MHSingleMuon::Draw(Option_t *o)
530{
531 TVirtualPad *pad = gPad ? gPad : MakeDefCanvas(this);
532 pad->SetBorderMode(0);
533
534 AppendPad("");
535
536 pad->Divide(1,2);
537
538 pad->cd(1);
539 gPad->SetBorderMode(0);
540 fHistPhi.Draw();
541
542 pad->cd(2);
543 gPad->SetBorderMode(0);
544 fHistWidth.Draw();
545}
Note: See TracBrowser for help on using the repository browser.