source: trunk/MagicSoft/Mars/mimage/MImgCleanStd.cc@ 8154

Last change on this file since 8154 was 7804, checked in by tbretz, 18 years ago
*** empty log message ***
File size: 29.3 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, 12/2000 <mailto:tbretz@astro.uni-wuerzburg.de>
19! Author(s): Harald Kornmayer, 1/2001
20! Author(s): Nadia Tonello, 4/2003 <mailto:tonello@mppmu.mpg.de>
21! Author(s): Stefan Ruegamer, 03/2006 <mailto:snruegam@astro.uni-wuerzburg.de>
22!
23! Copyright: MAGIC Software Development, 2000-2006
24!
25!
26\* ======================================================================== */
27
28/////////////////////////////////////////////////////////////////////////////
29//
30// MImgCleanStd
31//
32// The Image Cleaning task selects the pixels you use for the Hillas
33// parameters calculation.
34//
35// There are two methods to make the selection: the standard one, as done
36// in the analysis of CT1 data, and the democratic one, as suggested by
37// W.Wittek. The number of photo-electrons of a pixel is compared with the
38// pedestal RMS of the pixel itself (standard method) or with the average
39// RMS of the inner pixels (democratic method).
40// In both cases, the possibility to have a camera with pixels of
41// different area is taken into account.
42// The too noisy pixels can be recognized and eventually switched off
43// (Unmap: set blind pixels to UNUSED) separately, using the
44// MBlindPixelCalc Class. In the MBlindPixelCalc class there is also the
45// function to replace the value of the noisy pixels with the interpolation
46// of the content of the neighbors (SetUseInterpolation).
47//
48// Example:
49// ...
50// MBlindPixelCalc blind;
51// blind.SetUseInterpolation();
52// blind.SetUseBlindPixels();
53//
54// MImgCleanStd clean;
55// ...
56// tlist.AddToList(&blind);
57// tlist.AddToList(&clean);
58//
59// Look at the MBlindPixelCalc Class for more details.
60//
61// Starting point: default values ----------------------------------------
62//
63// When an event is read, before the image cleaning, all the pixels that
64// are in MSignalCam are set as USED and NOT CORE. All the pixels belong
65// to RING number 1 (like USED pixels).
66// Look at MSignalPix.h to see how these informations of the pixel are
67// stored.
68// The default cleaning METHOD is the STANDARD one and the number of the
69// rings around the CORE pixel it analyzes is 1. Look at the Constructor
70// of the class in MImgCleanStd.cc to see (or change) the default values.
71//
72// Example: To modify this setting, use the member functions
73// SetMethod(MImgCleanStd::kDemocratic) and SetCleanRings(UShort_t n).
74//
75// MImgCleanStd:CleanStep1 -----------------------------------------------
76//
77// The first step of cleaning defines the CORE pixels. The CORE pixels are
78// the ones which contain the informations about the core of the electro-
79// magnetic shower.
80// The ratio (A_0/A_i) is calculated from fCam->GetPixRatio(i). A_0 is
81// the area of the central pixel of the camera, A_i is the area of the
82// examined pixel. In this way, if we have a MAGIC-like camera, with the
83// outer pixels bigger than the inner ones, the level of cleaning in the
84// two different regions is weighted.
85// This avoids problems of deformations of the shower images.
86// The signal S_i and the pedestal RMS Prms_i of the pixel are called from
87// the object MSignalPix.
88// If (default method = kStandard)
89//Begin_Html
90//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="images/MImgCleanStd-f1.png">
91//End_Html
92// the pixel is set as CORE pixel. L_1 (n=1) is called "first level of
93// cleaning" (default: fCleanLvl1 = 3).
94// All the other pixels are set as UNUSED and belong to RING 0.
95// After this point, only the CORE pixels are set as USED, with RING
96// number 1.
97//
98// MImgCleanStd:CleanStep2 ----------------------------------------------
99//
100// The second step of cleaning looks at the isolated CORE pixels and sets
101// them to UNUSED. An isolated pixel is a pixel without CORE neighbors.
102// At the end of this point, we have set as USED only CORE pixels with at
103// least one CORE neighbor.
104//
105// MImgCleanStd:CleanStep3 ----------------------------------------------
106//
107// The third step of cleaning looks at all the pixels (USED or UNUSED) that
108// surround the USED pixels.
109// If the content of the analyzed pixel survives at the second level of
110// cleaning, i.e. if
111//Begin_Html
112//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="images/MImgCleanStd-f1.png">
113//End_Html
114// the pixel is set as USED. L_2 (n=2) is called "second level of cleaning"
115// (default:fCleanLvl2 = 2.5).
116//
117// When the number of RINGS to analyze is 1 (default value), only the
118// pixels that have a neighbor CORE pixel are analyzed.
119//
120// There is the option to decide the number of times you want to repeat
121// this procedure (number of RINGS analyzed around the core pixels = n).
122// Every time the level of cleaning is the same (fCleanLvl2) and the pixel
123// will belong to ring r+1, 1 < r < n+1. This is described in
124// MImgCleanStd:CleanStep4 .
125//
126// Dictionary and member functions ---------------------------------------
127//
128// Here there is the detailed description of the member functions and of
129// the terms commonly used in the class.
130//
131//
132// STANDARD CLEANING:
133// =================
134// This is the method used for the CT1 data analysis. It is the default
135// method of the class.
136// The number of photo-electrons of a pixel (S_i) is compared to the
137// pedestal RMS of the pixel itself (Prms_i). To have the comparison to
138// the same photon density for all the pixels, taking into account they
139// can have different areas, we have to keep in mind that the number of
140// photons that hit each pixel, goes linearly with the area of the pixel.
141// The fluctuations of the LONS are proportional to sqrt(A_i), so when we
142// compare S_i with Prms_i, only a factor sqrt(A_0/A_i) is missing to
143// have the same (N.photons/Area) threshold for all the pixels.
144//
145// !!WARNING: if noise independent from the
146// pixel size (example: electronic noise) is introduced,
147// then the noise fluctuations are no longer proportional
148// to sqrt(A_i), and then the cut value (for a camera with
149// pixels of different sizes) resulting from the above
150// procedure would not be proportional to pixel size as we
151// intend. In that case, democratic cleaning is preferred.
152//
153// If
154//Begin_Html
155//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="images/MImgCleanStd-f1.png">
156//End_Html
157// the pixel survives the cleaning and it is set as CORE (when L_n is the
158// first level of cleaning, fCleanLvl1) or USED (when L_n is the second
159// level of cleaning, fCleanLvl2).
160//
161// Example:
162//
163// MImgCleanStd clean;
164// //creates a default Cleaning object, with default setting
165// ...
166// tlist.AddToList(&clean);
167// // add the image cleaning to the main task list
168//
169//
170// DEMOCRATIC CLEANING:
171// ===================
172// You use this cleaning method when you want to compare the number of
173// photo-electrons of each pixel with the average pedestal RMS of the
174// inner pixels (for the MAGIC camera they are the smaller ones):
175//Begin_Html
176//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="images/MImgCleanStd-f2.png">
177//End_Html
178// In this case, the simple ratio (A_0/A_i) is used to weight the level of
179// cleaning, because both the inner and the outer pixels (that in MAGIC
180// have a different area) are compared to the same pedestal RMS, coming
181// from the inner pixels.
182//
183// Make sure that you used a class calculating the MPedPhotCam which also
184// updated the contents of the mean values (Recalc) correctly.
185//
186//
187// PROBABILITY CLEANING
188// ====================
189// This method takes signal height (over signal noise) and arrival time
190// into account. Instead of comparing signal/Noise with cleaning level
191// one and two, we calculate
192// - P_ped: The probability that a signal is a pedestal (using
193// the signal height and the pedestal) For this probability the
194// same algorithm like in kScaled is used (which is a standard
195// cleaning which scales the noise with the mean noise of pixels
196// with the same size)
197// - P_sig: The probability that the signal corresponds to the pixel
198// with the highest signal. For this probability we use the
199// arrival time only.
200//
201// The cleaning now is done in levels of Probability (eg. 0.2, 0.05)
202// The meaning of the cleaning levels is essentially the same (the same cleaning
203// algorithm is used) but the cleaning is not done in levels of signal/noise
204// but in level of this probability.
205//
206// This probability is calculated as (1-P_ped)*P_sig
207//
208// Example:
209//
210// MImgCleanStd clean(0.2, 0.05);
211// clean.SetMethod(MImgCleanStd::kProbability);
212//
213//
214// ABSOLUTE CLEANING
215// =================
216// This method takes signal height (photons) times area ratio
217// ad the cleaning levels.
218//
219// The cleaning now is done in these levels (eg. 16, 20)
220// The meaning of the cleaning levels is essentially the same (the same cleaning
221// algorithm is used) but the cleaning is not done in different 'units'
222//
223// Example:
224//
225// MImgCleanStd clean(20, 16);
226// clean.SetMethod(MImgCleanStd::kAbsolulte);
227//
228//
229// Member Function: SetMethod()
230// ============================
231// When you call the MImgCleanStd task, the default method is kStandard.
232//
233// If you want to switch to the kDemocratic method you have to
234// call this member function.
235//
236// Example:
237//
238// MImgCleanStd clean;
239// //creates a default Cleaning object, with default setting
240//
241// clean.SetMethod(MImgCleanStd::kDemocratic);
242// //now the method of cleaning is changed to Democratic
243//
244//
245// FIRST AND SECOND CLEANING LEVEL
246// ===============================
247// When you call the MImgCleanStd task, the default cleaning levels are
248// fCleanLvl1 = 3, fCleanLvl2 = 2.5. You can change them easily when you
249// create the MImgCleanStd object.
250//
251// Example:
252//
253// MImgCleanStd clean(Float_t lvl1,Float_t lvl2);
254// //creates a default cleaning object, but the cleaning levels are now
255// //lvl1 and lvl2.
256//
257// RING NUMBER
258// ===========
259// The standard cleaning procedure is such that it looks for the
260// informations of the boundary part of the shower only on the first
261// neighbors of the CORE pixels.
262// There is the possibility now to look not only at the first neighbors
263// (first ring),but also further away, around the CORE pixels. All the new
264// pixels you can find with this method, are tested with the second level
265// of cleaning and have to have at least an USED neighbor.
266//
267// They will be also set as USED and will be taken into account during the
268// calculation of the image parameters.
269// The only way to distinguish them from the other USED pixels, is the
270// Ring number, that is bigger than 1.
271//
272// Example: You can decide how many rings you want to analyze using:
273//
274// MImgCleanStd clean;
275// //creates a default cleaning object (default number of rings =1)
276// clean.SetCleanRings(UShort_t r);
277// //now it looks r times around the CORE pixels to find new pixels with
278// //signal.
279//
280//
281// Input Containers:
282// MGeomCam
283// MPedPhotCam
284// MSignalCam
285//
286// Output Containers:
287// MSignalCam
288//
289/////////////////////////////////////////////////////////////////////////////
290#include "MImgCleanStd.h"
291
292#include <stdlib.h> // atof
293#include <fstream> // ofstream, SavePrimitive
294
295#include <TEnv.h>
296
297#include <TGFrame.h> // TGFrame
298#include <TGLabel.h> // TGLabel
299#include <TGTextEntry.h> // TGTextEntry
300
301#include "MLog.h"
302#include "MLogManip.h"
303
304#include "MParList.h"
305#include "MCameraData.h"
306
307#include "MGeomPix.h"
308#include "MGeomCam.h"
309
310#include "MSignalPix.h"
311#include "MSignalCam.h"
312
313#include "MGGroupFrame.h" // MGGroupFrame
314
315ClassImp(MImgCleanStd);
316
317using namespace std;
318
319enum {
320 kImgCleanLvl1,
321 kImgCleanLvl2
322};
323
324static const TString gsDefName = "MImgCleanStd";
325static const TString gsDefTitle = "Task to perform image cleaning";
326
327const TString MImgCleanStd::gsNamePedPhotCam="MPedPhotCam"; // default name of the 'MPedPhotCam' container
328const TString MImgCleanStd::gsNameSignalCam ="MSignalCam"; // default name of the 'MSignalCam' container
329const TString MImgCleanStd::gsNameGeomCam ="MGeomCam"; // default name of the 'MGeomCam' container
330
331// --------------------------------------------------------------------------
332//
333// Default constructor. Here you can specify the cleaning method and levels.
334// If you don't specify them the 'common standard' values 3.0 and 2.5 (sigma
335// above mean) are used.
336// Here you can also specify how many rings around the core pixels you want
337// to analyze (with the fixed lvl2). The default value for "rings" is 1.
338//
339MImgCleanStd::MImgCleanStd(const Float_t lvl1, const Float_t lvl2,
340 const char *name, const char *title)
341 : fCleaningMethod(kStandard), fCleanLvl1(lvl1),
342 fCleanLvl2(lvl2), fCleanRings(1), fKeepSinglePixels(kFALSE),
343 fNamePedPhotCam(gsNamePedPhotCam), fNameGeomCam(gsNameGeomCam),
344 fNameSignalCam(gsNameSignalCam)
345{
346 fName = name ? name : gsDefName.Data();
347 fTitle = title ? title : gsDefTitle.Data();
348}
349
350// --------------------------------------------------------------------------
351//
352// The first step of cleaning defines the CORE pixels. All the other pixels
353// are set as UNUSED and belong to RING 0.
354// After this point, only the CORE pixels are set as USED, with RING
355// number 1.
356//
357// NT 28/04/2003: now the option to use the standard method or the
358// democratic method is implemented:
359//
360// kStandard: This method looks for all pixels with an entry (photons)
361// that is three times bigger than the noise of the pixel
362// (default: 3 sigma, clean level 1)
363//
364// kDemocratic: this method looks for all pixels with an entry (photons)
365// that is n times bigger than the noise of the mean of the
366// inner pixels (default: 3 sigmabar, clean level 1)
367//
368//
369void MImgCleanStd::CleanStep1()
370{
371 const TArrayD &data = fData->GetData();
372
373 //
374 // check the number of all pixels against the noise level and
375 // set them to 'unused' state if necessary
376 //
377 const UInt_t npixevt = fEvt->GetNumPixels();
378 for (UInt_t idx=0; idx<npixevt; idx++)
379 {
380 // The default for pixels is "used" set by
381 // MParContainer::Reset before processing
382 if (data[idx]>fCleanLvl1)
383 continue;
384
385 // Setting a pixel to unused if it is unmapped would overwrite
386 // the unmapped-status. Therefor this pixels are excluded.
387 MSignalPix &pix = (*fEvt)[idx];
388 if (!pix.IsPixelUnmapped())
389 pix.SetPixelUnused();
390 }
391}
392
393// --------------------------------------------------------------------------
394//
395// Check if the survived pixel have a neighbor, that also
396// survived. Set all single pixels Unused if !fKeepSinglePixels. Now we
397// declare all pixels that survived previous CleanSteps as CorePixels.
398// Return number of single pixels, and there cumulative size in size.
399//
400Short_t MImgCleanStd::CleanStep2(Float_t &size)
401{
402 Short_t n=0;
403 size = 0;
404
405 const UInt_t npixevt = fEvt->GetNumPixels();
406 for (UInt_t idx=0; idx<npixevt; idx++)
407 {
408 // Exclude all unused (this includes all unmapped) pixels
409 MSignalPix &pix = (*fEvt)[idx];
410 if (!pix.IsPixelUsed())
411 continue;
412
413 // check for 'used' neighbors of this pixel
414 const MGeomPix &gpix = (*fCam)[idx];
415 const Int_t nnmax = gpix.GetNumNeighbors();
416
417 Bool_t hasNeighbor = kFALSE;
418
419 //loop on the neighbors to check if they are used
420 for (Int_t j=0; j<nnmax; j++)
421 {
422 const Int_t idx2 = gpix.GetNeighbor(j);
423
424 // when you find an used neighbor (this excludes unused
425 // and unmapped pixels) break the loop
426 if ((*fEvt)[idx2].IsPixelUsed())
427 {
428 hasNeighbor = kTRUE;
429 break;
430 }
431 }
432
433 // If the pixel has at least one core-neighbor
434 // go on with the next pixel
435 if (hasNeighbor)
436 continue;
437
438 // If the pixel has no neighbors and the single pixels
439 // should not be kept turn the used- into an unused-status
440 if (!fKeepSinglePixels)
441 pix.SetPixelUnused();
442
443 // count size and number of single core-pixels
444 size += pix.GetNumPhotons();
445 n++;
446 }
447
448 // Now turn the used-status into the core-status
449 // (FIXME: A more intelligent handling of used/core in clean step1/2
450 // would make this loop obsolete!)
451 for (UInt_t idx=0; idx<npixevt; idx++)
452 {
453 MSignalPix &pix = (*fEvt)[idx];
454 pix.SetPixelCore(pix.IsPixelUsed());
455 }
456
457 return n;
458}
459
460void MImgCleanStd::CleanStep3b(Int_t idx)
461{
462 MSignalPix &pix = (*fEvt)[idx];
463
464 //
465 // check if the pixel's next neighbor is a core pixel.
466 // if it is a core pixel set pixel state to: used.
467 //
468 MGeomPix &gpix = (*fCam)[idx];
469 const Int_t nnmax = gpix.GetNumNeighbors();
470
471 for (Int_t j=0; j<nnmax; j++)
472 {
473 const Int_t idx2 = gpix.GetNeighbor(j);
474
475 // Check if the neighbor pixel is a core pixel. (Rem: Unampped
476 // pixels are never assigned the core-pixel status)
477 if (!(*fEvt)[idx2].IsPixelCore())
478 continue;
479
480 pix.SetPixelUsed();
481 break;
482 }
483}
484
485// --------------------------------------------------------------------------
486//
487// NT: Add option "rings": default value = 1.
488// Look n (n>1) times for the boundary pixels around the used pixels.
489// If a pixel has more than 2.5 (clean level 2.5) sigma,
490// it is declared as used.
491//
492// If a value<2 for fCleanRings is used, no CleanStep4 is done.
493//
494void MImgCleanStd::CleanStep4(UShort_t r, Int_t idx)
495{
496 MSignalPix &pix = (*fEvt)[idx];
497
498 //
499 // Skip events that have already a defined status;
500 //
501 if (pix.GetRing() != 0)
502 return;
503
504 //
505 // check if the pixel's next neighbor is a used pixel.
506 // if it is a used pixel set pixel state to: used,
507 // and tell to which ring it belongs to.
508 //
509 MGeomPix &gpix = (*fCam)[idx];
510
511 const Int_t nnmax = gpix.GetNumNeighbors();
512
513 for (Int_t j=0; j<nnmax; j++)
514 {
515 const Int_t idx2 = gpix.GetNeighbor(j);
516
517 const MSignalPix &npix = (*fEvt)[idx2];
518 if (!npix.IsPixelUsed() || npix.GetRing()>r-1 )
519 continue;
520
521 pix.SetRing(r);
522 break;
523 }
524}
525
526// --------------------------------------------------------------------------
527//
528// Look for the boundary pixels around the core pixels
529// if a pixel has more than 2.5 (clean level 2.5) sigma, and
530// a core neighbor, it is declared as used.
531//
532void MImgCleanStd::CleanStep3()
533{
534 const TArrayD &data = fData->GetData();
535
536 for (UShort_t r=1; r<fCleanRings+1; r++)
537 {
538 // Loop over all pixels
539 const UInt_t npixevt = fEvt->GetNumPixels();
540 for (UInt_t idx=0; idx<npixevt; idx++)
541 {
542 MSignalPix &pix = (*fEvt)[idx];
543
544 //
545 // if pixel is a core pixel or unmapped, go to the next pixel
546 //
547 if (pix.IsPixelCore() || pix.IsPixelUnmapped())
548 continue;
549
550 if (data[idx] <= fCleanLvl2)
551 continue;
552
553 if (r==1)
554 CleanStep3b(idx);
555 else
556 CleanStep4(r, idx);
557 }
558 }
559}
560
561// --------------------------------------------------------------------------
562//
563// Check if MEvtHeader exists in the Parameter list already.
564// if not create one and add them to the list
565//
566Int_t MImgCleanStd::PreProcess (MParList *pList)
567{
568 fCam = (MGeomCam*)pList->FindObject(AddSerialNumber(fNameGeomCam), "MGeomCam");
569 if (!fCam)
570 {
571 *fLog << err << fNameGeomCam << " [MGeomCam] not found (no geometry information available)... aborting." << endl;
572 return kFALSE;
573 }
574
575 fEvt = (MSignalCam*)pList->FindObject(AddSerialNumber(fNameSignalCam), "MSignalCam");
576 if (!fEvt)
577 {
578 *fLog << err << fNameSignalCam << " [MSignalCam] not found... aborting." << endl;
579 return kFALSE;
580 }
581
582 fPed=0;
583 if (fCleaningMethod!=kAbsolute && fCleaningMethod!=kTime)
584 {
585 fPed = (MPedPhotCam*)pList->FindObject(AddSerialNumber(fNamePedPhotCam), "MPedPhotCam");
586 if (!fPed)
587 {
588 *fLog << err << fNamePedPhotCam << " [MPedPhotCam] not found... aborting." << endl;
589 return kFALSE;
590 }
591 }
592
593 fData = (MCameraData*)pList->FindCreateObj(AddSerialNumber("MCameraData"));
594 if (!fData)
595 return kFALSE;
596
597 Print();
598
599 return kTRUE;
600}
601
602// --------------------------------------------------------------------------
603//
604// Cleans the image.
605//
606Int_t MImgCleanStd::Process()
607{
608 switch (fCleaningMethod)
609 {
610 case kStandard:
611 fData->CalcCleaningLevel(*fEvt, *fPed, *fCam);
612 break;
613 case kScaled:
614 fData->CalcCleaningLevel2(*fEvt, *fPed, *fCam);
615 break;
616 case kDemocratic:
617 fData->CalcCleaningLevelDemocratic(*fEvt, *fPed, *fCam);
618 break;
619 case kProbability:
620 fData->CalcCleaningProbability(*fEvt, *fPed, *fCam);
621 break;
622 case kAbsolute:
623 fData->CalcCleaningAbsolute(*fEvt, *fCam);
624 break;
625 case kTime:
626 fData->CalcCleaningArrivalTime(*fEvt, *fCam);
627 break;
628 default:
629 break;
630 }
631
632#ifdef DEBUG
633 *fLog << all << "CleanStep 1" << endl;
634#endif
635 CleanStep1();
636
637
638#ifdef DEBUG
639 *fLog << all << "CleanStep 2" << endl;
640#endif
641 Float_t size;
642 const Short_t n = CleanStep2(size);
643 fEvt->SetSinglePixels(n, size);
644
645 // For speed reasons skip the rest of the cleaning if no
646 // action will be taken!
647 if (fCleanLvl1>fCleanLvl2)
648 {
649#ifdef DEBUG
650 *fLog << all << "CleanStep 3" << endl;
651#endif
652 CleanStep3();
653 }
654
655#ifdef DEBUG
656 *fLog << all << "Calc Islands" << endl;
657#endif
658 // Takes roughly 10% of the time
659 fEvt->CalcIslands(*fCam);
660
661#ifdef DEBUG
662 *fLog << all << "Done." << endl;
663#endif
664
665 return kTRUE;
666}
667
668// --------------------------------------------------------------------------
669//
670// Print descriptor and cleaning levels.
671//
672void MImgCleanStd::Print(Option_t *o) const
673{
674 *fLog << all << GetDescriptor() << " using ";
675 switch (fCleaningMethod)
676 {
677 case kDemocratic:
678 *fLog << "democratic";
679 break;
680 case kStandard:
681 *fLog << "standard";
682 break;
683 case kScaled:
684 *fLog << "scaled";
685 break;
686 case kProbability:
687 *fLog << "probability";
688 break;
689 case kAbsolute:
690 *fLog << "absolute";
691 break;
692 case kTime:
693 *fLog << "time";
694 break;
695
696 }
697 *fLog << " cleaning" << endl;
698 *fLog << "initialized with level " << fCleanLvl1 << " and " << fCleanLvl2;
699 *fLog << " (CleanRings=" << fCleanRings << ")" << endl;
700
701 *fLog << "Name of MPedPhotCam container used: ";
702 *fLog << (fPed?((MParContainer*)fPed)->GetName():(const char*)fNamePedPhotCam) << endl;
703}
704
705// --------------------------------------------------------------------------
706//
707// Create two text entry fields, one for each cleaning level and a
708// describing text line.
709//
710void MImgCleanStd::CreateGuiElements(MGGroupFrame *f)
711{
712 //
713 // Create a frame for line 3 and 4 to be able
714 // to align entry field and label in one line
715 //
716 TGHorizontalFrame *f1 = new TGHorizontalFrame(f, 0, 0);
717 TGHorizontalFrame *f2 = new TGHorizontalFrame(f, 0, 0);
718
719 /*
720 * --> use with root >=3.02 <--
721 *
722
723 TGNumberEntry *fNumEntry1 = new TGNumberEntry(frame, 3.0, 2, M_NENT_LVL1, kNESRealOne, kNEANonNegative);
724 TGNumberEntry *fNumEntry2 = new TGNumberEntry(frame, 2.5, 2, M_NENT_LVL1, kNESRealOne, kNEANonNegative);
725
726 */
727 TGTextEntry *entry1 = new TGTextEntry(f1, "****", kImgCleanLvl1);
728 TGTextEntry *entry2 = new TGTextEntry(f2, "****", kImgCleanLvl2);
729
730 // --- doesn't work like expected (until root 3.02?) --- fNumEntry1->SetAlignment(kTextRight);
731 // --- doesn't work like expected (until root 3.02?) --- fNumEntry2->SetAlignment(kTextRight);
732
733 entry1->SetText("3.0");
734 entry2->SetText("2.5");
735
736 entry1->Associate(f);
737 entry2->Associate(f);
738
739 TGLabel *l1 = new TGLabel(f1, "Cleaning Level 1");
740 TGLabel *l2 = new TGLabel(f2, "Cleaning Level 2");
741
742 l1->SetTextJustify(kTextLeft);
743 l2->SetTextJustify(kTextLeft);
744
745 //
746 // Align the text of the label centered, left in the row
747 // with a left padding of 10
748 //
749 TGLayoutHints *laylabel = new TGLayoutHints(kLHintsCenterY|kLHintsLeft, 10);
750 TGLayoutHints *layframe = new TGLayoutHints(kLHintsCenterY|kLHintsLeft, 5, 0, 10);
751
752 //
753 // Add one entry field and the corresponding label to each line
754 //
755 f1->AddFrame(entry1);
756 f2->AddFrame(entry2);
757
758 f1->AddFrame(l1, laylabel);
759 f2->AddFrame(l2, laylabel);
760
761 f->AddFrame(f1, layframe);
762 f->AddFrame(f2, layframe);
763
764 f->AddToList(entry1);
765 f->AddToList(entry2);
766 f->AddToList(l1);
767 f->AddToList(l2);
768 f->AddToList(laylabel);
769 f->AddToList(layframe);
770}
771
772// --------------------------------------------------------------------------
773//
774// Process the GUI Events coming from the two text entry fields.
775//
776Bool_t MImgCleanStd::ProcessMessage(Int_t msg, Int_t submsg, Long_t param1, Long_t param2)
777{
778 if (msg!=kC_TEXTENTRY || submsg!=kTE_ENTER)
779 return kTRUE;
780
781 TGTextEntry *txt = (TGTextEntry*)FindWidget(param1);
782
783 if (!txt)
784 return kTRUE;
785
786 Float_t lvl = atof(txt->GetText());
787
788 switch (param1)
789 {
790 case kImgCleanLvl1:
791 fCleanLvl1 = lvl;
792 *fLog << "Cleaning level 1 set to " << lvl << endl;
793 return kTRUE;
794
795 case kImgCleanLvl2:
796 fCleanLvl2 = lvl;
797 *fLog << "Cleaning level 2 set to " << lvl << endl;
798 return kTRUE;
799 }
800
801 return kTRUE;
802}
803
804// --------------------------------------------------------------------------
805//
806// Implementation of SavePrimitive. Used to write the call to a constructor
807// to a macro. In the original root implementation it is used to write
808// gui elements to a macro-file.
809//
810void MImgCleanStd::StreamPrimitive(ostream &out) const
811{
812 out << " MImgCleanStd " << GetUniqueName() << "(";
813 out << fCleanLvl1 << ", " << fCleanLvl2;
814
815 if (fName!=gsDefName || fTitle!=gsDefTitle)
816 {
817 out << ", \"" << fName << "\"";
818 if (fTitle!=gsDefTitle)
819 out << ", \"" << fTitle << "\"";
820 }
821 out << ");" << endl;
822
823 if (fCleaningMethod!=kStandard)
824 {
825 out << " " << GetUniqueName() << ".SetMethod(MImgCleanStd::k";
826 switch (fCleaningMethod)
827 {
828 case kScaled: out << "Scaled"; break;
829 case kDemocratic: out << "Democratic"; break;
830 case kProbability: out << "Probability"; break;
831 case kAbsolute: out << "Absolute"; break;
832 case kTime : out << "Time"; break;
833 default:
834 break;
835 }
836 out << ");" << endl;
837 }
838 if (fCleanRings!=1)
839 out << " " << GetUniqueName() << ".SetCleanRings(" << fCleanRings << ");" << endl;
840
841 if (gsNamePedPhotCam!=fNamePedPhotCam)
842 out << " " << GetUniqueName() << ".SetNamePedPhotCam(\"" << fNamePedPhotCam << "\");" << endl;
843 if (gsNameGeomCam!=fNameGeomCam)
844 out << " " << GetUniqueName() << ".SetNameGeomCam(\"" << fNameGeomCam << "\");" << endl;
845 if (gsNameSignalCam!=fNameSignalCam)
846 out << " " << GetUniqueName() << ".SetNameSignalCam(\"" << fNameSignalCam << "\");" << endl;
847 if (fKeepSinglePixels)
848 out << " " << GetUniqueName() << ".SetKeepSinglePixels();" << endl;
849
850}
851
852// --------------------------------------------------------------------------
853//
854// Read the setup from a TEnv, eg:
855// MImgCleanStd.CleanLevel1: 3.0
856// MImgCleanStd.CleanLevel2: 2.5
857// MImgCleanStd.CleanMethod: Standard, Scaled, Democratic, Probability, Absolute
858// MImgCleanStd.CleanRings: 1
859// MImgCleanStd.KeepSinglePixels: yes, no
860//
861Int_t MImgCleanStd::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
862{
863 Bool_t rc = kFALSE;
864 if (IsEnvDefined(env, prefix, "CleanRings", print))
865 {
866 rc = kTRUE;
867 SetCleanRings(GetEnvValue(env, prefix, "CleanRings", fCleanRings));
868 }
869 if (IsEnvDefined(env, prefix, "CleanLevel1", print))
870 {
871 rc = kTRUE;
872 fCleanLvl1 = GetEnvValue(env, prefix, "CleanLevel1", fCleanLvl1);
873 }
874 if (IsEnvDefined(env, prefix, "CleanLevel2", print))
875 {
876 rc = kTRUE;
877 fCleanLvl2 = GetEnvValue(env, prefix, "CleanLevel2", fCleanLvl2);
878 }
879 if (IsEnvDefined(env, prefix, "KeepSinglePixels", print))
880 {
881 rc = kTRUE;
882 fKeepSinglePixels = GetEnvValue(env, prefix, "KeepSinglePixels", fKeepSinglePixels);
883 }
884
885 if (IsEnvDefined(env, prefix, "CleanMethod", print))
886 {
887 rc = kTRUE;
888 TString s = GetEnvValue(env, prefix, "CleanMethod", "");
889 s.ToLower();
890 if (s.BeginsWith("standard"))
891 SetMethod(kStandard);
892 if (s.BeginsWith("scaled"))
893 SetMethod(kScaled);
894 if (s.BeginsWith("democratic"))
895 SetMethod(kDemocratic);
896 if (s.BeginsWith("probability"))
897 SetMethod(kProbability);
898 if (s.BeginsWith("absolute"))
899 SetMethod(kAbsolute);
900 if (s.BeginsWith("time"))
901 SetMethod(kTime);
902 }
903
904 return rc;
905}
Note: See TracBrowser for help on using the repository browser.