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

Last change on this file since 8489 was 8489, checked in by tbretz, 17 years ago
*** empty log message ***
File size: 15.2 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-2007
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 <TArrayI.h>
41#include <TArrayD.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// reset counter and delete netries in list.
71//
72void MSignalCam::Reset()
73{
74 fNumSinglePixels = 0;
75 fSizeSinglePixels = 0;
76 fSizeSubIslands = 0;
77 fSizeMainIsland = 0;
78 fNumIslands = -1;
79
80 fNumPixelsSaturatedHiGain = -1;
81 fNumPixelsSaturatedLoGain = -1;
82
83 fPixels->R__FOR_EACH(TObject, Clear)();
84}
85
86// --------------------------------------------------------------------------
87//
88// Dump the cerenkov photon event to *fLog
89//
90void MSignalCam::Print(Option_t *) const
91{
92 const Int_t entries = fPixels->GetEntries();
93
94 *fLog << GetDescriptor() << dec << endl;
95 *fLog << " Number of Pixels: " << GetNumPixels() << "(" << entries << ")" << endl;
96
97 for (Int_t i=0; i<entries; i++ )
98 (*this)[i].Print();
99}
100
101// --------------------------------------------------------------------------
102//
103// Count and return the number of unmapped pixels
104//
105Int_t MSignalCam::GetNumPixelsUnmapped() const
106{
107 const UInt_t n = GetNumPixels();
108
109 if (n <= 0)
110 return -1;
111
112 Int_t cnt=0;
113 for (UInt_t i=0; i<n; i++)
114 {
115 if ((*this)[i].IsPixelUnmapped())
116 cnt++;
117 }
118
119 return cnt;
120}
121
122// --------------------------------------------------------------------------
123//
124// get the minimum number of photons of all valid pixels in the list
125// If you specify a geometry the number of photons is weighted with the
126// area of the pixel
127//
128Float_t MSignalCam::GetNumPhotonsMin(const MGeomCam *geom) const
129{
130 const UInt_t n = GetNumPixels();
131
132 if (n <= 0)
133 return -5.;
134
135 Float_t minval = FLT_MAX;
136
137 for (UInt_t i=0; i<n; i++)
138 {
139 const MSignalPix &pix = (*this)[i];
140 if (!pix.IsPixelUsed())
141 continue;
142
143 Float_t testval = pix.GetNumPhotons();
144
145 if (geom)
146 testval *= geom->GetPixRatio(i);
147
148 if (testval < minval)
149 minval = testval;
150 }
151
152 return minval;
153}
154
155// --------------------------------------------------------------------------
156//
157// get the maximum number of photons of all valid pixels in the list
158// If you specify a geometry the number of photons is weighted with the
159// area of the pixel
160//
161Float_t MSignalCam::GetNumPhotonsMax(const MGeomCam *geom) const
162{
163 const UInt_t n = GetNumPixels();
164
165 if (n <= 0)
166 return 50.;
167
168 Float_t maxval = -FLT_MAX;
169
170 for (UInt_t i=0; i<n; i++)
171 {
172 const MSignalPix &pix = (*this)[i];
173 if (!pix.IsPixelUsed())
174 continue;
175
176 Float_t testval = pix.GetNumPhotons();
177 if (geom)
178 testval *= geom->GetPixRatio(i);
179
180 if (testval > maxval)
181 maxval = testval;
182 }
183 return maxval;
184}
185
186// --------------------------------------------------------------------------
187//
188// get the minimum ratio of photons/error
189//
190Float_t MSignalCam::GetRatioMin(const MGeomCam *geom) const
191{
192 const UInt_t n = GetNumPixels();
193
194 if (n <= 0)
195 return -5.;
196
197 Float_t minval = FLT_MAX;
198
199 for (UInt_t i=0; i<n; i++)
200 {
201 const MSignalPix &pix = (*this)[i];
202 if (!pix.IsPixelUsed())
203 continue;
204
205 Float_t testval = pix.GetNumPhotons()/pix.GetErrorPhot();
206 if (geom)
207 testval *= geom->GetPixRatioSqrt(i);
208
209 if (testval < minval)
210 minval = testval;
211 }
212
213 return minval;
214}
215
216// --------------------------------------------------------------------------
217//
218// get the maximum ratio of photons/error
219//
220Float_t MSignalCam::GetRatioMax(const MGeomCam *geom) const
221{
222 const UInt_t n = GetNumPixels();
223
224 if (n <= 0)
225 return -5.;
226
227 Float_t maxval = -FLT_MAX;
228
229 for (UInt_t i=0; i<n; i++)
230 {
231 const MSignalPix &pix = (*this)[i];
232 if (!pix.IsPixelUsed())
233 continue;
234
235 Float_t testval = pix.GetNumPhotons()/pix.GetErrorPhot();
236 if (geom)
237 testval *= geom->GetPixRatioSqrt(i);
238
239 if (testval > maxval)
240 maxval = testval;
241 }
242
243 return maxval;
244}
245
246// --------------------------------------------------------------------------
247//
248// get the minimum of error
249// If you specify a geometry the number of photons is weighted with the
250// area of the pixel
251//
252Float_t MSignalCam::GetErrorPhotMin(const MGeomCam *geom) const
253{
254 const UInt_t n = GetNumPixels();
255
256 if (n <= 0)
257 return 50.;
258
259 Float_t minval = FLT_MAX;
260
261 for (UInt_t i=0; i<n; i++)
262 {
263 const MSignalPix &pix = (*this)[i];
264 if (!pix.IsPixelUsed())
265 continue;
266
267 Float_t testval = pix.GetErrorPhot();
268
269 if (geom)
270 testval *= geom->GetPixRatio(i);
271
272 if (testval < minval)
273 minval = testval;
274 }
275 return minval;
276}
277
278// --------------------------------------------------------------------------
279//
280// get the maximum ratio of photons/error
281// If you specify a geometry the number of photons is weighted with the
282// area of the pixel
283//
284Float_t MSignalCam::GetErrorPhotMax(const MGeomCam *geom) const
285{
286 const UInt_t n = GetNumPixels();
287
288 if (n <= 0)
289 return 50.;
290
291 Float_t maxval = -FLT_MAX;
292
293 for (UInt_t i=0; i<n; i++)
294 {
295 const MSignalPix &pix = (*this)[i];
296 if (!pix.IsPixelUsed())
297 continue;
298
299 Float_t testval = pix.GetErrorPhot();
300
301 if (geom)
302 testval *= geom->GetPixRatio(i);
303
304 if (testval > maxval)
305 maxval = testval;
306 }
307 return maxval;
308}
309
310MSignalPix *MSignalCam::AddPixel(Int_t idx, Float_t nph, Float_t er)
311{
312 MSignalPix *pix = static_cast<MSignalPix*>((*fPixels)[idx]);
313 pix->Set(nph, er);
314 return pix;
315}
316
317// --------------------------------------------------------------------------
318//
319// This function recursively finds all pixels of one island and assigns
320// the number num as island number to the pixel.
321//
322// 1) Check whether a pixel with the index idx exists, is unused
323// and has not yet a island number assigned.
324// 2) Assign the island number num to the pixel
325// 3) Loop over all its neighbors taken from the geometry geom. For all
326// neighbors recursively call this function (CalcIsland)
327// 4) Sum the size of the pixel and all neighbors newly assigned
328// (by CalcIsland) to this island
329//
330// Returns the sum of the pixel size.
331//
332Double_t MSignalCam::CalcIsland(const MGeomCam &geom, Int_t idx, Int_t num)
333{
334 // Get the pixel information of a pixel with this index
335 MSignalPix &pix = (*this)[idx];
336
337 // If an island number was already assigned to this pixel... do nothing.
338 if (pix.GetIdxIsland()>=0)
339 return 0;
340
341 // If the pixel is an unused pixel... do nothing.
342 if (!pix.IsPixelUsed())
343 return 0;
344
345 // Assign the new island number num to this used pixel
346 pix.SetIdxIsland(num);
347
348 // Get the geometry information (neighbors) of this pixel
349 const MGeomPix &gpix = geom[idx];
350
351 // Get the size of this pixel
352 Double_t size = pix.GetNumPhotons();
353
354 // Now do the same with all its neighbors and sum the
355 // sizes which they correspond to
356 const Int_t n = gpix.GetNumNeighbors();
357 for (int i=0; i<n; i++)
358 size += CalcIsland(geom, gpix.GetNeighbor(i), num);
359
360 // return size of this (sub)cluster
361 return size;
362}
363
364// --------------------------------------------------------------------------
365//
366// Each pixel which is maked as used is assigned an island number
367// (starting from 0). A pixel without an island number assigned
368// has island number -1.
369//
370// The index 0 corresponds to the island with the highest size (sum
371// of GetNumPhotons() in island). The size is decreasing with
372// increasing indices.
373//
374// The information about pixel neighbory is taken from the geometry
375// MGeomCam geom;
376//
377// You can access this island number of a pixel with a call to
378// MSignalPix->GetIdxIsland. The total number of islands available
379// can be accessed with MSignalCam->GetNumIslands.
380//
381// CalcIslands returns the number of islands found. If an error occurs,
382// eg the geometry has less pixels than the highest index stored, -1 is
383// returned.
384//
385Int_t MSignalCam::CalcIslands(const MGeomCam &geom)
386{
387 const UInt_t numpix = GetNumPixels();
388
389 if (/*fMaxIndex<0 ||*/ numpix==0)
390 {
391 *fLog << err << "ERROR - MSignalCam doesn't contain pixels!" << endl;
392 fNumIslands = 0;
393 return -1;
394 }
395/*
396 if ((UInt_t)fMaxIndex>=geom.GetNumPixels())
397 {
398 *fLog << err << "ERROR - MSignalCam::CalcIslands: Size mismatch - geometry too small!" << endl;
399 return -1;
400 }
401 */
402 // Create a list to hold the sizes of the islands (The maximum
403 // number of islands possible is roughly fNumPixels/4)
404 TArrayD size(numpix/3);
405
406 // Calculate Islands
407 Int_t n=0;
408 Float_t totsize = 0;
409
410 for (UInt_t idx=0; idx<numpix; idx++)
411 {
412 const MSignalPix &pix = (*this)[idx];
413 if (!pix.IsPixelUsed())
414 continue;
415
416 // This 'if' is necessary (although it is done in GetIsland, too)
417 // because otherwise the counter (n) would be wrong.
418 // So only 'start' a new island for used pixels (selected by
419 // using the Iterator) which do not yet belong to another island.
420 if (pix.GetIdxIsland()<0)
421 {
422 // Don't put this in one line! n is used twice...
423 const Double_t sz = CalcIsland(geom, idx/*pix->GetPixId()*/, n);
424 size[n++] = sz;
425 totsize += sz;
426 }
427 }
428
429 // Create an array holding the indices
430 TArrayI idxarr(n);
431
432 // Sort the sizes descending
433 TMath::Sort(n, size.GetArray(), idxarr.GetArray(), kTRUE);
434
435 // Replace island numbers by size indices -- After this
436 // islands indices are sorted by the island size
437 for (UInt_t idx=0; idx<numpix; idx++)
438 {
439 MSignalPix &pix = (*this)[idx];
440 if (!pix.IsPixelUsed())
441 continue;
442
443 const Short_t i = pix.GetIdxIsland();
444
445 // Find new index
446 Short_t j;
447 for (j=0; j<n; j++)
448 if (idxarr[j]==i)
449 break;
450
451 pix.SetIdxIsland(j==n ? -1 : j);
452 }
453
454 // Now assign number of islands found
455 fNumIslands = n;
456 fSizeSubIslands = n>0 ? totsize-size[idxarr[0]] : 0;
457 fSizeMainIsland = n>0 ? size[idxarr[0]] : 0;
458
459 // return number of island
460 return fNumIslands;
461}
462
463// --------------------------------------------------------------------------
464//
465// Returns, depending on the type flag:
466//
467// 0: Number of Photons*PixRatio <default>
468// 1: Error*sqrt(PixRatio)
469// 2: Cleaning level = Num Photons*sqrt(PixRatio)/Error
470// 3: Number of Photons
471// 4: Error
472// 5: Island index
473// 6: arrival time of mapped pixels
474// 7: arrival time if signa avove 20phe
475// 8: arrival time
476// 10: arrival time if extracted from lo-gain
477// 11: arrival time if extracted from hi-gain (and signal above 20phe)
478//
479Bool_t MSignalCam::GetPixelContent(Double_t &val, Int_t idx, const MGeomCam &cam, Int_t type) const
480{
481 if (idx<0 || (UInt_t)idx>GetNumPixels())
482 return kFALSE;
483
484 const MSignalPix &pix = (*this)[idx];
485
486 // Used inlcudes status unampped
487 if (!pix.IsPixelUsed() && (type<6 || type==8))
488 return kFALSE;
489
490 const Double_t ratio = cam.GetPixRatio(idx);
491
492 switch (type)
493 {
494 case 1: // scaled error of phtoons
495 val = pix.GetErrorPhot()*TMath::Sqrt(ratio);
496 return kTRUE;
497
498 case 2: // significance of number of photons
499 if (pix.GetErrorPhot()<=0)
500 return kFALSE;
501 val = pix.GetNumPhotons()*TMath::Sqrt(ratio)/pix.GetErrorPhot();
502 return kTRUE;
503
504 case 3: // number of photo electrons
505 val = pix.GetNumPhotons();
506 break;
507
508 case 4: // error of signal
509 val = pix.GetErrorPhot();
510 break;
511
512 case 5: // index of island
513 val = pix.GetIdxIsland();
514 break;
515
516 case 6: // arrival time of mapped pixels only
517 if (pix.IsPixelUnmapped())
518 return kFALSE;
519 val = pix.GetArrivalTime();
520 break;
521
522 case 7: // pulse position above 50phe
523 // The number of photons is not scaled with the ratio because
524 // otherwise to many large pixels survive (maybe because the
525 // fluctuations scale different than expected)
526 if (pix.IsPixelUnmapped() || pix.GetNumPhotons()<50)
527 return kFALSE;
528 val = pix.GetArrivalTime();
529 break;
530
531 case 8: // arrival time
532 val = pix.GetArrivalTime();
533 break;
534
535 /*
536 case 10: // lo gain time
537 if (pix.IsPixelUnmapped() || !pix.IsLoGainUsed() ||
538 pix.GetNumPhotons()<320)
539 return kFALSE;
540 val = pix.GetArrivalTime();
541 return kTRUE;
542
543 case 11: // hi gain time
544 // The number of photons is not scaled with the ratio because
545 // otherwise to many large pixels survive (maybe because the
546 // fluctuations scale different than expected)
547 if (pix.IsPixelUnmapped() || pix.IsLoGainUsed() ||
548 pix.GetNumPhotons()<50)
549 return kFALSE;
550 val = pix.GetArrivalTime();
551 return kTRUE;
552 */
553
554 default:
555 val = pix.GetNumPhotons()*ratio;
556 return kTRUE;
557 }
558 return kTRUE;
559}
560
561void MSignalCam::DrawPixelContent(Int_t num) const
562{
563 *fLog << warn << "MSignalCam::DrawPixelContent - not available." << endl;
564}
565
566TObject *MSignalCamIter::Next()
567{
568 if (!fUsedOnly)
569 {
570 fIdx++;
571 return TObjArrayIter::Next();
572 }
573
574 MSignalPix *pix;
575 while ((pix = (MSignalPix*)TObjArrayIter::Next()))
576 {
577 fIdx++;
578 if (pix->IsPixelUsed())
579 return pix;
580 }
581 return pix;
582}
Note: See TracBrowser for help on using the repository browser.