Index: trunk/MagicSoft/Mars/Changelog
===================================================================
--- trunk/MagicSoft/Mars/Changelog	(revision 2034)
+++ trunk/MagicSoft/Mars/Changelog	(revision 2035)
@@ -1,3 +1,15 @@
                                                  -*-*- END OF LINE -*-*-
+ 2003/04/28: Nadia Tonello 
+
+  * mimage/MImgCleanStd.[h,cc]
+     - added the option kDemocratic using sigmabar of the 
+	inner pixels
+     - added the option to select the number of rings of pixels 
+	to analyze around the core pixels 
+     - added documentation
+
+  * manalysis/MCerPhotPix.[h,cc]
+     - added fRing and Get-Set functions 
+ 
  2003/04/28: Oscar Blanch
 
@@ -20,5 +32,5 @@
        declared external.
 
- 2003/04/27: Thomas Bretz
+ 2003/04/28: Thomas Bretz
 
    * NEWS:
Index: trunk/MagicSoft/Mars/mimage/MImgCleanStd.cc
===================================================================
--- trunk/MagicSoft/Mars/mimage/MImgCleanStd.cc	(revision 2034)
+++ trunk/MagicSoft/Mars/mimage/MImgCleanStd.cc	(revision 2035)
@@ -28,6 +28,212 @@
 //  MImgCleanStd                                                           //
 //                                                                         //
