CFEL - ASG Software Suite  2.5.0
CASS
hitfinder.cpp
Go to the documentation of this file.
1 // Copyright (C) 2013,2018 Lutz Foucar
2 
3 /** @file hitfinder.cpp contains processors that will extract pixels of
4  * interrest from 2d histograms.
5  * @author Lutz Foucar
6  */
7 
8 #include <QtCore/QString>
9 #include <iterator>
10 #include <algorithm>
11 
12 #include "cass.h"
13 #include "hitfinder.h"
14 #include "convenience_functions.h"
15 #include "cass_settings.h"
16 #include "log.h"
17 #include "geom_parser.h"
18 
19 using namespace std;
20 using namespace cass;
21 using tr1::bind;
22 using tr1::placeholders::_1;
23 using tr1::placeholders::_2;
24 
25 
26 // ********** processor 203: subtract local background ************
27 
28 pp203::pp203(const name_t &name)
29  : Processor(name)
30 {
31  loadSettings(0);
32 }
33 
34 void pp203::loadSettings(size_t)
35 {
36  CASSSettings s;
37 
38  s.beginGroup("Processor");
40 
41  // size of box for median
42  _boxSize = make_pair(s.value("BoxSizeX", 10).toUInt(),
43  s.value("BoxSizeY",10).toUInt());
44  _sectionSize = make_pair(s.value("SectionSizeX", 1024).toUInt(),
45  s.value("SectionSizeY",512).toUInt());
46 
47  setupGeneral();
48 
49  // Get the input
50  _hist = setupDependency("ImageName");
51  bool ret (setupCondition());
52  if (!(_hist && ret)) return;
53 
54  // Create the output
55  createHistList(_hist->result().clone());
56 
57  Log::add(Log::INFO,"Processor '" + name() +
58  "' removes median of a box with size x'" + toString(_boxSize.first) +
59  "' and y '" + toString(_boxSize.second) + "' from individual pixels" +
60  " of hist in pp '"+ _hist->name() + "'. Condition is '" +
61  _condition->name() + "'");
62 }
63 
64 void pp203::process(const CASSEvent& evt, result_t &result)
65 {
66  // Get the input
67  const result_t &image(_hist->result(evt.id()));
68  QReadLocker lock(&image.lock);
69 
70  const size_t xsize(image.axis(result_t::xAxis).nBins);
71  const size_t ysize(image.axis(result_t::yAxis).nBins);
72  const size_t xsectionsize(_sectionSize.first);
73  const size_t ysectionsize(_sectionSize.second);
74  const size_t xnbrsections(xsize/xsectionsize);
75  const size_t ynbrsections(ysize/ysectionsize);
76  const size_t xboxsize(_boxSize.first);
77  const size_t yboxsize(_boxSize.second);
78 
79  vector<float> box;
80  for (size_t sy=0; sy<ynbrsections; ++sy)
81  {
82  for (size_t sx=0; sx<xnbrsections; ++sx)
83  {
84  const size_t xsectionbegin(sx*xsectionsize);
85  const size_t xsectionend(sx*xsectionsize + xsectionsize);
86  const size_t ysectionbegin(sy*ysectionsize);
87  const size_t ysectionend(sy*ysectionsize + ysectionsize);
88 
89 // cout << xsectionbegin << " "<<xsectionend << " "<<ysectionbegin << " "<<ysectionend<<endl;
90  for (size_t y=ysectionbegin; y<ysectionend; ++y)
91  {
92  for (size_t x=xsectionbegin; x<xsectionend; ++x)
93  {
94  const size_t pixAddr(y*xsize+x);
95  const float pixel(image[pixAddr]);
96 
97  if (fuzzycompare(pixel,0.f) )
98  {
99  result[pixAddr] = pixel;
100  continue;
101  }
102 
103  const size_t xboxbegin(max(static_cast<int>(xsectionbegin),static_cast<int>(x)-static_cast<int>(xboxsize)));
104  const size_t xboxend(min(xsectionend,x+xboxsize));
105  const size_t yboxbegin(max(static_cast<int>(ysectionbegin),static_cast<int>(y)-static_cast<int>(yboxsize)));
106  const size_t yboxend(min(ysectionend,y+yboxsize));
107 
108 // cout <<x << " " << xboxbegin << " "<<xboxend <<" : " <<y<< " "<<yboxbegin << " "<<yboxend<<endl;
109  box.clear();
110  for (size_t yb=yboxbegin; yb<yboxend;++yb)
111  {
112  for (size_t xb=xboxbegin; xb<xboxend;++xb)
113  {
114  const size_t pixAddrBox(yb*xsize+xb);
115  const float pixel_box(image[pixAddrBox]);
116  if ( ! fuzzyIsNull(pixel_box) )
117  box.push_back(pixel_box);
118  }
119  }
120 
121  if (box.empty())
122  {
123  result[pixAddr] = pixel;
124  }
125  else
126  {
127  const size_t mid(0.5*box.size());
128  nth_element(box.begin(), box.begin() + mid, box.end());
129  const float median = box[mid];
130  result[pixAddr] = median;
131 // const float backgroundsubstractedPixel(pixel-median);
132 // image_out[pixAddr] = backgroundsubstractedPixel;
133  }
134  }
135  }
136  }
137  }
138 }
139 
140 
141 
142 // ********** processor 204: find bragg peaks ************
143 
144 pp204::pp204(const name_t &name)
145  : Processor(name)
146 {
147  loadSettings(0);
148 }
149 
151 {
152  CASSSettings s;
153 
154  s.beginGroup("Processor");
156 
157  // size of box for median
158  const int peakRadius(s.value("BraggPeakRadius",2).toInt());
159  _peakRadiusSq = peakRadius*peakRadius;
160  const int goodBoxSize(sqrt(3.1415) * peakRadius);
161  _box = make_pair(s.value("BoxSizeX", goodBoxSize).toUInt(),
162  s.value("BoxSizeY",goodBoxSize).toUInt());
163  _section = make_pair(s.value("SectionSizeX", 1024).toUInt(),
164  s.value("SectionSizeY",512).toUInt());
165  _threshold = s.value("Threshold",300).toFloat();
166  _minSnr = s.value("MinSignalToNoiseRatio",20).toFloat();
167  _minNeighbourSNR = s.value("MinNeighbourSNR",3).toFloat();
168  _minBckgndPixels = s.value("MinNbrBackgrndPixels",10).toInt();
169 
170  setupGeneral();
171 
172  _hist = setupDependency("ImageName");
173 
174  bool ret (setupCondition());
175  if (!(_hist && ret))
176  return;
177 
178  /** Create the resulting table */
180 
181  /** log what the user was requesting */
182  string output("Processor '" + name() + "' finds bragg peaks." +
183  "'. Boxsize '" + toString(_box.first)+"x"+ toString(_box.second)+
184  "'. SectionSize '" + toString(_section.first)+"x"+ toString(_section.second)+
185  "'. Threshold '" + toString(_threshold) +
186  "'. MinSignalToNoiseRatio '" + toString(_minSnr) +
187  "'. MinNbrBackgrndPixels '" + toString(_minBckgndPixels) +
188  "'. Square BraggPeakRadius '" + toString(_peakRadiusSq) +
189  "'. Using input histogram :" + _hist->name() +
190  "'. Condition is '" + _condition->name() + "'");
191  Log::add(Log::INFO,output);
192 }
193 
194 
196  const imagepos_t ncols,
197  pixelval_t &mean, pixelval_t &stdv, int &count)
198 {
199  enum{good,skip};
201  for (imagepos_t bRow=-_box.second; bRow <= _box.second; ++bRow)
202  {
203  for (imagepos_t bCol=-_box.first; bCol <= _box.first; ++bCol)
204  {
205  /** only consider pixels that are not in the origin of the box */
206  if (bRow == 0 && bCol == 0)
207  continue;
208 
209  /** check if the current box pixel value is bigger than the center pixel
210  * value. If so skip this pixel
211  */
212  const imagepos_t bLocIdx(bRow*ncols+bCol);
213  const pixelval_t bPixel(pixel[bLocIdx]);
214  if(*pixel < bPixel )
215  return skip;
216 
217  /** if box pixel is outside the radius, add it to the statistics, if it
218  * is inside the radius bad then skip, as no pixel that could potentially
219  * be part of the peak should be a bad pixel.
220  */
221  const bool pixIsBad(qFuzzyIsNull(bPixel));
222  const int radiussq(bRow*bRow + bCol*bCol);
223  if (_peakRadiusSq < radiussq)
224  stat.addDatum(bPixel);
225  else if (pixIsBad)
226  return skip;
227  }
228  }
229  count = stat.count();
230  mean = stat.mean();
231  stdv = stat.stdv();
232  return good;
233 }
234 
235 void pp204::process(const CASSEvent& evt, result_t &result)
236 {
237  const result_t &image(_hist->result(evt.id()));
238  QReadLocker lock(&image.lock);
239 
240  /** reset the nbr of y entries */
241  result.resetTable();
242 
243  const imagepos_t ncols(image.shape().first);
244  const imagepos_t nrows(image.shape().second);
245 
246  imagepos_t neigbourOffsetArray[] =
247  {
248  ncols-1,
249  ncols,
250  ncols+1,
251  -1,
252  1,
253  -ncols-1,
254  -ncols,
255  -ncols+1,
256  };
257  vector<imagepos_t> neighboursOffsets(neigbourOffsetArray,
258  neigbourOffsetArray + sizeof(neigbourOffsetArray)/sizeof(int));
259  table_t peak(nbrOf,0);
260  vector<bool> checkedPixels(image.size(),false);
261 
262  vector<bool>::iterator checkedPixel(checkedPixels.begin());
264  imagepos_t idx(0);
265  for (;pixel != image.end(); ++pixel,++idx, ++checkedPixel)
266  {
267  /** check if pixel has been touched before */
268  if (*checkedPixel)
269  continue;
270 
271  /** check above a set threshold */
272  if (*pixel < _threshold)
273  continue;
274 
275  /** get coordinates of pixel and tell that it is touched */
276  const uint16_t col(idx % ncols);
277  const uint16_t row(idx / ncols);
278 
279  /** make sure that pixel is located such that the box will not conflict with
280  * the image and section boundaries
281  */
282  if (col < _box.first || ncols - _box.first < col || //within box in x
283  row < _box.second || nrows - _box.second < row || //within box in y
284  (col - _box.first) / _section.first != (col + _box.first) / _section.first || //x within same section
285  (row - _box.second) / _section.second != (row + _box.second) / _section.second) //y within same section
286  continue;
287 
288  /** check wether current pixel value is highest and generate background values */
289  pixelval_t mean,stdv;
290  int count;
291  if (getBoxStatistics(pixel,ncols,mean,stdv,count))
292  continue;
293 
294  /** check that we took more than the minimum pixels for the background */
295  if (count < _minBckgndPixels)
296  continue;
297 
298  /** check if signal to noise ration is good for the current pixel */
299  const pixelval_t snr((*pixel - mean) / stdv);
300  if (snr < _minSnr)
301  continue;
302 
303  /** from the central pixel look around and see which pixels are direct
304  * part of the peak. If a neighbour is found, mask it such that one does
305  * not use it twice.
306  *
307  * Create a list that should contain the indizes of the pixels that are
308  * part of the peak. Go through that list and check for each found
309  * neighbour whether it also has a neighbour. If so add it to the list, but
310  * only if it is part of the box.
311  */
312  vector<imagepos_t> peakIdxs;
313  peakIdxs.push_back(idx);
314  *checkedPixel = true;
315  for (size_t pix=0; pix < peakIdxs.size(); ++pix)
316  {
317  const imagepos_t pixpos(peakIdxs[pix]);
318  vector<imagepos_t>::const_iterator nOffset(neighboursOffsets.begin());
319  vector<imagepos_t>::const_iterator neighboursEnd(neighboursOffsets.end());
320  while(nOffset != neighboursEnd)
321  {
322  const size_t nIdx(pixpos + *nOffset++);
323  const imagepos_t nCol(nIdx % ncols);
324  const imagepos_t nRow(nIdx / ncols);
325  if (checkedPixels[nIdx] ||
326  _box.first < abs(col - nCol) ||
327  _box.second < abs(row - nRow))
328  continue;
329  const pixelval_t nPixel(image[nIdx]);
330  const pixelval_t nPixelWOBckgnd(nPixel - mean);
331  const pixelval_t nSNR(nPixelWOBckgnd / stdv);
332  if (_minNeighbourSNR < nSNR)
333  {
334  peakIdxs.push_back(nIdx);
335  checkedPixels[nIdx] = true;
336  }
337  }
338  }
339 
340  /** go through all pixels in the box, find out which pixels are part of the
341  * peak and centroid them. Mask all pixels in the box as checked so one
342  * does not check them again
343  */
344  pixelval_t integral = 0;
345  pixelval_t weightCol = 0;
346  pixelval_t weightRow = 0;
347  imagepos_t nPix = 0;
348  imagepos_t max_radiussq=0;
349  imagepos_t min_radiussq=max(_box.first,_box.second)*max(_box.first,_box.second);
350  for (int bRow=-_box.second; bRow <= _box.second; ++bRow)
351  {
352  for (int bCol=-_box.first; bCol <= _box.first; ++bCol)
353  {
354  const imagepos_t bLocIdx(bRow*ncols+bCol);
355  const pixelval_t bPixel(pixel[bLocIdx]);
356  const pixelval_t bPixelWOBckgnd(bPixel - mean);
357  if (checkedPixel[bLocIdx])
358  {
359  const imagepos_t radiussq(bRow*bRow + bCol*bCol);
360  if (radiussq > max_radiussq)
361  max_radiussq = radiussq;
362  if (radiussq < min_radiussq)
363  min_radiussq = radiussq;
364  integral += bPixelWOBckgnd;
365  weightCol += (bPixelWOBckgnd * (bCol+col));
366  weightRow += (bPixelWOBckgnd * (bRow+row));
367  ++nPix;
368  }
369  checkedPixel[bLocIdx] = true;
370  }
371  }
372  peak[centroidColumn] = weightCol / integral;
373  peak[centroidRow] = weightRow / integral;
374  peak[Intensity] = integral;
375  peak[nbrOfPixels] = nPix;
376  peak[SignalToNoise] = snr;
377  peak[MaxRadius] = sqrt(max_radiussq);
378  peak[MinRadius] = sqrt(min_radiussq);
379  peak[Index] = idx;
380  peak[Column] = col;
381  peak[Row] = row;
382  peak[MaxADU] = *pixel;
383  peak[LocalBackground] = mean;
384  peak[LocalBackgroundDeviation] = stdv;
385  peak[nbrOfBackgroundPixels] = count;
386 
387  result.appendRows(peak);
388 
389  }
390 
391 }
392 
393 
394 
395 
396 
397 
398 
399 // ********** processor 205: display peaks ************
400 
401 pp205::pp205(const name_t &name)
402  : Processor(name)
403 {
404  loadSettings(0);
405 }
406 
408 {
409  CASSSettings s;
410 
411  s.beginGroup("Processor");
413 
414  setupGeneral();
415 
416  // Get the input
417  _hist = setupDependency("ImageName");
418  _table = setupDependency("TableName");
419  bool ret (setupCondition());
420  if (!(_hist && ret && _table))
421  return;
422 
423  _boxsize = make_pair(s.value("BoxSizeX", 10).toUInt(),
424  s.value("BoxSizeY",10).toUInt());
425  _drawVal = s.value("DrawPixelValue",16000.f).toFloat();
426  _drawInner = s.value("DrawInnerPixel",false).toBool();
427  _drawInnerValue = s.value("InnerPixelValue",16000.f).toFloat();
428  _radius = s.value("Radius",2.f).toFloat();
429  _idxCol = s.value("IndexColumn").toUInt();
430  _drawCircle = s.value("DrawCircle",true).toBool();
431  _drawBox = s.value("DrawBox",true).toBool();
432 
433  size_t maxIdx(_table->result().axis(result_t::xAxis).nBins);
434  if (_idxCol >= maxIdx)
435  throw runtime_error("pp205::loadSettings(): '" + name() + "' The requested " +
436  "column '" + toString(_idxCol) + " 'exeeds the " +
437  "maximum possible value of '" + toString(maxIdx) + "'");
438 
439  // Create the output
440  createHistList(_hist->result().clone());
441 
442  Log::add(Log::INFO,"Processor '" + name() +
443  "' displays the peaks that are listed in '" + _table->name() +
444  "' and that were found in '" + _hist->name() + "'. Condition is '" +
445  _condition->name() + "'");
446 }
447 
448 void pp205::process(const CASSEvent& evt, result_t &result)
449 {
450  // Get the input
451  const result_t &image(_hist->result(evt.id()));
452  QReadLocker lock1(&image.lock);
453  const result_t &table(_table->result(evt.id()));
454  QReadLocker lock2(&table.lock);
455 
456  /** copy the input image to the resulting image */
457  copy(image.begin(),image.end(),result.begin());
458 
459  /** extract the nbr of rows and columns of this table and the image */
460  const size_t nTableCols(table.shape().first);
461  const size_t nTableRows(table.shape().second);
462  const size_t nImageCols(image.shape().first);
463 
464  /** go through all rows in table */
465  for (size_t row=0; row < nTableRows; ++row)
466  {
467  /** extract the column with the global index of the peak center */
468  const int idx(table[row*nTableCols + _idxCol]);
469  result_t::iterator centerpixel(result.begin()+idx);
470 
471  /** draw user requested info (extract other stuff from table) */
472  //box
473  if (_drawBox)
474  {
475 // //lower row
476 // for (int bCol=-_boxsize.first; bCol <= _boxsize.first; ++bCol)
477 // {
478 // const int bRow = -_boxsize.second;
479 // const int bLocIdx(bRow*nImageCols+bCol);
480 // centerpixel[bLocIdx] = _drawVal;
481 // }
482 // //upper row
483 // for (int bCol=-_boxsize.first; bCol <= _boxsize.first; ++bCol)
484 // {
485 // const int bRow = _boxsize.second;
486 // const int bLocIdx(bRow*nImageCols+bCol);
487 // centerpixel[bLocIdx] = _drawVal;
488 // }
489 // //left col
490 // for (int bRow=-_boxsize.second; bRow <= _boxsize.second; ++bRow)
491 // {
492 // const int bCol = -_boxsize.first;
493 // const int bLocIdx(bRow*nImageCols+bCol);
494 // centerpixel[bLocIdx] = _drawVal;
495 // }
496 // //right col
497 // for (int bRow=-_boxsize.second; bRow <= _boxsize.second; ++bRow)
498 // {
499 // const int bCol = _boxsize.first;
500 // const int bLocIdx(bRow*nImageCols+bCol);
501 // centerpixel[bLocIdx] = _drawVal;
502 // }
503 
504  for (int bRow = -_boxsize.second; bRow <= _boxsize.second; ++bRow)
505  {
506  for (int bCol = -_boxsize.first; bCol <= _boxsize.first; ++bCol)
507  {
508  const int bLocIdx(idx + bRow*nImageCols+bCol);
509  if (bLocIdx >= static_cast<int>(result.size()) || bLocIdx < 0)
510  {
511  string tableRow;
512  for (size_t i(0); i<nTableCols; ++i)
513  tableRow += toString(i) + "'" +
514  toString(table[row*nTableCols + i])
515  +"', ";
516  throw logic_error("pp205 '" + name() +
517  "': Calculated index out of bounds: " +
518  "nTableRows'" + toString(nTableRows) + "', " +
519  "tableRow'" + toString(row) + "', " +
520  "tableRowContent'" + tableRow + "', " +
521  "bRow'" + toString(bRow) + "', " +
522  "bCol'" + toString(bCol) + "', " +
523  "size'" + toString(result.size()) + "', " +
524  "idx'" + toString(idx) + "', " +
525  "nImageCols'" + toString(nImageCols) + "', " +
526  "localIdx'" + toString(bLocIdx) + "'");
527  }
528  const bool border = (bCol == _boxsize.first ||
529  bCol == -_boxsize.first ||
530  bRow == _boxsize.second ||
531  bRow == -_boxsize.second);
532  if (border)
533  result[bLocIdx] = _drawVal;
534  else if (_drawInner)
535  result[bLocIdx] = _drawInnerValue;
536  }
537  }
538  }
539 
540  //circle
541  if (_drawCircle)
542  {
543  for(size_t angle_deg = 0; angle_deg <360; ++angle_deg)
544  {
545  const float angle_rad(3.14 * static_cast<float>(angle_deg)/180.);
546  const int cCol (static_cast<size_t>(round(_radius*sin(angle_rad))));
547  const int cRow (static_cast<size_t>(round(_radius*cos(angle_rad))));
548  const int cLocIdx(cRow*nImageCols+cCol);
549  centerpixel[cLocIdx] = _drawVal;
550  }
551  }
552 
553  }
554 }
555 
556 
557 
558 
559 
560 
561 // ********** processor 206: find pixels of bragg peaks ************
562 
563 pp206::pp206(const name_t &name)
564  : Processor(name)
565 {
566  loadSettings(0);
567 }
568 
570 {
571  CASSSettings s;
572 
573  s.beginGroup("Processor");
575 
576  // size of box for median
577  _box = make_pair(s.value("BoxSizeX", 10).toUInt(),
578  s.value("BoxSizeY",10).toUInt());
579  _section = make_pair(s.value("SectionSizeX", 1024).toUInt(),
580  s.value("SectionSizeY",512).toUInt());
581  _threshold = s.value("Threshold",300).toFloat();
582  _multiplier = s.value("Multiplier",4).toFloat();
583 
584  setupGeneral();
585 
586  _imagePP = setupDependency("ImageName");
587  _noisePP = setupDependency("NoiseName");
588 
589  bool ret (setupCondition());
590  if (!(_imagePP && ret && _noisePP))
591  return;
592 
593  /** Create the result output */
595 
596  /** log what the user was requesting */
597  string output("Processor '" + name() + "' finds bragg peaks." +
598  "'. Boxsize '" + toString(_box.first)+"x"+ toString(_box.second)+
599  "'. SectionSize '" + toString(_section.first)+"x"+ toString(_section.second)+
600  "'. Threshold '" + toString(_threshold) +
601  "'. Image Histogram :" + _imagePP->name() +
602  "'. Noise Histogram :" + _noisePP->name() +
603  "'. Condition is '" + _condition->name() + "'");
604  Log::add(Log::INFO,output);
605 }
606 
607 void pp206::process(const CASSEvent& evt, result_t &result)
608 {
609  const result_t &image(_imagePP->result(evt.id()));
610  QReadLocker lock1(&(image.lock));
611  const result_t &noisemap(_noisePP->result(evt.id()));
612  QReadLocker lock2(&(noisemap.lock));
613 
614  /** reset the table */
615  result.resetTable();
616 
617 
618  table_t peak(pp204::nbrOf,0);
619 
621  result_t::const_iterator imageEnd(image.end());
623  size_t idx(0);
624  vector<float> box;
625  const uint16_t ncols(image.shape().first);
626  const uint16_t nrows(image.shape().second);
627  for (; pixel != imageEnd; ++pixel, ++noise, ++idx)
628  {
629 // if(*noise * _multiplier < *pixel)
630  if (_threshold < *pixel)
631  {
632  const uint16_t x(idx % ncols);
633  const uint16_t y(idx / ncols);
634 
635  const uint16_t xboxbegin(max(static_cast<int>(0),static_cast<int>(x)-static_cast<int>(_box.first)));
636  const uint16_t xboxend(min(ncols,static_cast<uint16_t>(x+_box.first)));
637  const uint16_t yboxbegin(max(static_cast<int>(0),static_cast<int>(y)-static_cast<int>(_box.second)));
638  const uint16_t yboxend(min(nrows,static_cast<uint16_t>(y+_box.second)));
639 
640  box.clear();
641  for (size_t yb=yboxbegin; yb<yboxend;++yb)
642  {
643  for (size_t xb=xboxbegin; xb<xboxend;++xb)
644  {
645  const size_t pixAddrBox(yb*ncols+xb);
646  const float pixel_box(image[pixAddrBox]);
647  /** check if current sourrounding pixel is a bad pixel (0.),
648  * if so we should disregard the pixel as a candiate and check the
649  * next pixel.
650  */
651  if (qFuzzyCompare(pixel_box,0.f) )
652  goto NEXTPIXEL;
653  else
654  box.push_back(pixel_box);
655  }
656  }
657 
658  if (box.size() > 1)
659  {
660  const size_t mid(0.5*box.size());
661  nth_element(box.begin(), box.begin() + mid, box.end());
662  const float bckgnd = box[mid];
663  const float clrdpixel(*pixel - bckgnd);
664 // if(*noise * _multiplier < clrdpixel)
665  if (_threshold < clrdpixel)
666  {
667  peak[pp204::Column] = x;
668  peak[pp204::Row] = y;
669  peak[pp204::MaxADU] = *pixel;
670  peak[pp204::Intensity] = clrdpixel;
671 
672  result.appendRows(peak);
673  }
674  }
675 NEXTPIXEL:;
676  }
677  }
678 }
679 
680 
681 
682 
683 
684 
685 
686 
687 
688 // ********** processor 208: find bragg peaks ************
689 
690 pp208::pp208(const name_t &name)
691  : Processor(name)
692 {
693  loadSettings(0);
694 
695 }
696 
698 {
699  CASSSettings s;
700 
701  s.beginGroup("Processor");
703 
704  _section = make_pair(s.value("SectionSizeX", 1024).toUInt(),
705  s.value("SectionSizeY",512).toUInt());
706  _minSnr = s.value("MinSignalToNoiseRatio",4).toFloat();
707  _minRatio = s.value("MinRatio",3).toFloat();
708 
709  const int peakDiameter(s.value("BraggPeakDiameter",2).toInt());
710  /** area of box should at least be ratio times area of peak.
711  * \f{eqnarray*}{
712  * A_{box}&=& ratio \times A_{circle} \\
713  * size^2 &=& ratio \times \pi r^2 \\
714  * size &=& \sqrt{\pi r^2 \times ratio} \\
715  * &=& r \sqrt{\pi \times ratio} \\
716  * &=& 0.5 d \sqrt{\pi \times ratio}
717  * \f}
718  * If \f$ size \f$ goes from \f$-s ... s\f$ then \f$ size = 2s+1 \f$
719  * \f{eqnarray*}{
720  * 2s + 1 &=& 0.5 d \sqrt{\pi \times ratio} \\
721  * s &=& 0.5 \times 0.5 d \sqrt{\pi \times ratio} - 0.5 \\
722  * &=& 0.25 d \sqrt{\pi \times ratio} - 0.5
723  * \f}
724  * convert to integer
725  * \f{eqnarray*}{
726  * (int)s &=& 0.25d\sqrt{\pi \times ratio} - 0.5 + 0.5 \\
727  * &=& 0.25d\sqrt{\pi \times ratio}
728  * \f}
729  */
730  const int bsize(2 * peakDiameter );
731  _box = make_pair(s.value("BoxSizeX", bsize).toInt(),
732  s.value("BoxSizeY",bsize).toInt());
733 
734  /** min nbr of pixels should reflect the area under the bragg peak
735  * \f$ nbrPeaks = 0.25 \pi d \f$
736  */
737  _minNbrPixels = s.value("MinNbrPixels",0.25*3.14159*square(peakDiameter)).toInt();
738 
739  setupGeneral();
740  bool ret (setupCondition());
741 
742  /** use fixed value for wavelength if value can be converted to double,
743  * otherwise use the wavelength from the processor
744  */
745  bool wlIsDouble(false);
746  QString wlkey("Wavelength_A");
747  QString wlparam(s.value(wlkey,"1").toString());
748  double wlval(wlparam.toDouble(&wlIsDouble));
749  if (wlIsDouble)
750  {
751  _wavelength = wlval;
752  _getLambda = std::tr1::bind(&pp208::lambdaFromConstant,this,_1);
753  }
754  else
755  {
756  _wavelengthPP = setupDependency(wlkey.toStdString());
757  ret = _wavelengthPP && ret;
758  _getLambda = std::tr1::bind(&pp208::lambdaFromProcessor,this,_1);
759  }
760  /** use fixed value for detector distance if value can be converted to double,
761  * otherwise use the detector distance from the processor
762  */
763  bool ddIsDouble(false);
764  QString ddkey("DetectorDistance_m");
765  QString ddparam(s.value(ddkey,"60e-2").toString());
766  double ddval(ddparam.toDouble(&ddIsDouble));
767  if (ddIsDouble)
768  {
769  _detdist = ddval;
770  _getDistance = std::tr1::bind(&pp208::distanceFromConstant,this,_1);
771  }
772  else
773  {
774  _detdistPP = setupDependency(ddkey.toStdString());
775  ret = _detdistPP && ret;
776  _getDistance = std::tr1::bind(&pp208::distanceFromProcessor,this,_1);
777  }
778  /** use fixed value for threshold if value can be converted to double,
779  * otherwise use the detector distance from the processor
780  */
781  bool threshIsDouble(false);
782  QString threshkey("Threshold");
783  QString threshparam(s.value(threshkey,"0").toString());
784  const double threshval(threshparam.toDouble(&threshIsDouble));
785  if (threshIsDouble)
786  {
787  _threshold = threshval;
788  _thresh = std::tr1::bind(&pp208::thresholdFromConstant,this,_1);
789  }
790  else
791  {
792  _threshPP = setupDependency(threshkey.toStdString());
793  ret = _threshPP && ret;
794  _thresh = std::tr1::bind(&pp208::thresholdFromProcessor,this,_1);
795  }
796 
797  _imagePP = setupDependency("ImageName");
798 
799  if (!(_imagePP && ret))
800  return;
801 
802  /** check if the input processors have the correct type */
803  if (_imagePP->result().dim() != 2)
804  throw invalid_argument("pp208:loadSettings '" +name() +
805  "': input processor '" + _imagePP->name() +
806  "' is not a 2d result");
807  if (!wlIsDouble && _wavelengthPP->result().dim() != 0)
808  throw invalid_argument("pp208:loadSettings '" +name() +
809  "': wavelength processor '" + wlparam.toStdString() +
810  "' is not a 0d result");
811  if (!ddIsDouble && _detdistPP->result().dim() != 0)
812  throw invalid_argument("pp208:loadSettings '" +name() +
813  "': detector distance processor '" + ddparam.toStdString() +
814  "' is not a 0d result");
815  if (!threshIsDouble && _threshPP->result().dim() != 0)
816  throw invalid_argument("pp208:loadSettings '" +name() +
817  "': threshold processor '" + threshparam.toStdString()+
818  "' is not a 0d result");
819 
820  /** generate the lookuptable for the radia, if no geom file is provided,
821  * set the radia to 0
822  */
823  const string filename = s.value("GeometryFilename","wrong_file").toString().toStdString();
824  const bool convertCheetahToCASSLayout = s.value("ConvertCheetahToCASSLayout",true).toBool();
825  const double pixsizeX_m = s.value("PixelSizeX_m",109.92e-6).toDouble();
826  const double pixsizeY_m = s.value("PixelSizeY_m",109.92e-6).toDouble();
827  const result_t &srcImageHist(_imagePP->result());
828  if (filename != "wrong_file")
829  {
832  srcImageHist.size(),
833  srcImageHist.shape().first,
834  convertCheetahToCASSLayout);
835  _src2labradius.resize(src2lab.size());
836  for (size_t i=0; i < src2lab.size(); ++i)
837  {
838  const double x_m(src2lab[i].x *pixsizeX_m);
839  const double y_m(src2lab[i].y *pixsizeY_m);
840  _src2labradius[i] = sqrt(x_m*x_m + y_m*y_m);
841  }
842  }
843  else
844  {
845  _src2labradius.resize(srcImageHist.size(),0);
846  }
847 
848  /** set up the neighbouroffset list */
849  _imageShape = srcImageHist.shape();
850  _neighbourOffsets.clear();
851 // _neighbourOffsets.push_back(+_imageShape.first-1); //up left
852  _neighbourOffsets.push_back(+_imageShape.first+0); //up
853 // _neighbourOffsets.push_back(+_imageShape.first+1); //up right
854  _neighbourOffsets.push_back(-1); //left
855  _neighbourOffsets.push_back(+1); //right
856 // _neighbourOffsets.push_back(-_imageShape.first-1); //low left
857  _neighbourOffsets.push_back(-_imageShape.first+0); //low
858 // _neighbourOffsets.push_back(-_imageShape.first+1); //low right
859 
860  /** Create the result output */
862 
863  /** log what the user was requesting */
864  string output("Processor '" + name() + "' finds bragg peaks." +
865  "'. Boxsize '" + toString(_box.first)+"x"+ toString(_box.second)+
866  "'. SectionSize '" + toString(_section.first)+"x"+ toString(_section.second)+
867  "'. Threshold '" + threshparam.toStdString() +
868  "'. MinSignalToNoiseRatio '" + toString(_minSnr) +
869  "'. MinPixels '" + toString(_minNbrPixels) +
870  "'. MinFraction '" + toString(_minRatio) +
871  "'. Using input histogram :" + _imagePP->name() +
872  "'. Wavelength :" + wlparam.toStdString() +
873  "'. Detector Distance :" + ddparam.toStdString() +
874  "'. Geomfile :" + filename +
875  "'. Convert Cheetah to CASS :" + (convertCheetahToCASSLayout? "true":"false") +
876  "'. Pixelsize [m] :" + toString(pixsizeX_m) + "x" + toString(pixsizeY_m) +
877  "'. Condition is '" + _condition->name() + "'");
878  Log::add(Log::INFO,output);
879 }
880 
882 {
883  const result_t &wavelength(_wavelengthPP->result(id));
884  QReadLocker lock(&wavelength.lock);
885  return wavelength.getValue();
886 }
887 
889 {
890  const result_t &detdist(_detdistPP->result(id));
891  QReadLocker lock(&detdist.lock);
892  return detdist.getValue();
893 }
894 
896 {
897  const result_t &thresh(_threshPP->result(id));
898  QReadLocker lock(&thresh.lock);
899  return thresh.getValue();
900 }
901 
903 {
904  return _threshold;
905 }
906 
908  const index_t linIdx, const shape_t &box, stat_t &stat)
909 {
910  enum{use,skip};
911 
912  /** get coordinates of pixel from the linearized index */
913  const index_t col(linIdx % _imageShape.first);
914  const index_t row(linIdx / _imageShape.first);
915 
916  /** make sure that pixel is located such that the box will not conflict with
917  * the image and section boundaries. If it does continue with next pixel
918  */
919  if (col < box.first || _imageShape.first - box.first < col || //within box in x
920  row < box.second || _imageShape.second - box.second < row || //within box in y
921  (col - box.first) / _section.first != (col + box.first) / _section.first || //x within same section
922  (row - box.second) / _section.second != (row + box.second) / _section.second) //y within same section
923  return skip;
924 
925  /** go through all pixels defined by the box from -rows ... rows, -cols ... cols */
926  for (shape_t::second_type bRow = -box.second; bRow <= box.second; ++bRow)
927  {
928  for (shape_t::first_type bCol = -box.first; bCol <= box.first; ++bCol)
929  {
930  /** check if the current box pixel value is bigger than the center pixel
931  * value. If so skip this pixel
932  */
933  const index_t bLocIdx(bRow*_imageShape.first+bCol);
934  const pixelval_t bPixel(pixel[bLocIdx]);
935  if(*pixel < bPixel )
936  return skip;
937 
938  /** if its not a bad pixel add pixel to statistics */
939  if (!qFuzzyIsNull(bPixel))
940  stat.addDatum(bPixel);
941  }
942  }
943  return use;
944 }
945 
947  const index_t linIdx, shape_t box, stat_t &stat)
948 {
949  enum{use,skip};
950 
951  bool boxsizeincreased(false);
952  do
953  {
954  /** check whether current pixel value is highest and generate background values */
955  stat.reset();
956  if (getBoxStatistics(pixel,linIdx,box,stat))
957  return skip;
958 
959  /** increase the box size and start over if the fraction of outliers to
960  * points used in the statistics is smaller than requested.
961  */
962  if (stat.nbrPointsUsed() < _minRatio * stat.nbrUpperOutliers())
963  {
964  ++(box.first);
965  ++(box.second);
966  boxsizeincreased = true;
967  }
968  else
969  {
970  boxsizeincreased = false;
971  }
972  }
973  while(boxsizeincreased);
974 
975  /** skip this pixel if there are not enough pixels that could potentially be
976  * part of the bragg peak.
977  */
978  if (stat.nbrUpperOutliers() < _minNbrPixels)
979  return skip;
980 
981  return use;
982 }
983 
984 
985 void pp208::process(const CASSEvent & evt, result_t &result)
986 {
987  const result_t &image(_imagePP->result(evt.id()));
988  QReadLocker hLock(&image.lock);
989 
990  /** clear the resulting table to fill it with the values of this image */
991  result.resetTable();
992 
993  /** get a table row that we can later add to the table */
994  table_t peak(nbrOf,0);
995 
996  /** set up a mask that we can see which pixels have been treated */
997  vector<bool> checkedPixels(image.size(),false);
998 
999  /** get iterators for the mask and the image with which we can iterate through
1000  * the image, also rember which linearized index we are working on right
1001  * now, to be able to retrieve the column and row that the current pixel
1002  * corresponsed to.
1003  */
1004  const pixelval_t thresh(_thresh(evt.id()));
1005  vector<bool>::iterator checkedPixel(checkedPixels.begin());
1007  result_t::const_iterator ImageEnd(image.end());
1008  index_t idx(0);
1009  for (;pixel != ImageEnd; ++pixel,++idx, ++checkedPixel)
1010  {
1011  /** check if pixel should be treated, when it has been treated before
1012  * continue with the next pixel
1013  */
1014  if (*checkedPixel)
1015  continue;
1016 
1017  /** check if pixel is above the threshold, otherwise continue with the next
1018  * pixel
1019  */
1020  if (*pixel < thresh)
1021  continue;
1022 
1023  /** check if pixel is highest within box. If so, check if there are enough
1024  * pixels that are not outliers. If there are not enough pixels in the box
1025  * increase the box size and do the checks all over again. If the pixel is
1026  * not highest within the bigger box continue with the next pixel.
1027  */
1028  shape_t box(_box);
1029  stat_t stat(_minSnr);
1030  if (isNotHighest(pixel, idx, box, stat))
1031  continue;
1032 
1033  /** retrive statistical values from the calculator */
1034  const stat_t::value_type mean(stat.mean());
1035  const stat_t::value_type stdv(stat.stdv());
1036 
1037  /** get coordinates of pixel in image from the linearized index */
1038  const index_t col(idx % _imageShape.first);
1039  const index_t row(idx / _imageShape.first);
1040 
1041  /** from the central pixel look around and see which pixels are direct
1042  * part of the peak. If a neighbour is found, mask it such that one does
1043  * not use it twice.
1044  *
1045  * Create a list that should contain the indizes of the pixels that are
1046  * part of the peak. Go through that list and check for each found
1047  * neighbour whether it also has a neighbour. If so add it to the list, but
1048  * only if it is part of the box.
1049  */
1050  vector<index_t> peakIdxs;
1051  peakIdxs.push_back(idx);
1052  *checkedPixel = true;
1053  for (size_t pix=0; pix < peakIdxs.size(); ++pix)
1054  {
1055  const index_t pixpos(peakIdxs[pix]);
1056  neighbourList_t::const_iterator ngbrOffset(_neighbourOffsets.begin());
1057  neighbourList_t::const_iterator neighboursEnd(_neighbourOffsets.end());
1058  while(ngbrOffset != neighboursEnd)
1059  {
1060  const index_t ngbrIdx(pixpos + *ngbrOffset++);
1061  const index_t ngbrCol(ngbrIdx % _imageShape.first);
1062  const index_t ngbrRow(ngbrIdx / _imageShape.first);
1063  /** @note need to check if the pixel has been used after verifiying that
1064  * the pixel is within the box. Otherwise in rare occasions it will
1065  * happen that the pixelindex is not within the boolean array which
1066  * will cause a segfault.
1067  */
1068  if (box.first < abs(col - ngbrCol) || //pixel not inside box col
1069  box.second < abs(row - ngbrRow)) //pixel not inside box row
1070  continue;
1071  if (checkedPixels[ngbrIdx]) //pixel has been used
1072  continue;
1073  const pixelval_t ngbrPixel(image[ngbrIdx]);
1074  const pixelval_t ngbrPixelWOBckgnd(ngbrPixel - mean);
1075  if ((_minSnr * stdv) < ngbrPixelWOBckgnd)
1076  {
1077  peakIdxs.push_back(ngbrIdx);
1078  checkedPixels[ngbrIdx] = true;
1079  }
1080  }
1081  }
1082 
1083  /** if the peak doesn't have enough pixels continue with next pixel */
1084  if (static_cast<int>(peakIdxs.size()) < _minNbrPixels)
1085  continue;
1086 
1087  /** go through all pixels in the box, find out which pixels are part of the
1088  * peak and centroid them. Mask all pixels in the box as checked so one
1089  * does not check them again
1090  */
1091  pixelval_t integral = 0;
1092  pixelval_t weightCol = 0;
1093  pixelval_t weightRow = 0;
1094  index_t max_radiussq=0;
1095  index_t min_radiussq=max(box.first,box.second)*max(box.first,box.second);
1096  for (int bRow = -box.second; bRow <= box.second; ++bRow)
1097  {
1098  for (int bCol = -box.first; bCol <= box.first; ++bCol)
1099  {
1100  const index_t bLocIdx(bRow*_imageShape.first+bCol);
1101  if (checkedPixel[bLocIdx])
1102  {
1103  const pixelval_t bPixel(pixel[bLocIdx]);
1104  const pixelval_t bPixelWOBckgnd(bPixel - mean);
1105  const index_t radiussq(bRow*bRow + bCol*bCol);
1106  if (radiussq > max_radiussq)
1107  max_radiussq = radiussq;
1108  if (radiussq < min_radiussq)
1109  min_radiussq = radiussq;
1110  integral += bPixelWOBckgnd;
1111  weightCol += (bPixelWOBckgnd * (bCol+col));
1112  weightRow += (bPixelWOBckgnd * (bRow+row));
1113  }
1114  checkedPixel[bLocIdx] = true;
1115  }
1116  }
1117 
1118  /** set the peak's properties and add peak to the list of found peaks */
1119  peak[centroidColumn] = weightCol / integral;
1120  peak[centroidRow] = weightRow / integral;
1121  peak[Intensity] = integral;
1122  peak[nbrOfPixels] = peakIdxs.size();
1123  peak[SignalToNoiseHighestPixel] = (*pixel-mean)/stdv;
1124  peak[SignalToNoiseSpot] = integral/stdv;
1125  peak[MaxRadius] = sqrt(max_radiussq);
1126  peak[MinRadius] = sqrt(min_radiussq);
1127  peak[Index] = idx;
1128  peak[Column] = col;
1129  peak[Row] = row;
1130  peak[MaxADU] = *pixel;
1131  peak[LocalBackground] = mean;
1132  peak[LocalBackgroundDeviation] = stdv;
1133  peak[nUpOutliers] = stat.nbrUpperOutliers();
1134  peak[Resolution] = 1.0 / ((2.0/_getLambda(evt.id())) *
1135  sin(0.5*atan(_src2labradius[idx]/_getDistance(evt.id()))));
1136 
1137  result.appendRows(peak);
1138  }
1139 
1140  /** tell that only the result of one event (image) is present in the table */
1141 }
1142 
1143 
1144 
1145 
1146 
1147 //******************** processor 209: cluster pixels ************
1148 
1149 
1150 pp209::pp209(const name_t &name)
1151  : Processor(name)
1152 {
1153  loadSettings(0);
1154 }
1155 
1157 {
1158  CASSSettings s;
1159 
1160  s.beginGroup("Processor");
1162 
1163  _factor = s.value("Factor",1).toFloat();
1164  setupGeneral();
1165  bool ret (setupCondition());
1166  _imagePP = setupDependency("ImageName");
1167  ret = _imagePP && ret;
1168  _threshPP = setupDependency("Threshold");
1169  ret = _threshPP && ret;
1170 
1171  if (!ret)
1172  return;
1173 
1174  /** get references to the input results */
1175  const result_t &srcImageHist(_imagePP->result());
1176  const result_t &srcThreshHist(_threshPP->result());
1177 
1178  /** get the shape of the input results */
1179  _imageShape = srcImageHist.shape();
1180  shape_t threshShape = srcThreshHist.shape();
1181 
1182 
1183  /** check if the input processors have the correct type */
1184  if (srcImageHist.dim() != 2)
1185  throw invalid_argument("pp209:loadSettings '" +name() +
1186  "': image processor '" + _imagePP->name() +
1187  "' doesn't contain a 2d result");
1188  if (srcThreshHist.dim() != 2)
1189  throw invalid_argument("pp209:loadSettings '" +name() +
1190  "': threshold processor '" + _threshPP->name() +
1191  "' doesn't contain a 2d result");
1192  if (_imageShape.first != threshShape.first)
1193  throw invalid_argument("pp209:loadSettings '" +name() +
1194  "': threshold processor '" + _threshPP->name() +
1195  "' x-size '" + toString(threshShape.first) +
1196  "' while image processor '" + _imagePP->name() +
1197  "' has x-size '" + toString(_imageShape.first));
1198  if (_imageShape.second != threshShape.second)
1199  throw invalid_argument("pp209:loadSettings '" +name() +
1200  "': threshold processor '" + _threshPP->name() +
1201  "' y-size '" + toString(threshShape.second) +
1202  "' while image processor '" + _imagePP->name() +
1203  "' has y-size '" + toString(_imageShape.second));
1204 
1205  /** set up the neighbouroffset list */
1206  _neighbourOffsets.clear();
1207  _neighbourOffsets.push_back(+_imageShape.first+0); //up
1208  _neighbourOffsets.push_back(-1); //left
1209  _neighbourOffsets.push_back(+1); //right
1210 
1211  /** Create the result output */
1213 
1214  /** log what the user was requesting */
1215  string output("Processor '" + name() + "' clusters pixels above threshold in '" +
1216  _imagePP->name() +
1217  "'. Threshold '" + _threshPP->name() +
1218  "'. Factor '" + toString(_factor) +
1219  "'. Condition is '" + _condition->name() + "'");
1220  Log::add(Log::INFO,output);
1221 }
1222 
1223 void pp209::process(const CASSEvent & evt, result_t &result)
1224 {
1225  const result_t &image(_imagePP->result(evt.id()));
1226  QReadLocker imageLock(&image.lock);
1227 
1228  const result_t &thresholds(_threshPP->result(evt.id()));
1229  QReadLocker threshLock(&image.lock);
1230 
1231  /** clear the resulting table to fill it with the values of this image */
1232  result.resetTable();
1233 
1234  /** get a table row that we can later add to the table */
1235  table_t peak(nbrOf,0);
1236 
1237  /** set up a mask that we can see which pixels have been treated */
1238  vector<bool> checkedPixels(image.size(),false);
1239 
1240  /** get iterators for the mask and the image with which we can iterate through
1241  * the image, also rember which linearized index we are working on right
1242  * now, to be able to retrieve the column and row that the current pixel
1243  * corresponsed to.
1244  */
1245  vector<bool>::iterator checkedPixel(checkedPixels.begin());
1247  result_t::const_iterator ImageEnd(image.begin() + image.datasize());
1248  result_t::const_iterator thresh(thresholds.begin());
1249  index_t idx(0);
1250  for (;pixel != ImageEnd; ++pixel, ++idx, ++checkedPixel, ++thresh)
1251  {
1252  /** check if pixel should be treated, when it has been treated before
1253  * continue with the next pixel
1254  */
1255  if (*checkedPixel)
1256  continue;
1257 
1258  /** if it wasn't checked, then its checked now */
1259  *checkedPixel = true;
1260 
1261  /** check if pixel is above the pixelwise threshold, which is increased
1262  * by the user provided factor, this allows to check the pixels using
1263  * a noise map.
1264  */
1265  if (*pixel < (_factor * (*thresh)))
1266  continue;
1267 
1268  /** from the pixel look around and see which pixels are also above the
1269  * threshold. If a neighbour is found, mask it such that one does
1270  * not use it twice.
1271  *
1272  * Create a list that should contain the indizes of the pixels that are
1273  * part of the peak. Go through that list and check for each found
1274  * neighbour whether it also has a neighbour. If so add it to the list, but
1275  * only if its above the threshold
1276  */
1277  vector<index_t> pixIdxs;
1278  pixIdxs.push_back(idx);
1279  for (size_t pix(0); pix < pixIdxs.size(); ++pix)
1280  {
1281  const index_t pixpos(pixIdxs[pix]);
1282  neighbourList_t::const_iterator ngbrOffset(_neighbourOffsets.begin());
1283  neighbourList_t::const_iterator neighboursEnd(_neighbourOffsets.end());
1284  while(ngbrOffset != neighboursEnd)
1285  {
1286  const index_t ngbrIdx(pixpos + *ngbrOffset++);
1287  const index_t ngbrCol(ngbrIdx % _imageShape.first);
1288  const index_t ngbrRow(ngbrIdx / _imageShape.first);
1289  /** check if the neighbour is within the image shape */
1290  if ( ngbrCol < 0 || // neighbour is to the left of image
1291  ngbrCol >= _imageShape.first || // neighbour is to the right of image
1292  ngbrRow < 0 || // neighbour is below the image
1293  ngbrRow >= _imageShape.second) // neighbour is above the image
1294  continue;
1295  /** check if neighbour was already treated */
1296  if (checkedPixels[ngbrIdx])
1297  continue;
1298  /** when the checks have passed it will be treated */
1299  checkedPixels[ngbrIdx] = true;
1300  /** check whether its above the threshold, if so add it to the pixellist */
1301  if ((_factor * thresholds[ngbrIdx])< image[ngbrIdx])
1302  pixIdxs.push_back(ngbrIdx);
1303  }
1304  }
1305 
1306  /** now that we found all the pixels that are connected to the starting
1307  * pixel, go through all pixels in the list and centroid them.
1308  */
1309  pixelval_t integral(0);
1310  pixelval_t weightCol(0);
1311  pixelval_t weightRow(0);
1312  pixelval_t maxPixVal(0);
1313  index_t maxPixIdx(0);
1314  index_t maxPixCol(0);
1315  index_t maxPixRow(0);
1316  index_t minCol(0);
1317  index_t maxCol(_imageShape.first);
1318  index_t minRow(0);
1319  index_t maxRow(_imageShape.second);
1320  vector<index_t>::const_iterator pixIdx(pixIdxs.begin());
1321  vector<index_t>::const_iterator pixIdxEnd(pixIdxs.end());
1322  for (; pixIdx != pixIdxEnd; ++pixIdx)
1323  {
1324  /** get the pixel parameters */
1325  const index_t pixCol(*pixIdx % _imageShape.first);
1326  const index_t pixRow(*pixIdx / _imageShape.first);
1327  const pixelval_t pixVal(image[*pixIdx]);
1328 
1329  /** calculate the peak properties */
1330  integral += pixVal;
1331  weightCol += (pixVal * static_cast<pixelval_t>(pixCol));
1332  weightRow += (pixVal * static_cast<pixelval_t>(pixRow));
1333 
1334  /** find the maximum pixel */
1335  if (maxPixVal < pixVal)
1336  {
1337  maxPixVal = pixVal;
1338  maxPixIdx = *pixIdx;
1339  maxPixCol = pixCol;
1340  maxPixRow = pixRow;
1341  }
1342 
1343  /** find min and max col and row */
1344  if (maxCol < pixCol)
1345  maxCol = pixCol;
1346  if (pixCol < minCol)
1347  minCol = pixCol;
1348  if (maxRow < pixRow)
1349  maxRow = pixRow;
1350  if (pixRow < minRow)
1351  minRow = pixRow;
1352  }
1353 
1354  /** set the peak's properties and add peak to the list of found peaks */
1355  peak[Integral] = integral;
1356  peak[CentroidColumn] = weightCol / integral;
1357  peak[CentroidRow] = weightRow / integral;
1358  peak[MaxADU] = maxPixVal;
1359  peak[Index] = maxPixIdx;
1360  peak[Column] = maxPixCol;
1361  peak[Row] = maxPixRow;
1362  peak[MaxColumn] = maxCol;
1363  peak[MinColumn] = minCol;
1364  peak[ColumnSize] = maxCol - minCol;
1365  peak[MaxRow] = maxRow;
1366  peak[MinRow] = minRow;
1367  peak[RowSize] = maxRow - minRow;
1368  peak[NbrOfPixels] = pixIdxs.size();
1369 
1370  result.appendRows(peak);
1371  }
1372 
1373  /** tell that only the result of one event (image) is present in the table */
1374 }
1375 
1376 
1377 
1378 
1379 
1380 //******************** processor 210: Find Bragg peaks using MAD **************
1381 
1382 pp210::pp210(const name_t &name)
1383  : Processor(name)
1384 {
1385  loadSettings(0);
1386 }
1387 
1389 {
1390  CASSSettings s;
1391 
1392  s.beginGroup("Processor");
1394 
1395  _threshold = s.value("Threshold",10).toFloat();
1396  _minSnr = s.value("MinSignalToNoiseRatio",8).toFloat();
1397  _minNbrSnr = s.value("MinSignalToNoiseRatioForNeighbours",4).toFloat();
1398  _maxAdditionalPixels = s.value("MaxAdditionalPixels",2).toFloat();
1399  _minNbrPixels = s.value("MinNbrPixels",2).toInt();
1400  _badPixVal = s.value("BadPixelValue",0).toFloat();
1401  _box = make_pair(s.value("BoxSizeX", 5).toInt(),
1402  s.value("BoxSizeY",5).toInt());
1403  _section = make_pair(s.value("SectionSizeX", 1024).toUInt(),
1404  s.value("SectionSizeY",512).toUInt());
1405 
1406  setupGeneral();
1407  bool ret (setupCondition());
1408 
1409  _imagePP = setupDependency("ImageName");
1410 
1411  /** return if any of the dependecies has not been loaded */
1412  if (!(_imagePP && ret))
1413  return;
1414 
1415  const result_t &srcImageHist(_imagePP->result());
1416  _imageShape = srcImageHist.shape();
1417 
1418  _neighbourOffsets.clear();
1419 // _neighbourOffsets.push_back(+_imageShape.first-1); //up left
1420  _neighbourOffsets.push_back(+_imageShape.first+0); //up
1421 // _neighbourOffsets.push_back(+_imageShape.first+1); //up right
1422  _neighbourOffsets.push_back(-1); //left
1423  _neighbourOffsets.push_back(+1); //right
1424 // _neighbourOffsets.push_back(-_imageShape.first-1); //low left
1425  _neighbourOffsets.push_back(-_imageShape.first+0); //low
1426 // _neighbourOffsets.push_back(-_imageShape.first+1); //low right
1427 
1428  /** Create the result output */
1430 
1431  /** log what the user was requesting */
1432  string output("Processor '" + name() + "' finds bragg peaks using mad." +
1433  ". Boxsize '" + to_string(_box.first)+"x"+ to_string(_box.second)+
1434  "'. SectionSize '" + to_string(_section.first)+"x"+ to_string(_section.second)+
1435  "'. Threshold '" + to_string(_threshold) +
1436  "'. MinSignalToNoiseRatio '" + to_string(_minSnr) +
1437  "'. MinPixels '" + to_string(_minNbrPixels) +
1438  "'. Condition is '" + _condition->name() + "'");
1439  Log::add(Log::INFO,output);
1440 }
1441 
1442 void pp210::process(const CASSEvent & evt, result_t &result)
1443 {
1444  const result_t &image(_imagePP->result(evt.id()));
1445  QReadLocker hLock(&image.lock);
1446 
1447  /** clear the resulting table to fill it with the values of this image */
1448  result.resetTable();
1449 
1450  /** get a table row that we can later add to the table */
1451  table_t peak(nbrOf,0);
1452 
1453  /** set up a mask that we can see which pixels have been treated */
1454  vector<bool> checkedPixels(image.size(),false);
1455  vector<bool>::iterator checkedPixel(checkedPixels.begin());
1456 
1457  /** get iterators to the beginning and end of the image */
1459  result_t::const_iterator ImageEnd(image.end());
1460  index_t idx(0);
1461  for (;pixel != ImageEnd; ++pixel,++idx, ++checkedPixel)
1462  {
1463  /** check if pixel should be treated, when it has been treated before
1464  * continue with the next pixel
1465  */
1466  if (*checkedPixel)
1467  continue;
1468 
1469  /** check if pixel is above the threshold, otherwise continue with the next
1470  * pixel
1471  */
1472  if (*pixel < _threshold)
1473  continue;
1474 
1475  /** caluclate where we are within the image */
1476  const index_t col(idx % _imageShape.first);
1477  const index_t row(idx / _imageShape.first);
1478 
1479  /** get the right box boundaries, so that we're within the image and the
1480  * sections
1481  */
1482  const shape_t::first_type colLow (col - _box.first);
1483  const shape_t::first_type colHigh(col + _box.first);
1484  const shape_t::second_type rowLow (row - _box.second);
1485  const shape_t::second_type rowHigh(row + _box.second);
1486  if (colLow < 0 || _imageShape.first < colHigh ||
1487  rowLow < 0 || _imageShape.second < rowHigh)
1488  continue;
1489 
1490  /** calc the section that the box edges are in */
1491  const int colLowSection (colLow / _section.first);
1492  const int colHighSection(colHigh / _section.first);
1493  const int rowLowSection (rowLow / _section.second);
1494  const int rowHighSection(rowHigh / _section.second);
1495  if (colLowSection != colHighSection ||
1496  rowLowSection != rowHighSection)
1497  continue;
1498 
1499  /** check if pixel is highest within box. If so, check if there are enough
1500  * pixels that are not outliers. If there are not enough pixels in the box
1501  * increase the box size and do the checks all over again. If the pixel is
1502  * not highest within the bigger box continue with the next pixel.
1503  */
1504  /** now check if its the highest pixel */
1505  vector<float> medCont;
1506  bool isHighest(true);
1507  for (shape_t::second_type bRow(rowLow);(isHighest) && (bRow < rowHigh); ++bRow)
1508  {
1509  for (shape_t::first_type bCol(colLow); (isHighest) && (bCol < colHigh); ++bCol)
1510  {
1511  /** check if we're still inside the image */
1512  const float bPixel(image[bCol + bRow*_imageShape.first]);
1513  if ( *pixel < bPixel)
1514  {
1515  isHighest = false;
1516  break;
1517  }
1518  medCont.push_back(bPixel);
1519  }
1520  }
1521  if (!isHighest)
1522  continue;
1523 
1524  /** calculate the MAD */
1525  const size_t medianpos(0.5*medCont.size());
1526  const auto target(medCont.begin() + medianpos);
1527  std::nth_element(medCont.begin(), target, medCont.end());
1528  const float median(*target);
1529  for (auto &val : medCont) val = fabs(val-median);
1530  std::nth_element(medCont.begin(), target, medCont.end());
1531  const float mad((*target)*1.4862);
1532 
1533  /** check if the median is postive */
1534  if ( median < 0 )
1535  continue;
1536 
1537  /** check if pixel satifies the snr requirement */
1538  const float snr((*pixel - median) / mad);
1539  if (snr < _minSnr)
1540  continue;
1541 
1542 // /** retrive statistical values from the calculator */
1543 // const stat_t::value_type mean(stat.mean());
1544 // const stat_t::value_type stdv(stat.stdv());
1545 
1546  /** from the central pixel look around and see which pixels are direct
1547  * part of the peak. If a neighbour is found, mask it such that one does
1548  * not use it twice.
1549  *
1550  * Create a list that should contain the indizes of the pixels that are
1551  * part of the peak. Go through that list and check for each found
1552  * neighbour whether it also has a neighbour. If so add it to the list, but
1553  * only if it is part of the box.
1554  */
1555  vector<index_t> peakIdxs;
1556  peakIdxs.push_back(idx);
1557  *checkedPixel = true;
1558  bool isGoodSpot(true);
1559  for (size_t pix=0; isGoodSpot && (pix < peakIdxs.size()); ++pix)
1560  {
1561  const index_t pixpos(peakIdxs[pix]);
1562  neighbourList_t::const_iterator ngbrOffset(_neighbourOffsets.begin());
1563  neighbourList_t::const_iterator neighboursEnd(_neighbourOffsets.end());
1564  while(ngbrOffset != neighboursEnd)
1565  {
1566  const index_t ngbrIdx(pixpos + *ngbrOffset++);
1567  const index_t ngbrCol(ngbrIdx % _imageShape.first);
1568  const index_t ngbrRow(ngbrIdx / _imageShape.first);
1569  /** @note need to check if the pixel has been used after verifiying that
1570  * the pixel is within the box. Otherwise in rare occasions it will
1571  * happen that the pixelindex is not within the boolean array which
1572  * will cause a segfault.
1573  */
1574  if (_box.first < abs(col - ngbrCol) || //pixel not inside box col
1575  _box.second < abs(row - ngbrRow)) //pixel not inside box row
1576  continue;
1577  if (checkedPixels[ngbrIdx]) //pixel has been used
1578  continue;
1579  checkedPixels[ngbrIdx] = true;
1580  const pixelval_t ngbrPixel(image[ngbrIdx]);
1581  /** check if the potential neighbour is a bad pixel, if so ignore this
1582  * bragg spot
1583  */
1584  if (abs(ngbrPixel - _badPixVal) < std::numeric_limits<pixelval_t>::epsilon())
1585  {
1586  isGoodSpot = false;
1587  break;
1588  }
1589  const pixelval_t ngbrPixelWOBckgnd(ngbrPixel - median);
1590  if ((_minNbrSnr * mad) < ngbrPixelWOBckgnd)
1591  {
1592  peakIdxs.push_back(ngbrIdx);
1593  }
1594  }
1595  }
1596 
1597  if (!isGoodSpot)
1598  continue;
1599 
1600  /** if the peak doesn't have enough pixels continue with next pixel */
1601  if (static_cast<int>(peakIdxs.size()) < _minNbrPixels)
1602  continue;
1603 
1604  /** go through all pixels in the box, find out which pixels are part of the
1605  * peak and centroid them. Mask all pixels in the box as checked so one
1606  * does not check them again
1607  */
1608  pixelval_t integral = 0;
1609  pixelval_t weightCol = 0;
1610  pixelval_t weightRow = 0;
1611  index_t max_radiussq=0;
1612  index_t min_radiussq=max(_box.first,_box.second)*max(_box.first,_box.second);
1613  size_t badcount(0);
1614  for (int bRow(-_box.second); bRow <= _box.second; ++bRow)
1615  {
1616  for (int bCol(-_box.first); bCol <= _box.first; ++bCol)
1617  {
1618  const index_t bLocIdx(bRow*_imageShape.first+bCol);
1619  const pixelval_t bPixel(pixel[bLocIdx]);
1620  const pixelval_t bPixelWOBckgnd(bPixel - median);
1621  if (checkedPixel[bLocIdx])
1622  {
1623  const index_t radiussq(bRow*bRow + bCol*bCol);
1624  if (radiussq > max_radiussq)
1625  max_radiussq = radiussq;
1626  if (radiussq < min_radiussq)
1627  min_radiussq = radiussq;
1628  integral += bPixelWOBckgnd;
1629  weightCol += (bPixelWOBckgnd * (bCol+col));
1630  weightRow += (bPixelWOBckgnd * (bRow+row));
1631  }
1632  /** count how many pixels are not connected to the center one but still
1633  * above the snr
1634  */
1635  else if ((_minNbrSnr * mad) < bPixelWOBckgnd)
1636  {
1637  ++badcount;
1638  }
1639  checkedPixel[bLocIdx] = true;
1640  }
1641  }
1642 
1643  /** check how many pixels that are not part of the main peak there are */
1644  if (_maxAdditionalPixels < badcount)
1645  continue;
1646 
1647 
1648  /** set the peak's properties and add peak to the list of found peaks */
1649  peak[centroidColumn] = weightCol / integral;
1650  peak[centroidRow] = weightRow / integral;
1651  peak[Intensity] = integral;
1652  peak[nbrOfPixels] = peakIdxs.size();
1653  peak[SignalToNoiseHighestPixel] = snr;
1654  peak[SignalToNoiseSpot] = integral/mad;
1655  peak[MaxRadius] = sqrt(max_radiussq);
1656  peak[MinRadius] = sqrt(min_radiussq);
1657  peak[Index] = idx;
1658  peak[Column] = col;
1659  peak[Row] = row;
1660  peak[MaxADU] = *pixel;
1661  peak[LocalBackground] = median;
1662  peak[LocalBackgroundDeviation] = mad;
1663  peak[AdditionalPixels] = badcount;
1664 
1665  result.appendRows(peak);
1666  }
1667 }
1668 
1669 
result_t::storage_t::value_type pixelval_t
define the type of the pixel in image
Definition: hitfinder.h:724
CachedList::item_type result_t
define the results
Definition: processor.h:52
shared_pointer _noisePP
processor containing the noise image for thresholding
Definition: hitfinder.h:294
shared_pointer _wavelengthPP
pp containing wavelength in case its not fixed
Definition: hitfinder.h:538
storage_t::const_iterator const_iterator
a const iterator on the storage
Definition: result.hpp:338
void addDatum(const value_type &datum)
add a datum to the distribution
virtual void loadSettings(size_t)
load the settings of this pp
Definition: hitfinder.cpp:407
double _detdist
the detector distance in case its fixed
Definition: hitfinder.h:544
pixelval_t _threshold
pixel threshold to be exceeded
Definition: hitfinder.h:553
float _minSnr
the min signal to noise ratio that needs to be exceeded
Definition: hitfinder.h:180
std::tr1::function< double(const CASSEvent::id_t &)> _getLambda
function that gets the wavelength
Definition: hitfinder.h:541
void appendRows(const storage_t &rows)
add row(s) to the result
Definition: result.hpp:724
double lambdaFromProcessor(const CASSEvent::id_t &id)
retrieve the wavelength from the processor
Definition: hitfinder.cpp:881
size_t _idxCol
the number of the column where the global index of the pixel is
Definition: hitfinder.h:250
double distanceFromProcessor(const CASSEvent::id_t &id)
retrieve the detector distance from the processor
Definition: hitfinder.cpp:888
pp209(const name_t &name)
constructor
Definition: hitfinder.cpp:1150
Event to store all LCLS Data.
Definition: cass_event.h:32
virtual void createHistList(result_t::shared_pointer result)
create result list.
Definition: processor.cpp:79
float _minNeighbourSNR
the min signal to noise ratio that needs to be exceeded
Definition: hitfinder.h:183
bool fuzzycompare(const T &first, const T &second)
fuzzy compare two floating point variables
const_iterator end() const
retrieve iterator to the end of storage
Definition: result.hpp:632
result_t::value_t pixelval_t
define the values of the pixels
Definition: hitfinder.h:139
shared_pointer _table
pp containing the results
Definition: hitfinder.h:241
counter_type count() const
retrieve the number of datum that have been added
std::tr1::function< double(const CASSEvent::id_t &)> _getDistance
function that gets the detectordistance
Definition: hitfinder.h:550
neighbourList_t _neighbourOffsets
the list of offsets to next neighbours
Definition: hitfinder.h:784
double _wavelength
the wavelength in case its fixed
Definition: hitfinder.h:535
shape_t _box
the size of the box within which the peak should lie
Definition: hitfinder.h:511
pp204(const name_t &name)
constructor
Definition: hitfinder.cpp:144
float _threshold
pixel threshold to be exceeded
Definition: hitfinder.h:307
count_type nbrUpperOutliers()
retrieve the number of outliers higher than the distribution used
float _multiplier
multiplier for the noise threshold
Definition: hitfinder.h:310
virtual void process(const CASSEvent &, result_t &)
process event
Definition: hitfinder.cpp:235
result_t::storage_t table_t
definition of the table
Definition: hitfinder.h:721
virtual void process(const CASSEvent &, result_t &)
process event
Definition: hitfinder.cpp:985
const name_t name() const
retrieve the name of this processor
Definition: processor.h:167
result_t::storage_t table_t
definition of the table
Definition: hitfinder.h:114
stat_t::value_type _minSnr
minimum Signal to Noise Ratio thats is needed for a pixel to be an outlier
Definition: hitfinder.h:775
virtual void loadSettings(size_t)
load the settings for this processor
Definition: hitfinder.cpp:1388
Settings for CASS.
Definition: cass_settings.h:30
shared_pointer _hist
pp containing 2d histogram
Definition: hitfinder.h:61
value_type mean()
retrieve the mean of the distribution without outliers
std::tr1::shared_ptr< self_type > shared_pointer
a shared pointer of this class
Definition: result.hpp:323
std::pair< int, int > _box
the size of the box within which the peak should lie
Definition: hitfinder.h:301
statistics calculator for a cummulative statistic, removes outliers
pixelval_t thresholdFromProcessor(const CASSEvent::id_t &id)
retrieve the threshold from the processor
Definition: hitfinder.cpp:895
size_type size() const
return the raw size of the storage
Definition: result.hpp:881
uint64_t id_t
define the id type
Definition: cass_event.h:52
statistics calculator for a cummulative statistic
STL namespace.
std::vector< pos_t > conversion_t
define the conversion table type
Definition: geom_parser.h:29
std::pair< size_t, size_t > _sectionSize
size of a image section
Definition: hitfinder.h:67
std::pair< int, int > _boxsize
Definition: hitfinder.h:246
void resetTable()
reset the table like result
Definition: result.hpp:740
virtual void loadSettings(size_t)
load the settings of this pp
Definition: hitfinder.cpp:1156
int getBoxStatistics(result_t::const_iterator centerPixel, const imagepos_t nColumns, pixelval_t &mean, pixelval_t &stdv, int &count)
check highest pixel and generate the mean and standart deviation
Definition: hitfinder.cpp:195
substract the median of the integral from the integral and use
virtual void process(const CASSEvent &, result_t &)
process event
Definition: hitfinder.cpp:448
shared_pointer _detdistPP
pp containing detector distance in case its not fixed
Definition: hitfinder.h:547
stat_t::count_type _minNbrPixels
the minimum nbr of pixels in the bragg peak
Definition: hitfinder.h:526
value_type mean() const
retrieve the mean of the distribution
bool _drawBox
Definition: hitfinder.h:247
conversion_t generateConversionMap(const std::string &filename, const size_t sizeOfSrc, const size_t nSrcCols, const bool convertFromCheetahToCASS)
parse the geom file and generate a lookup table
Definition: geom_parser.cpp:60
int64_t index_t
define the index in the image
Definition: hitfinder.h:413
T square(const T &val)
multiply number by itself
Definition: cass.h:78
std::pair< int, int > _section
size of a image section
Definition: hitfinder.h:304
shared_pointer _imagePP
processor containing the image to find the bragg peaks in
Definition: hitfinder.h:766
static void add(Level level, const std::string &line)
add a string to the log
Definition: log.cpp:31
const_iterator begin() const
retrieve a iterator for read access to beginning
Definition: result.hpp:608
count_type nbrPointsUsed()
retrieve the number of points used in the statistics
fromStdString(const std::string &str)
virtual void process(const CASSEvent &, result_t &)
process event
Definition: hitfinder.cpp:1442
double distanceFromConstant(const CASSEvent::id_t &)
retrieve the constant detector distance
Definition: hitfinder.h:489
std::tr1::function< pixelval_t(const CASSEvent::id_t &)> _thresh
function that gets the detectordistance
Definition: hitfinder.h:559
pp210(const name_t &name)
constructor
Definition: hitfinder.cpp:1382
shared_pointer _hist
processor containing the image to find the bragg peaks in
Definition: hitfinder.h:111
base class for processors.
Definition: processor.h:39
shape_t _imageShape
size of the incomming image
Definition: hitfinder.h:517
shared_pointer setupDependency(const std::string &depVarName, const name_t &name="")
setup the dependecy.
Definition: processor.cpp:114
pixelval_t _minNbrSnr
minimum snr when pixel is an neighbour
Definition: hitfinder.h:778
result_t::value_t _drawInnerValue
Definition: hitfinder.h:244
std::pair< imagepos_t, imagepos_t > _section
size of a image section
Definition: hitfinder.h:171
result_t::value_t _drawVal
draw flags as bitmask
Definition: hitfinder.h:244
std::vector< double > _src2labradius
the conversion table from raw to lab
Definition: hitfinder.h:532
const axis_t & axis() const
read access to the axis
Definition: result.hpp:449
float _radius
Definition: hitfinder.h:245
virtual void process(const CASSEvent &, result_t &)
process event
Definition: hitfinder.cpp:64
neighbourList_t _neighbourOffsets
the list of offsets to next neighbours
Definition: hitfinder.h:529
result_t::storage_t table_t
definition of the table
Definition: hitfinder.h:604
shape_t _imageShape
size of the incomming image
Definition: hitfinder.h:646
file contains declaration of classes and functions that help other processors to do their job...
virtual void loadSettings(size_t)
load the settings of this pp
Definition: hitfinder.cpp:697
neighbourList_t _neighbourOffsets
the list of offsets to next neighbours
Definition: hitfinder.h:649
double lambdaFromConstant(const CASSEvent::id_t &)
retrieve the constant wavelength
Definition: hitfinder.h:477
shape_t _section
size of a image section
Definition: hitfinder.h:769
result_t::storage_t::value_type pixelval_t
define the type of the pixel in image
Definition: hitfinder.h:407
QReadWriteLock lock
lock for locking operations on the data of the container
Definition: result.hpp:954
bool _drawInner
Definition: hitfinder.h:247
bool _drawCircle
Definition: hitfinder.h:247
bool fuzzyIsNull(const T &val)
fuzzy compare a floating point number to 0
file contains global definitions for project cass
contains processors that will extract pixels of interrest from 2d histograms.
size_t _maxAdditionalPixels
pixel value of a bad pixel
Definition: hitfinder.h:793
id_t & id()
setters
Definition: cass_event.h:64
pp206(const name_t &name)
constructor
Definition: hitfinder.cpp:563
float _minRatio
minimum ratio of nbr of points used for statistics to nbr of outliers
Definition: hitfinder.h:523
class to parse and retrieve info from geom files.
std::string toString(const Type &t)
convert any type to a string
Definition: cass.h:63
shared_pointer _hist
pp containing 2d histogram
Definition: hitfinder.h:238
std::pair< index_t, index_t > shape_t
define the shape of the image
Definition: hitfinder.h:613
result_t::storage_t table_t
definition of the table
Definition: hitfinder.h:297
std::pair< index_t, index_t > shape_t
define the shape of the image
Definition: hitfinder.h:416
shared_pointer _imagePP
processor containing the image to find the bragg peaks in
Definition: hitfinder.h:401
value(const QString &key, const QVariant &defaultValue=QVariant()
virtual void process(const CASSEvent &, result_t &)
process event
Definition: hitfinder.cpp:607
int64_t index_t
define the index in the image
Definition: hitfinder.h:730
stat_t::count_type _minNbrPixels
the minimum nbr of pixels in the bragg peak
Definition: hitfinder.h:781
pp205(const name_t &name)
constructor
Definition: hitfinder.cpp:401
std::pair< imagepos_t, imagepos_t > _box
the size of the box within which the peak should lie
Definition: hitfinder.h:168
void addDatum(const value_type &datum)
add a datum to the container
storage_t::iterator iterator
a iterator on the storage
Definition: result.hpp:335
shared_pointer _threshPP
processor containing the threshold for each pixel of the image
Definition: hitfinder.h:643
std::pair< size_t, size_t > _boxSize
the size of the box used for the median filter
Definition: hitfinder.h:64
pixelval_t _factor
the factor that the pixelwise threshold is multuplied with
Definition: hitfinder.h:652
void setupGeneral()
general setup of the processor
Definition: processor.cpp:85
shape_t _imageShape
size of the incomming image
Definition: hitfinder.h:772
result_t::storage_t::value_type pixelval_t
define the type of the pixel in image
Definition: hitfinder.h:607
file contains specialized class that do the settings for cass
pp208(const name_t &name)
constructor
Definition: hitfinder.cpp:690
int _minBckgndPixels
min amount of pixels for the background calc
Definition: hitfinder.h:186
int imagepos_t
define the positions in the image
Definition: hitfinder.h:142
int isNotHighest(result_t::const_iterator pixel, const index_t linIdx, shape_t box, stat_t &stat)
check if pixel is not highest within box
Definition: hitfinder.cpp:946
shape_t _box
the size of the box within which the peak should lie
Definition: hitfinder.h:763
float _threshold
pixel threshold to be exceeded
Definition: hitfinder.h:174
shape_t _section
size of a image section
Definition: hitfinder.h:514
pixelval_t thresholdFromConstant(const CASSEvent::id_t &id)
retrieve the threshold constant
Definition: hitfinder.cpp:902
shared_pointer _condition
pointer to the processor that will contain the condition
Definition: processor.h:277
pixelval_t _threshold
pixel threshold to be exceeded
Definition: hitfinder.h:787
shared_pointer _imagePP
processor containing the image to find the bragg peaks in
Definition: hitfinder.h:291
shape_t shape() const
return the shape of the result
Definition: result.hpp:811
bool setupCondition(bool defaultConditionType=true)
setup the condition.
Definition: processor.cpp:94
std::string name_t
define the name type
Definition: processor.h:46
shared_pointer _imagePP
processor containing the image
Definition: hitfinder.h:640
contains a logger for cass
virtual void loadSettings(size_t)
load the settings of this pp
Definition: hitfinder.cpp:569
int16_t pixel
define a pixel
Definition: hlltypes.hpp:27
stat_t::value_type _minSnr
minimum Signal to Noise Ratio thats is needed for a pixel to be an outlier
Definition: hitfinder.h:520
virtual void loadSettings(size_t)
load the settings of this pp
Definition: hitfinder.cpp:34
result_t::storage_t table_t
definition of the table
Definition: hitfinder.h:404
virtual void loadSettings(size_t)
load the settings of this pp
Definition: hitfinder.cpp:150
value_type stdv()
retrieve the standart deviation of the distribution
size_type datasize() const
return the size of the data as determined by the axis
Definition: result.hpp:872
virtual void process(const CASSEvent &, result_t &)
process event
Definition: hitfinder.cpp:1223
int64_t index_t
define the index in the image
Definition: hitfinder.h:610
value_type stdv() const
retrieve the standart deviation of the distribution
beginGroup(const QString &prefix)
pixelval_t _badPixVal
pixel value of a bad pixel
Definition: hitfinder.h:790
shared_pointer _threshPP
pp containing threshold in case its not fixed
Definition: hitfinder.h:556
int _peakRadiusSq
the square size of bragg peak radius
Definition: hitfinder.h:177
int getBoxStatistics(result_t::const_iterator pixel, const index_t linIdx, const shape_t &box, stat_t &stat)
retrieve the box statistics
Definition: hitfinder.cpp:907
set up how to create the noise