source: trunk/MagicSoft/Mars/msignal/MSignalCam.cc@ 7876

Last change on this file since 7876 was 7876, checked in by tbretz, 18 years ago
*** empty log message ***
File size: 18.6 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, 03/2005 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2005
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MSignalCam
28//
29// Class Version 1:
30// ----------------
31// - first version
32//
33/////////////////////////////////////////////////////////////////////////////
34#include "MSignalCam.h"
35
36#include <math.h>
37#include <limits.h>
38#include <fstream>
39
40#include <TArrayD.h>
41#include <TCanvas.h>
42
43#include "MLog.h"
44#include "MLogManip.h"
45
46#include "MGeomCam.h"
47#include "MGeomPix.h"
48
49ClassImp(MSignalCam);
50ClassImp(MSignalCamIter);
51
52using namespace std;
53
54// --------------------------------------------------------------------------
55//
56// Creates a MSignalPix object for each pixel in the event
57//
58MSignalCam::MSignalCam(const char *name, const char *title) /*: fNumPixels(0)*/
59{
60 fName = name ? name : "MSignalCam";
61 fTitle = title ? title : "(Number of Photon)-Event Information";
62
63 fPixels = new TClonesArray("MSignalPix", 0);
64
65 Reset();
66}
67
68// --------------------------------------------------------------------------
69//
70// This is not yet implemented like it should.
71//
72/*
73void MSignalCam::Draw(Option_t* option)
74{
75 //
76 // FIXME!!! Here the Draw function of the CamDisplay
77 // should be called to add the CamDisplay to the Pad.
78 // The drawing should be done in MCamDisplay::Paint
79 //
80
81 // MGeomCam *geom = fType ? new MGeomCamMagic : new MGeomCamCT1;
82 // MCamDisplay *disp = new MCamDisplay(geom);
83 // delete geom;
84 // disp->DrawPhotNum(this);
85}
86*/
87
88// --------------------------------------------------------------------------
89//
90// reset counter and delete netries in list.
91//
92void MSignalCam::Reset()
93{
94 //fNumPixels = 0;
95 fNumSinglePixels = 0;
96 fSizeSinglePixels = 0;
97 fSizeSubIslands = 0;
98 fSizeMainIsland = 0;
99 //fMaxIndex = -1;
100 fNumIslands = -1;
101 //fLut.Set(0);
102
103 fNumPixelsSaturatedHiGain = -1;
104 fNumPixelsSaturatedLoGain = -1;
105
106 fPixels->R__FOR_EACH(TObject, Clear)();
107}
108/*
109void MSignalCam::FixSize()
110{
111 fLut.Set(fMaxIndex+1);
112
113 if (fPixels->GetEntriesFast() == (Int_t)fNumPixels)
114 return;
115
116 fPixels->ExpandCreateFast(fNumPixels);
117}*/
118
119// --------------------------------------------------------------------------
120//
121// Dump the cerenkov photon event to *fLog
122//
123void MSignalCam::Print(Option_t *) const
124{
125 const Int_t entries = fPixels->GetEntries();
126
127 *fLog << GetDescriptor() << dec << endl;
128 *fLog << " Number of Pixels: " << GetNumPixels() << "(" << entries << ")" << endl;
129
130 for (Int_t i=0; i<entries; i++ )
131 (*this)[i].Print();
132}
133
134// --------------------------------------------------------------------------
135//
136// Checks if in the pixel list is an entry with pixel id
137//
138Bool_t MSignalCam::IsPixelExisting(Int_t id) const
139{
140 return GetPixById(id) ? kTRUE : kFALSE;
141}
142
143// --------------------------------------------------------------------------
144//
145// Checks if in the pixel list is an entry with pixel id
146//
147Bool_t MSignalCam::IsPixelUsed(Int_t id) const
148{
149 const MSignalPix *pix = GetPixById(id);
150 return pix ? pix->IsPixelUsed() : kFALSE;
151}
152
153// --------------------------------------------------------------------------
154//
155// Checks if in the pixel list is an entry with pixel id
156//
157Bool_t MSignalCam::IsPixelCore(Int_t id) const
158{
159 const MSignalPix *pix = GetPixById(id);
160 return pix ? pix->IsPixelCore() : kFALSE;
161}
162
163// --------------------------------------------------------------------------
164//
165// get the minimum number of photons of all valid pixels in the list
166// If you specify a geometry the number of photons is weighted with the
167// area of the pixel
168//
169Float_t MSignalCam::GetNumPhotonsMin(const MGeomCam *geom) const
170{
171 if (GetNumPixels() <= 0)
172 return -5.;
173
174 const UInt_t n = GetNumPixels();
175
176 Float_t minval = FLT_MAX;
177
178 for (UInt_t i=0; i<n; i++)
179 {
180 const MSignalPix &pix = (*this)[i];
181 if (!pix.IsPixelUsed())
182 continue;
183
184 //const UInt_t id = pix.GetPixId();
185 //if (id<0 || id>=n)
186 // continue;
187
188 Float_t testval = pix.GetNumPhotons();
189
190 if (geom)
191 testval *= geom->GetPixRatio(i);
192
193 if (testval < minval)
194 minval = testval;
195 }
196
197 return minval;
198}
199
200// --------------------------------------------------------------------------
201//
202// get the maximum number of photons of all valid pixels in the list
203// If you specify a geometry the number of photons is weighted with the
204// area of the pixel
205//
206Float_t MSignalCam::GetNumPhotonsMax(const MGeomCam *geom) const
207{
208 if (GetNumPixels() <= 0)
209 return 50.;
210
211 const UInt_t n = GetNumPixels();
212
213 Float_t maxval = -FLT_MAX;
214
215 for (UInt_t i=0; i<n; i++)
216 {
217 const MSignalPix &pix = (*this)[i];
218 if (!pix.IsPixelUsed())
219 continue;
220
221 //const UInt_t id = pix.GetPixId();
222 //if (id<0 || id>=n)
223 // continue;
224
225 Float_t testval = pix.GetNumPhotons();
226 if (geom)
227 testval *= geom->GetPixRatio(i);
228
229 if (testval > maxval)
230 maxval = testval;
231 }
232 return maxval;
233}
234
235// --------------------------------------------------------------------------
236//
237// get the minimum ratio of photons/error
238//
239Float_t MSignalCam::GetRatioMin(const MGeomCam *geom) const
240{
241 if (GetNumPixels() <= 0)
242 return -5.;
243
244 Float_t minval = FLT_MAX;
245
246 for (UInt_t i=0; i<GetNumPixels(); i++)
247 {
248 const MSignalPix &pix = (*this)[i];
249 if (!pix.IsPixelUsed())
250 continue;
251
252 Float_t testval = pix.GetNumPhotons()/pix.GetErrorPhot();
253 if (geom)
254 testval *= geom->GetPixRatioSqrt(i/*pix.GetPixId()*/);
255
256 if (testval < minval)
257 minval = testval;
258 }
259
260 return minval;
261}
262
263// --------------------------------------------------------------------------
264//
265// get the maximum ratio of photons/error
266//
267Float_t MSignalCam::GetRatioMax(const MGeomCam *geom) const
268{
269 if (GetNumPixels() <= 0)
270 return -5.;
271
272 Float_t maxval = -FLT_MAX;
273
274 for (UInt_t i=0; i<GetNumPixels(); i++)
275 {
276 const MSignalPix &pix = (*this)[i];
277 if (!pix.IsPixelUsed())
278 continue;
279
280 Float_t testval = pix.GetNumPhotons()/pix.GetErrorPhot();
281 if (geom)
282 testval *= geom->GetPixRatioSqrt(i/*pix.GetPixId()*/);
283
284 if (testval > maxval)
285 maxval = testval;
286 }
287
288 return maxval;
289}
290
291// --------------------------------------------------------------------------
292//
293// get the minimum of error
294// If you specify a geometry the number of photons is weighted with the
295// area of the pixel
296//
297Float_t MSignalCam::GetErrorPhotMin(const MGeomCam *geom) const
298{
299 if (GetNumPixels() <= 0)
300 return 50.;
301
302 Float_t minval = FLT_MAX;
303
304 for (UInt_t i=0; i<GetNumPixels(); i++)
305 {
306 const MSignalPix &pix = (*this)[i];
307 if (!pix.IsPixelUsed())
308 continue;
309
310 Float_t testval = pix.GetErrorPhot();
311
312 if (geom)
313 testval *= geom->GetPixRatio(i/*pix.GetPixId()*/);
314
315 if (testval < minval)
316 minval = testval;
317 }
318 return minval;
319}
320
321// --------------------------------------------------------------------------
322//
323// get the maximum ratio of photons/error
324// If you specify a geometry the number of photons is weighted with the
325// area of the pixel
326//
327Float_t MSignalCam::GetErrorPhotMax(const MGeomCam *geom) const
328{
329 if (GetNumPixels() <= 0)
330 return 50.;
331
332 Float_t maxval = -FLT_MAX;
333
334 for (UInt_t i=0; i<GetNumPixels(); i++)
335 {
336 const MSignalPix &pix = (*this)[i];
337 if (!pix.IsPixelUsed())
338 continue;
339
340 Float_t testval = pix.GetErrorPhot();
341
342 if (geom)
343 testval *= geom->GetPixRatio(i/*pix.GetPixId()*/);
344
345 if (testval > maxval)
346 maxval = testval;
347 }
348 return maxval;
349}
350/*
351void MSignalCam::RemoveUnusedPixels()
352{
353 // Create iterator
354 TIter Next(fPixels);
355 MSignalPix *pix = NULL;
356
357 fMaxIndex = -1;
358
359 // Remove all unused pixels from list, calculate new fMaxIndex
360 while ((pix=(MSignalPix*)Next()))
361 {
362 if (!pix->IsPixelUsed())
363 fPixels->Remove(pix);
364 else
365 fMaxIndex = TMath::Max(fMaxIndex, pix->GetPixId());
366 }
367
368 // Crompress array
369 fPixels->Compress();
370
371 // Get new number of entries in array
372 fNumPixels=fPixels->GetEntriesFast();
373
374 // Rebuild lookup table
375 RebuildLut();
376}
377*/
378// --------------------------------------------------------------------------
379//
380// Return a pointer to the pixel with the requested idx. NULL if it doesn't
381// exist. The Look-up-table fLut is used. If its size is zero (according
382// to Rene this will happen if an old class object is loaded) we still
383// try to search in the array.
384//
385MSignalPix *MSignalCam::GetPixById(Int_t idx) const
386{
387 return (MSignalPix*)(fPixels->UncheckedAt(idx));
388 /*
389 if (idx<0)
390 return 0;
391
392 if (fLut.GetSize()>0)
393 {
394 if (idx>=fLut.GetSize())
395 return 0;
396 return fLut[idx]<0 ? 0 : (MSignalPix*)(fPixels->UncheckedAt(fLut[idx]));
397 }
398
399 TIter Next(fPixels);
400 MSignalPix *pix = NULL;
401
402 while ((pix=(MSignalPix*)Next()))
403 if (pix->GetPixId()==idx)
404 return pix;
405
406 return NULL;*/
407}
408
409MSignalPix *MSignalCam::AddPixel(Int_t idx, Float_t nph, Float_t er)
410{
411 /*
412 //
413 // If this is too slow or takes to much space we might use
414 // MGeomApply and an InitSize member function instead.
415 //
416 if (idx>=fLut.GetSize())
417 {
418 const Int_t n = fLut.GetSize();
419 fLut.Set(idx*2+1); //idx+1 is slower than idx*2+1
420 for (int i=n; i<idx*2+1; i++)
421 fLut[i] = -1;
422 }
423
424 fLut[idx] = fNumPixels;
425 if (idx>fMaxIndex)
426 fMaxIndex=idx;
427
428 return new ((*fPixels)[fNumPixels++]) MSignalPix(idx, nph, er);
429 */
430 //return new ((*fPixels)[idx]) MSignalPix(nph, er);
431
432 MSignalPix *pix = static_cast<MSignalPix*>((*fPixels)[idx]);
433 pix->Set(nph, er);
434 return pix;
435}
436
437// --------------------------------------------------------------------------
438//
439// This function recursively finds all pixels of one island and assigns
440// the number num as island number to the pixel.
441//
442// 1) Check whether a pixel with the index idx exists, is unused
443// and has not yet a island number assigned.
444// 2) Assign the island number num to the pixel
445// 3) Loop over all its neighbors taken from the geometry geom. For all
446// neighbors recursively call this function (CalcIsland)
447// 4) Sum the size of the pixel and all neighbors newly assigned
448// (by CalcIsland) to this island
449//
450// Returns the sum of the pixel size.
451//
452Double_t MSignalCam::CalcIsland(const MGeomCam &geom, Int_t idx, Int_t num)
453{
454 // Try to get the pixel information of a pixel with this index
455 MSignalPix *pix = GetPixById(idx);
456
457 // If a pixel with this index is not existing... do nothing.
458 if (!pix)
459 return 0;
460
461 // If an island number was already assigned to this pixel... do nothing.
462 if (pix->GetIdxIsland()>=0)
463 return 0;
464
465 // If the pixel is an unused pixel... do nothing.
466 if (!pix->IsPixelUsed())
467 return 0;
468
469 // Assign the new island number num to this used pixel
470 pix->SetIdxIsland(num);
471
472 // Get the geometry information (neighbors) of this pixel
473 const MGeomPix &gpix = geom[idx];
474
475 // Get the size of this pixel
476 Double_t size = pix->GetNumPhotons();
477
478 // Now do the same with all its neighbors and sum the
479 // sizes which they correspond to
480 const Int_t n = gpix.GetNumNeighbors();
481 for (int i=0; i<n; i++)
482 size += CalcIsland(geom, gpix.GetNeighbor(i), num);
483
484 // return size of this (sub)cluster
485 return size;
486}
487
488// --------------------------------------------------------------------------
489//
490// Each pixel which is maked as used is assigned an island number
491// (starting from 0). A pixel without an island number assigned
492// has island number -1.
493//
494// The index 0 corresponds to the island with the highest size (sum
495// of GetNumPhotons() in island). The size is decreasing with
496// increasing indices.
497//
498// The information about pixel neighbory is taken from the geometry
499// MGeomCam geom;
500//
501// You can access this island number of a pixel with a call to
502// MSignalPix->GetIdxIsland. The total number of islands available
503// can be accessed with MSignalCam->GetNumIslands.
504//
505// CalcIslands returns the number of islands found. If an error occurs,
506// eg the geometry has less pixels than the highest index stored, -1 is
507// returned.
508//
509Int_t MSignalCam::CalcIslands(const MGeomCam &geom)
510{
511 const UInt_t numpix = GetNumPixels();
512
513 if (/*fMaxIndex<0 ||*/ numpix==0)
514 {
515 *fLog << err << "ERROR - MSignalCam doesn't contain pixels!" << endl;
516 fNumIslands = 0;
517 return -1;
518 }
519/*
520 if ((UInt_t)fMaxIndex>=geom.GetNumPixels())
521 {
522 *fLog << err << "ERROR - MSignalCam::CalcIslands: Size mismatch - geometry too small!" << endl;
523 return -1;
524 }
525 */
526 // Create a list to hold the sizes of the islands (The maximum
527 // number of islands possible is roughly fNumPixels/4)
528 TArrayD size(numpix/3);
529
530 // Calculate Islands
531 Int_t n=0;
532 Float_t totsize = 0;
533
534 for (UInt_t idx=0; idx<numpix; idx++)
535 {
536 const MSignalPix &pix = (*this)[idx];
537 if (!pix.IsPixelUsed())
538 continue;
539
540 // This 'if' is necessary (although it is done in GetIsland, too)
541 // because otherwise the counter (n) would be wrong.
542 // So only 'start' a new island for used pixels (selected by
543 // using the Iterator) which do not yet belong to another island.
544 if (pix.GetIdxIsland()<0)
545 {
546 // Don't put this in one line! n is used twice...
547 const Double_t sz = CalcIsland(geom, idx/*pix->GetPixId()*/, n);
548 size[n++] = sz;
549 totsize += sz;
550 }
551 }
552
553 // Create an array holding the indices
554 TArrayI idxarr(n);
555
556 // Sort the sizes descending
557 TMath::Sort(n, size.GetArray(), idxarr.GetArray(), kTRUE);
558
559 // Replace island numbers by size indices -- After this
560 // islands indices are sorted by the island size
561 for (UInt_t idx=0; idx<numpix; idx++)
562 {
563 MSignalPix &pix = (*this)[idx];
564 if (!pix.IsPixelUsed())
565 continue;
566
567 const Short_t i = pix.GetIdxIsland();
568
569 // Find new index
570 Short_t j;
571 for (j=0; j<n; j++)
572 if (idxarr[j]==i)
573 break;
574
575 pix.SetIdxIsland(j==n ? -1 : j);
576 }
577
578 // Now assign number of islands found
579 fNumIslands = n;
580 fSizeSubIslands = n>0 ? totsize-size[idxarr[0]] : 0;
581 fSizeMainIsland = n>0 ? size[idxarr[0]] : 0;
582
583 // return number of island
584 return fNumIslands;
585}
586
587// --------------------------------------------------------------------------
588//
589// Returns, depending on the type flag:
590//
591// 0: Number of Photons*PixRatio <default>
592// 1: Error*sqrt(PixRatio)
593// 2: Cleaning level = Num Photons*sqrt(PixRatio)/Error
594// 3: Number of Photons
595// 4: Error
596// 5: Island index
597// 6: arrival time of mapped pixels
598// 7: arrival time if signa avove 20phe
599// 8: arrival time
600// 10: arrival time if extracted from lo-gain
601// 11: arrival time if extracted from hi-gain (and signal above 20phe)
602//
603Bool_t MSignalCam::GetPixelContent(Double_t &val, Int_t idx, const MGeomCam &cam, Int_t type) const
604{
605 MSignalPix *pix = GetPixById(idx);
606 if (!pix)
607 return kFALSE;
608
609 // Used inlcudes status unampped
610 if (!pix->IsPixelUsed() && (type<6 || type==8))
611 return kFALSE;
612
613 const Double_t ratio = cam.GetPixRatio(idx);
614
615 switch (type)
616 {
617 case 1: // scaled error of phtoons
618 val = pix->GetErrorPhot()*TMath::Sqrt(ratio);
619 return kTRUE;
620
621 case 2: // significance of number of photons
622 if (pix->GetErrorPhot()<=0)
623 return kFALSE;
624 val = pix->GetNumPhotons()*TMath::Sqrt(ratio)/pix->GetErrorPhot();
625 return kTRUE;
626
627 case 3: // number of photo electrons
628 val = pix->GetNumPhotons();
629 break;
630
631 case 4: // error of signal
632 val = pix->GetErrorPhot();
633 break;
634
635 case 5: // index of island
636 val = pix->GetIdxIsland();
637 break;
638
639 case 6: // arrival time of mapped pixels only
640 if (pix->IsPixelUnmapped())
641 return kFALSE;
642 val = pix->GetArrivalTime();
643 break;
644
645 case 7: // pulse position above 50phe
646 // The number of photons is not scaled with the ratio because
647 // otherwise to many large pixels survive (maybe because the
648 // fluctuations scale different than expected)
649 if (pix->IsPixelUnmapped() || pix->GetNumPhotons()<50)
650 return kFALSE;
651 val = pix->GetArrivalTime();
652 break;
653
654 case 8: // arrival time
655 val = pix->GetArrivalTime();
656 break;
657
658 /*
659 case 10: // lo gain time
660 if (pix->IsPixelUnmapped() || !pix->IsLoGainUsed() ||
661 pix->GetNumPhotons()<320)
662 return kFALSE;
663 val = pix->GetArrivalTime();
664 return kTRUE;
665
666 case 11: // hi gain time
667 // The number of photons is not scaled with the ratio because
668 // otherwise to many large pixels survive (maybe because the
669 // fluctuations scale different than expected)
670 if (pix->IsPixelUnmapped() || pix->IsLoGainUsed() ||
671 pix->GetNumPhotons()<50)
672 return kFALSE;
673 val = pix->GetArrivalTime();
674 return kTRUE;
675 */
676
677 default:
678 val = pix->GetNumPhotons()*ratio;
679 return kTRUE;
680 }
681 return kTRUE;
682}
683
684void MSignalCam::DrawPixelContent(Int_t num) const
685{
686 *fLog << warn << "MSignalCam::DrawPixelContent - not available." << endl;
687}
688
689TObject *MSignalCamIter::Next()
690{
691 if (!fUsedOnly)
692 {
693 fIdx++;
694 return TObjArrayIter::Next();
695 }
696
697 MSignalPix *pix;
698 while ((pix = (MSignalPix*)TObjArrayIter::Next()))
699 {
700 fIdx++;
701 if (pix->IsPixelUsed())
702 return pix;
703 }
704 return pix;
705}
Note: See TracBrowser for help on using the repository browser.