-//  This is the standard image cleaning. If you want to know how it works  //
-//  Please look at the three CleanSteps and Process                        //
+// The Image Cleaning task selects the pixels you use for the Hillas       //
+// parameters calculation.						   //
+//									   //
+// There are two methods to make the selection: the standard one, as done  //
+// in the analysis of CT1 data, and the democratic one, as suggested by    //
+// W.Wittek. The number of photo-electrons of a pixel is compared with the // 
+// pedestal RMS of the pixel itself (standard method) or with the average  //
+// RMS of the inner pixels (democratic method).				   //
+// In both cases, the possibility to have a camera with pixels of          //
+// different area is taken into account.                                   //
+// The too noisy pixels can be recognized and eventally switched off       //
+// (Unmap: set blinb pixels to UNUSED) separately, using the               //
+// MBlindPixelCalc Class. In the MBlindPixelCalc class there is also the   //
+// function to replace the value of the noisy pixels with the interpolation// 
+// of the content of the neighbors (SetUseInterpolation).                  //
+//                                                                         //
+// Example:                                                                //
+// ...                                                                     //
+// MBlindPixelCalc blind;                                                  //
+// blind.SetUseInterpolation();						   //
+// blind.SetUseBlindPixels();						   //
+//                                                                         //
+// MImgCleanStd clean;                                                     //
+// ...									   //
+// tlist.AddToList(&blind);                                                //
+// tlist.AddToList(&clean);						   //
+//                                                                         //
+// Look at the MBlindPixelCalc Class for more details.                     //   
+//									   //
+// Starting point: default values ---------------------------------------- //
+//                                                                         //
+// When an event is read, before the image cleaning, all the pixels that   // 
+// are in MCerPhotEvt are set as USED and NOT CORE. All the pixels belong  //
+// to RING number 1 (like USED pixels).                                    //
+// Look at MCerPhotPix.h to see how these informations of the pixel are    //
+// stored.                                                                 //
+// The default  cleaning METHOD is the STANDARD one and the number of the  //
+// rings around the CORE pixel it analyzes is 1. Look at the Constructor   // 
+// of the class in MImgCleanStd.cc to see (or change) the default values.  //
+//                                                                         //
+// Example: To modify this setting, use the member functions               //
+// SetMethod(MImgCleanStd::kDemocratic) and SetCleanRings(UShort_t n).     //
+//                                                                         //
+// MImgCleanStd:CleanStep1 -------------------------------------------- ---//
+//                                                                         //
+// The first step of cleaning defines the CORE pixels. The CORE pixels are //
+// the ones which contain the informations about the core of the electro-  //
+// magnetic shower.                                                        //
+// The ratio  (A_0/A_i) is calculated from fCam->GetPixRatio(i). A_0 is    //
+// the area of the central pixel of the camera, A_i is the area of the 	   //
+// examined pixel. In this way, if we have a MAGIC-like camera, with the   //
+// outer pixels bigger than the inner ones, the level of cleaning in the   //
+// two different regions is weighted.  	                                   //
+// This avoids problems of deformations of the shower images.  		   //
+// The signal S_i and the pedestal RMS Prms_i of the pixel are called from //
+// the object MCerPhotPix. 		                                   //
+// If (default method = kStandard) 		                           //
+//                                                                         //
+//         S_i > L_1 * Prms_i / sqrt(A_0/A_i)                              //
+//                                                                         //
+// the pixel is set as CORE pixel. L_1 is called "first level of cleaning" // 
+// (default: fCleanLvl1 = 3).                                              //
+// All the other pixels are set as UNUSED and belong to RING 0.		   //
+// After this point, only the CORE pixels are set as USED, with RING 	   //
+// number 1.								   //
+//                                                                         //
+// MImgCleanStd:CleanStep2 ----------------------------------------------  //
+//                                                                         //	
+// The second step of cleaning looks at the isolated CORE pixels and sets  // 
+// them to UNUSED. An isolated pixel is a pixel without CORE neighbors.    //
+// At the end of this point, we have set as USED only CORE pixels with at  // 
+// least one CORE neighbor.						   //
+//                                                                         //        
+// MImgCleanStd:CleanStep3  ---------------------------------------------- //
+//                                                                         //
+// The third step of cleaning looks at all the pixels (USED or UNUSED) that// 
+// surround the USED pixels.						   //
+// If the content of the analyzed pixel survives at the second level of    //
+// cleaning, i.e. if							   //
+//                                                                         //
+//          S_i > L_2 * Prms_i /  sqrt(A_0/A_i)				   //
+//                                                                         //
+// the pixel is set as USED. L_2 is called "second level of cleaning"      // 
+// (default:fCleanLvl2 = 2.5).			                	   //
+//									   //
+// When the number of RINGS to analyze is 1 (default value), only the      //
+// pixels that have a neighbor CORE pixel are analyzed.                    //
+//									   //
+// There is the option to decide the number of times you want to repeat    // 
+// this procedure (number of RINGS analyzed around the core pixels = n).   //
+// Every time the level of cleaning is the same (fCleanLvl2) and the pixel //
+// will belong to ring r+1, 1 < r < n+1. This is described in              //
+// MImgCleanStd:CleanStep4 .	          				   // 
+//                                                                         //
+// Dictionary and member functions --------------------------------------- //
+//									   //
+// Here there is the detailed description of the member functions and of   // 
+// the terms commonly used in the class.				   //  
+//                                                                         //
+// STANDARD CLEANING:							   //
+// =================							   //
+// This is the method used for the CT1 data analysis. It is the default    //
+// method of the class.                                                    //
+// The number of photo-electrons of a pixel (S_i) is compared to the       //
+// pedestal RMS of the pixel itself (Prms_i). To have the comparison to    //
+// the same photon density for all the pixels, taking into account they    //
+// can have different areas, we have to keep in mind that the number of    //
+// photons that hit each pixel, goes linearly with the area of the pixel.  //
+// The fluctuations of the LONS are proportional to sqrt(A_i), so when we  //
+// compare S_i with Prms_i, only a factor  sqrt(A_0/A_i) is missing to     //
+// have the same (N.photons/Area) threshold for all the pixels.            //
+//                                                                         //
+//              !!WARNING: if noise independent from the                   //
+//                        pixel size is considered,                        //
+//                  this weight can give wrong results!!                   //
+// If                                                                      //
+//                                                                         //
+//           S_i > L_n * Prms_i / sqrt(A_0/A_i)                            //
+//                                                                         //
+// the pixel survives the cleaning and it is set as CORE (when L_n is the  // 
+// first level of cleaning, fCleanLvl1) or USED ((when L_n is the second   //
+// level of cleaning, fCleanLvl2).					   //
+//									   //
+// Example:                                                                //
+//									   //
+// MImgCleanStd clean;             					   //
+// //creates a default Cleaning object, with default setting		   //
+// ...			        					   //
+// tlist.AddToList(&clean);                                                //
+// // add the image cleaning to the main task list                         //
+//									   //
+// DEMOCRATIC CLEANING:							   //
+// ===================							   //
+// You use this cleaning method when you want to compare the number of 	   //
+// photo-electons of each pixel with the average pedestal RMS 		   //
+// (fInnerNoise = fSgb->GetSigmabarInner()) of the inner pixels (for the   //
+// MAGIC camera they are the smaller ones):				   //
+//									   //
+//  S_i > L_n * fInnerNoise / (A_0/A_i)                                    //
+//                                                                         //
+// In this case, the simple ratio (A_0/A_i) is used to weight the level of //
+// cleaning, because both the inner and the outer pixels (that in MAGIC    //
+// have a different area) are compared to the same pedestal RMS, coming    //
+// from the inner pixels. 						   //
+// To calculate the average pedestal RMS of the inner pixels, you have to  //
+// add to the main task list an object of type MSigmabarCalc before the    //
+// MImgCleanStd object. To know how the calculation of fInnerNoise is done //
+// look at the MSigmabarCalc Class.					   //
+//									   //
+// Example:								   //
+// 									   //
+// MSigmabarCalc   sbcalc;						   //
+// //creates an object that calcutates the average pedestal RMS 	   //
+// MImgCleanStd clean;							   //
+// ...									   //
+// tlist.AddToList(&sbcalc);						   //
+// tlist.AddToList(&clean);						   //
+//                                  					   //
+// Member Function:  SetMethod()					   //
+// ============================						   //
+// When you call the MImgCleanStd task, the default method is kStandard.   //
+//                                                                         //
+// If you want to switch to the kDemocratic method you have to             //
+// call this member function.                                              //
+//                                  					   //
+// Example:								   //
+//                                  					   //
+// MImgCleanStd clean;             					   //
+// //creates a default Cleaning object, with default setting		   //
+//									   //
+// clean.SetMethod(MImgCleanStd::kDemocratic); 				   //
+// //now the method of cleaning is changed to Democratic		   //
+//									   //
+// FIRST AND SECOND CLEANING LEVEL					   //
+// ===============================					   //
+// When you call the MImgCleanStd task, the default cleaning levels are    //
+// fCleanLvl1 = 3, fCleanLvl2 = 2.5. You can change them easily when you   //
+// create the MImgCleanStd object.					   //
+//									   //
+// Example:								   //
+//									   //
+// MImgCleanStd clean(Float_t lvl1,Float_t lvl2);			   //
+// //creates a default cleaning object, but the cleaning levels are now    //
+// //lvl1 and lvl2. 							   //
+//									   //
+// RING NUMBER 								   //
+// ===========								   //
+// The standard cleaning procedure is such that it looks for the 	   //
+// informations of the boundary part of the shower only on the first       //
+// neighbors of the CORE pixels.					   //
+// There is the possibility now to look not only at the firs neighbors 	   //
+// (first ring),but also further away, around the CORE pixels. All the new // 
+// pixels you can find with this method, are tested with the second level  //  
+// of cleaning and have to have at least an USED neighbor. 		   //
+// 									   //
+// They will be also set as USED and will be taken into account during the // 
+// calculation of the image parameters. 				   //
+// The only way to distinguish them from the other USED pixels, is the     // 
+// Ring number, that is bigger than 1.					   //
+//                                                                         //
+// Example: You can decide how many rings you want to analyze using:	   //
+//									   //
+// MImgCleanStd clean;							   //
+// //creates a default cleaning object (default number of rings =1)	   //
+// clean.SetCleanRings(UShort\_t r);					   //
+// //now it looks r times around the CORE pixels to find new pixels with   //
+// //signal.								   //
+//									   //
 //                                                                         //
 //   FIXME: MImgCleanStd is not yet completely optimized for speed.        //
