/* ======================================================================== *\ ! ! * ! * 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): Sebastian Raducci, 12/2003 ! ! Copyright: MAGIC Software Development, 2000-2003 ! ! \* ======================================================================== */ ///////////////////////////////////////////////////////////////////////////// // // MArrivalTime // // Times are calculated using the TSpline5 Root Class // ///////////////////////////////////////////////////////////////////////////// #include "MArrivalTime.h" #include "MGeomCam.h" #include "MGeomPix.h" #include "MLog.h" #include "MLogManip.h" #include "MRawEvtPixelIter.h" #include "MRawEvtData.h" ClassImp(MArrivalTime); using namespace std; // -------------------------------------------------------------------------- // // Creates an object containing the arrival time for each pixel in the event // MArrivalTime::MArrivalTime(const char *name, const char *title) { fName = name ? name : "MArrivalTime"; fTitle = title ? title : "Photons arrival times Information"; } // // Calculates the arrival time for each pixel // Possible Methods // Case 1: Spline5 (From TSpline5 Root Class) // // void MArrivalTime::Calc(const MRawEvtData &evt, const MGeomCam &geom) { const Int_t n = geom.GetNumPixels(); fData.Set(n); fData.Reset(); MRawEvtPixelIter pixel((MRawEvtData*)&evt); while ( pixel.Next() ) { const UInt_t idx = pixel.GetPixelId(); //If pixel has saturated and hasn't lo gains we return -1 if (pixel.GetMaxHiGainSample() == 0xff) { if (!pixel.HasLoGain()) { fData[idx]=-1.0; } else //Calculate time using Lo Gains { Byte_t *ptr = pixel.GetLoGainSamples(); Int_t nSlice = evt.GetNumLoGainSamples(); //Some casts are needed because TSpline5 constructor accepts only Double_t values Double_t ptr2[nSlice]; for (Int_t i = 0; i < nSlice; i++) ptr2[i]=(Double_t)ptr[i]; TSpline5 *spline = new TSpline5("spline",(Double_t) 0,(Double_t)(nSlice - 1),ptr2,nSlice); //Now find the maximum evaluating the spline function at every 1/10 time slice Double_t abscissa=0.0; Double_t maxAb=0.0; Double_t maxOrd=0.0; Double_t swap; while (abscissa <= nSlice - 1) { swap=spline->Eval(abscissa); if (swap > maxOrd) { maxOrd = swap; maxAb = abscissa; } abscissa += 0.1; } fData[idx]=maxAb; } } else //Calculate time using Hi Gains { Byte_t *ptr = pixel.GetHiGainSamples(); Int_t nSlice = evt.GetNumHiGainSamples(); //Some casts are needed because TSpline5 constructor accepts only Double_t values Double_t ptr2[nSlice]; for (Int_t i = 0; i < nSlice; i++) ptr2[i]=(Double_t)ptr[i]; TSpline5 *spline = new TSpline5("spline",(Double_t) 0,(Double_t)(nSlice - 1),ptr2,nSlice); //Now find the maximum evaluating the spline function at every 1/10 time slice Double_t abscissa=0.0; Double_t maxAb=0.0; Double_t maxOrd=0.0; Double_t swap; while (abscissa <= nSlice - 1) { swap=spline->Eval(abscissa); if (swap > maxOrd) { maxOrd = swap; maxAb = abscissa; } abscissa += 0.1; } fData[idx]=maxAb; } } } // ------------------------------------------------------------------------- // // Finds the clusters with similar Arrival Time // // PRELIMINARY!! For now the Arrival Time is not the one calculated with // the splines, but it's the Max Slice Idx // // TEST!! This method is used only for test. Do not use it until // it becomes stable // void MArrivalTime::EvalClusters(const MRawEvtData &evt, const MGeomCam &geom) { const Int_t n = geom.GetNumPixels(); fData2.Set(n); fData2.Reset(-1); fData3.Set(n); fData3.Reset(-1); fData4.Set(n); fData4.Reset(-1); fData5.Set(n); fData5.Reset(-1); MRawEvtPixelIter pixel((MRawEvtData*)&evt); // Array that says if a pixel has been already checked or not for (Int_t i = 0; i < n; i++) fPixelChecked[i] = kFALSE; // This fakeData array will be subsituted with the fData Array. fakeData.Set(n); fakeData.Reset(); while ( pixel.Next() ) { fakeData[pixel.GetPixelId()]=pixel.GetIdxMaxHiLoGainSample(); } // End of fakeData preparation // Max dimension of cluster Short_t dimCluster; while ( pixel.Next() ) { if (!fPixelChecked[pixel.GetPixelId()]) { dimCluster = 0; fCluster.Set(n); fCluster.Reset(-1); fCluster[dimCluster]=pixel.GetPixelId(); dimCluster++; CheckNeighbours(evt,geom, pixel.GetPixelId(), &dimCluster); if (dimCluster > 4) { for (Int_t i = 0; i < dimCluster; i++) fData5[fCluster[i]]=fakeData[fCluster[i]]; } if (dimCluster > 3) { for (Int_t i = 0; i < dimCluster; i++) fData4[fCluster[i]]=fakeData[fCluster[i]]; } if (dimCluster > 2) { for (Int_t i = 0; i < dimCluster; i++) fData3[fCluster[i]]=fakeData[fCluster[i]]; } if (dimCluster > 1) { for (Int_t i = 0; i < dimCluster; i++) fData2[fCluster[i]]=fakeData[fCluster[i]]; } } } } // -------------------------------------------------------------------------- // // Function to check the nearest neighbour pixels arrivaltime // void MArrivalTime::CheckNeighbours(const MRawEvtData &evt, const MGeomCam &geom, Short_t idx, Short_t *dimCluster) { Byte_t numNeighbors=geom[idx].GetNumNeighbors(); fPixelChecked[idx] = kTRUE; for (Byte_t i=0x00; i < numNeighbors; i++) { if (!fPixelChecked[geom[idx].GetNeighbor(i)] && fakeData[idx] == fakeData[geom[idx].GetNeighbor(i)]) { fCluster[*dimCluster]=geom[idx].GetNeighbor(i); *dimCluster++; CheckNeighbours(evt, geom, geom[idx].GetNeighbor(i), dimCluster); } } } // -------------------------------------------------------------------------- // // Returns the arrival time value // Bool_t MArrivalTime::GetPixelContent(Double_t &val, Int_t idx, const MGeomCam &cam, Int_t type) const { if (idx<0 || idx>=fData.GetSize()) return kFALSE; switch (type) { case 0: case 1: val = fData[idx]; break; case 2: val = fData2[idx]; break; case 3: val = fData3[idx]; break; case 4: val = fData4[idx]; break; case 5: val = fData5[idx]; break; } return kTRUE; } void MArrivalTime::DrawPixelContent(Int_t num) const { *fLog << warn << "MArrivalTime::DrawPixelContent - not available." << endl; }