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

Last change on this file since 17839 was 17833, checked in by tbretz, 11 years ago
First working version.
File size: 7.4 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 Island island(pix1.GetNumPhotons(), time1);
102
103 for (UInt_t i=0; i<gpix1.GetNumNeighbors(); i++)
104 {
105 const Int_t idx2 = gpix1.GetNeighbor(i);
106
107 MSignalPix &pix2 = (*fEvt)[idx2];
108
109 const Int_t island2 = pix2.GetIdxIsland();
110 if (island2>=0)
111 {
112 if (island1==island2)
113 continue;
114
115 // The entries are sorted naturally, therefore
116 // there is no need to check the whole array
117 const auto it = fContacts.rbegin();
118 if (it==fContacts.rend() ||
119 (it->first!=island1 && it->second!=island2))
120 fContacts.emplace_back(island1, island2);
121
122 continue;
123 }
124
125 const Float_t time2 = pix2.GetArrivalTime();
126 if (fabs(time2-time1)<fDeltaT) // FIXME: Scale with distance?
127 island += CalcIsland(pix2, (*fCam)[idx2], island1);
128 }
129
130 return island;
131}
132
133// --------------------------------------------------------------------------
134//
135// Cleans the image.
136//
137Int_t MImgCleanTime::Process()
138{
139 // The assumption is that all pixels contain valid data
140 const UInt_t npix = fEvt->GetNumPixels();
141 for (UInt_t i=0; i<npix; i++)
142 {
143 MSignalPix &pix = (*fEvt)[i];
144 pix.SetPixelUnused();
145 pix.SetPixelCore(kFALSE);
146 pix.SetIdxIsland(-1);
147 }
148
149 // Contains the id of the island for each pixel
150 fIslands.clear();
151 fContacts.clear();
152
153 // Start with island idx==0
154 UShort_t idx = 0;
155 for (UInt_t i=0; i<npix; i++)
156 {
157 MSignalPix &spix = (*fEvt)[i];
158
159 // The following might be much more efficient and faster
160 // if we omit small counted and sized islands already,
161 // but what is the disadvantage?
162 if (spix.GetIdxIsland()<0)
163 fIslands.emplace_back(CalcIsland(spix, (*fCam)[i], idx++));
164 }
165
166 fLut.resize(fIslands.size());
167 for (UInt_t i=0; i<fLut.size(); i++)
168 fLut[i] = i;
169
170 // Unify touching islands if their arrival time ranges overlap
171 for (auto it=fContacts.begin(); it!=fContacts.end(); it++)
172 {
173 const uint16_t &idx1 = fLut[it->first];
174 const uint16_t &idx2 = fLut[it->second];
175 if (idx1==idx2)
176 continue;
177
178 // FIXME: Put a limit on count? Put a limit on size?
179 if ((fIslands[idx1].min<fIslands[idx2].min || fIslands[idx1].min>fIslands[idx2].max) &&
180 (fIslands[idx1].max<fIslands[idx2].min || fIslands[idx1].max>fIslands[idx2].max) &&
181 (fIslands[idx2].min<fIslands[idx1].min || fIslands[idx2].min>fIslands[idx1].max) &&
182 (fIslands[idx2].max<fIslands[idx1].min || fIslands[idx2].max>fIslands[idx1].max))
183 continue;
184
185 // Combine both islands
186 fIslands[idx1] += fIslands[idx2];
187
188 // Remove idx2 from the list
189 for (auto is=fLut.begin(); is!=fLut.end(); is++)
190 if (*is==idx2)
191 *is=idx1;
192
193 // Erase entry form contact list
194 fContacts.erase(it);
195
196 // Start over again
197 it = fContacts.begin();
198 }
199
200 uint16_t num_islands = 0;
201 double size_main = 0;
202 double size_tot = 0;
203
204 vector<bool> used(fIslands.size());
205 for (UInt_t i=0; i<npix; i++)
206 {
207 MSignalPix &pix = (*fEvt)[i];
208
209 // At the end every pixel has an island assigned
210 const Short_t ii = fLut[pix.GetIdxIsland()];
211
212 const Island &island = fIslands[ii];
213
214 if (island.count<=fMinCount || island.size<=fMinSize)
215 continue;
216
217 if (!used[ii])
218 {
219 used[ii] = true;
220 num_islands++;
221
222 size_tot += island.size;
223 if (island.size>size_main)
224 size_main = island.size;
225 }
226
227 pix.SetPixelUsed();
228 pix.SetPixelCore();
229 }
230
231 fEvt->SetIslandInfo(num_islands, size_main, size_tot-size_main);
232
233 return kTRUE;
234}
235
236// --------------------------------------------------------------------------
237//
238Int_t MImgCleanTime::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
239{
240 Bool_t rc = kFALSE;
241 if (IsEnvDefined(env, prefix, "MinSize", print))
242 {
243 rc = kTRUE;
244 SetMinSize(GetEnvValue(env, prefix, "MinSize", fMinSize));
245 }
246 if (IsEnvDefined(env, prefix, "MinCount", print))
247 {
248 rc = kTRUE;
249 SetMinSize(GetEnvValue(env, prefix, "MinCount", (Int_t)fMinCount));
250 }
251 if (IsEnvDefined(env, prefix, "DeltaT", print))
252 {
253 rc = kTRUE;
254 SetMinSize(GetEnvValue(env, prefix, "DeltaT", fDeltaT));
255 }
256
257 return rc;
258}
Note: See TracBrowser for help on using the repository browser.