source: trunk/Mars/mimage/MImgCleanTime.cc@ 20103

Last change on this file since 20103 was 18286, checked in by Daniela Dorner, 9 years ago
fixed bug (signle pixels were not ignored) and ignore unmapped pixels
File size: 7.5 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, 4/2014 <mailto:tbretz@phys.ethz.ch>
19!
20! Copyright: MAGIC Software Development, 2014
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MImgCleanTime
28//
29// Input Containers:
30// MGeomCam
31// MSignalCam
32//
33// Output Containers:
34// MSignalCam
35//
36/////////////////////////////////////////////////////////////////////////////
37#include "MImgCleanTime.h"
38
39#include <TEnv.h>
40
41#include "MLog.h"
42#include "MLogManip.h"
43
44#include "MParList.h"
45
46#include "MGeomPix.h"
47#include "MGeomCam.h"
48
49#include "MSignalPix.h"
50#include "MSignalCam.h"
51
52ClassImp(MImgCleanTime);
53
54using namespace std;
55
56// --------------------------------------------------------------------------
57//
58// Default constructor. Here you can specify the cleaning method and levels.
59// If you don't specify them the 'common standard' values 3.0 and 2.5 (sigma
60// above mean) are used.
61// Here you can also specify how many rings around the core pixels you want
62// to analyze (with the fixed lvl2). The default value for "rings" is 1.
63//
64MImgCleanTime::MImgCleanTime(const char *name, const char *title)
65 : fCam(0), fEvt(0), fMinCount(0), fMinSize(25), fDeltaT(2.5*17.5*0.1111),
66 fNameSignalCam("MSignalCam")
67{
68 fName = name ? name : "MImgCleanTime";
69 fTitle = title ? title : "Task to perform image cleaning";
70}
71
72// --------------------------------------------------------------------------
73//
74// Check if MEvtHeader exists in the Parameter list already.
75// if not create one and add them to the list
76//
77Int_t MImgCleanTime::PreProcess (MParList *pList)
78{
79 fCam = (MGeomCam*)pList->FindObject("MGeomCam");
80 if (!fCam)
81 {
82 *fLog << err << "MGeomCam not found (no geometry information available)... aborting." << endl;
83 return kFALSE;
84 }
85 fEvt = (MSignalCam*)pList->FindObject(fNameSignalCam, "MSignalCam");
86 if (!fEvt)
87 {
88 *fLog << err << fNameSignalCam << " [MSignalCam] not found... aborting." << endl;
89 return kFALSE;
90 }
91
92 return kTRUE;
93}
94
95Island MImgCleanTime::CalcIsland(MSignalPix &pix1, const MGeom &gpix1, const uint16_t &island1)
96{
97 pix1.SetIdxIsland(island1);
98
99 const Float_t time1 = pix1.GetArrivalTime();
100
101 if (pix1.IsPixelUnmapped())
102 return Island(0,time1);
103
104 Island island(pix1.GetNumPhotons(), time1);
105
106 for (UInt_t i=0; i<gpix1.GetNumNeighbors(); i++)
107 {
108 const Int_t idx2 = gpix1.GetNeighbor(i);
109
110 MSignalPix &pix2 = (*fEvt)[idx2];
111 if (pix2.IsPixelUnmapped())
112 continue;
113
114 const Int_t island2 = pix2.GetIdxIsland();
115 if (island2>=0)
116 {
117 if (island1==island2)
118 continue;
119
120 // The entries are sorted naturally, therefore
121 // there is no need to check the whole array
122 const auto it = fContacts.rbegin();
123 if (it==fContacts.rend() ||
124 (it->first!=island1 && it->second!=island2))
125 fContacts.emplace_back(island1, island2);
126
127 continue;
128 }
129
130 const Float_t time2 = pix2.GetArrivalTime();
131 if (fabs(time2-time1)<fDeltaT) // FIXME: Scale with distance?
132 island += CalcIsland(pix2, (*fCam)[idx2], island1);
133 }
134
135 return island;
136}
137
138// --------------------------------------------------------------------------
139//
140// Cleans the image.
141//
142Int_t MImgCleanTime::Process()
143{
144 // The assumption is that all mapped pixels contain valid data
145 const UInt_t npix = fEvt->GetNumPixels();
146 for (UInt_t i=0; i<npix; i++)
147 {
148 MSignalPix &pix = (*fEvt)[i];
149 if (!pix.IsPixelUnmapped())
150 pix.SetPixelUnused();
151 pix.SetPixelCore(kFALSE);
152 pix.SetIdxIsland(-1);
153 }
154
155 // Contains the id of the island for each pixel
156 fIslands.clear();
157 fContacts.clear();
158
159 // Start with island idx==0
160 UShort_t idx = 0;
161 for (UInt_t i=0; i<npix; i++)
162 {
163 MSignalPix &spix = (*fEvt)[i];
164
165 // The following might be much more efficient and faster
166 // if we omit small counted and sized islands already,
167 // but what is the disadvantage?
168 if (spix.GetIdxIsland()<0)
169 fIslands.emplace_back(CalcIsland(spix, (*fCam)[i], idx++));
170 }
171
172 fLut.resize(fIslands.size());
173 for (UInt_t i=0; i<fLut.size(); i++)
174 fLut[i] = i;
175
176 // Unify touching islands if their arrival time ranges overlap
177 for (auto it=fContacts.begin(); it!=fContacts.end(); it++)
178 {
179 const uint16_t &idx1 = fLut[it->first];
180 const uint16_t &idx2 = fLut[it->second];
181 if (idx1==idx2)
182 continue;
183
184 Island &I1 = fIslands[idx1];
185 const Island &I2 = fIslands[idx2];
186
187 // FIXME: Put a limit on count? Put a limit on size?
188 // The ideal cut would be to allow that a single
189 // pixel still can connect two clusters
190 if (I1.count==1 || I2.count==1)
191 continue;
192
193 if (I1.max<I2.min || I2.max<I1.min)
194 continue;
195
196 // Combine both islands
197 I1 += I2;
198
199 // Remove idx2 from the list
200 for (auto is=fLut.begin(); is!=fLut.end(); is++)
201 if (*is==idx2)
202 *is=idx1;
203
204 // Erase entry form contact list
205 fContacts.erase(it);
206
207 // Start over again
208 it = fContacts.begin();
209 }
210
211 uint16_t num_islands = 0;
212 double size_main = 0;
213 double size_tot = 0;
214
215 vector<bool> used(fIslands.size());
216 for (UInt_t i=0; i<npix; i++)
217 {
218 MSignalPix &pix = (*fEvt)[i];
219
220 // At the end every pixel has an island assigned
221 const Short_t ii = fLut[pix.GetIdxIsland()];
222
223 const Island &island = fIslands[ii];
224
225 if (island.count<=fMinCount || island.size<=fMinSize)
226 continue;
227
228 if (!used[ii])
229 {
230 used[ii] = true;
231 num_islands++;
232
233 size_tot += island.size;
234 if (island.size>size_main)
235 size_main = island.size;
236 }
237
238 pix.SetPixelUsed();
239 pix.SetPixelCore();
240 }
241
242 fEvt->SetIslandInfo(num_islands, size_main, size_tot-size_main);
243
244 return kTRUE;
245}
246
247// --------------------------------------------------------------------------
248//
249Int_t MImgCleanTime::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
250{
251 Bool_t rc = kFALSE;
252 if (IsEnvDefined(env, prefix, "MinSize", print))
253 {
254 rc = kTRUE;
255 SetMinSize(GetEnvValue(env, prefix, "MinSize", fMinSize));
256 }
257 if (IsEnvDefined(env, prefix, "MinCount", print))
258 {
259 rc = kTRUE;
260 SetMinSize(GetEnvValue(env, prefix, "MinCount", (Int_t)fMinCount));
261 }
262 if (IsEnvDefined(env, prefix, "DeltaT", print))
263 {
264 rc = kTRUE;
265 SetMinSize(GetEnvValue(env, prefix, "DeltaT", fDeltaT));
266 }
267
268 return rc;
269}
Note: See TracBrowser for help on using the repository browser.