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

Last change on this file since 9573 was 9573, checked in by tbretz, 14 years ago
*** empty log message ***
File size: 17.3 KB
Line 
1/* ======================================================================== *\
2! $Name: not supported by cvs2svn $:$Id: MHSingleMuon.cc,v 1.20 2010-04-19 12:40:16 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// Class Version 2:
78// ----------------
79// + Double_t fRelTimeMean; // Result of the gaus fit to the arrival time
80// + Double_t fRelTimeSigma; // Result of the gaus fit to the arrival time
81//
82////////////////////////////////////////////////////////////////////////////
83#include "MHSingleMuon.h"
84
85#include <TF1.h>
86#include <TPad.h>
87#include <TCanvas.h>
88
89#include "MLog.h"
90#include "MLogManip.h"
91
92#include "MBinning.h"
93#include "MParList.h"
94
95#include "MGeomCam.h"
96#include "MGeomPix.h"
97
98#include "MSignalCam.h"
99#include "MSignalPix.h"
100
101#include "MMuonSetup.h"
102#include "MMuonCalibPar.h"
103#include "MMuonSearchPar.h"
104
105ClassImp(MHSingleMuon);
106
107using namespace std;
108
109// --------------------------------------------------------------------------
110//
111// Setup histograms
112//
113MHSingleMuon::MHSingleMuon(const char *name, const char *title) :
114 fSignalCam(0), fMuonSearchPar(0), fGeomCam(0), fMargin(0)
115{
116 fName = name ? name : "MHSingleMuon";
117 fTitle = title ? title : "Histograms of muon parameters";
118
119 fHistPhi.SetName("HistPhi");
120 fHistPhi.SetTitle("HistPhi");
121 fHistPhi.SetXTitle("\\phi [\\circ]");
122 fHistPhi.SetYTitle("sum of ADC");
123 fHistPhi.SetDirectory(NULL);
124 fHistPhi.SetFillStyle(4000);
125 fHistPhi.UseCurrentStyle();
126
127 fHistWidth.SetName("HistWidth");
128 fHistWidth.SetTitle("HistWidth");
129 fHistWidth.SetXTitle("distance from the ring center [\\circ]");
130 fHistWidth.SetYTitle("sum of ADC");
131 fHistWidth.SetDirectory(NULL);
132 fHistWidth.SetFillStyle(4000);
133 fHistWidth.UseCurrentStyle();
134
135 fHistTime.SetName("HistTime");
136 fHistTime.SetTitle("HistTime");
137 fHistTime.SetXTitle("timing difference");
138 fHistTime.SetYTitle("Counts");
139 fHistTime.SetDirectory(NULL);
140 fHistTime.SetFillStyle(4000);
141 fHistTime.UseCurrentStyle();
142
143 MBinning bins;
144 bins.SetEdges(20, -180, 180);
145 bins.Apply(fHistPhi);
146
147 bins.SetEdges(28, 0.3, 1.7);
148 bins.Apply(fHistWidth);
149
150 bins.SetEdges(101, -33, 33); // +/- 33ns
151 bins.Apply(fHistTime);
152}
153
154// --------------------------------------------------------------------------
155//
156// Setup the Binning for the histograms automatically if the correct
157// instances of MBinning
158//
159Bool_t MHSingleMuon::SetupFill(const MParList *plist)
160{
161 fGeomCam = (MGeomCam*)plist->FindObject("MGeomCam");
162 if (!fGeomCam)
163 {
164 *fLog << warn << "MGeomCam not found... abort." << endl;
165 return kFALSE;
166 }
167 fMuonSearchPar = (MMuonSearchPar*)plist->FindObject("MMuonSearchPar");
168 if (!fMuonSearchPar)
169 {
170 *fLog << warn << "MMuonSearchPar not found... abort." << endl;
171 return kFALSE;
172 }
173 fSignalCam = (MSignalCam*)plist->FindObject("MSignalCam");
174 if (!fSignalCam)
175 {
176 *fLog << warn << "MSignalCam not found... abort." << endl;
177 return kFALSE;
178 }
179
180 MMuonSetup *setup = (MMuonSetup*)const_cast<MParList*>(plist)->FindCreateObj("MMuonSetup");
181 if (!setup)
182 return kFALSE;
183
184 fMargin = setup->GetMargin()/fGeomCam->GetConvMm2Deg();
185
186 ApplyBinning(*plist, "ArcPhi", &fHistPhi);
187 ApplyBinning(*plist, "MuonWidth", &fHistWidth);
188 ApplyBinning(*plist, "MuonTime", &fHistTime);
189
190 return kTRUE;
191}
192
193// --------------------------------------------------------------------------
194//
195// Fill the histograms with data from a MMuonCalibPar and
196// MMuonSearchPar container.
197//
198Int_t MHSingleMuon::Fill(const MParContainer *par, const Stat_t w)
199{
200 fRelTimeMean = 0;
201 fRelTimeSigma = -1;
202
203 fHistPhi.Reset();
204 fHistWidth.Reset();
205 fHistTime.Reset();
206
207 const Int_t entries = fSignalCam->GetNumPixels();
208
209 // the position of the center of a muon ring
210 const Float_t cenx = fMuonSearchPar->GetCenterX();
211 const Float_t ceny = fMuonSearchPar->GetCenterY();
212
213 for (Int_t i=0; i<entries; i++)
214 {
215 const MSignalPix &pix = (*fSignalCam)[i];
216 const MGeom &gpix = (*fGeomCam)[i];
217
218 const Float_t dx = gpix.GetX() - cenx;
219 const Float_t dy = gpix.GetY() - ceny;
220
221 const Float_t dist = TMath::Hypot(dx, dy);
222
223 // if the signal is not near the estimated circle, it is ignored.
224 if (TMath::Abs(dist-fMuonSearchPar->GetRadius())<fMargin)
225 {
226 // The arrival time is aligned around 0 for smaller
227 // and more stable histogram range
228 fHistTime.Fill(pix.GetArrivalTime()-fMuonSearchPar->GetTime());
229 }
230
231 // use only the inner pixles. FIXME: This is geometry dependent
232 if (gpix.GetAidx()>0)
233 continue;
234
235 fHistWidth.Fill(dist*fGeomCam->GetConvMm2Deg(), pix.GetNumPhotons());
236 }
237
238 // Setup the function and perform the fit
239 TF1 g1("g1", "gaus");//, -fHistTime.GetXmin(), fHistTime.GetXmax());
240
241 // Choose starting values as accurate as possible
242 g1.SetParameter(0, fHistTime.GetMaximum());
243 g1.SetParameter(1, 0);
244 g1.SetParameter(2, 0.7); // FIXME! GetRMS instead???
245
246 // According to fMuonSearchPar->GetTimeRMS() identified muons
247 // do not have an arrival time rms>3
248 g1.SetParLimits(1, -1.7, 1.7);
249 g1.SetParLimits(2, 0, 3.4);
250
251 // options : N do not store the function, do not draw
252 // I use integral of function in bin rather than value at bin center
253 // R use the range specified in the function range
254 // Q quiet mode
255 if (fHistTime.Fit(&g1, "QNB"))
256 return kTRUE;
257
258 fRelTimeMean = g1.GetParameter(1);
259 fRelTimeSigma = g1.GetParameter(2);
260
261 // The mean arrival time which was subtracted before will
262 // be added again, now
263 const Double_t tm0 = fMuonSearchPar->GetTime()+fRelTimeMean;
264
265 for (Int_t i=0; i<entries; i++)
266 {
267 const MSignalPix &pix = (*fSignalCam)[i];
268 const MGeom &gpix = (*fGeomCam)[i];
269
270 const Float_t dx = gpix.GetX() - cenx;
271 const Float_t dy = gpix.GetY() - ceny;
272
273 const Float_t dist = TMath::Hypot(dx, dy);
274
275 // if the signal is not near the estimated circle, it is ignored.
276 if (TMath::Abs(dist-fMuonSearchPar->GetRadius())<fMargin &&
277 TMath::Abs(pix.GetArrivalTime()-tm0) < 2*fRelTimeSigma)
278 {
279 fHistPhi.Fill(TMath::ATan2(dx, dy)*TMath::RadToDeg(), pix.GetNumPhotons());
280 }
281 }
282
283 return kTRUE;
284
285/*
286 // Because the errors (sqrt(content)) are only scaled by a fixed
287 // factor, and the absolute value of the error is nowhere
288 // needed we skip this step
289
290 // error estimation (temporarily)
291 // The error is estimated from the signal. In order to do so, we have to
292 // once convert the signal from ADC to photo-electron. Then we can get
293 // the fluctuation such as F-factor*sqrt(phe).
294 // Up to now, the error of pedestal is not taken into accout. This is not
295 // of course correct. We will include this soon.
296 const Double_t Ffactor = 1.4;
297 for (Int_t i=0; i<fHistPhi.GetNbinsX()+1; i++)
298 fHistPhi.SetBinError(i, fHistPhi.GetBinError(i)*Ffactor);
299
300 for (Int_t i=0; i<fHistWidth.GetNbinsX()+1; i++)
301 fHistWidth.SetBinError(i, fHistWidth.GetBinError(i)*Ffactor);
302
303 return kTRUE;
304 */
305}
306
307// --------------------------------------------------------------------------
308//
309// Find the first bins starting at the bin with maximum content in both
310// directions which are below threshold.
311// If in a range of half the histogram size in both directions no bin
312// below the threshold is found, kFALSE is returned.
313//
314Bool_t MHSingleMuon::FindRangeAboveThreshold(const TProfile &h, Float_t thres, Int_t &first, Int_t &last) const
315{
316 const Int_t n = h.GetNbinsX();
317 const Int_t maxbin = h.GetMaximumBin();
318 const Int_t edge = maxbin+n/2;
319
320 // Search from the peak to the right
321 last = -1;
322 for (Int_t i=maxbin; i<edge; i++)
323 {
324 const Float_t val = h.GetBinContent(i%n + 1);
325 if (val<thres)
326 {
327 last = i%n+1;
328 break;
329 }
330 }
331
332 // Search from the peak to the left
333 first = -1;
334 for (Int_t i=maxbin+n-1; i>=edge; i--)
335 {
336 const Float_t val = h.GetBinContent(i%n + 1);
337 if (val<thres)
338 {
339 first = i%n+1;
340 break;
341 }
342 }
343
344 return first>=0 && last>=0;
345}
346
347// --------------------------------------------------------------------------
348//
349// Photon distribution along the estimated circle is fitted with theoritical
350// function in order to get some more information such as Arc Phi and Arc
351// Length.
352//
353Bool_t MHSingleMuon::CalcPhi(Double_t thres, Double_t &peakphi, Double_t &arcphi) const
354{
355 if (fHistPhi.GetMaximum()<thres)
356 return kFALSE;
357
358 peakphi = 180.-fHistPhi.GetBinCenter(fHistPhi.GetMaximumBin());
359
360 // Now find the position at which the peak edges crosses the threshold
361 Int_t first, last;
362
363 FindRangeAboveThreshold(fHistPhi, thres, first, last);
364
365 const Int_t n = fHistPhi.GetNbinsX();
366 const Int_t edge = fHistPhi.GetMaximumBin()+n/2;
367 if (first<0)
368 first = (edge-1)%n+1;
369 if (last<0)
370 last = edge%n+1;;
371
372 const Float_t startfitval = fHistPhi.GetBinLowEdge(first+1);
373 const Float_t endfitval = fHistPhi.GetBinLowEdge(last);
374
375 arcphi = last-1<first ? 360+(endfitval-startfitval) : endfitval-startfitval;
376
377 //if (fEnableImpactCalc)
378 // CalcImpact(effbinnum, startfitval, endfitval);
379
380 return kTRUE;
381}
382
383// --------------------------------------------------------------------------
384//
385// Photon distribution of distance from the center of estimated ring is
386// fitted in order to get some more information such as ARC WIDTH which
387// can represent to the PSF of our reflector.
388//
389// thres: Threshold above zero to determin the edges of the peak which
390// is used as fit range
391// width: ArcWidth returned in deg
392// chi: Chi^2/NDF of the fit
393//
394Bool_t MHSingleMuon::CalcWidth(Double_t thres, Double_t &width, Double_t &chi)
395{
396 Int_t first, last;
397
398 if (!FindRangeAboveThreshold(fHistWidth, thres, first, last))
399 return kFALSE;
400
401 // This happens in some cases
402 const Int_t n = fHistWidth.GetNbinsX()/2;
403 const Int_t m = fHistWidth.GetMaximumBin();
404 if (first>last)
405 {
406 if (m>n) // If maximum is on the right side of histogram
407 last = n;
408 else
409 first = 0; // If maximum is on the left side of histogram
410 }
411
412 if (last-first<=3)
413 return kFALSE;
414
415 // Now get the fit range
416 const Float_t startfitval = fHistWidth.GetBinLowEdge(first+1);
417 const Float_t endfitval = fHistWidth.GetBinLowEdge(last);
418
419 // Setup the function and perform the fit
420 TF1 f1("f1", "gaus + [3]", startfitval, endfitval);
421 f1.SetLineColor(kBlue);
422
423 // Choose starting values as accurate as possible
424 f1.SetParameter(0, fHistWidth.GetMaximum());
425 f1.SetParameter(1, fHistWidth.GetBinCenter(m));
426// f1.SetParameter(2, (endfitval-startfitval)/2);
427 f1.SetParameter(2, 0.1);
428 f1.SetParameter(3, 1.8);
429
430 // options : N do not store the function, do not draw
431 // I use integral of function in bin rather than value at bin center
432 // R use the range specified in the function range
433 // Q quiet mode
434// fHistWidth.Fit(&f1, "QRO");
435 fHistWidth.Fit(&f1, "QRN");
436
437 if (!gMinuit)
438 return kFALSE;
439
440 chi = f1.GetChisquare()/f1.GetNDF();
441 width = f1.GetParameter(2);
442
443 return kTRUE;
444}
445
446/*
447// --------------------------------------------------------------------------
448//
449// An impact parameter is calculated by fitting the histogram of photon
450// distribution along the circle with a theoritical model.
451// (See G. Vacanti et. al., Astroparticle Physics 2, 1994, 1-11.
452// The function (6) is used here.)
453//
454// By default this calculation is suppressed because this calculation is
455// very time consuming. If you want to calculate an impact parameter,
456// you can call the function of EnableImpactCalc().
457//
458void MMuonCalibParCalc::CalcImpact(Int_t effbinnum, Float_t startfitval, Float_t endfitval)
459{
460 // Fit the distribution with Vacanti function. The function is different
461 // for the impact parameter of inside or outside of our reflector.
462 // Then two different functions are applied to the photon distribution,
463 // and the one which give us smaller chisquare value is taken as a
464 // proper one.
465
466 Double_t val1,err1,val2,err2;
467 // impact parameter inside mirror radius (8.5m)
468 TString func1;
469 Float_t tmpval = (*fMuonSearchPar).GetRadius()*(*fGeomCam).GetConvMm2Deg()*TMath::DegToRad();
470 tmpval = sin(2.*tmpval)*8.5;
471 func1 += "[0]*";
472 func1 += tmpval;
473 func1 += "*(sqrt(1.-([1]/8.5)**2*sin((x-[2])*3.1415926/180.)**2)+([1]/8.5)*cos((x-[2])*3.1415926/180.))";
474
475 TF1 f1("f1",func1,startfitval,endfitval);
476 f1.SetParameters(2000,3,0);
477 f1.SetParLimits(1,0,8.5);
478 f1.SetParLimits(2,-180.,180.);
479
480 fMuonCalibPar->fHistPhi->Fit("f1","RQEM");
481
482 Float_t chi1 = -1;
483 Float_t chi2 = -1;
484 if(effbinnum>3)
485 chi1 = f1.GetChisquare()/((Float_t)(effbinnum-3));
486
487 gMinuit->GetParameter(1,val1,err1); // get the estimated IP
488 Float_t estip1 = val1;
489
490 // impact parameter beyond mirror area (8.5m)
491 TString func2;
492 Float_t tmpval2 = (*fMuonSearchPar).GetRadius()*(*fGeomCam).GetConvMm2Deg()*TMath::DegToRad();
493 tmpval2 = sin(2.*tmpval2)*8.5*2.;
494 func2 += "[0]*";
495 func2 += tmpval2;
496 func2 += "*sqrt(1.-(([1]/8.5)*sin((x-[2])*3.1415926/180.))**2)";
497
498 TF1 f2("f2",func2,startfitval,endfitval);
499 f2.SetParameters(2000,20,0);
500 f2.SetParLimits(1,8.5,300.);
501 f2.SetParLimits(2,-180.,180.);
502
503 fMuonCalibPar->fHistPhi->Fit("f2","RQEM+");
504
505 if(effbinnum>3)
506 chi2 = f2.GetChisquare()/((Float_t)(effbinnum-3));
507
508 gMinuit->GetParameter(1,val2,err2); // get the estimated IP
509 Float_t estip2 = val2;
510
511 if(effbinnum<=3)
512 {
513 fMuonCalibPar->SetEstImpact(-1.);
514 }
515 if(chi2 > chi1)
516 {
517 fMuonCalibPar->SetEstImpact(estip1);
518 fMuonCalibPar->SetChiArcPhi(chi1);
519 }
520 else
521 {
522 fMuonCalibPar->SetEstImpact(estip2);
523 fMuonCalibPar->SetChiArcPhi(chi2);
524 }
525}
526*/
527
528Float_t MHSingleMuon::CalcSize() const
529{
530 const Int_t n = fHistPhi.GetNbinsX();
531
532 Double_t sz=0;
533 for (Int_t i=1; i<=n; i++)
534 sz += fHistPhi.GetBinContent(i)*fHistPhi.GetBinEntries(i);
535
536 return sz;
537}
538
539void MHSingleMuon::Paint(Option_t *o)
540{
541 TF1 *f = fHistWidth.GetFunction("f1");
542 if (f)
543 f->ResetBit(1<<9);
544}
545
546void MHSingleMuon::Draw(Option_t *o)
547{
548 TVirtualPad *pad = gPad ? gPad : MakeDefCanvas(this);
549 pad->SetBorderMode(0);
550
551 AppendPad("");
552
553 pad->Divide(1,2);
554
555 pad->cd(1);
556 gPad->SetBorderMode(0);
557 fHistPhi.Draw();
558
559 pad->cd(2);
560 gPad->SetBorderMode(0);
561 fHistWidth.Draw();
562}
Note: See TracBrowser for help on using the repository browser.