/* ======================================================================== *\ ! ! * ! * This file is part of MARS, the MAGIC Analysis and Reconstruction ! * Software. It is distributed to you in the hope that it can be a useful ! * and timesaving tool in analysing Data of imaging Cerenkov telescopes. ! * It is distributed WITHOUT ANY WARRANTY. ! * ! * Permission to use, copy, modify and distribute this software and its ! * documentation for any purpose is hereby granted without fee, ! * provided that the above copyright notice appear in all copies and ! * that both that copyright notice and this permission notice appear ! * in supporting documentation. It is provided "as is" without express ! * or implied warranty. ! * ! ! ! Author(s): Oscar Blanch 12/2001 ! Author(s): Thomas Bretz 08/2002 ! ! Copyright: MAGIC Software Development, 2000-2004 ! ! \* ======================================================================== */ ///////////////////////////////////////////////////////////////////////////// // // MBadPixelsTreat // // You can use MBadPixelsTreat::SetUseInterpolation to replaced the // bad pixels by the average of its neighbors instead of unmapping // them. If you want to include the central pixel use // MBadPixelsTreat::SetUseCentralPixel. The bad pixels are taken from // an existing MBadPixelsCam. // // It check if there are enough neighbors to calculate the mean // If not, unmap the pixel. The minimum number of good neighbors // should be set using SetNumMinNeighbors // // If you want to interpolate unreliable pixels and unsuitable // (broken) pixels use SetHardTreatment(). // // // Options: // -------- // SetHardTreatment: Also interpolate unreliable pixels not only unsuitable // SetUseInterpolation: Interpolate pixels instead of unmapping them // SetUseCentralPixel: also use the pixel itself for interpolation // SetProcessPedestalRun: process the pedestals once per run/file // SetProcessPedestalEvt: process the pedestal once per event // SetProcessTimes: also do some rough interpolation of the arrival time // // // Input Containers: // MCerPhotEvt // MPedPhotCam // MBadPixelsCam // [MGeomCam] // // Output Containers: // MCerPhotEvt // ///////////////////////////////////////////////////////////////////////////// #include "MBadPixelsTreat.h" #include #include #include #include "MArrayD.h" // Used instead of TArrayD because operator[] has no range check #include "MLog.h" #include "MLogManip.h" #include "MParList.h" #include "MGeomPix.h" #include "MGeomCam.h" #include "MCerPhotPix.h" #include "MCerPhotEvt.h" #include "MPedPhotPix.h" #include "MPedPhotCam.h" #include "MBadPixelsPix.h" #include "MBadPixelsCam.h" #include "MArrivalTime.h" ClassImp(MBadPixelsTreat); using namespace std; static const TString gsDefName = "MBadPixelsTreat"; static const TString gsDefTitle = "Task to treat bad pixels (interpolation, unmapping)"; // -------------------------------------------------------------------------- // // Default constructor. // MBadPixelsTreat::MBadPixelsTreat(const char *name, const char *title) : fFlags(0), fNumMinNeighbors(3) { fName = name ? name : gsDefName.Data(); fTitle = title ? title : gsDefTitle.Data(); SetUseInterpolation(); SetProcessPedestal(); SetProcessTimes(); } // -------------------------------------------------------------------------- // // Returns the status of a pixel. If kHardTreatment is set a pixel must // be unsuitable or uriliable to be treated. If not it is treated only if // it is unsuitable // (IsBad() checks for any flag) // Bool_t MBadPixelsTreat::IsPixelBad(Int_t idx) const { return TESTBIT(fFlags, kHardTreatment) ? (*fBadPixels)[idx].IsBad():(*fBadPixels)[idx].IsUnsuitable(); } void MBadPixelsTreat::AddNamePedPhotCam(const char *name) { fNamePedPhotCams.Add(new TObjString(name)); } // -------------------------------------------------------------------------- // // - Try to find or create MBlindPixels in parameter list. // - get the MCerPhotEvt from the parlist (abort if missing) // - if no pixels are given by the user try to determin the starfield // from the monte carlo run header. // Int_t MBadPixelsTreat::PreProcess (MParList *pList) { fBadPixels = (MBadPixelsCam*)pList->FindObject(AddSerialNumber("MBadPixelsCam")); if (!fBadPixels) { *fLog << err << AddSerialNumber("MBadPixelsCam") << " not found... aborting." << endl; return kFALSE; } fEvt = (MCerPhotEvt*)pList->FindObject(AddSerialNumber("MCerPhotEvt")); if (!fEvt) { *fLog << err << AddSerialNumber("MCerPhotEvt") << " not found... aborting." << endl; return kFALSE; } fGeomCam = 0; if (!IsUseInterpolation()) return kTRUE; fGeomCam = (MGeomCam*)pList->FindObject(AddSerialNumber("MGeomCam")); if (!fGeomCam) { *fLog << err << AddSerialNumber("MGeomCam") << " not found - can't use interpolation... abort." << endl; *fLog << " Use MBadPixelsTreat::SetUseInterpolation(kFALSE) to switch interpolation" << endl; *fLog << " off and use unmapping instead." << endl; return kFALSE; } const Bool_t proc = IsProcessPedestalEvt() || IsProcessPedestalRun(); if (fNamePedPhotCams.GetSize()>0 && !proc) { *fLog << err << "Pedestal list contains entries, but pedestal treatment is switched off... abort." << endl; return kFALSE; } if (proc) { if (fNamePedPhotCams.GetSize()==0) { *fLog << inf << "No container names specified... using default: MPedPhotCam." << endl; AddNamePedPhotCam(); } fPedPhotCams.Clear(); TIter Next(&fNamePedPhotCams); TObject *o=0; while ((o=Next())) { TObject *p = pList->FindObject(AddSerialNumber(o->GetName()), "MPedPhotCam"); if (!p) { *fLog << err << AddSerialNumber(o->GetName()) << " [MPedPhotCam] not found... aborting." << endl; //*fLog << " Use MBadPixelsTreat::SetProcessPedestalRun(kFALSE) and" << endl; //*fLog << " MBadPixelsTreat::SetProcessPedestalEvt(kFALSE) to switch" << endl; //*fLog << " Pedestal treatment off." << endl; return kFALSE; } fPedPhotCams.Add(p); } } fTimes = 0; if (IsProcessTimes()) { fTimes = (MArrivalTime*)pList->FindObject(AddSerialNumber("MArrivalTime")); if (!fTimes) { *fLog << err << AddSerialNumber("MArrivalTime") << " not found... aborting." << endl; *fLog << " Use MBadPixelsTreat::SetProcessTimes(kFALSE) to switch time interpolation off." << endl; return kFALSE; } } if (IsProcessPedestalEvt()) *fLog << inf << "Processing Pedestals once per event..." << endl; if (IsProcessPedestalRun()) *fLog << inf << "Processing Pedestals once per run..." << endl; if (IsProcessTimes()) *fLog << inf << "Processing Arrival Times once per event..." << endl; return kTRUE; } // -------------------------------------------------------------------------- // // Replaces each pixel (signal, signal error, pedestal, pedestal rms) // by the average of its surrounding pixels. // If TESTBIT(fFlags, kUseCentralPixel) is set the central pixel is also // included. // void MBadPixelsTreat::InterpolateSignal() const { const UShort_t entries = fGeomCam->GetNumPixels(); // // Create arrays (FIXME: Check if its possible to create it only once) // MArrayD nphot(entries); MArrayD perr(entries); // // Loop over all pixels // for (UShort_t i=0; iGetPixById(i); // // Check whether pixel with idx i is blind // if (pix && !IsPixelBad(i)) continue; // // Get a pointer to this pixel. If it is not yet existing // create a new entry for this pixel in MCerPhotEvt // if (!pix) { pix = fEvt->AddPixel(i, 0, 0); (*fBadPixels)[i].SetUnsuitable(MBadPixelsPix::kUnsuitableEvt); } // // Get the corresponding geometry and pedestal // const MGeomPix &gpix = (*fGeomCam)[i]; // Do Not-Use-Central-Pixel const Bool_t nucp = !TESTBIT(fFlags, kUseCentralPixel); Int_t num = nucp ? 0 : 1; nphot[i] = nucp ? 0 : pix->GetNumPhotons(); perr[i] = nucp ? 0 : Pow2(pix->GetErrorPhot()); // // The values are rescaled to the small pixels area for the right comparison // const Double_t ratio = fGeomCam->GetPixRatio(i); nphot[i] *= ratio; perr[i] *= ratio; // // Loop over all its neighbors // const Int_t n = gpix.GetNumNeighbors(); for (int j=0; jGetPixById(nidx); if (!evtpix) continue; // // Get the geometry for the neighbor // const Double_t nratio = fGeomCam->GetPixRatio(nidx); // //The error is calculated as the quadratic sum of the errors // nphot[i] += nratio*evtpix->GetNumPhotons(); perr[i] += nratio* Pow2(evtpix->GetErrorPhot()); num++; } // Check if there are enough neighbors to calculate the mean // If not, unmap the pixel. The maximum number of blind neighbors // should be 2 if (numSetPixelUnmapped(); continue; } // // Now the mean is calculated and the values rescaled back // to the pixel area // nphot[i] /= (num*ratio); perr[i] = TMath::Sqrt(perr[i]/(num*ratio)); pix->Set(nphot[i], perr[i]); } } // -------------------------------------------------------------------------- // void MBadPixelsTreat::InterpolatePedestals(MPedPhotCam &pedphot) const { const Int_t entries = pedphot.GetSize(); // Create arrays (FIXME: Check if its possible to create it only once) MArrayD ped(entries); MArrayD rms(entries); // // Loop over all pixels // for (UShort_t i=0; iGetPixRatio(i); ped[i] *= ratio; rms[i] *= ratio; // // Loop over all its neighbors // const Int_t n = gpix.GetNumNeighbors(); for (int j=0; jGetPixRatio(nidx); const MPedPhotPix &nppix = pedphot[nidx]; // //The error is calculated as the quadratic sum of the errors // ped[i] += nratio*nppix.GetMean(); rms[i] += nratio*Pow2(nppix.GetRms()); num++; } // Check if there are enough neighbors to calculate the mean // If not, unmap the pixel. The minimum number of good neighbors // should be fNumMinNeighbors if (num < fNumMinNeighbors) { MCerPhotPix *pix =fEvt->GetPixById(i); if (!pix) pix = fEvt->AddPixel(i, 0, 0); pix->SetPixelUnmapped(); continue; } // // Now the mean is calculated and the values rescaled back // to the pixel area // ped[i] /= (num*ratio); rms[i] = TMath::Sqrt(rms[i]/(num*ratio)); pedphot[i].Set(ped[i], rms[i]); } pedphot.SetReadyToSave(); } // -------------------------------------------------------------------------- // // loop over all MPedPhotCam and interpolate them // void MBadPixelsTreat::InterpolatePedestals() const { TIter Next(&fPedPhotCams); MPedPhotCam *cam=0; while ((cam=(MPedPhotCam*)Next())) { InterpolatePedestals(*cam); cam->ReCalc(*fGeomCam, fBadPixels); } } // -------------------------------------------------------------------------- // void MBadPixelsTreat::InterpolateTimes() const { Int_t n = fTimes->GetSize(); for (int i=0; i=0) time[n0++] = t; } Int_t p0=-1; Int_t p1=-1; Double_t min=FLT_MAX; for (int j=0; j=min && diff<250) continue; p0 = j; p1 = k; min = diff; } // FIXME: Request a minimum number of neighbors to take action? if (p0>=0 && p1>=0 && TMath::Abs(time[p0] - time[p1])<250) fTimes->SetTime(i, (time[p0]+time[p1])/2); } } // -------------------------------------------------------------------------- // // Replaces each pixel (signal, signal error, pedestal, pedestal rms) // by the average of its surrounding pixels. // If TESTBIT(fFlags, kUseCentralPixel) is set the central pixel is also // included. // // NT: Informations about the interpolated pedestals are added. // When the option Interpolated is called, the blind pixel with the new // values of signal and fluttuation is included in the calculation of // the Image Parameters. // /* void MBadPixelsTreat::Interpolate() const { const UShort_t entries = fGeomCam->GetNumPixels(); // // Create arrays // TArrayD nphot(entries); TArrayD perr(entries); TArrayD ped(entries); TArrayD pedrms(entries); // // Loop over all pixels // for (UShort_t i=0; iGetPixById(i); // // Check whether pixel with idx i is blind // if (pix && (*fBadPixels)[i].IsOK()) continue; // // Get a pointer to this pixel. If it is not yet existing // create a new entry for this pixel in MCerPhotEvt // if (!pix) { pix = fEvt->AddPixel(i, 0, 0); (*fBadPixels)[i].SetUnsuitable(MBadPixelsPix::kUnsuitableEvt); } // // Get the corresponding geometry and pedestal // const MGeomPix &gpix = (*fGeomCam)[i]; const MPedPhotPix &ppix = (*fPedPhot)[i]; // Do Not-Use-Central-Pixel const Bool_t nucp = !TESTBIT(fFlags, kUseCentralPixel); Int_t num = nucp ? 0 : 1; nphot[i] = nucp ? 0 : pix->GetNumPhotons(); ped[i] = nucp ? 0 : ppix.GetMean(); perr[i] = nucp ? 0 : Pow2(pix->GetErrorPhot()); pedrms[i] = nucp ? 0 : Pow2(ppix.GetRms()); // // The values are rescaled to the small pixels area for the right comparison // const Double_t ratio = fGeomCam->GetPixRatio(i); if (nucp) { nphot[i] *= ratio; perr[i] *= ratio; ped[i] *= ratio; pedrms[i] *= ratio; } // // Loop over all its neighbors // const Int_t n = gpix.GetNumNeighbors(); for (int j=0; jGetPixById(nidx); if (!evtpix) continue; // // Get the geometry for the neighbor // const Double_t nratio = fGeomCam->GetPixRatio(nidx); MPedPhotPix &nppix = (*fPedPhot)[nidx]; // // The error is calculated as the quadratic sum of the errors // nphot[i] += nratio*evtpix->GetNumPhotons(); ped[i] += nratio*nppix.GetMean(); perr[i] += nratio*Pow2(evtpix->GetErrorPhot()); pedrms[i] += nratio*Pow2(nppix.GetRms()); num++; } if (numSetPixelUnmapped(); nphot[i] = 0; ped[i] = 0; perr[i] = 0; pedrms[i] = 0; continue; } // // Now the mean is calculated and the values rescaled back to the pixel area // nphot[i] /= num*ratio; ped[i] /= num*ratio; perr[i] = TMath::Sqrt(perr[i]/(num*ratio)); pedrms[i] = TMath::Sqrt(pedrms[i]/(num*ratio)); } // // Now the new pixel values are calculated and can be replaced in // the corresponding containers // for (UShort_t i=0; iGetPixById(i)->Set(nphot[i], perr[i]); (*fPedPhot)[i].Set(ped[i], pedrms[i]); } } */ // -------------------------------------------------------------------------- // // Removes all blind pixels from the analysis by setting their state // to unused. // void MBadPixelsTreat::Unmap() const { const UShort_t entries = fEvt->GetNumPixels(); // // remove the pixels in fPixelsIdx if they are set to be used, // (set them to 'unused' state) // for (UShort_t i=0; i