@@ -35,13 +241,12 @@
 //                                                                         //
 //  Input Containers:                                                      //
-//   MGeomCam, MCerPhotEvt                                                 //
+//   MGeomCam, MCerPhotEvt, MSigmabar                                      //
 //                                                                         //
 //  Output Containers:                                                     //
 //   -/-                                                                   //
 //                                                                         //
-/////////////////////////////////////////////////////////////////////////////
-#include "MImgCleanStd.h"
-
-#include <stdlib.h>       // atof
+////////////////////////////////////////////////////////////////////////// //
+#include "MImgCleanStd.h"							   
+#include <stdlib.h>       // atof					  
 #include <fstream.h>      // ofstream, SavePrimitive
 
@@ -58,4 +263,5 @@
 #include "MCerPhotPix.h"
 #include "MCerPhotEvt.h"
+#include "MSigmabar.h"
 
 #include "MGGroupFrame.h" // MGGroupFrame
@@ -69,15 +275,19 @@
 
 static const TString gsDefName  = "MImgCleanStd";
-static const TString gsDefTitle = "Perform standard image cleaning";
-
-// --------------------------------------------------------------------------
-//
-// Default constructor. Here you can specify the cleaning levels. If you
-// don't specify them the 'common standard' values 3.0 and 2.5 (sigma
-// above mean) are used
+static const TString gsDefTitle = "Task to perform image cleaning";
+
+// --------------------------------------------------------------------------
+//
+// Default constructor. Here you can specify the cleaning method and levels. 
+// If you don't specify them the 'common standard' values 3.0 and 2.5 (sigma
+// above mean) are used.
+// Here you can also specify how many rings around the core pixels you want 
+// to analyze (with the fixed lvl2). The default value for "rings" is 1.
 //
 MImgCleanStd::MImgCleanStd(const Float_t lvl1, const Float_t lvl2,
-                           const char *name, const char *title)
-    : fCleanLvl1(lvl1), fCleanLvl2(lvl2)
+                     const char *name, const char *title)
+    : fSgb(NULL), fCleaningMethod(kStandard), fCleanLvl1(lvl1),
+    fCleanLvl2(lvl2), fCleanRings(1)
+
 {
     fName  = name  ? name  : gsDefName.Data();
@@ -89,16 +299,17 @@
 // --------------------------------------------------------------------------
 //
-//  This method looks for all pixels with an entry (photons)
-//  that is three times bigger than the noise of the pixel
-//  (std: 3 sigma, clean level 1)
-//
-//
-//  AM 18/11/2002: now cut levels are proportional to the square root
-//  of the pixel area. In this way the cut corresponds to a fixed 
+//  NT 28/04/2003: now the option to use the standard method or the 
+//  democratic method is implemented:
+//
+//  KStandard: This method looks for all pixels with an entry (photons)
+//             that is three times bigger than the noise of the pixel
+//             (default: 3 sigma, clean level 1)
+//  AM 18/11/2002: now cut levels are proportional to the pixel area. 
+//  In this way the cut corresponds to a fixed 
 //  phe-density (otherwise, it would bias the images).
 //
 //  Returns the maximum Pixel Id (used for ispixused in CleanStep2)
 //
-Int_t MImgCleanStd::CleanStep1()
+Int_t MImgCleanStd::CleanStep1Std()
 {
     const Int_t entries = fEvt->GetNumPixels();
@@ -109,5 +320,5 @@
     // check the number of all pixels against the noise level and
     // set them to 'unused' state if necessary
-    //
+    // 
     for (Int_t i=0; i<entries; i++ )
     {
@@ -118,9 +329,8 @@
 
         const Int_t id = pix.GetPixId();
-
-        const Double_t ratio = fCam->GetPixRatio(id);
+        const Double_t ratio = TMath::Sqrt(fCam->GetPixRatio(id));
 
         // COBB: '<=' to skip entry=noise=0
-        if (entry*ratio <= fCleanLvl1*noise)
+        if (entry <= fCleanLvl1 * noise / ratio)
             pix.SetPixelUnused();
 
@@ -128,4 +338,5 @@
             max = id;
     }
+
     return max;
 }
@@ -133,9 +344,71 @@
 // --------------------------------------------------------------------------
 //
-//  check if the survived pixel have a neighbor, that also
-//  survived, otherwise set pixel to unused. (removes pixels without
-//  neighbors)
-//
-//  takes the maximum pixel id from CleanStep1 as an argument
+//  NT 28/04/2003: now the option to use the standard method or the 
+//  democratic method is implemented:
+//
+//  "KDemocratic": this method looks for all pixels with an entry (photons)
+//                 that is n times bigger than the noise of the mean of the 
+//                 inner pixels (default: 3 sigmabar, clean level 1)
+//
+//  Returns the maximum Pixel Id (used for ispixused in CleanStep2)
+//
+Int_t MImgCleanStd::CleanStep1Dem()
+{
+    const Int_t entries = fEvt->GetNumPixels();
+
+    Int_t max = entries;
+
+    //
+    // check the number of all pixels against the noise level and
+    // set them to 'unused' state if necessary
+    // 
+    for (Int_t i=0; i<entries; i++ )
+    {
+        MCerPhotPix &pix = (*fEvt)[i];
+
+        const Float_t entry = pix.GetNumPhotons();
+
+        const Int_t id = pix.GetPixId();
+
+        const Double_t ratio = fCam->GetPixRatio(id);
+
+	    // COBB: '<=' to skip entry=noise=0
+
+        if (entry <= fCleanLvl1 * fInnerNoise / ratio)
+            pix.SetPixelUnused();
+
+        if (id>max)
+            max = id;
+    }
+    return max;
+}
+
+// --------------------------------------------------------------------------
+// The first step of cleaning defines the CORE pixels. All the other pixels 
+// are set as UNUSED and belong to RING 0.		  
+// After this point, only the CORE pixels are set as USED, with RING 	  
+// number 1.								  
+// Returns the maximum Pixel Id (used for ispixused in CleanStep2)
+//
+Int_t MImgCleanStd::CleanStep1()
+{
+   switch (fCleaningMethod)
+    {
+    case kStandard:
+        return CleanStep1Std();
+    case kDemocratic:
+        return CleanStep1Dem();
+    }
+
+    return 0;
+}
+
+// --------------------------------------------------------------------------
+//
+//  Check if the survived pixel have a neighbor, that also
+//  survived, otherwise set pixel to unused (removes pixels without
+//  neighbors).
+//
+//  Takes the maximum pixel id from CleanStep1 as an argument
 //
 void MImgCleanStd::CleanStep2(Int_t max)
@@ -150,78 +423,49 @@
     //
     Byte_t *ispixused = new Byte_t[max+1];
-    memset(ispixused, 0, max+1);
 
     for (Int_t i=0; i<entries; i++)
     {
-        MCerPhotPix &pix = (*fEvt)[i];
-        ispixused[pix.GetPixId()] = pix.IsPixelUsed();
+        const MCerPhotPix &pix = (*fEvt)[i];
+        ispixused[pix.GetPixId()] = pix.IsPixelUsed() ? 1 : 0 ;
     }
 
     for (Int_t i=0; i<entries; i++)
     {
-        //
         // get entry i from list
         //
         MCerPhotPix &pix = (*fEvt)[i];
 
-        //
-        // check if pixel is in use, if not goto next pixel in list
-        //
-#if 0
-        if (!pix.IsPixelUsed())
-            continue;
-#endif
-
-        //
-        // get pixel id of this entry
+	// get pixel id of this entry
         //
         const Int_t id = pix.GetPixId();
 
+	// check if pixel is in use, if not goto next pixel in list
         //
-        // check for 'used' neighbors this pixel which
+	if (ispixused[id] == 0)
+            continue;
+ 
+        // check for 'used' neighbors of this pixel
         //
         const MGeomPix &gpix  = (*fCam)[id];
         const Int_t     nnmax = gpix.GetNumNeighbors();
 
-#if 0
-        Bool_t cnt = kFALSE;
+        Bool_t hasNeighbor = kFALSE;
+
+	//loop on the neighbors to check if they are used
+	//
         for (Int_t j=0; j<nnmax; j++)
         {
             const Int_t id2 = gpix.GetNeighbor(j);
 
-            if (id2>max || !ispixused[id2])
-                continue;
-
-            cnt = kTRUE;
-            break;
+	    // when you find an used  neighbor, break the loop
+            if (ispixused[id2] == 1  )
+	      {
+		hasNeighbor = kTRUE ;
+		break;
+	      }
         }
-        if (cnt)
-            continue;
-#else
-        Int_t cnt = 0;
-        for (Int_t j=0; j<nnmax; j++)
-        {
-            const Int_t id2 = gpix.GetNeighbor(j);
-
-            if (id2>max || !ispixused[id2])
-                continue;
-
-            if (cnt++>nnmax-4)
-                break;
-        }
-        if (cnt==nnmax-2 && nnmax>=4)
-        {
-            pix.SetPixelUsed();
-            continue;
-        }
-        if (cnt>0)
-            continue;
-#endif
-
-        //
-        // check if no next neighbor has the state 'used'
-        // set this pixel to 'unused', too.
-        //
-        pix.SetPixelUnused();
+	
+	if (hasNeighbor == kFALSE)
+	  pix.SetPixelUnused();
     }
 
@@ -246,53 +490,149 @@
 //   a core neigbor it is declared as used.
 //
+Bool_t MImgCleanStd::CleanStep3Std(const MCerPhotPix &pix)
+{
+    //
+    // get pixel id of this entry
+    //
+    const Int_t id = pix.GetPixId();
+
+    //
+    // check the num of photons against the noise level
+    //
+    const Float_t entry = pix.GetNumPhotons();
+    const Float_t noise = pix.GetErrorPhot();
+
+    const Double_t ratio = TMath::Sqrt(fCam->GetPixRatio(id));
+
+    return (entry <= fCleanLvl2 * noise / ratio);
+}
+
+// --------------------------------------------------------------------------
+//
+//   Look for the boundary pixels around the core pixels
+//   if a pixel has more than 2.5 (clean level 2.5) sigmabar and
+//   a core neighbor, it is declared as used.
+//
+Bool_t MImgCleanStd::CleanStep3Dem(const MCerPhotPix &pix)
+{
+    //
+    // get pixel id of this entry
+    //
+    const Int_t id = pix.GetPixId();
+
+    //
+    // check the num of photons against the noise level
+    //
+    const Float_t entry = pix.GetNumPhotons();
+
+    const Double_t ratio = fCam->GetPixRatio(id);
+
+    return (entry <= fCleanLvl2 * fInnerNoise / ratio);
+}
+
+void MImgCleanStd::CleanStep3b(MCerPhotPix &pix)
+{
+    const Int_t id = pix.GetPixId();
+
+    //
+    // check if the pixel's next neighbor is a core pixel.
+    // if it is a core pixel set pixel state to: used.
+    //
+    MGeomPix   &gpix  = (*fCam)[id];
+    const Int_t nnmax = gpix.GetNumNeighbors();
+
+    for (Int_t j=0; j<nnmax; j++)
+    {
+        const Int_t id2 = gpix.GetNeighbor(j);
+
+	if (!fEvt->GetPixById(id2) || !fEvt->IsPixelCore(id2)) 
+	  continue;
+
+        pix.SetPixelUsed();
+	   break;
+    }
+}
+
+// --------------------------------------------------------------------------
+//
+//   NT: Add option "rings": default value = 1. 
+//   Look n (n>1) times for the boundary pixels around the used pixels.
+//   If a pixel has more than 2.5 (clean level 2.5) sigma,
+//   it is declared as used.
+//
+//   If a value<2 for fCleanRings is used, no CleanStep4 is done.
+//
+void MImgCleanStd::CleanStep4(UShort_t r, MCerPhotPix &pix)
+{
+    //
+    // check if the pixel's next neighbor is a used pixel.
+    // if it is a used pixel set pixel state to: used,
+    // and tell to which ring it belongs to.
+    //
+    const Int_t id = pix.GetPixId();
+    MGeomPix  &gpix  = (*fCam)[id];
+
+    const Int_t nnmax = gpix.GetNumNeighbors();
+
+    for (Int_t j=0; j<nnmax; j++)
+    {
+        const Int_t id2 = gpix.GetNeighbor(j);
+
+        MCerPhotPix &npix = *fEvt->GetPixById(id2);
+
+	// FIXME!
+	// Needed check to read CT1 data without having a Segmentation fault
+	if (!fEvt->GetPixById(id2)) 
+	    continue; 
+
+        if (!npix.IsPixelUsed() || npix.GetRing()>r-1 )
+            continue;
+
+        pix.SetRing(r);
+	    break;
+    }
+}
+
+// --------------------------------------------------------------------------
+//
+//   Look for the boundary pixels around the core pixels
+//   if a pixel has more than 2.5 (clean level 2.5) sigma, and
+//   a core neigbor, it is declared as used.
+//
 void MImgCleanStd::CleanStep3()
 {
     const Int_t entries = fEvt->GetNumPixels();
 
-    for (Int_t i=0; i<entries; i++)
-    {
-        //
-        // get pixel as entry il from list
-        //
-        MCerPhotPix &pix = (*fEvt)[i];
-
-        //
-        // if pixel is a core pixel go to the next pixel
-        //
-        if (pix.IsPixelCore())
-            continue;
-
-        //
-        // check the num of photons against the noise level
-        //
-        const Float_t entry = pix.GetNumPhotons();
-        const Float_t noise = pix.GetErrorPhot();
-
-        //
-        // get pixel id of this entry
-        //
-        const Int_t id = pix.GetPixId();
-
-        const Double_t ratio = TMath::Sqrt(fCam->GetPixRatio(id));
-
-        if (entry*ratio <= fCleanLvl2*noise)
-            continue;
-
-        //
-        // check if the pixel's next neighbor is a core pixel.
-        // if it is a core pixel set pixel state to: used.
-        //
-        MGeomPix   &gpix  = (*fCam)[id];
-        const Int_t nnmax = gpix.GetNumNeighbors();
-
-        for (Int_t j=0; j<nnmax; j++)
+    for (UShort_t r=1; r<fCleanRings+1; r++)
+    {
+        for (Int_t i=0; i<entries; i++)
         {
-            const Int_t id2 = gpix.GetNeighbor(j);
-
-            if (!fEvt->IsPixelCore(id2))
+            //
+            // get pixel as entry il from list
+            //
+            MCerPhotPix &pix = (*fEvt)[i];
+
+            //
+            // if pixel is a core pixel go to the next pixel
+            //
+            if (pix.IsPixelCore())
                 continue;
 
-            pix.SetPixelUsed();
-            break;
+            switch (fCleaningMethod)
+            {
+            case kStandard:
+                if (CleanStep3Std(pix))
+                    continue;
+                break;
+            case kDemocratic:
+                if (CleanStep3Dem(pix))
+                    continue;
+                break;
+            }
+
+            if (r==1)
+                CleanStep3b(pix);
+            else
+                CleanStep4(r, pix);
         }
     }
@@ -301,5 +641,5 @@
 // --------------------------------------------------------------------------
 //
-//  check if MEvtHeader exists in the Parameter list already.
+//  Check if MEvtHeader exists in the Parameter list already.
 //  if not create one and add them to the list
 //
@@ -320,8 +660,17 @@
     }
 
+    if (fCleaningMethod != kDemocratic)
+        return kTRUE;
+
+    fSgb = (MSigmabar*)pList->FindObject("MSigmabar");
+    if (!fSgb)
+    {
+        *fLog << dbginf << "MSigmabar not found... aborting." << endl;
+        return kFALSE;
+    }
+
     return kTRUE;
 }
 
-
 // --------------------------------------------------------------------------
 //
@@ -330,4 +679,7 @@
 Bool_t MImgCleanStd::Process()
 {
+    if (fSgb)
+        fInnerNoise = fSgb->GetSigmabarInner();
+
     const Int_t max = CleanStep1();
     CleanStep2(max);
@@ -343,85 +695,83 @@
 void MImgCleanStd::Print(Option_t *o) const
 {
-    *fLog << GetDescriptor() << " initialized with noise level ";
-    *fLog << fCleanLvl1 << " and " << fCleanLvl2 << endl;
-}
-
-// --------------------------------------------------------------------------
-//
-//  Craete two text entry fields, one for each cleaning level and a
+    *fLog << all << GetDescriptor() << " using ";
+    switch (fCleaningMethod)
+    {
+    case kDemocratic:
+        *fLog << "democratic";
+        break;
+    case kStandard:
+        *fLog << "standard";
+        break;
+    }
+    *fLog << " cleaning initialized with noise level " << fCleanLvl1 << " and " << fCleanLvl2;
+    *fLog << " (CleanRings=" << fCleanRings << ")" << endl;
+}
+
+// --------------------------------------------------------------------------
+//
+//  Create two text entry fields, one for each cleaning level and a
 //  describing text line.
 //
 void MImgCleanStd::CreateGuiElements(MGGroupFrame *f)
 {
-    //
-    // Create a frame for line 3 and 4 to be able
-    // to align entry field and label in one line
-    //
-    TGHorizontalFrame *f1 = new TGHorizontalFrame(f, 0, 0);
-    TGHorizontalFrame *f2 = new TGHorizontalFrame(f, 0, 0);
-
-    /*
-     * --> use with root >=3.02 <--
-     *
-
-     TGNumberEntry *fNumEntry1 = new TGNumberEntry(frame, 3.0, 2, M_NENT_LVL1, kNESRealOne, kNEANonNegative);
-     TGNumberEntry *fNumEntry2 = new TGNumberEntry(frame, 2.5, 2, M_NENT_LVL1, kNESRealOne, kNEANonNegative);
-
-     */
-    TGTextEntry *entry1 = new TGTextEntry(f1, "****", kImgCleanLvl1);
-    TGTextEntry *entry2 = new TGTextEntry(f2, "****", kImgCleanLvl2);
-
-    // --- doesn't work like expected (until root 3.02?) --- fNumEntry1->SetAlignment(kTextRight);
-    // --- doesn't work like expected (until root 3.02?) --- fNumEntry2->SetAlignment(kTextRight);
-
-    entry1->SetText("3.0");
-    entry2->SetText("2.5");
-
-    entry1->Associate(f);
-    entry2->Associate(f);
-
-    TGLabel *l1 = new TGLabel(f1, "Cleaning Level 1");
-    TGLabel *l2 = new TGLabel(f2, "Cleaning Level 2");
-
-    l1->SetTextJustify(kTextLeft);
-    l2->SetTextJustify(kTextLeft);
-
-    //
-    // Align the text of the label centered, left in the row
-    // with a left padding of 10
-    //
-    TGLayoutHints *laylabel = new TGLayoutHints(kLHintsCenterY|kLHintsLeft, 10);
-    TGLayoutHints *layframe = new TGLayoutHints(kLHintsCenterY|kLHintsLeft,  5, 0, 10);
-
-    //
-    // Add one entry field and the corresponding label to each line
-    //
-    f1->AddFrame(entry1);
-    f2->AddFrame(entry2);
-
-    f1->AddFrame(l1, laylabel);
-    f2->AddFrame(l2, laylabel);
-
-    f->AddFrame(f1, layframe);
-    f->AddFrame(f2, layframe);
-
-    f->AddToList(entry1);
-    f->AddToList(entry2);
-    f->AddToList(l1);
-    f->AddToList(l2);
-    f->AddToList(laylabel);
-    f->AddToList(layframe);
-}
-
-void MImgCleanStd::SetLvl1(Float_t lvl)
-{
-    fCleanLvl1 = lvl;
-    *fLog << inf << "Cleaning level 1 set to " << lvl << " sigma." << endl;
-}
-
-void MImgCleanStd::SetLvl2(Float_t lvl)
-{
-    fCleanLvl2 = lvl;
-    *fLog << inf << "Cleaning level 2 set to " << lvl << " sigma." << endl;
+  //
+  // Create a frame for line 3 and 4 to be able
+  // to align entry field and label in one line
+  //
+  TGHorizontalFrame *f1 = new TGHorizontalFrame(f, 0, 0);
+  TGHorizontalFrame *f2 = new TGHorizontalFrame(f, 0, 0);
+  
+  /*
+   * --> use with root >=3.02 <--
+   *
+   
+   TGNumberEntry *fNumEntry1 = new TGNumberEntry(frame, 3.0, 2, M_NENT_LVL1, kNESRealOne, kNEANonNegative);
+   TGNumberEntry *fNumEntry2 = new TGNumberEntry(frame, 2.5, 2, M_NENT_LVL1, kNESRealOne, kNEANonNegative);
+
+  */
+  TGTextEntry *entry1 = new TGTextEntry(f1, "****", kImgCleanLvl1);
+  TGTextEntry *entry2 = new TGTextEntry(f2, "****", kImgCleanLvl2);
+  
+  // --- doesn't work like expected (until root 3.02?) --- fNumEntry1->SetAlignment(kTextRight);
+  // --- doesn't work like expected (until root 3.02?) --- fNumEntry2->SetAlignment(kTextRight);
+  
+  entry1->SetText("3.0");
+  entry2->SetText("2.5");
+  
+  entry1->Associate(f);
+  entry2->Associate(f);
+  
+  TGLabel *l1 = new TGLabel(f1, "Cleaning Level 1");
+  TGLabel *l2 = new TGLabel(f2, "Cleaning Level 2");
+  
+  l1->SetTextJustify(kTextLeft);
+  l2->SetTextJustify(kTextLeft);
+  
+  //
+  // Align the text of the label centered, left in the row
+  // with a left padding of 10
+  //
+  TGLayoutHints *laylabel = new TGLayoutHints(kLHintsCenterY|kLHintsLeft, 10);
+  TGLayoutHints *layframe = new TGLayoutHints(kLHintsCenterY|kLHintsLeft,  5, 0, 10);
+  
+  //
+  // Add one entry field and the corresponding label to each line
+  //
+  f1->AddFrame(entry1);
+  f2->AddFrame(entry2);
+  
+  f1->AddFrame(l1, laylabel);
+  f2->AddFrame(l2, laylabel);
+  
+  f->AddFrame(f1, layframe);
+  f->AddFrame(f2, layframe);
+  
+  f->AddToList(entry1);
+  f->AddToList(entry2);
+  f->AddToList(l1);
+  f->AddToList(l2);
+  f->AddToList(laylabel);
+  f->AddToList(layframe);
 }
 
@@ -445,9 +795,11 @@
     {
     case kImgCleanLvl1:
-        SetLvl1(lvl);
+        fCleanLvl1 = lvl;
+        *fLog << "Cleaning level 1 set to " << lvl << " sigma." << endl;
         return kTRUE;
 
     case kImgCleanLvl2:
-        SetLvl2(lvl);
+        fCleanLvl2 = lvl;
+        *fLog << "Cleaning level 2 set to " << lvl << " sigma." << endl;
         return kTRUE;
     }
@@ -475,38 +827,2 @@
     out << ");" << endl;
 }
