CFEL - ASG Software Suite  2.5.0
CASS
coalesce_simple.cpp
Go to the documentation of this file.
1 // Copyright (C) 2011 Lutz Foucar
2 
3 /**
4  * @file coalesce_simple.cpp contains class that does the pixel coalescing in a
5  * simple way.
6  *
7  * @author Lutz Foucar
8  */
9 
10 #include <algorithm>
11 #include <limits>
12 #include <cmath>
13 
14 #include "coalesce_simple.h"
15 
16 #include "cass_settings.h"
17 #include "advanced_pixeldetector.h"
18 
19 using namespace cass;
20 using namespace pixeldetector;
21 using namespace std;
22 
23 namespace cass
24 {
25 namespace pixeldetector
26 {
27 namespace Direction
28 {
29 /** enum for easier code */
31 }
32 
33 /** check if pixel is neighbour
34  *
35  * predicate struct for find if. Will return true when a pixel is a neighbour.
36  * It will check whether the position of the pixel is identical to the
37  * coordinate that was given to this predicate in the constructor. The pixel
38  * also is not allowed to be used before as a neighbour of another pixel.
39  *
40  * @author Lutz Foucar
41  */
43 {
44  /** the coordinate of the neighbour to check */
45  pair<uint16_t,uint16_t> _neighbourCoordinate;
46 
47  /** constructor
48  *
49  * @param coordinate the coordinate of the neighbour
50  */
51  isNeighbour(const pair<uint16_t,uint16_t> & coordinate)
52  :_neighbourCoordinate(coordinate)
53  {}
54 
55  /** the operator
56  *
57  * @return true when pixel has not been used and is neighbour
58  * @param pixel reference to the potential neighbour
59  */
60  bool operator()(const Pixel &pixel)
61  {
62  return (!pixel.used &&
63  pixel.x == _neighbourCoordinate.first &&
64  pixel.y == _neighbourCoordinate.second);
65  }
66 };
67 
68 /** find all neighbours of a pixel
69  *
70  * This function is meant to be called recursively only to a depth of 5. First
71  * it will add the pixel that is passed to this function to the split pixel
72  * list and is marked as used. Then it will try to find another pixel in the
73  * pixellist of the frame, that is a neighbour of that pixel. It will search
74  * whether there is a pixel above, underneath, left or right from the pixel
75  * and call this function for this pixel recursively and increases the depth
76  * by one. As parameter it will also tell the callee where the orignal pixel
77  * was, so that when checking for neightbours we can omit the directions we
78  * came from.
79  *
80  * This idea was inspired by Tom White.
81  *
82  * @param depth The recursive depth of calling this function
83  * @param maxDepth The maximum allowed recursive depth of calling this function
84  * @param pixel The pixel whos neighbours we are searching for
85  * @param direction The direction that we came from
86  * @param frame Reference to the frame containing the frame data an info about
87  * the coulumns and rows of the frame.
88  * @param pixels the list of pixels that should be coalesced
89  * @param splitpixelslist Reference to the list of pixels that have neighbours
90  * The event (hit) that all these pixels belong to has
91  * been split among the pixels in this list.
92  *
93  * @author Lutz Foucar
94  */
95 void findNeighbours(uint16_t depth,
96  const uint16_t maxDepth,
97  Pixel& pixel,
99  const Frame &frame,
100  CoalescingBase::pixels_t &pixels,
101  CoalescingBase::pixels_t &splitpixelslist)
102 {
103  typedef pair<uint16_t,uint16_t> position_t;
104 
105  if (depth > maxDepth)
106  return;
107  pixel.used = true;
108  splitpixelslist.push_back(pixel);
109 
110  /** check for neighbour to the west */
111  if (direction != Direction::east)
112  {
113  if (pixel.x != 0)
114  {
115  position_t left(make_pair(pixel.x-1,pixel.y));
116  CoalescingBase::pixels_t::iterator neighbourPixelIt
117  (find_if(pixels.begin(), pixels.end(), isNeighbour(left)));
118  if (neighbourPixelIt != pixels.end())
119  findNeighbours(depth+1,maxDepth,*neighbourPixelIt, Direction::west, frame, pixels, splitpixelslist);
120  }
121  }
122  /** check for neighbour to the east */
123  if (direction != Direction::west)
124  {
125  if (pixel.x < frame.columns-1)
126  {
127  position_t right(make_pair(pixel.x+1,pixel.y));
128  CoalescingBase::pixels_t::iterator neighbourPixelIt
129  (find_if(pixels.begin(), pixels.end(), isNeighbour(right)));
130  if (neighbourPixelIt != pixels.end())
131  findNeighbours(depth+1,maxDepth,*neighbourPixelIt, Direction::east, frame, pixels, splitpixelslist);
132  }
133  }
134  /** check for neighbour to the north */
135  if (direction != Direction::south)
136  {
137  if (pixel.y < frame.rows-1)
138  {
139  position_t top(make_pair(pixel.x,pixel.y+1));
140  CoalescingBase::pixels_t::iterator neighbourPixelIt
141  (find_if(pixels.begin(), pixels.end(), isNeighbour(top)));
142  if (neighbourPixelIt != pixels.end())
143  findNeighbours(depth+1,maxDepth,*neighbourPixelIt, Direction::north, frame, pixels, splitpixelslist);
144  }
145  }
146  /** check for neighbour to the south*/
147  if (direction != Direction::north)
148  {
149  if (pixel.y != 0)
150  {
151  position_t bottom(make_pair(pixel.x,pixel.y-1));
152  CoalescingBase::pixels_t::iterator neighbourPixelIt
153  (find_if(pixels.begin(), pixels.end(), isNeighbour(bottom)));
154  if (neighbourPixelIt != pixels.end())
155  findNeighbours(depth+1,maxDepth,*neighbourPixelIt, Direction::south, frame, pixels, splitpixelslist);
156  }
157  }
158 }
159 
160 /** coalesce the pixels
161  *
162  * Coalesce the pixels in the pixel list to an hit on the detector. The value
163  * (Z) of the pixels will be added. The position of the hit is defined by
164  * the center of mass of the pixel group. Also remember how many pixels
165  * contributed to the hit.
166  *
167  * @return the hit, which is the coalesced pixels
168  * @param splitpixelslist The list of pixels that belong to one hit on the
169  * detector.
170  *
171  * @author Lutz Foucar
172  */
173 Hit coalesce(const CoalescingBase::pixels_t &splitpixelslist)
174 {
175  Hit hit;
176  if (!splitpixelslist.empty())
177  {
178  hit.x = splitpixelslist.front().x;
179  hit.y = splitpixelslist.front().y;
180  hit.z = splitpixelslist.front().z;
181  float weightX(hit.x*hit.z);
182  float weightY(hit.y*hit.z);
183  CoalescingBase::pixels_t::const_iterator pixel(splitpixelslist.begin()+1);
184  for (; pixel != splitpixelslist.end(); ++pixel)
185  {
186  weightX += (pixel->z*pixel->x);
187  weightY += (pixel->z*pixel->y);
188  hit.z += pixel->z;
189  }
190  hit.x = weightX / hit.z;
191  hit.y = weightY / hit.z;
192  hit.nbrPixels = splitpixelslist.size();
193  }
194  return hit;
195 }
196 
197 /** check whether list of pixel should be coalesced
198  *
199  * Checks whether the pixels in the list are a massiv ionizing particle (MIP)
200  * candidate. This means whether the value (z) of that pixel is above a user
201  * set threshold. If this is true then the list should not be coalesced.
202  * Then check whether one of the neighbouring pixels in the raw frame is 0.
203  * This means that it has been marked as bad by either the darkframe
204  * calibration or by the user.
205  *
206  * @return true when the pixels in the list should be coalesced
207  * @param splitpixelslist The list of pixels that belong to one hit on the
208  * detector.
209  * @param mipThreshold The threshold above which a pixel is identified as MIP
210  * signature
211  * @param frame The frame of this detector
212  *
213  * @author Lutz Foucar
214  */
215 bool shouldCoalescePixel(const CoalescingBase::pixels_t &splitpixelslist,
216  const float mipThreshold,
217  const Frame &frame)
218 {
219  CoalescingBase::pixels_t::const_iterator pixel(splitpixelslist.begin());
220  const size_t framewidth(frame.columns);
221  const size_t frameheight(frame.rows);
222  const Detector::frame_t &data(frame.data);
223  for (; pixel != splitpixelslist.end(); ++pixel)
224  {
225  if (pixel->z > mipThreshold)
226  {
227  // cout <<" mpiThreshold reached: " <<pixel->z()<<endl;
228  return false;
229  }
230  const size_t idx(pixel->y*framewidth + pixel->x);
231  // lower row
232  if (pixel->y != 0)
233  {
234  if (qFuzzyIsNull(data[idx-framewidth])) //lower middle
235  {
236  // cout << "lower middle is " << frame[idx-framewidth]<<endl;
237  return false;
238  }
239  if (pixel->x != 0 && qFuzzyIsNull(data[idx-framewidth-1])) //lower left
240  {
241  // cout << "lower left is " << frame[idx-framewidth-1]<<endl;
242  return false;
243  }
244  if (pixel->x < framewidth-1 && qFuzzyIsNull(data[idx-framewidth+1])) //lower right
245  {
246  // cout << "lower right is " << frame[idx-framewidth+1]<<endl;
247  return false;
248  }
249  }
250 
251  // same row
252  if (pixel->x != 0 && qFuzzyIsNull(data[idx-1])) //left
253  {
254  // cout << "left is " << frame[idx-1]<<endl;
255  return false;
256  }
257  if (pixel->x < framewidth-1 && qFuzzyIsNull(data[idx+1])) //right
258  {
259  // cout << "right is " << frame[idx+1]<<endl;
260  return false;
261  }
262 
263  // upper row
264  if (pixel->y < frameheight-1)
265  {
266  if (qFuzzyIsNull(data[idx+framewidth])) //lower middle
267  {
268  // cout << "upper middle is " << frame[idx+framewidth]<<endl;
269  return false;
270  }
271  if (pixel->x != 0 && qFuzzyIsNull(data[idx+framewidth-1])) //upper left
272  {
273  // cout << "upper left is " << frame[idx+framewidth-1]<<endl;
274  return false;
275  }
276  if (pixel->x < framewidth-1 && qFuzzyIsNull(data[idx+framewidth+1])) //upper right
277  {
278  // cout << "uppper right is " << frame[idx+framewidth+1]<<endl;
279  return false;
280  }
281  }
282  }
283  return true;
284 }
285 
286 }//end namespace pixeldetector
287 }//end namespace cass
288 
290 {}
291 
293 {
294  s.beginGroup("SimpleCoalescing");
295  _maxPixelListSize = s.value("MaxPixelListSize",10000).toUInt();
296  _maxRecursionDepth = s.value("MaxRecursionDepth",7).toUInt();
297  _mipThreshold = s.value("MipThreshold",1e6).toFloat();
298  _notCheckCoalesce = s.value("ShouldNotCheckCoalsescing",false).toBool();
299  s.endGroup();
300 }
301 
303  pixels_t &pixels,
304  hits_t &hits)
305 {
306  if (pixels.size() > _maxPixelListSize)
307  return hits;
308 
309  pixels_t::iterator pixel(pixels.begin());
310  for(; pixel != pixels.end(); ++pixel)
311  {
312  if (!pixel->used)
313  {
314  pixels_t splitHit_pixels;
315  findNeighbours(0,_maxRecursionDepth,*pixel, Direction::origin, frame, pixels, splitHit_pixels);
316  if (_notCheckCoalesce || shouldCoalescePixel(splitHit_pixels,_mipThreshold,frame))
317  {
318  Hit hit(coalesce(splitHit_pixels));
319  hits.push_back(hit);
320  }
321  }
322  }
323  return hits;
324 }
float x
the x coordinate of hit
std::vector< Hit > hits_t
define the list of coalesced pixels
direction
enum for easier code
check if pixel is neighbour
Settings for CASS.
Definition: cass_settings.h:30
uint16_t y
y coordinate of the pixel
define which of the hitfinders defined above will be used as hit
STL namespace.
Average out the iShit status to get the avererage hits
contains class that does the pixel coalescing in a simple way.
std::vector< pixel_t > frame_t
a frame is a vector of pixels
uint16_t columns
how many columns
hits_t & operator()(const Frame &frame, pixels_t &pixels, hits_t &hits)
coalesce the pixels
bool operator()(const Pixel &pixel)
the operator
void loadSettings(CASSSettings &s)
load the settings of this
A Hit on a pixel detector.
auxiliary data[Processor]
bool shouldCoalescePixel(const CoalescingBase::pixels_t &splitpixelslist, const float mipThreshold, const Frame &frame)
check whether list of pixel should be coalesced
value(const QString &key, const QVariant &defaultValue=QVariant()
float y
the x coordinate of hit
uint32_t used
value to mark pixel any analysis of the pixels
A Frame of an advance Pixel Detector.
size_t nbrPixels
number of pixels that this hit consists of
uint16_t x
x coordinate of the pixel
Detector::frame_t data
the frame data
file contains specialized class that do the settings for cass
uint64_t z
the value of the hit
void findNeighbours(uint16_t depth, const uint16_t maxDepth, Pixel &pixel, Direction::direction direction, const Frame &frame, CoalescingBase::pixels_t &pixels, CoalescingBase::pixels_t &splitpixelslist)
find all neighbours of a pixel
Hit coalesce(const CoalescingBase::pixels_t &splitpixelslist)
coalesce the pixels
advanced pixeldetectors
int16_t pixel
define a pixel
Definition: hlltypes.hpp:27
isNeighbour(const pair< uint16_t, uint16_t > &coordinate)
constructor
pair< uint16_t, uint16_t > _neighbourCoordinate
the coordinate of the neighbour to check
beginGroup(const QString &prefix)