CFEL - ASG Software Suite  2.5.0
CASS
result.hpp
Go to the documentation of this file.
1 // Copyright (C) 2011, 2012, 2015 Lutz Foucar
2 
3 /**
4  * @file result.hpp result classes
5  *
6  * @author Lutz Foucar
7  */
8 
9 #ifndef __RESULTCONTAINER__
10 #define __RESULTCONTAINER__
11 
12 #include <vector>
13 #include <string>
14 #include <stdexcept>
15 #include <limits>
16 #include <tr1/memory>
17 #include <cmath>
18 #ifdef CASS_DEBUG
19 #include <iostream>
20 #endif
21 
22 #include <QtCore/QReadWriteLock>
23 
24 #include "serializable.hpp"
25 
26 namespace cass
27 {
28 //forward declarations
29 template<typename T>struct Axis;
30 template <typename T> class Result;
31 
32 
33 /** add an Axis to a stream
34  *
35  * @tparam T the precision of the axis values
36  * @param serializer the serializer to serialize the axis to
37  * @param axis the axis to serialize
38  *
39  * @author Lutz Foucar
40  */
41 template <typename T>
42 SerializerBackend& operator<<(SerializerBackend& serializer, const Axis<T>& axis)
43 {
44  serializer.add(static_cast<uint16_t>(Axis<T>::serializationVersion));
45  serializer.add(axis.nBins);
46  serializer.add(axis.low);
47  serializer.add(axis.up);
48  serializer.add(axis.title);
49  return serializer;
50 }
51 
52 /** read an Axis from a stream
53  *
54  * @tparam T the precision of the axis values
55  * @param serializer the serializer to serialize the axis to
56  * @param axis the axis to serialize
57  *
58  * @author Lutz Foucar
59  */
60 template <typename T>
62 {
63  uint16_t version(serializer.retrieve<uint16_t>());
64  if(version != Axis<T>::serializationVersion)
65  throw std::runtime_error("operator>>(serializer,Axis<T>): Version conflict");
66  axis.nBins = serializer.retrieve<size_t>();
67  axis.low = serializer.retrieve<T>();
68  axis.up = serializer.retrieve<T>();
69  axis.title = serializer.retrieve<std::string>();
70  return serializer;
71 }
72 
73 /** add a Result to a stream
74  *
75  * @todo add the type info to the stream and check it
76  *
77  * @tparam T the precision of the axis values
78  * @param serializer the serializer to serialize the axis to
79  * @param result the Result to serialize
80  *
81  * @author Lutz Foucar
82  */
83 template <typename T>
85  const Result<T>& result)
86 {
87  serializer.add(static_cast<uint16_t>(Result<T>::serializationVersion));
88  serializer.add(result._id);
89  serializer.add(result._name);
90  serializer.add(static_cast<size_t>(result._axis.size()));
91  for (typename Result<T>::axis_t::const_iterator it=result._axis.begin(), end = result._axis.end(); it != end; ++it)
92  serializer << *it;
93  serializer.add(static_cast<size_t>(result._storage.size()));
94  for (typename Result<T>::const_iterator it=result.begin(),end=result.end(); it != end; ++it)
95  serializer.add(*it);
96  return serializer;
97 }
98 
99 /** read a Result from a stream
100  *
101  * @todo add the type info to the stream and check it
102  *
103  * @tparam T the precision of the axis values
104  * @param serializer the serializer to serialize the axis to
105  * @param result the Result to write to
106  *
107  * @author Lutz Foucar
108  */
109 template <typename T>
111  Result<T>& result)
112 {
113  uint16_t version(serializer.retrieve<uint16_t>());
114  if (version != Result<T>::serializationVersion)
115  throw std::runtime_error("operator>>(serializer,Result<T>): Version conflict");
116  result._id = serializer.retrieve<uint64_t>();
117  result._name = serializer.retrieve<std::string>();
118  result._axis.resize(serializer.retrieve<size_t>());
119  for (typename Result<T>::axis_t::iterator it=result._axis.begin(), end = result._axis.end(); it != end; ++it)
120  serializer >> (*it);
121  const size_t size(serializer.retrieve<size_t>());
122  result._storage.clear();
123  for (size_t i(0); i < size; ++i)
124  result._storage.push_back(serializer.retrieve<typename Result<T>::value_t>());
125  return serializer;
126 }
127 
128 namespace histogramming
129 {
130 
131 /** calculate the index of the lineared array
132  *
133  * calculates the bin Index of the linearized array that the provided position
134  * corresponds to
135  *
136  * @tparam AxisPrecessionType the precision of the axis values
137  * @tparam ResultValueType the type within the result container
138  * @return correct bin index of 1d histogram or overflow / underflow
139  * @param xAxis The axis used to determin the bin for the value
140  * @param value The value whos corresponding bin should be found
141  */
142 template <typename AxisPrecessionType, typename ResultValueType>
143 size_t bin(const Axis<AxisPrecessionType>& xaxis, const ResultValueType &value)
144 {
145  const int xBin(xaxis.bin(value));
146  if (xaxis.isOverflow(xBin))
148  else if (xaxis.isUnderflow(xBin))
150  else
151  return xBin;
152 }
153 
154 /** calculate the corresponding index in the linearized array of a coordinate
155  *
156  * calculates the bin index of the linearized array that the provided coordinate
157  * corresponds to. It uses the two provided axis object to do so.
158  *
159  * @tparam AxisPrecessionType the precision of the axis values
160  * @tparam coordinate_t the coordinate type. Expected to be std::pair
161  * @return correct bin index of 1d histogram or overflow / underflow
162  * @param xAxis The x-axis used to determin the bin for the coordinate
163  * @param yAxis The y-axis used to determin the bin for the coordinate
164  * @param coordinate The coordinate whos corresponding bin should be found
165  */
166 template <typename AxisPrecessionType, typename coordinate_t>
167 size_t bin(const Axis<AxisPrecessionType> &xAxis,
168  const Axis<AxisPrecessionType> &yAxis,
169  const coordinate_t &coordinate)
170 {
172  const int xBin(xAxis.bin(coordinate.first));
173  const int yBin(yAxis.bin(coordinate.second));
174  const long maxSize(xAxis.nBins*yAxis.nBins);
175  const bool xUnderflow(xAxis.isUnderflow(xBin));
176  const bool xOverflow(xAxis.isOverflow(xBin));
177  const bool xInRange(!xUnderflow && !xOverflow);
178  const bool yUnderflow(yAxis.isUnderflow(yBin));
179  const bool yOverflow(yAxis.isOverflow(yBin));
180  const bool yInRange(!yUnderflow && !yOverflow);
181  if (xUnderflow && yUnderflow)
182  return maxSize+result_t::LowerLeft;
183  else if (xUnderflow && yOverflow)
184  return maxSize+result_t::UpperRight;
185  else if (xUnderflow && yOverflow)
186  return maxSize+result_t::UpperLeft;
187  else if (xOverflow && yUnderflow)
188  return maxSize+result_t::LowerRight;
189  else if (xInRange && yUnderflow)
190  return maxSize+result_t::LowerMiddle;
191  else if (xInRange && yOverflow)
192  return maxSize+result_t::UpperMiddle;
193  else if (xUnderflow && yInRange)
194  return maxSize+result_t::Left;
195  else if (xOverflow && yInRange)
196  return maxSize+result_t::Right;
197  else
198  return yBin*xAxis.nBins + xBin;
199 }
200 }//end nampespace histogramming
201 
202 
203 /** an axis of a more than 0 dimensional container
204  *
205  * @tparam the type in which the bin limits are given
206  *
207  * @author Lutz Foucar
208  */
209 template<typename T>
210 struct Axis
211 {
212  /** the serialization version of this class */
214 
215  /** the presision type of the axis boundaries */
216  typedef T value_t;
217 
218  /** default Constructor */
220  : nBins(0),
221  low(0.),
222  up(0.),
223  title()
224  {}
225 
226  /** Constructor
227  *
228  * will set the properties in the initializtion list. Will also set the version
229  * for the de / serialization.
230  *
231  * @param nbrBins The Number of Bins the axis contains
232  * @param lowerLimit The lower end of the axis
233  * @param upperLimit The upper end of the axis
234  */
235  Axis(size_t nbrBins, value_t lowerLimit, value_t upperLimit, std::string title="Axis Title")
236  : nBins(nbrBins),
237  low(lowerLimit),
238  up(upperLimit),
239  title(title)
240  {}
241 
242  /** calculate the position for a given bin
243  *
244  * @return the position of the bin
245  * @param bin the bin to calculate the postion for
246  */
247  value_t pos(const int bin) const
248  {
249  return (low + (bin*(up - low)/nBins));
250  }
251 
252  /** return the bin that a value will fall in
253  *
254  * in case the value is nan return a value that states and underflow
255  *
256  * @return the bin that the value will fall into or -1 in case value is nan
257  * @param val the value that should be histogrammed
258  */
259  int bin(const value_t &val) const
260  {
261  if (!std::isfinite(val))
262  return -1;
263  return(static_cast<int>(nBins * (val - low) / (up-low)));
264  }
265 
266  /** check if a bin is an underflow
267  *
268  * @return true if bin is underflow
269  * @param bin the bin to check
270  */
271  bool isUnderflow(int bin) const
272  {
273  return (bin < 0);
274  }
275 
276  /** check if a bin is an overflow
277  *
278  * @return true if bin is overflow
279  * @param bin the bin to check
280  */
281  bool isOverflow(int bin) const
282  {
283  return (static_cast<int>(nBins) <= bin);
284  }
285 
286  /** the number of bins in this axis */
287  size_t nBins;
288 
289  /** lower end of the axis */
290  value_t low;
291 
292  /** upper end of the axis */
293  value_t up;
294 
295  /** the title of the axis */
296  std::string title;
297 };
298 
299 /** A result of a processor
300  *
301  * The result can be a value or an 1d or 2d array. The 1d or 2d can be used as
302  * a histogram.
303  *
304  * @todo add statistics for the histograming functionality
305  *
306  * @tparam T the type of data that the result is made of
307  * @tparam precision how the precision for adding something to the array
308  * @tparam world2hist function to convert world coordinates to histogram coordinates
309  *
310  * @author Lutz Foucar
311  */
312 template <typename T>
313 class Result
314 {
315 public:
316  /** the serialization version of this class */
318 
319  /** this classes type */
321 
322  /** a shared pointer of this class */
323  typedef std::tr1::shared_ptr<self_type> shared_pointer;
324 
325  /** the values of this container */
326  typedef T value_t;
327 
328  /** a coordinate of a 2d array */
329  typedef std::pair<double, double> coordinate_t;
330 
331  /** the storage of this container */
332  typedef std::vector<value_t> storage_t;
333 
334  /** a iterator on the storage */
335  typedef typename storage_t::iterator iterator;
336 
337  /** a const iterator on the storage */
338  typedef typename storage_t::const_iterator const_iterator;
339 
340  /** a reference to the storage */
341  typedef typename storage_t::reference reference;
342 
343  /** a const reference to the storage */
344  typedef typename storage_t::const_reference const_reference;
345 
346  /** define the size type of the storage */
347  typedef typename storage_t::size_type size_type;
348 
349  /** define the shape of the result */
350  typedef std::pair<size_type,size_type> shape_t;
351 
352  /** the axis descriptions of this container */
354 
355  /** the axis descriptions of this container */
356  typedef std::vector<axe_t > axis_t;
357 
358  /** which axis one wants to have */
359  enum axis_name {xAxis=0, yAxis};
360 
361  /** over/ underflow of 2d histogram */
365 
366  /** the over/underflow bin of 1d histogram */
368 
369  /** default constructor
370  *
371  * using this constructor will create a value container. Only one element is
372  * allocated in the storage and no axis are defined.
373  */
375  : _storage(1,0)
376  {}
377 
378  /** 1d array container constructor
379  *
380  * use this constructor if you want to create a one dimensional array. In this
381  * case the axis automatically set to go from 0 to size -1 having size bins.
382  * The vector will be created with size elements
383  *
384  * @param xaxis The x-axis of the histogram
385  */
386  explicit Result(const size_type& size)
387  : _axis(1),
388  _storage(size,0)
389  {
390  _axis[xAxis] = axe_t(size,0,size,"x-Axis");
391  }
392 
393  /** 1d histogram constructor
394  *
395  * use this constructor if you want to create a one dimensional histogram.
396  * The axis container is resized to fit the xaxis. The storage is set up so
397  * that it can hold all the bins of the 1D histogram.
398  *
399  * @param xaxis The x-axis of the histogram
400  */
401  explicit Result(const axe_t& xaxis)
402  : _axis(1),
403  _storage(xaxis.nBins+OneDStatSize,0)
404  {
405  _axis[xAxis] = xaxis;
406  }
407 
408  /** 2d array container or table constructor
409  *
410  * use this constructor if you want to create a two dimensional array. The
411  * 2d array itself is represented in a linearized array.
412  * The axis are created such that they will go from 0 .. rows or cols and have
413  * rows or cols bins for the y- and x-axis respectively.
414  * The axis container is allocated to fit both axis. The storage is set up so
415  * that it can hold rows * cols elemnts in the linearized array.
416  *
417  * @param cols The x-axis of the histogram
418  * @param rows The y-axis of the histogram
419  */
420  Result(const size_type& cols, const size_type& rows)
421  : _axis(2),
422  _storage(cols*rows,0)
423  {
424  _axis[xAxis] = axe_t(cols,0,cols,"x-Axis");
425  _axis[yAxis] = axe_t(rows,0,rows,"y-Axis");
426  }
427 
428  /** 2d histogram constructor
429  *
430  * use this constructor if you want to create a two dimensional histogram.
431  * The axis container is allocated to fit both axis. The storage is set up so
432  * that it can hold all the bins of the 2D histogram in a linearized array.
433  *
434  * @param xaxis The x-axis of the histogram
435  * @param yaxis The y-axis of the histogram
436  */
437  Result(const axe_t& xaxis, const axe_t& yaxis)
438  : _axis(2),
439  _storage(xaxis.nBins * yaxis.nBins + TwoDStatSize,0)
440  {
441  _axis[xAxis] = xaxis;
442  _axis[yAxis] = yaxis;
443  }
444 
445  /** read access to the axis
446  *
447  * @return const reference to the axis object
448  */
449  const axis_t& axis() const
450  {
451  return _axis;
452  }
453 
454  /** write access to the axis
455  *
456  * @return reference to the axis object
457  */
458  axis_t& axis()
459  {
460  return _axis;
461  }
462 
463  /** read access to a specific axis
464  *
465  * only 1d and 2d histograms have axis. Therefore throws invalid_argument if
466  * the requested axis does not exist
467  *
468  * @param axis the requested axis
469  */
470  const axe_t& axis(const axis_name& axis) const
471  {
472 #ifdef CASS_DEBUG
473  if (static_cast<int>(_axis.size()) <= axis)
474  throw std::invalid_argument("Result::axis: the requested axis does not exist");
475 #endif
476  return _axis[axis];
477  }
478 
479  /** write accesss to a specific axis
480  *
481  * only 1d and 2d histograms have axis. Therefore throws invalid_argument if
482  * the requested axis does not exist
483  *
484  * @param axis the requested axis
485  */
486  axe_t& axis(const axis_name& axis)
487  {
488 #ifdef CASS_DEBUG
489  if (static_cast<int>(_axis.size()) <= axis)
490  throw std::invalid_argument("Result::axis: the requested axis does not exist");
491 #endif
492  return _axis[axis];
493  }
494 
495 
496  /** what is the dimension of the result
497  *
498  * depending on the size of the axis one can determine the dimension of the
499  * result.
500  *
501  * @return dimension of the result
502  */
503  size_t dim() const
504  {
505  return _axis.size();
506  }
507 
508  /** friend for serialization
509  *
510  * @note make one single instance (called "specialization" in generic terms)
511  * of the template a friend. Because the compiler knows from the
512  * parameter list that the template arguments one does not have to put
513  * those between <...>, so they can be left empty
514  */
515  friend SerializerBackend& operator<< <> (SerializerBackend&, const self_type&);
516 
517  /** friend for deserialization
518  *
519  * @note make one single instance (called "specialization" in generic terms)
520  * of the template a friend. Because the compiler knows from the
521  * parameter list that the template arguments one does not have to put
522  * those between <...>, so they can be left empty
523  */
524  friend SerializerBackend& operator>> <> (SerializerBackend&, self_type&);
525 
526  /** clear the contents of the result
527  *
528  * overwrite all values of the storage with 0.
529  */
530  void clear()
531  {
532  std::fill(_storage.begin(),_storage.end(),0.f);
533  }
534 
535  /** assign the result container to a value
536  *
537  * this function should be used in case the result container is holding just
538  * a value. In this case the storage should have only one element which is then
539  * assigned to the passed value.
540  *
541  * @param value the value that is assigned to this container
542  */
543  void setValue(const_reference value)
544  {
545 #ifdef CASS_DEBUG
546  if (!_axis.empty())
547  throw std::logic_error("Result::setValue: Try using the result as a value, but it has axis");
548 #endif
549  _storage.front() = value;
550  }
551 
552  /** return the value
553  *
554  * should only be used when container acts as a value
555  *
556  * @return the value of the Value like container
557  */
558  value_t getValue() const
559  {
560 #ifdef CASS_DEBUG
561  if (!_axis.empty())
562  throw std::logic_error("Result::getValue: Try using the result as a value, but it has axis");
563 #endif
564  return _storage.front();
565  }
566 
567  /** evaluate whether value is zero
568  *
569  * asserts that the container is used as value by checking for 0 axis
570  *
571  * since the value will most likely be a floating point variable we check
572  * whether the absolute value is smaller than the square root of epsilon of the
573  * data type.
574  *
575  * @return true if the result value is non-zero, false otherwise
576  */
577  bool isTrue() const
578  {
579 #ifdef CASS_DEBUG
580  if (!_axis.empty())
581  throw std::logic_error("Result::isTrue: Try using the result as a value, but it has axis");
582 #endif
583  return !(std::abs(_storage.front()) < std::sqrt(std::numeric_limits<value_t>::epsilon()));
584  }
585 
586  /** read access to the storage
587  *
588  * @return const reference to the storage
589  */
590  const storage_t& storage() const
591  {
592  return _storage;
593  }
594 
595  /** write access to the storage
596  *
597  * @return reference to the storage
598  */
599  storage_t& storage()
600  {
601  return _storage;
602  }
603 
604  /** retrieve a iterator for read access to beginning
605  *
606  * @return const iterator to beginning
607  */
608  const_iterator begin() const {return _storage.begin();}
609 
610  /** retrieve iterator for write access to beginning
611  *
612  * @return iterator to beginning
613  */
614  iterator begin() {return _storage.begin();}
615 
616  /** retrieve reference to the first element
617  *
618  * @return reference to the first element
619  */
620  reference front() {return _storage.front();}
621 
622  /** retrieve const reference to the first element
623  *
624  * @return const reference to the first element
625  */
626  const_reference front() const {return _storage.front();}
627 
628  /** retrieve iterator to the end of storage
629  *
630  * @return const iterator to end
631  */
632  const_iterator end() const {return _storage.end();}
633 
634  /** retrieve iterator to the end of storage
635  *
636  * @return iterator to end
637  */
638  iterator end() {return _storage.end();}
639 
640  /** add the weight at the right bin for the value in the 1d array
641  *
642  * the position that is passed will be converted to the right bin number
643  * using the world2hist function. The value in this bin is increased
644  * by weight.
645  *
646  * @return iterator to the bin in the storage that was increased
647  * @param pos the position that is converted to the bin in the histogram
648  * @param weight the value that should be added to the value in the bin.
649  * Default ist 1.
650  */
651  iterator histogram(const value_t& pos, const value_t& weight=1)
652  {
653 #ifdef CASS_DEBUG
654  if (_axis.size() != 1)
655  throw std::logic_error("Result::histogram(pos): Result doesn't have dimension 1");
656 #endif
657  //const size_t histbin(bin(pos));
658  const size_t histbin(histogramming::bin(_axis[xAxis],pos));
659 #ifdef CASS_DEBUG
660  if (histbin >= size())
661  {
662  std::cout << std:: boolalpha<<
663  name() <<" " << size() <<" "<< datasize() <<" "<<
664  shape().first<<"x"<<shape().second<<" "<<
665  pos <<" " <<
666  axis(xAxis).bin(pos)<< " " <<
667  "xOverflow:"<<axis(xAxis).isOverflow(axis(xAxis).bin(pos))<< " " <<
668  "xUnderflow:"<<axis(xAxis).isUnderflow(axis(xAxis).bin(pos))<< " " <<
669  histbin<<std::endl;
670  throw std::out_of_range("Result::histogram(pos): calculated bin isn't within the size of the storage");
671  }
672 #endif
673  iterator it(begin() + histbin);
674  *it += weight;
675  return it;
676  }
677 
678  /** add the weight at the right bin for the coordinate in the 2d array
679  *
680  * the position passed will be converted to the right bin number for each axis
681  * using the utility world2hist function. The value in this bin is increased
682  * by weight.
683  *
684  * @return iterator to the bin in the storage that was increased
685  * @param pos the position that is converted to the bin in the histogram
686  * @param weight the value that should be added to the value in the bin.
687  * Default ist 1.
688  */
689  iterator histogram(const coordinate_t& pos, const value_t& weight=1)
690  {
691 #ifdef CASS_DEBUG
692  if (_axis.size() != 2)
693  throw std::logic_error("Result::histogram(coordinate): Result doesn't have dimension 2");
694 #endif
695  const size_t histbin(histogramming::bin(_axis[xAxis], _axis[yAxis], pos));
696 #ifdef CASS_DEBUG
697  if (histbin >= size())
698  {
699  std::cout << std:: boolalpha<<
700  name() <<" " << size() <<" "<< datasize() <<" "<<
701  shape().first<<"x"<<shape().second<<" "<<
702  pos.first <<"x"<<pos.second <<" " <<
703  axis(xAxis).bin(pos.first)<< " " <<
704  axis(yAxis).bin(pos.second)<< " " <<
705  "xOverflow:"<<axis(xAxis).isOverflow(axis(xAxis).bin(pos.first))<< " " <<
706  "xUnderflow:"<<axis(xAxis).isUnderflow(axis(xAxis).bin(pos.first))<< " " <<
707  "yOverflow:"<<axis(yAxis).isOverflow(axis(yAxis).bin(pos.second))<< " " <<
708  "yUnderflow:"<<axis(yAxis).isUnderflow(axis(yAxis).bin(pos.second))<< " " <<
709  histbin<<std::endl;
710  throw std::out_of_range("Result::histogram(coordinate): calculated bin isn't within the size of the storage");
711  }
712 #endif
713  iterator it(begin() + histbin);
714  *it += weight;
715  return it;
716  }
717 
718  /** add row(s) to the result
719  *
720  * in case the result is used as a table this will add row(s) to the table
721  *
722  * @param rows the rows to be appended to the table like result
723  */
724  void appendRows(const storage_t &rows)
725  {
726 #ifdef CASS_DEBUG
727  if (_axis.size() != 2)
728  throw std::logic_error("Result::appendRows(): Result doesn't have dimension 2");
729  if (rows.size() % _axis[xAxis].nBins)
730  throw std::runtime_error("Result::appendRows: The rowsize is not a modulo of the rowsize of the table '");
731 #endif
732  const int nRows(rows.size() / _axis[xAxis].nBins);
733  _axis[yAxis].nBins += nRows;
734  _axis[yAxis].up = axis(yAxis).nBins - 1;
735 
736  _storage.insert(_storage.end(),rows.begin(),rows.end());
737  }
738 
739  /** reset the table like result */
740  void resetTable()
741  {
742 #ifdef CASS_DEBUG
743  if (_axis.size() != 2)
744  throw std::logic_error("Result::resetTable(): Result doesn't have dimension 2");
745 #endif
746  _storage.clear();
747  _axis[yAxis].nBins = 0;
748  _axis[yAxis].up = -1;
749  }
750 
751  /** append a value to the end of the result
752  *
753  * append the value and set the axis to reflect the new content
754  * @param val the value to append
755  */
756  void append(const value_t &val)
757  {
758 #ifdef CASS_DEBUG
759  if (_axis.size() != 1)
760  throw std::logic_error("Result::push_back(): Result doesn't have dimension 1");
761 #endif
762  _storage.push_back(val);
763  _axis[xAxis].nBins = _storage.size();
764  _axis[xAxis].up = _axis[xAxis].nBins - 1;
765  }
766 
767  /** clear the appendable 1d like result
768  *
769  * clears the storage and reset xaxis to reflect the new content
770  */
771  void reset()
772  {
773 #ifdef CASS_DEBUG
774  if (_axis.size() != 1)
775  throw std::logic_error("Result::reset(): Result doesn't have dimension 1");
776 #endif
777  _storage.clear();
778  _axis[xAxis].nBins = _storage.size();
779  _axis[xAxis].up = _axis[xAxis].nBins - 1;
780  }
781 
782  /** enable accessing elements of the storage directly
783  *
784  * @return a reference to the element at position pos in the container.
785  * @param pos Position of requested element in the container
786  */
787  reference operator[](size_type pos)
788  {
789  return _storage[pos];
790  }
791 
792  /** enable accessing elements of the storage directly
793  *
794  * Returns a reference to the element at position pos in the container.
795  *
796  * @param pos Position of requested element in the container
797  */
798  const_reference operator[](size_type pos) const
799  {
800  return _storage[pos];
801  }
802 
803  /** return the shape of the result
804  *
805  * in case it is a value the constant 1,1 will be returned. In case it is a
806  * 1d result the second parameter is 0, and the full shape in case it is a
807  * 2d result will be returned.
808  *
809  * @return the shape of the result
810  */
811  shape_t shape() const
812  {
813  switch (_axis.size())
814  {
815  case 0:
816  return std::make_pair(1,1);
817  break;
818  case 1:
819  return std::make_pair(axis(xAxis).nBins,1);
820  break;
821  case 2:
822  return std::make_pair(axis(xAxis).nBins,axis(yAxis).nBins);
823  break;
824  default:
825  throw std::logic_error("Result::shape(): Result doesn't have dimension 2");
826  }
827  }
828 
829  /** return the shape of the result as numpy / hdf5 shape
830  *
831  * the convention is that the first dimension of the shape is the slowest
832  * changing dimesnsion in the linearized array, and the second ist the one
833  * faster changeing axis ... The last will be the fastest changing dimension
834  * of the linearized array. Thus in case the result is a value a 1 dim shape
835  * with 1 entry will be returned. For array like results a 1 dim shape with
836  * the length of the array will be returned and for matrix or table like
837  * results a 2 dim with the y axis as 0 and x-axis as the last dimension of
838  * the shape will be returned
839  *
840  * @return the numpy / hdf5 like shape of the result
841  */
842  std::vector<size_t> np_shape() const
843  {
844  switch (_axis.size())
845  {
846  case 0:
847  return std::vector<size_t>(1,1);
848  break;
849  case 1:
850  return std::vector<size_t>(1,axis(xAxis).nBins);
851  break;
852  case 2:
853  {
854  std::vector<size_t> s(2);
855  s[0] = axis(yAxis).nBins;
856  s[1] = axis(xAxis).nBins;
857  return s;
858  break;
859  }
860  default:
861  throw std::logic_error("Result::shape(): Result doesn't have dimension 2");
862  }
863  }
864 
865  /** return the size of the data as determined by the axis
866  *
867  * This size will be the size of the data without the space reserved for the
868  * statistics
869  *
870  * @return the data size
871  */
872  size_type datasize() const
873  {
874  return (shape().first * shape().second);
875  }
876 
877  /** return the raw size of the storage
878  *
879  * @return the size of the storage
880  */
881  size_type size() const
882  {
883  return _storage.size();
884  }
885 
886  /** create a copy of the result
887  *
888  * @return shared pointer to this result
889  */
890  shared_pointer clone() const
891  {
892  shared_pointer sp(new self_type);
893  sp->_axis = _axis;
894  sp->_storage = _storage;
895  sp->_name = _name;
896  sp->_id = _id;
897  return sp;
898  }
899 
900  /** copy the contents of a different result to this result
901  *
902  * copy the axis and the storage only
903  *
904  * @param in input whos contents should be copied to here
905  */
906  void assign(const self_type& in)
907  {
908  _storage = in._storage;
909  _axis = in._axis;
910  }
911 
912  /** retrieve the name of the result
913  *
914  * @return the name of the result
915  */
916  std::string name() const
917  {
918  return _name;
919  }
920 
921  /** set the name of the result
922  *
923  * @param name the name that the result should have
924  */
925  void name(const std::string & name)
926  {
927  _name = name;
928  }
929 
930  /** retrieve the id of the result
931  *
932  * @return the id
933  */
934  uint64_t id()const
935  {
936  return _id;
937  }
938 
939  /** set the id of the result
940  *
941  * @param id the id that the result should have
942  */
943  void id(uint64_t id)
944  {
945  _id = id;
946  }
947 
948 public:
949  /** lock for locking operations on the data of the container
950  *
951  * @note this needs to be mutable since we need to lock the data when
952  * serializing it and serializing is const by definition.
953  */
955 
956 protected:
957  /** copy constructor
958  *
959  * @note We need to implement this ourselves, since it is not possitble to copy
960  * construct the lock
961  *
962  * @param in the result to copy the values from
963  */
964  Result(const Result& in)
965  : Serializable(in),
966  _axis(in._axis),
967  _storage(in._storage),
968  _name(in._name),
969  _id(in._id)
970  {}
971 
972  /** prevent self assigment */
973  self_type& operator=(const self_type&) {}
974 
975 protected:
976  /** the axis of the histogram */
977  axis_t _axis;
978 
979  /** result storage */
980  storage_t _storage;
981 
982  /** the name of this result */
983  std::string _name;
984 
985  /** the id of the event that the contents reflect */
986  uint64_t _id;
987 };
988 }// end namespace cass
989 #endif
std::vector< axe_t > axis_t
the axis descriptions of this container
Definition: result.hpp:356
storage_t::const_iterator const_iterator
a const iterator on the storage
Definition: result.hpp:338
size_t dim() const
what is the dimension of the result
Definition: result.hpp:503
void clear()
clear the contents of the result
Definition: result.hpp:530
axis_name
which axis one wants to have
Definition: result.hpp:359
iterator histogram(const coordinate_t &pos, const value_t &weight=1)
add the weight at the right bin for the coordinate in the 2d array
Definition: result.hpp:689
reference front()
retrieve reference to the first element
Definition: result.hpp:620
void appendRows(const storage_t &rows)
add row(s) to the result
Definition: result.hpp:724
value_t getValue() const
return the value
Definition: result.hpp:558
Result(const axe_t &xaxis)
1d histogram constructor
Definition: result.hpp:401
storage_t _storage
result storage
Definition: result.hpp:980
const_iterator end() const
retrieve iterator to the end of storage
Definition: result.hpp:632
storage_t::reference reference
a reference to the storage
Definition: result.hpp:341
Axis()
default Constructor
Definition: result.hpp:219
std::string _name
the name of this result
Definition: result.hpp:983
void reset()
clear the appendable 1d like result
Definition: result.hpp:771
void name(const std::string &name)
set the name of the result
Definition: result.hpp:925
const_reference operator[](size_type pos) const
enable accessing elements of the storage directly
Definition: result.hpp:798
std::vector< value_t > storage_t
the storage of this container
Definition: result.hpp:332
int bin(const value_t &val) const
return the bin that a value will fall in
Definition: result.hpp:259
value_t pos(const int bin) const
calculate the position for a given bin
Definition: result.hpp:247
size_t bin(const Axis< AxisPrecessionType > &xAxis, const Axis< AxisPrecessionType > &yAxis, const coordinate_t &coordinate)
calculate the corresponding index in the linearized array of a coordinate
Definition: result.hpp:167
T value_t
the values of this container
Definition: result.hpp:326
std::tr1::shared_ptr< self_type > shared_pointer
a shared pointer of this class
Definition: result.hpp:323
std::pair< size_type, size_type > shape_t
define the shape of the result
Definition: result.hpp:350
void assign(const self_type &in)
copy the contents of a different result to this result
Definition: result.hpp:906
size_type size() const
return the raw size of the storage
Definition: result.hpp:881
std::string name() const
retrieve the name of the result
Definition: result.hpp:916
an axis of a more than 0 dimensional container
Definition: result.hpp:29
std::string title
the title of the axis
Definition: result.hpp:296
void resetTable()
reset the table like result
Definition: result.hpp:740
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
size_t nBins
the number of bins in this axis
Definition: result.hpp:287
Axis< double > axe_t
the axis descriptions of this container
Definition: result.hpp:353
uint64_t id() const
retrieve the id of the result
Definition: result.hpp:934
storage_t::size_type size_type
define the size type of the storage
Definition: result.hpp:347
axis_t & axis()
write access to the axis
Definition: result.hpp:458
void setValue(const_reference value)
assign the result container to a value
Definition: result.hpp:543
const_iterator begin() const
retrieve a iterator for read access to beginning
Definition: result.hpp:608
bool isUnderflow(int bin) const
check if a bin is an underflow
Definition: result.hpp:271
storage_t::const_reference const_reference
a const reference to the storage
Definition: result.hpp:344
Result()
default constructor
Definition: result.hpp:374
bool isTrue() const
evaluate whether value is zero
Definition: result.hpp:577
Result(const axe_t &xaxis, const axe_t &yaxis)
2d histogram constructor
Definition: result.hpp:437
shared_pointer clone() const
create a copy of the result
Definition: result.hpp:890
const_reference front() const
retrieve const reference to the first element
Definition: result.hpp:626
self_type & operator=(const self_type &)
prevent self assigment
Definition: result.hpp:973
const axis_t & axis() const
read access to the axis
Definition: result.hpp:449
Result(const size_type &size)
1d array container constructor
Definition: result.hpp:386
file contains base class all serializable classes
A result of a processor.
Definition: result.hpp:30
storage_t & storage()
write access to the storage
Definition: result.hpp:599
iterator end()
retrieve iterator to the end of storage
Definition: result.hpp:638
QReadWriteLock lock
lock for locking operations on the data of the container
Definition: result.hpp:954
Result(const size_type &cols, const size_type &rows)
2d array container or table constructor
Definition: result.hpp:420
axis_t _axis
the axis of the histogram
Definition: result.hpp:977
void append(const value_t &val)
append a value to the end of the result
Definition: result.hpp:756
void id(uint64_t id)
set the id of the result
Definition: result.hpp:943
bool isOverflow(int bin) const
check if a bin is an overflow
Definition: result.hpp:281
SerializerBackend & operator<<(SerializerBackend &serializer, const Axis< T > &axis)
add an Axis to a stream
Definition: result.hpp:42
storage_t::iterator iterator
a iterator on the storage
Definition: result.hpp:335
value_t low
lower end of the axis
Definition: result.hpp:290
SerializerBackend & operator>>(SerializerBackend &serializer, Axis< T > &axis)
read an Axis from a stream
Definition: result.hpp:61
iterator begin()
retrieve iterator for write access to beginning
Definition: result.hpp:614
value_t up
upper end of the axis
Definition: result.hpp:293
std::vector< size_t > np_shape() const
return the shape of the result as numpy / hdf5 shape
Definition: result.hpp:842
uint64_t _id
the id of the event that the contents reflect
Definition: result.hpp:986
const axe_t & axis(const axis_name &axis) const
read access to a specific axis
Definition: result.hpp:470
iterator histogram(const value_t &pos, const value_t &weight=1)
add the weight at the right bin for the value in the 1d array
Definition: result.hpp:651
Axis(size_t nbrBins, value_t lowerLimit, value_t upperLimit, std::string title="Axis Title")
Constructor.
Definition: result.hpp:235
Type retrieve()
read arbitrary value from stream
Definition: serializer.hpp:169
OverUnderFlow
the over/underflow bin of 1d histogram
Definition: result.hpp:367
const storage_t & storage() const
read access to the storage
Definition: result.hpp:590
shape_t shape() const
return the shape of the result
Definition: result.hpp:811
Quadrant
over/ underflow of 2d histogram
Definition: result.hpp:362
Result(const Result &in)
copy constructor
Definition: result.hpp:964
check if there is some light in the chamber based upon the GMD value
Serializable.
size_type datasize() const
return the size of the data as determined by the axis
Definition: result.hpp:872
void add(const Type &value)
add arbitrary value to the stream
Definition: serializer.hpp:158
std::pair< double, double > coordinate_t
a coordinate of a 2d array
Definition: result.hpp:329
reference operator[](size_type pos)
enable accessing elements of the storage directly
Definition: result.hpp:787
axe_t & axis(const axis_name &axis)
write accesss to a specific axis
Definition: result.hpp:486
Result< T > self_type
this classes type
Definition: result.hpp:320
T value_t
the presision type of the axis boundaries
Definition: result.hpp:216