-
-// --------------------------------------------------------------------------
-//
-// Read the setup from a TEnv:
-//   Float_t fCleanLvl1: CleaningLevel1
-//   Float_t fCleanLvl2: CleaningLevel2
-//
-Bool_t MImgCleanStd::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
-{
-    Bool_t rc = kTRUE;
-    if (!IsEnvDefined(env, prefix, "CleaningLevel1", print))
-        rc = kFALSE;
-    else
-    {
-        SetLvl1(GetEnvValue(env, prefix, "CleaningLevel1", fCleanLvl1));
-        if (fCleanLvl1<0)
-        {
-            *fLog << err << "ERROR - Negative values for Cleaning Level 1 forbidden." << endl;
-            return kERROR;
-        }
-    }
-
-    if (!IsEnvDefined(env, prefix, "CleaningLevel2", print))
-        rc = kFALSE;
-    else
-    {
-        SetLvl2(GetEnvValue(env, prefix, "CleaningLevel2", fCleanLvl2));
-        if (fCleanLvl2<0)
-        {
-            *fLog << err << "ERROR - Negative values for Cleaning Level 2 forbidden." << endl;
-            return kERROR;
-        }
-    }
-
-    return rc;
-}
Index: trunk/MagicSoft/Mars/mimage/MImgCleanStd.h
===================================================================
--- trunk/MagicSoft/Mars/mimage/MImgCleanStd.h	(revision 2034)
+++ trunk/MagicSoft/Mars/mimage/MImgCleanStd.h	(revision 2035)
@@ -7,4 +7,6 @@
 
 class MGeomCam;
