CFEL - ASG Software Suite  2.5.0
CASS
imaging.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010-2013 Lutz Foucar
2 
3 /**
4  * @file imaging.cpp processors to generate a test image
5  *
6  * @author Stephan Kassemeyer
7  * @author Lutz Foucar
8  */
9 
10 #include <QtCore/QString>
11 
12 #include "imaging.h"
13 
14 #include "cass_settings.h"
15 #include "log.h"
16 
17 
18 using namespace cass;
19 using namespace std;
20 using namespace std::tr1;
21 using std::tr1::placeholders::_1;
22 using std::tr1::placeholders::_2;
23 
24 namespace cass
25 {
26 
27 /** helper to convert shape into the 1D index
28  *
29  * @return index in the linearised array
30  * @param matrixIndex in the matrix
31  * @param width the width of the matrix
32  */
33 pp240::index_t::first_type toOneD(const pp240::index_t matrixIndex, pp240::index_t::first_type width)
34 {
35  return matrixIndex.second * width + matrixIndex.first;
36 }
37 
38 /** operates a minus on two indices
39  *
40  * performs \f$(lhs_1-rhs_1)(lhs_2-rhs_2)\f$.
41  *
42  * @return the result of the operation
43  * @param lhs the left hand side of the operation
44  * @param rhs the right hand side of the opeation
45  */
47 {
48  return make_pair(lhs.first - rhs.first, lhs.second - rhs.second);
49 }
50 
51 /** operates times on two indices
52  *
53  * performs \f$(lhs_1*rhs_1)(lhs_2*rhs_2)\f$.
54  *
55  * @return the result of the operation
56  * @param lhs the left hand side of the operation
57  * @param rhs the right hand side of the opeation
58  */
60 {
61  return make_pair(lhs.first * rhs.first, lhs.second * rhs.second);
62 }
63 
64 /** operates a plus on two indices
65  *
66  * performs \f$(lhs_1+rhs_1)(lhs_2+rhs_2)\f$.
67  *
68  * @return the result of the operation
69  * @param lhs the left hand side of the operation
70  * @param rhs the right hand side of the opeation
71  */
73 {
74  return make_pair(lhs.first + rhs.first, lhs.second + rhs.second);
75 }
76 
77 /** operates less of an indices to a scalar
78  *
79  * performs \f$(lhs_1+lhs_2)<rhs\f$.
80  *
81  * @return the result of the operation
82  * @param lhs the left hand side of the operation
83  * @param rhs the right hand side of the opeation
84  *
85  * @author Lutz Foucar
86  */
87 bool operator<(const pp240::indexf_t& lhs, const pp240::indexf_t::first_type rhs)
88 {
89  return ((lhs.first + lhs.second) < rhs);
90 }
91 
92 /** operates devides on two indices
93  *
94  * performs \f$(lhs_1/rhs_1)(lhs_2/rhs_2)\f$.
95  *
96  * @return the result of the operation
97  * @param lhs the left hand side of the operation
98  * @param rhs the right hand side of the opeation
99  *
100  * @author Lutz Foucar
101  */
103 {
104  return make_pair(lhs.first / rhs.first,
105  lhs.second / rhs.second);
106 }
107 
108 } //end namespace cass
109 
110 // *** test image ***
111 pp240::pp240(const name_t &name)
112  : Processor(name)
113 {
114  loadSettings(0);
115 }
116 
118 {
119  CASSSettings s;
120  s.beginGroup("Processor");
122  _result = result_t::shared_pointer(new result_t(s.value("sizeX", 1024).toInt(),
123  s.value("sizeY", 1024).toInt()));
124  for (int xx=0; xx<s.value("sizeX", 1024).toInt(); ++xx)
125  for (int yy=0; yy<s.value("sizeY", 1024).toInt(); ++yy)
127  _result->axis(result_t::yAxis),
128  make_pair(yy,xx))] =
129  s.value("FixedValue",false).toBool() ? s.value("Value",0).toFloat() : xx*yy;
130  string logout("processor " + name() +": creates test image with shape '" +
131  toString(s.value("sizeX", 1024).toInt()) + "x" +
132  toString(s.value("sizeY", 1024).toInt()) + "'");
133  // now add masks elements to it
134  map<string,std::tr1::function<void(result_t&, CASSSettings&)> > functions;
135  functions["circle"] = std::tr1::bind(&pp240::circle,this,_1,_2);
136  functions["square"] = std::tr1::bind(&pp240::square,this,_1,_2);
137  functions["triangle"] = std::tr1::bind(&pp240::triangle,this,_1,_2);
138  functions["ellipse"] = std::tr1::bind(&pp240::ellipse,this,_1,_2);
139  functions["ring"] = std::tr1::bind(&pp240::ring,this,_1,_2);
140  int size = s.beginReadArray("Mask");
141  for (int i = 0; i < size; ++i)
142  {
143  s.setArrayIndex(i);
144  string type(s.value("Type","Unknown").toString().toStdString());
145  if (type == "Unknown")
146  continue;
147  if (functions.find(type) == functions.end())
148  throw invalid_argument("pp240(): '" + name() + "': Unknown Mask Type '" +
149  type + "'");
150  Log::add(Log::DEBUG0,"pp240 '"+name()+"': add mask element type '" + type +"'");
151  functions[type](*_result,s);
152  }
153  s.endArray();
154 
155  Log::add(Log::INFO,logout);
156 }
157 
158 
160 {
161  const index_t center(make_pair(s.value("CenterX",500).toUInt(),
162  s.value("CenterY",500).toUInt()));
163  const index_t::first_type radius(s.value("Radius",2).toUInt());
164 
165  if ((center.first < radius) ||
166  (center.second < radius) ||
167  (static_cast<int>(data.shape().first) <= (center.first + radius)) ||
168  (static_cast<int>(data.shape().second) <= (center.second + radius)))
169  {
170  throw out_of_range("pp204:circle(): The radius '" + toString(radius) +
171  "' is choosen to big and does not fit the image. Center of circle ("
172  + toString(center.first) +","
173  + toString(center.second)+")");
174  }
175  const size_t radius_sq(radius*radius);
176  const index_t lowerLeft(make_pair(center.first-radius, center.second-radius));
177  const index_t upperRight(make_pair(center.first+radius, center.second+radius));
178  const size_t width(data.shape().first);
179 
180  for (index_t::first_type row(lowerLeft.second); row < upperRight.second; ++row)
181  {
182  for (index_t::first_type column(lowerLeft.first); column < upperRight.first; ++column)
183  {
184  const index_t idx(make_pair(column,row));
185  const index_t idx_sq((idx - center)*(idx - center));
186  if (idx_sq < radius_sq)
187  data[toOneD(idx,width)] = s.value("Value",1.f).toFloat();
188  }
189  }
190 }
191 
193 {
194  const index_t lowerLeft(make_pair(s.value("LowerLeftX",0).toUInt(),
195  s.value("LowerLeftY",0).toUInt()));
196  const index_t upperRight(make_pair(s.value("UpperRightX",1024).toUInt(),
197  s.value("UpperRightY",1024).toUInt()));
198  if ((static_cast<int>(data.shape().first) <= upperRight.first) ||
199  (static_cast<int>(data.shape().second) <= upperRight.second))
200  throw invalid_argument("addSquare(): The upper right coordinate ("
201  + toString(upperRight.first) +","
202  + toString(upperRight.second)+") "+
203  "is too big for the mask that has a size of ("
204  + toString(data.shape().first) +","
205  + toString(data.shape().second)+") ");
206  if((upperRight.first < lowerLeft.first) ||
207  (upperRight.second < lowerLeft.second))
208  throw out_of_range("addSquare(): The lowerLeft corner ("
209  + toString(lowerLeft.first) +","
210  + toString(lowerLeft.second)+") "+
211  "is not really to the lower left of ("
212  + toString(upperRight.first) +","
213  + toString(upperRight.second)+") ");
214 
215  const size_t width(data.shape().first);
216  for (index_t::first_type row(lowerLeft.second); row <= upperRight.second; ++row)
217  {
218  for (index_t::first_type column(lowerLeft.first); column <= upperRight.first; ++column)
219  {
220  const index_t idx(make_pair(column,row));
221  data[toOneD(idx,width)] = s.value("Value",1.f).toFloat();
222  }
223  }
224 }
225 
227 {
228  const index_t center(make_pair(s.value("CenterX",500).toUInt(),
229  s.value("CenterY",500).toUInt()));
230  const index_t::first_type a(s.value("SemiAxisX",5).toUInt());
231  const index_t::first_type b(s.value("SemiAxisY",2).toUInt());
232  const size_t width(data.shape().first);
233 
234  if ((center.first < a) ||
235  (center.second < b))
236  throw invalid_argument("addCircle(): The semi axis a '" + toString(a) +
237  "' and b '" + toString(b) +
238  "' are choosen to big and do not fit with center ("
239  + toString(center.first) +","
240  + toString(center.second)+")");
241  if((static_cast<int>(data.shape().first) <= (center.first + a)) ||
242  (static_cast<int>(data.shape().second) <= (center.second + b)))
243  throw out_of_range("addCircle(): The semi axis boundaries a '" + toString(center.first + a) +
244  "' and b '" + toString(center.second + b) +
245  "' are choosen to big and do not fit with center ("
246  + toString(data.shape().first) +","
247  + toString(data.shape().second)+")");
248 
249  const index_t lowerLeft(make_pair(center.first-a, center.second-b));
250  const index_t upperRight(make_pair(center.first+a, center.second+b));
251  const index_t axis_sq(make_pair(a,b)*make_pair(a,b));
252 
253  for (index_t::first_type row(lowerLeft.second); row <= upperRight.second; ++row)
254  {
255  for (index_t::first_type column(lowerLeft.first); column <= upperRight.first; ++column)
256  {
257  /** @todo check whether this works */
258  const index_t idx(make_pair(column,row));
259  const index_t idx_sq((idx - center)*(idx - center));
260  const indexf_t idx_tmp(idx_sq / axis_sq);
261  if (idx_tmp < 1)
262  data[toOneD(idx,width)] = s.value("Value",1.f).toFloat();
263  }
264  }
265 }
266 
268 {
269  const index_t outer_center(make_pair(s.value("OuterCenterX",500).toUInt(),
270  s.value("OuterCenterY",500).toUInt()));
271  const index_t::first_type outer_a(s.value("OuterSemiAxisX",5).toUInt());
272  const index_t::first_type outer_b(s.value("OuterSemiAxisY",2).toUInt());
273  const index_t inner_center(make_pair(s.value("InnerCenterX",500).toUInt(),
274  s.value("InnerCenterY",500).toUInt()));
275  const index_t::first_type inner_a(s.value("InnerSemiAxisX",20).toUInt());
276  const index_t::first_type inner_b(s.value("InnerSemiAxisY",20).toUInt());
277  const size_t width(data.shape().first);
278 
279  if ((outer_center.first < outer_a) ||
280  (outer_center.second < outer_b))
281  throw invalid_argument("addCircle(): The outer semi axis x '" +
282  toString(outer_a) + "' and b '" + toString(outer_b) +
283  "' are choosen to big and do not fit with center ("
284  + toString(outer_center.first) +","
285  + toString(outer_center.second)+")");
286  if ((static_cast<int>(data.shape().first) <= (outer_center.first + outer_a)) ||
287  (static_cast<int>(data.shape().second) <= (outer_center.second + outer_b)))
288  throw out_of_range(string("addCircle(): The outer semi axis boundaries a '") +
289  toString(outer_center.first + outer_a) +
290  "' and b '" + toString(outer_center.second + outer_b) +
291  "' are choosen to big and do not fit into image ("
292  + toString(data.shape().first) +","
293  + toString(data.shape().second)+")");
294 
295  if ((inner_center.first < inner_a) ||
296  (inner_center.second < inner_b))
297  throw invalid_argument(string("addCircle(): The inner semi axis x '") +
298  toString(inner_a) + "' and b '" + toString(inner_b) +
299  "' are choosen to big and do not fit with center ("
300  + toString(inner_center.first) +","
301  + toString(inner_center.second)+")");
302 
303  if((static_cast<int>(data.shape().first) <= (inner_center.first + inner_a)) ||
304  (static_cast<int>(data.shape().second) <= (inner_center.second + inner_b)))
305  throw out_of_range(string("addCircle(): The inner semi axis boundaries a '") +
306  toString(inner_center.first + inner_a) + "' and b '" +
307  toString(inner_center.second + inner_b) +
308  "' are choosen to big and do not fit into image ("
309  + toString(data.shape().first) +","
310  + toString(data.shape().second)+")");
311 
312  const size_t min_col(min(outer_center.first - outer_a,
313  inner_center.first - inner_a));
314  const size_t max_col(max(outer_center.first + outer_a,
315  inner_center.first + inner_a));
316  const size_t min_row(min(outer_center.second - outer_b,
317  inner_center.second - inner_b));
318  const size_t max_row(max(outer_center.second + outer_b,
319  inner_center.second + inner_b));
320 
321  const index_t outer_axis_sq(make_pair(outer_a,outer_b)*make_pair(outer_a,outer_b));
322  const index_t inner_axis_sq(make_pair(inner_a,inner_b)*make_pair(inner_a,inner_b));
323 
324  for (size_t row(min_row); row <= max_row; ++row)
325  {
326  for (size_t column(min_col); column <= max_col; ++column)
327  {
328  const index_t idx(make_pair(column,row));
329 
330  const index_t idx_sq_inner((idx - inner_center)*(idx - inner_center));
331  const indexf_t idx_tmp_inner(idx_sq_inner / inner_axis_sq);
332  const bool isNotInInner(!(idx_tmp_inner < 1));
333 
334  const index_t idx_sq_outer((idx - outer_center)*(idx - outer_center));
335  const indexf_t idx_tmp_outer(idx_sq_outer / outer_axis_sq);
336  const bool isInOuter(idx_tmp_outer < 1);
337 
338  if (isInOuter && isNotInInner)
339  data[toOneD(idx,width)] = s.value("Value",1.f).toFloat();
340  }
341  }
342 }
343 
345 {
346  const index_t A(make_pair(s.value("PointA_X",500).toUInt(),
347  s.value("PointA_Y",500).toUInt()));
348  const index_t B(make_pair(s.value("PointB_X",500).toUInt(),
349  s.value("PointB_Y",500).toUInt()));
350  const index_t C(make_pair(s.value("PointC_X",500).toUInt(),
351  s.value("PointC_Y",500).toUInt()));
352 
353  if (A == B ||
354  B == C ||
355  A == C)
356  throw invalid_argument("addTriangle(): the 3 Points "
357  "A("+toString(A.first)+","+toString(A.second)+"), "
358  "B("+toString(B.first)+","+toString(B.second)+"), "
359  "C("+toString(C.first)+","+toString(C.second)+"), "
360  "are inconsistent.");
361 
362  if (static_cast<int>(data.shape().first) <= A.first ||
363  static_cast<int>(data.shape().first) <= B.first ||
364  static_cast<int>(data.shape().first) <= C.first ||
365  static_cast<int>(data.shape().second) <= A.second ||
366  static_cast<int>(data.shape().second) <= B.second ||
367  static_cast<int>(data.shape().second) <= C.second )
368  throw out_of_range("addTriangle(): the 3 Points "
369  "A("+toString(A.first)+","+toString(A.second)+"), "
370  "B("+toString(B.first)+","+toString(B.second)+"), "
371  "C("+toString(C.first)+","+toString(C.second)+"), "
372  "are outside the the mask boundaries "+
373  toString(data.shape().first) +","+ toString(data.shape().second));
374 
375  const size_t width(data.shape().first);
376  const index_t::first_type minX(min(min(A.first,B.first),C.first));
377  const index_t::first_type minY(min(min(A.second,B.second),C.second));
378  const index_t::first_type maxX(max(max(A.first,B.first),C.first));
379  const index_t::first_type maxY(max(max(A.second,B.second),C.second));
380  const index_t lowerLeft(make_pair(minX,minY));
381  const index_t upperRight(make_pair(maxX,maxY));
382  const float x1(A.first);
383  const float x2(B.first);
384  const float x3(C.first);
385  const float y1(A.second);
386  const float y2(B.second);
387  const float y3(C.second);
388  const float denom( (y2-y3)*(x1-x3) + (x3-x2)*(y1-y3) );
389 
390  for (index_t::first_type row(lowerLeft.second); row <= upperRight.second; ++row)
391  {
392  for (index_t::first_type column(lowerLeft.first); column <= upperRight.first; ++column)
393  {
394  const index_t P(make_pair(column,row));
395  const float x(P.first);
396  const float y(P.second);
397 
398  const float l1( ( (y2-y3)*(x-x3) + (x3-x2)*(y-y3) ) / denom );
399  const float l2( ( (y3-y1)*(x-x3) + (x1-x3)*(y-y3) ) / denom );
400  const float l3( 1 - l1 - l2 );
401 
402  if ((0<=l1) && (l1<=1) && (0<=l2) && (l2<=1) && (0<=l3) && (l3<=1))
403  data[toOneD(P,width)] = s.value("Value",1.f).toFloat();
404  }
405  }
406 }
CachedList::item_type result_t
define the results
Definition: processor.h:52
setArrayIndex(int i)
void triangle(result_t &data, CASSSettings &s)
add a triangluar element to the mask
Definition: imaging.cpp:344
void ring(result_t &data, CASSSettings &s)
add a ring
Definition: imaging.cpp:267
pp240::indexf_t operator/(const pp240::indexf_t &lhs, const pp240::indexf_t &rhs)
operates devides on two indices
Definition: imaging.cpp:102
pp240::index_t::first_type toOneD(const pp240::index_t matrixIndex, pp240::index_t::first_type width)
helper to convert shape into the 1D index
Definition: imaging.cpp:33
const name_t name() const
retrieve the name of this processor
Definition: processor.h:167
result_t::shared_pointer _result
the constant image
Definition: imaging.h:216
Settings for CASS.
Definition: cass_settings.h:30
std::tr1::shared_ptr< self_type > shared_pointer
a shared pointer of this class
Definition: result.hpp:323
pp240::index_t operator*(const pp240::index_t &lhs, const pp240::index_t &rhs)
operates times on two indices
Definition: imaging.cpp:59
pp240::index_t operator+(const pp240::index_t &lhs, const pp240::index_t &rhs)
operates a plus on two indices
Definition: imaging.cpp:72
STL namespace.
size_t bin(const Axis< AxisPrecessionType > &xaxis, const ResultValueType &value)
calculate the index of the lineared array
Definition: result.hpp:143
things written only at end of run H5Dump ProcessorSummary size
bool operator<(const pp240::indexf_t &lhs, const pp240::indexf_t::first_type rhs)
operates less of an indices to a scalar
Definition: imaging.cpp:87
static void add(Level level, const std::string &line)
add a string to the log
Definition: log.cpp:31
fromStdString(const std::string &str)
beginReadArray(const QString &prefix)
base class for processors.
Definition: processor.h:39
std::pair< int, int > index_t
define the index type
Definition: imaging.h:80
pp240::index_t operator-(const pp240::index_t &lhs, const pp240::index_t &rhs)
operates a minus on two indices
Definition: imaging.cpp:46
void ellipse(result_t &data, CASSSettings &s)
add a ellipsodial element to the mask
Definition: imaging.cpp:226
std::string toString(const Type &t)
convert any type to a string
Definition: cass.h:63
auxiliary data[Processor]
photon wavelength A
value(const QString &key, const QVariant &defaultValue=QVariant()
void circle(result_t &data, CASSSettings &s)
add a circle to the mask
Definition: imaging.cpp:159
file contains specialized class that do the settings for cass
void square(result_t &data, CASSSettings &s)
add a square element to the mask
Definition: imaging.cpp:192
pp240(const name_t &)
constructor.
Definition: imaging.cpp:111
std::pair< float, float > indexf_t
define a floating point version of the index
Definition: imaging.h:83
shape_t shape() const
return the shape of the result
Definition: result.hpp:811
std::string name_t
define the name type
Definition: processor.h:46
contains a logger for cass
virtual void loadSettings(size_t)
load the settings of this pp
Definition: imaging.cpp:117
processors to generate a test image
beginGroup(const QString &prefix)