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

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