+class MSigmabar;
+class MCerPhotPix;
 class MCerPhotEvt;
 
@@ -13,20 +15,37 @@
 class MImgCleanStd : public MGTask
 {
+public:
+    typedef enum {
+        kStandard,
+        kDemocratic
+    } CleaningMethod_t;
+
 private:
     const MGeomCam    *fCam;  //!
           MCerPhotEvt *fEvt;  //!
+	  MSigmabar   *fSgb;  //!
+
+    CleaningMethod_t fCleaningMethod;
 
     Float_t fCleanLvl1;
     Float_t fCleanLvl2;
 
-    void SetLvl1(Float_t lvl);
-    void SetLvl2(Float_t lvl);
+    UShort_t fCleanRings;
+
+    Float_t fInnerNoise;      //!
 
     void CreateGuiElements(MGGroupFrame *f);
     void StreamPrimitive(ofstream &out) const;
 
+    Int_t  CleanStep1Dem();
+    Int_t  CleanStep1Std();
+    Bool_t CleanStep3Dem(const MCerPhotPix &pix);
+    Bool_t CleanStep3Std(const MCerPhotPix &pix);
+    void   CleanStep3b(MCerPhotPix &pix);
+    void   CleanStep4(UShort_t r, MCerPhotPix &pix);
+
 public:
     MImgCleanStd(const Float_t lvl1=3.0, const Float_t lvl2=2.5,
-                 const char *name=NULL, const char *title=NULL);
+              const char *name=NULL, const char *title=NULL);
 
     Int_t CleanStep1();
@@ -41,11 +60,21 @@
     Float_t GetCleanLvl1() const { return fCleanLvl1; }
     Float_t GetCleanLvl2() const { return fCleanLvl2; }
+    UShort_t  GetCleanRings() const { return fCleanRings;}
+
+    void SetCleanRings(UShort_t r) { fCleanRings=r; }
+    void SetMethod(CleaningMethod_t m) { fCleaningMethod = m; }
 
     Bool_t ProcessMessage(Int_t msg, Int_t submsg, Long_t param1, Long_t param2);
-    Bool_t ReadEnv(const TEnv &env, TString prefix, Bool_t print);
 
-    ClassDef(MImgCleanStd, 0)    // task doing a standard image cleaning
+    ClassDef(MImgCleanStd, 2)    // task doing the image cleaning
 }; 
 
 #endif
 
+
+
+
+
+
+
+
