CFEL - ASG Software Suite  2.5.0
CASS
autocorrelation.cpp
Go to the documentation of this file.
1 //Copyright (C) 2013 Lutz Foucar
2 
3 /**
4  * @file autocorrelation.cpp containing the class to calculate the
5  * autocorrelation of a 2d histogram
6  *
7  * @author Lutz Foucar
8  */
9 
10 #include <algorithm>
11 #include <functional>
12 #include <numeric>
13 
14 #include "autocorrelation.h"
15 #include "cass_event.h"
16 #include "cass_settings.h"
17 #include "log.h"
18 
19 using namespace cass;
20 using namespace std;
21 
22 
23 pp310::pp310(const name_t &name)
24  : Processor(name)
25 {
26  loadSettings(0);
27 }
28 
29 void pp310::loadSettings(size_t)
30 {
31  setupGeneral();
32  _hist = setupDependency("ImageName");
33  bool ret (setupCondition());
34  if (!(ret && _hist))
35  return;
36  const result_t &srcImageHist(_hist->result());
37  if (srcImageHist.dim() != 2)
38  throw invalid_argument("pp310:setup: '" + name() +
39  "' The input histogram is not a 2d histogram");
40  createHistList(srcImageHist.clone());
41 
42  Log::add(Log::INFO,"Processor '" + name() +
43  "' will calculate the autocorrelation of '" + _hist->name() +
44  "'. Condition is '" + _condition->name() + "'");
45 }
46 
47 void pp310::process(const CASSEvent &evt, result_t &result)
48 {
50  const result_t& hist(_hist->result(evt.id()));
51  QReadLocker lock2(&hist.lock);
52 
53  size_t nCols(hist.axis(result_t::xAxis).nBins);
54  size_t nRows(hist.axis(result_t::yAxis).nBins);
55 
56  result_t::storage_t row_buffer(nCols);
57  /** go through each row (radius) of input */
58  for (size_t row(0); row < nRows; ++row)
59  {
60  const_iterator rowStart(hist.begin() + row*nCols);
61  const_iterator rowEnd(hist.begin() + row*nCols + nCols);
62  /** go through each col (phi) of input */
63  for (size_t col(0); col < nCols; ++col)
64  {
65  /** rotate the input to get the current d_phi and put result into buffer */
66  rotate_copy(rowStart, rowStart+col, rowEnd, row_buffer.begin());
67 
68  /** multiply the original phi with the rotated phi and put result into buffer */
69  transform(rowStart,rowEnd,row_buffer.begin(),row_buffer.begin(),multiplies<float>());
70 
71  /** sum up the contents of the buffer which gives the correlation value */
72  const float autocorval(accumulate(row_buffer.begin(),row_buffer.end(),0));
73 
74  /** put value into correlatoin value at position radius, d_phi */
75  result[row*nCols + col] = autocorval;
76  }
77  }
78 }
79 
80 
81 
82 //*** autocorrelation from image in kartesian coordinates ***
83 pp311::pp311(const name_t &name)
84  : Processor(name)
85 {
86  loadSettings(0);
87 }
88 
89 void pp311::loadSettings(size_t)
90 {
91  CASSSettings s;
92  s.beginGroup("Processor");
94  setupGeneral();
95  _hist = setupDependency("ImageName");
96  bool ret (setupCondition());
97  if (!(ret && _hist))
98  return;
99 
100  std::pair<int,int> usercenter = make_pair(s.value("CenterX",0).toInt(),
101  s.value("CenterY",0).toInt());
102  const int maxradius(s.value("MaximumRadius",0).toInt());
103 
104  const result_t &srcImageHist(_hist->result());
105  if (srcImageHist.dim() != 2)
106  throw invalid_argument("pp311:setup: '" + name() +
107  "' The input histogram is not a 2d histogram");
108  /** determine the center in histogram coordinates */
109  const result_t::axe_t &xaxis(srcImageHist.axis(result_t::xAxis));
110  const result_t::axe_t &yaxis(srcImageHist.axis(result_t::yAxis));
111  _center = make_pair(xaxis.bin(usercenter.first),
112  yaxis.bin(usercenter.second));
113 
114  /** check if coordinates are ok */
115  if ((static_cast<int>(srcImageHist.shape().first) < _center.first + maxradius) ||
116  (_center.first - maxradius < 0) )
117  throw out_of_range("pp311:loadSettings: '" + name() + "'. Center in lab X '" +
118  toString(_center.first) + "' and maximum radius '" +
119  toString(maxradius) + "' do not fit in image with width '" +
120  toString(srcImageHist.shape().first) + "'");
121  if ((static_cast<int>(srcImageHist.shape().second) < _center.second + maxradius) ||
122  (_center.second - maxradius < 0))
123  throw out_of_range("pp311:loadSettings: '" + name() + "'. Center in lab Y '" +
124  toString(_center.second) + "' and maximum radius '" +
125  toString(maxradius) + "' do not fit in image with height '" +
126  toString(srcImageHist.shape().second) + "'");
127  _maxrad = maxradius;
128 
129  createHistList(srcImageHist.clone());
130 
131  Log::add(Log::INFO,"Processor '" + name() +
132  "' will calculate the autocorrelation of '" + _hist->name() +
133  "'. Condition is '" + _condition->name() + "'");
134 }
135 
136 int pp311::getCircleLength(const int rad)
137 {
138  int npix = 0;
139  int x = 0;
140  int y = rad;
141  int f = 1-rad;
142  int ddF_x = 0;
143  int ddF_y = -2 * rad;
144  npix += 4;
145  while (x<(y-1))
146  {
147  if (f>=0)
148  {
149  --y;
150  ddF_y += 2;
151  f += ddF_y;
152  }
153  ++x;
154  ddF_x += 2;
155  f += ddF_x + 1;
156  npix += 4;
157  if (x!=y)
158  npix += 4;
159  }
160  return npix;
161 }
162 
163 void pp311::fillRing(const result_t &image,
164  const int rad, const int x0, const int y0, const int nxx,
165  ring_t &ring)
166 {
167  const int nAngles(ring.size());
168  int f = 1-rad;
169  int ddF_x = 0;
170  int ddF_y = -2 * rad;
171  int x = 0;
172  int y = rad;
173  int angle = 0;
174  const int angsym2 = nAngles*2*0.125;
175  const int angsym4 = nAngles*4*0.125;
176  const int angsym6 = nAngles*6*0.125;
177  const int angsym8 = nAngles;
178 
179  ring[angle].first= x0 + nxx*(y0+rad);
180  ring[angle].second = image[ring[angle].first];
181 
182  ring[angle+angsym4].first= x0 + nxx*(y0 - rad);
183  ring[angle+angsym4].second = image[ring[angle+angsym4].first];
184 
185  ring[angle+angsym2].first= x0 + rad + nxx*(y0);
186  ring[angle+angsym2].second = image[ring[angle+angsym2].first];
187 
188  ring[angle+angsym6].first= x0 - rad + nxx*(y0);
189  ring[angle+angsym6].second = image[ring[angle+angsym6].first];
190 
191  while (x < (y-1))
192  {
193  ++angle;
194  if (f>=0)
195  {
196  --y;
197  ddF_y += 2;
198  f += ddF_y;
199  }
200  ++x;
201  ddF_x += 2;
202  f += ddF_x + 1;
203 
204  ring[angle].first= x0 + x + nxx*(y0 + y);
205  ring[angle].second = image[ring[angle].first];
206 
207  ring[angsym8-angle].first= x0 - x + nxx*(y0 + y);
208  ring[angsym8-angle].second = image[ring[angsym8-angle].first];
209 
210  ring[angsym4-angle].first= x0 + x + nxx*(y0 - y);
211  ring[angsym4-angle].second = image[ring[angsym4-angle].first];
212 
213  ring[angsym4+angle].first= x0 - x + nxx*(y0 - y);
214  ring[angsym4+angle].second = image[ring[angsym4+angle].first];
215 
216  if ( x!=y )
217  {
218  ring[angsym2-angle].first= x0 + y + nxx*(y0 + x);
219  ring[angsym2-angle].second = image[ring[angsym2-angle].first];
220 
221  ring[angsym6+angle].first= x0 - y + nxx*(y0 + x);
222  ring[angsym6+angle].second = image[ring[angsym6+angle].first];
223 
224  ring[angsym2+angle].first= x0 + y + nxx*(y0 - x);
225  ring[angsym2+angle].second = image[ring[angsym2+angle].first];
226 
227  ring[angsym6-angle].first= x0 - y + nxx*(y0 - x);
228  ring[angsym6-angle].second = image[ring[angsym6-angle].first];
229  }
230  }
231 }
232 
233 void pp311::process(const CASSEvent &evt, result_t &result)
234 {
235  const result_t& hist(_hist->result(evt.id()));
236  QReadLocker lock1(&hist.lock);
237 
238  const int nxx(hist.shape().first);
239 
240  ring_t ring;
241  for(int rad=0; rad<_maxrad; ++rad)
242  {
243  const int ringsize(getCircleLength(rad));
244  ring.resize(ringsize);
245  fillRing(hist,rad,_center.first,_center.second,nxx,ring);
246 #ifdef _OPENMP
247 #pragma omp parallel for
248 #endif
249  for (int d_phi_pix=0; d_phi_pix < ringsize; ++d_phi_pix)
250  {
251  float res = 0.0;
252  for (int ii=0; ii<ringsize; ++ii)
253  res += ring[ii].second * ring[(ii+d_phi_pix)%ringsize].second;
254  res /= static_cast<float>(ringsize);
255  result[ring[d_phi_pix].first] = res;
256  }
257  }
258 }
storage_t::const_iterator const_iterator
a const iterator on the storage
Definition: result.hpp:338
void fillRing(const result_t &image, const int rad, const int x0, const int y0, const int nxx, ring_t &ring)
fill the ring with the pixels that belong to a certain radius around a given center ...
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
virtual void process(const CASSEvent &, result_t &)
process the event
std::vector< value_t > storage_t
the storage of this container
Definition: result.hpp:332
virtual void loadSettings(size_t)
load the settings of this pp
const name_t name() const
retrieve the name of this processor
Definition: processor.h:167
file contains declaration of the CASSEvent
Settings for CASS.
Definition: cass_settings.h:30
std::pair< int, int > _center
the used center of the image
virtual void process(const CASSEvent &, result_t &)
process the event
STL namespace.
an axis of a more than 0 dimensional container
Definition: result.hpp:29
int _maxrad
the used maximum radius
int getCircleLength(const int rad)
retrieve the length of the ring for a given radius
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
fromStdString(const std::string &str)
base class for processors.
Definition: processor.h:39
pp311(const name_t &)
constructor
shared_pointer setupDependency(const std::string &depVarName, const name_t &name="")
setup the dependecy.
Definition: processor.cpp:114
const axis_t & axis() const
read access to the axis
Definition: result.hpp:449
virtual void loadSettings(size_t)
load the settings of this pp
pp310(const name_t &)
constructor
QReadWriteLock lock
lock for locking operations on the data of the container
Definition: result.hpp:954
shared_pointer _hist
pp containing histogram to calculate the autocorrelation for
id_t & id()
setters
Definition: cass_event.h:64
std::vector< std::pair< int, result_t::value_t > > ring_t
define a ring that knows its position in the original image and the value at that position ...
std::string toString(const Type &t)
convert any type to a string
Definition: cass.h:63
value(const QString &key, const QVariant &defaultValue=QVariant()
shared_pointer _hist
pp containing histogram to calculate the autocorrelation for
void setupGeneral()
general setup of the processor
Definition: processor.cpp:85
file contains specialized class that do the settings for cass
shared_pointer _condition
pointer to the processor that will contain the condition
Definition: processor.h:277
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
contains a logger for cass
containing the class to calculate the autocorrelation of a 2d histogram
beginGroup(const QString &prefix)