cartodata  5.1.2
volumeutil_d.h
Go to the documentation of this file.
1 /* This software and supporting documentation are distributed by
2  * Institut Federatif de Recherche 49
3  * CEA/NeuroSpin, Batiment 145,
4  * 91191 Gif-sur-Yvette cedex
5  * France
6  *
7  * This software is governed by the CeCILL-B license under
8  * French law and abiding by the rules of distribution of free software.
9  * You can use, modify and/or redistribute the software under the
10  * terms of the CeCILL-B license as circulated by CEA, CNRS
11  * and INRIA at the following URL "http://www.cecill.info".
12  *
13  * As a counterpart to the access to the source code and rights to copy,
14  * modify and redistribute granted by the license, users are provided only
15  * with a limited warranty and the software's author, the holder of the
16  * economic rights, and the successive licensors have only limited
17  * liability.
18  *
19  * In this respect, the user's attention is drawn to the risks associated
20  * with loading, using, modifying and/or developing or reproducing the
21  * software by the user in light of its specific status of free software,
22  * that may mean that it is complicated to manipulate, and that also
23  * therefore means that it is reserved for developers and experienced
24  * professionals having in-depth computer knowledge. Users are therefore
25  * encouraged to load and test the software's suitability as regards their
26  * requirements in conditions enabling the security of their systems and/or
27  * data to be ensured and, more generally, to use and operate it in the
28  * same conditions as regards security.
29  *
30  * The fact that you are presently reading this means that you have had
31  * knowledge of the CeCILL-B license and that you accept its terms.
32  */
33 
34 #ifndef CARTODATA_VOLUME_VOLUMEUTIL_D_H
35 #define CARTODATA_VOLUME_VOLUMEUTIL_D_H
36 
47 #include <cartobase/type/converter.h> // carto::min_limit<T>()
48 #include <limits>
49 
50 /* bug in gcc 4.2, accumulate doesn't accept std::max<T> or std::min<T> as
51  argument, but accepts a function without a namespace */
52 /* in C++11 (g++ --std=c++11) std::min and std::max<T> cannot be passed to a
53  function also - because there are other variants, like
54  max( std::initializer_list<T> ilist ). */
55 
56 namespace
57 {
58  template <typename T>
59  inline
60  T internal_max( const T x, const T y )
61  { return std::max<T>( x, y ); }
62 
63  template <typename T>
64  inline
65  T internal_min( const T x, const T y )
66  { return std::min<T>( x, y ); }
67 }
68 
69 
70 namespace carto
71 {
72 
73  template <typename T> template <class UnaryFunction>
74  VolumeRef<T> VolumeUtil<T>::apply( UnaryFunction f, const VolumeRef<T> & o )
75  {
76  VolumeRef<T> res( new Volume<T>( o->getSize() ) );
77  res->header() = o->header();
78 
79  const_line_NDIterator<T> it( &o->at( 0 ), o->getSize(), o->getStrides() );
80  line_NDIterator<T> rit( &res->at( 0 ), res->getSize(), res->getStrides() );
81  const T *op, *pp;
82  T *rp;
83 
84  for( ; !it.ended(); ++it, ++rit )
85  {
86  op = &*it;
87  rp = &*rit;
88  for( pp=op + it.line_length(); op!=pp;
89  it.inc_line_ptr( op ), rit.inc_line_ptr( rp ) )
90  *rp = f( *op );
91  }
92 
93  return res;
94  }
95 
96 
97  namespace internal
98  {
99 
100  template <typename T> inline T _neutral()
101  {
102  return T();
103  }
104 
105  template<> inline int8_t _neutral<int8_t>()
106  {
107  return 0;
108  }
109 
110  template<> inline uint8_t _neutral<uint8_t>()
111  {
112  return 0;
113  }
114 
115  template<> inline int16_t _neutral<int16_t>()
116  {
117  return 0;
118  }
119 
120  template<> inline uint16_t _neutral<uint16_t>()
121  {
122  return 0;
123  }
124 
125  template<> inline int32_t _neutral<int32_t>()
126  {
127  return 0;
128  }
129 
130  template<> inline uint32_t _neutral<uint32_t>()
131  {
132  return 0;
133  }
134 
135  template<> inline float _neutral<float>()
136  {
137  return 0;
138  }
139 
140  template<> inline double _neutral<double>()
141  {
142  return 0;
143  }
144 
145  }
146 
147 #if 0
148  template <typename T> template <class BinaryFunction>
149  VolumeRef<T> VolumeUtil<T>::apply( BinaryFunction f,
150  const VolumeRef<T> & o1,
151  const VolumeRef<T> & o2 )
152  {
153  std::cout << "VolumeUtil::apply(BinaryFunction)\n";
154  std::vector<int> ns = o1->getSize(), s1 = ns, s2 = o2->getSize();
155  while( ns.size() < s2.size() )
156  ns.push_back( s2[ ns.size() ] );
157 
158  for( int i=0; i<s2.size(); ++i )
159  {
160  if( ns[i] < s2[i] )
161  ns[i] = s2[i];
162  std::cout << "size " << i << ": " << ns[i] << std::endl;
163  }
164 
165 
166 
167  int x, nx = o1->getSizeX(), y, ny = o1->getSizeY(),
168  z, nz = o1->getSizeZ(), t, nt = o1->getSizeT(), nx2, ny2, nz2, nt2, nx3;
169  if( o2->getSizeX() < nx )
170  {
171  nx2 = nx;
172  nx = o2->getSizeX();
173  }
174  else
175  nx2 = o2->getSizeX();
176  if( o2->getSizeY() < ny )
177  {
178  ny2 = ny;
179  ny = o2->getSizeY();
180  }
181  else
182  ny2 = o2->getSizeY();
183  if( o2->getSizeZ() < nz )
184  {
185  nz2 = nz;
186  nz = o2->getSizeZ();
187  }
188  else
189  nz2 = o2->getSizeZ();
190  if( o2->getSizeT() < nt )
191  {
192  nt2 = nt;
193  nt = o2->getSizeT();
194  }
195  else
196  nt2 = o2->getSizeT();
197 
198  VolumeRef<T> res( new Volume<T>( ns ) );
199  res->copyHeaderFrom( o1->header() );
200 
201  bool x1, y1, z1, x2, y2, z2;
202  T *o1p, *o2p, *rp;
203  for( t=0; t<nt2; ++t )
204  {
205  if( t >= nt )
206  if( nt == o1->getSizeT() )
207  {
208  z1 = false;
209  z2 = true;
210  }
211  else
212  {
213  z1 = true;
214  z2 = false;
215  }
216  else
217  {
218  z1 = true;
219  z2 = true;
220  }
221 
222  for( z=0; z<nz2; ++z )
223  {
224  y1 = z1;
225  y2 = z2;
226  if( z >= nz )
227  {
228  if( nz == o1->getSizeZ() )
229  y1 = false;
230  else
231  y2 = false;
232  }
233 
234  for( y=0; y<ny2; ++y )
235  {
236  x1 = y1;
237  x2 = y2;
238  if( y >= ny )
239  {
240  if( ny == o1->getSizeY() )
241  x1 = false;
242  else
243  x2 = false;
244  }
245  if( x1 )
246  o1p = &o1->at( 0, y, z, t );
247  else
248  o1p = 0;
249  if( x2 )
250  o2p = &o2->at( 0, y, z, t );
251  else
252  o2p = 0;
253  rp = &res->at( 0, y, z, t );
254 
255  /*
256  std::cout << "pos: " << t << ", " << z << ", " << y
257  << ", x1: " << x1 << ", " << y1 << ", " << z1
258  << ", x2: " << x2 << ", " << y2 << ", " << z2
259  << std::endl;
260  */
261 
262  x = 0;
263  if( x1 && x2 )
264  {
265  for( ; x<nx; ++x )
266  res->at( x, y, z, t ) = f( o1->at( x, y, z, t ),
267  o2->at( x, y, z, t ) );
268  nx3 = nx2;
269  if( nx == o1->getSizeX() )
270  x1 = false;
271  else
272  x2 = false;
273  }
274  else if( x1 )
275  nx3 = o1->getSizeX();
276  else if( x2 )
277  nx3 = o2->getSizeX();
278  else
279  nx3 = 0;
280  if( !x1 && x2 )
281  for( ; x<nx3; ++x )
282  res->at( x, y, z, t ) = f( internal::_neutral<T>(),
283  o2->at( x, y, z, t ) );
284  else if( x1 && !x2 )
285  for( ; x<nx3; ++x )
286  res->at( x, y, z, t ) = f( o1->at( x, y, z, t ),
287  internal::_neutral<T>() );
288  for( ; x<nx2; ++x )
289  res->at( x, y, z, t ) = f( internal::_neutral<T>(),
290  internal::_neutral<T>() );
291  }
292  }
293  }
294  return res;
295  }
296 #endif
297 
298  template <typename T> template <class UnaryFunction>
299  void VolumeUtil<T>::selfApply( UnaryFunction f, VolumeRef<T> & o )
300  {
301  line_NDIterator<T> it( &o->at( 0 ), o->getSize(), o->getStrides(), true );
302  T *op, *pp;
303 
304  for( ; !it.ended(); ++it )
305  {
306  op = &*it;
307  for( pp=op + it.line_length(); op!=pp; it.inc_line_ptr( op ) )
308  *op = f( *op );
309  }
310  }
311 
312 
313  template <typename T> template <class BinaryFunction>
314  void VolumeUtil<T>::selfApply( BinaryFunction f, VolumeRef<T> & o1,
315  const VolumeRef<T> & o2 )
316  {
317  int x, nx = o1->getSizeX(), y, ny = o1->getSizeY(),
318  z, nz = o1->getSizeZ(), t, nt = o1->getSizeT();
319 
320  if( o2->getSizeX() < nx )
321  nx = o2->getSizeX();
322  if( o2->getSizeY() < ny )
323  ny = o2->getSizeY();
324  if( o2->getSizeZ() < nz )
325  nz = o2->getSizeZ();
326  if( o2->getSizeT() < nt )
327  nt = o2->getSizeT();
328 
329  line_NDIterator<T> o1it( &o1->at( 0 ), o1->getSize(), o1->getStrides() );
330  const_line_NDIterator<T> o2it( &o2->at( 0 ), o2->getSize(),
331  o2->getStrides() );
332  T *o1p, *pp;
333  const T *o2p;
334 
335  for( ; !o1it.ended(); ++o1it, ++o2it )
336  {
337  o1p = &*o1it;
338  o2p = &*o2it;
339  for( pp=o1p + o1it.line_length(); o1p!=pp;
340  o1it.inc_line_ptr( o1p ), o2it.inc_line_ptr( o2p ) )
341  *o1p = f( *o1p, *o2p );
342  }
343  }
344 
345 
346  template <typename T> template <class BinaryFunction>
347  T VolumeUtil<T>::accumulate( BinaryFunction f,
348  const Volume<T> & o, T initial )
349  {
350  T res = initial;
351 
352  const_line_NDIterator<T> it( &o.at( 0 ), o.getSize(), o.getStrides(),
353  true );
354  const T *op, *pp;
355 
356  for( ; !it.ended(); ++it )
357  {
358  op = &*it;
359  for( pp=op + it.line_length(); op!=pp; it.inc_line_ptr( op ) )
360  res = f( *op, res );
361  }
362 
363  return res;
364  }
365 
366 
367  template <typename T>
369  {
371  internal_min<T>, o, std::numeric_limits<T>::max() );
372  }
373 
374  template <typename T>
376  {
378  internal_max<T>, o, min_limit<T>() );
379  }
380 
381 
382  // matrix product
383  template <typename T>
384  VolumeRef<T> matrix_product( const Volume<T> & v1, const Volume<T> & v2 )
385  {
386  std::vector<int> size1 = v1.getSize();
387  std::vector<int> size2 = v2.getSize();
388  if( size1[1] != size2[0] )
389  throw std::runtime_error( "matrix dimensions do not match" );
390 
391  VolumeRef<T> prod( size1[0], size2[1], 1, 1,
392  std::max( v1.getBorders()[0], v2.getBorders()[0] ) );
393  for( long y = 0; y < size2[1]; y++ )
394  for( long x = 0; x < size1[0]; x++ )
395  {
396  prod->at( x, y ) = T( 0 );
397  for( long k = 0; k < size1[1]; k++ )
398  prod->at( x, y ) += v1.at( x, k ) * v2.at( k, y );
399  }
400 
401  return prod;
402  }
403 
404 
405  // matrix product
406  template <typename T>
408  const rc_ptr<Volume<T> > & v2 )
409  {
410  return matrix_product( *v1, *v2 );
411  }
412 
413 
414  // transpose
415  template <typename T>
417  {
418  std::vector<int> size1 = v.getSize();
419  int s0 = size1[0];
420  size1[0] = size1[1];
421  size1[1] = s0;
422 
423  VolumeRef<T> trans( size1,
424  std::max( v.getBorders()[1], v.getBorders()[0] ) );
425 
426  const_line_NDIterator<T> it( &v.at( 0 ), v.getSize(), v.getStrides() );
427  const T *op, *pp;
428  T *rp;
429  long inc = &trans->at(0, 1) - &trans->at(0);
430 
431  for( ; !it.ended(); ++it )
432  {
433  op = &*it;
434  std::vector<int> pos = it.position();
435  int p0 = pos[0];
436  pos[0] = pos[1];
437  pos[1] = p0;
438  rp = &trans->at( pos );
439 
440  for( pp=op + it.line_length(); op!=pp;
441  it.inc_line_ptr( op ), rp += inc )
442  *rp = *op;
443  }
444 
445  return trans;
446  }
447 
448 
449  // transpose
450  template <typename T>
452  {
453  if( copy )
454  return transpose( *v );
455  else
456  {
457  std::vector<int> size1 = v->getSize();
458  int s0 = size1[0];
459  size1[0] = size1[1];
460  size1[1] = s0;
461 
462  std::vector<size_t> strides = v->getStrides();
463  size_t st0 = strides[0];
464  strides[0] = strides[1];
465  strides[1] = st0;
466 
467  VolumeRef<T> trans( new Volume<T>( v,
468  std::vector<int>( size1.size(), 0 ),
469  size1, &v->at(0),
470  strides ) );
471  return trans;
472  }
473  }
474 
475 
476 #if 0
477  // VolumeUtil declarations (needed on Mac)
478  extern template VolumeRef<VoxelRGB>
479  VolumeUtil<VoxelRGB>::apply( Scaler<VoxelRGB, double>,
480  const VolumeRef<VoxelRGB> & );
481  extern template void
482  VolumeUtil<VoxelRGB>::selfApply( Scaler<VoxelRGB, double>,
483  VolumeRef<VoxelRGB> & );
484  extern template VolumeRef<VoxelRGB>
485  VolumeUtil<VoxelRGB>::apply( std::plus<VoxelRGB>, const VolumeRef<VoxelRGB> &,
486  const VolumeRef<VoxelRGB> & );
487  extern template void
488  VolumeUtil<VoxelRGB>::selfApply( std::plus<VoxelRGB>, VolumeRef<VoxelRGB> &,
489  const VolumeRef<VoxelRGB> & );
490  extern template VolumeRef<VoxelRGB>
491  VolumeUtil<VoxelRGB>::apply( UnaryFromConstantBinaryFunctor<VoxelRGB,
492  std::plus<VoxelRGB> >,
493  const VolumeRef<VoxelRGB> & );
494  extern template void
495  VolumeUtil<VoxelRGB>::selfApply( UnaryFromConstantBinaryFunctor<VoxelRGB,
496  std::plus<VoxelRGB> >, VolumeRef<VoxelRGB> & );
497  extern template VolumeRef<VoxelRGB>
498  VolumeUtil<VoxelRGB>::apply( UnaryFromConstantBinaryFunctor2<VoxelRGB,
499  std::plus<VoxelRGB> >,
500  const VolumeRef<VoxelRGB> & );
501  extern template VolumeRef<VoxelRGB>
502  VolumeUtil<VoxelRGB>::apply( std::minus<VoxelRGB>, const VolumeRef<VoxelRGB> &,
503  const VolumeRef<VoxelRGB> & );
504  extern template void
505  VolumeUtil<VoxelRGB>::selfApply( std::minus<VoxelRGB>, VolumeRef<VoxelRGB> &,
506  const VolumeRef<VoxelRGB> & );
507  extern template VolumeRef<VoxelRGB>
508  VolumeUtil<VoxelRGB>::apply( UnaryFromConstantBinaryFunctor<VoxelRGB,
509  std::minus<VoxelRGB> >,
510  const VolumeRef<VoxelRGB> & );
511  extern template void
512  VolumeUtil<VoxelRGB>::selfApply( UnaryFromConstantBinaryFunctor<VoxelRGB,
513  std::minus<VoxelRGB> >,
514  VolumeRef<VoxelRGB> & );
515  extern template VolumeRef<VoxelRGB>
516  VolumeUtil<VoxelRGB>::apply( UnaryFromConstantBinaryFunctor2<VoxelRGB,
517  std::minus<VoxelRGB> >,
518  const VolumeRef<VoxelRGB> & );
519 
520  extern template VolumeRef<VoxelRGBA>
521  VolumeUtil<VoxelRGBA>::apply( Scaler<VoxelRGBA, double>,
522  const VolumeRef<VoxelRGBA> & );
523  extern template void
524  VolumeUtil<VoxelRGBA>::selfApply( Scaler<VoxelRGBA, double>,
525  VolumeRef<VoxelRGBA> & );
526  extern template VolumeRef<VoxelRGBA>
527  VolumeUtil<VoxelRGBA>::apply( std::plus<VoxelRGBA>,
528  const VolumeRef<VoxelRGBA> &,
529  const VolumeRef<VoxelRGBA> & );
530  extern template void
531  VolumeUtil<VoxelRGBA>::selfApply( std::plus<VoxelRGBA>, VolumeRef<VoxelRGBA> &,
532  const VolumeRef<VoxelRGBA> & );
533  extern template VolumeRef<VoxelRGBA>
534  VolumeUtil<VoxelRGBA>::apply( UnaryFromConstantBinaryFunctor<VoxelRGBA,
535  std::plus<VoxelRGBA> >,
536  const VolumeRef<VoxelRGBA> & );
537  extern template void
538  VolumeUtil<VoxelRGBA>::selfApply( UnaryFromConstantBinaryFunctor<VoxelRGBA,
539  std::plus<VoxelRGBA> >,
540  VolumeRef<VoxelRGBA> & );
541  extern template VolumeRef<VoxelRGBA>
542  VolumeUtil<VoxelRGBA>::apply( UnaryFromConstantBinaryFunctor2<VoxelRGBA,
543  std::plus<VoxelRGBA> >,
544  const VolumeRef<VoxelRGBA> & );
545  extern template VolumeRef<VoxelRGBA>
546  VolumeUtil<VoxelRGBA>::apply( std::minus<VoxelRGBA>,
547  const VolumeRef<VoxelRGBA> &,
548  const VolumeRef<VoxelRGBA> & );
549  extern template void
550  VolumeUtil<VoxelRGBA>::selfApply( std::minus<VoxelRGBA>,
551  VolumeRef<VoxelRGBA> &,
552  const VolumeRef<VoxelRGBA> & );
553  extern template VolumeRef<VoxelRGBA>
554  VolumeUtil<VoxelRGBA>::apply( UnaryFromConstantBinaryFunctor<VoxelRGBA,
555  std::minus<VoxelRGBA> >,
556  const VolumeRef<VoxelRGBA> & );
557  extern template void
558  VolumeUtil<VoxelRGBA>::selfApply( UnaryFromConstantBinaryFunctor<VoxelRGBA,
559  std::minus<VoxelRGBA> >,
560  VolumeRef<VoxelRGBA> & );
561  extern template VolumeRef<VoxelRGBA>
562  VolumeUtil<VoxelRGBA>::apply( UnaryFromConstantBinaryFunctor2<VoxelRGBA,
563  std::minus<VoxelRGBA> >,
564  const VolumeRef<VoxelRGBA> & );
565 #endif
566 
567 }
568 
569 #endif
570 
const std::vector< int > & position() const
std::vector< int > getSize() const
get the 4 dimensions in a vector
Definition: volumeproxy.h:129
Convenient handle for a Volume - this is normally the entry point for all volumes handling.
Definition: volumeref.h:60
std::vector< int > getSize() const
const T & at(long x, long y=0, long z=0, long t=0) const
const PropertySet & header() const
std::vector< size_t > getStrides() const
static T accumulate(BinaryFunction f, const VolumeRef< T > &o2, T initial)
Apply a binary function to each voxel of the volume, with a "current" value as second argument.
Definition: volumeutil.h:1684
static void selfApply(UnaryFunction f, VolumeRef< T > &o)
applies a binary function to each voxel of a pair of volumes
Definition: volumeutil_d.h:299
static VolumeRef< T > apply(UnaryFunction f, const VolumeRef< T > &o)
applies a unary function to each voxel of a volume
Definition: volumeutil_d.h:74
N-D Volume main class.
Definition: volumebase.h:119
std::vector< size_t > getStrides() const
Get strides for the volume.
Definition: volumebase_d.h:726
std::vector< int > getBorders() const
Get borders for the volume.
Definition: volumebase_d.h:707
const T & at(long x, long y=0, long z=0, long t=0) const
void inc_line_ptr(const T *&p) const
long line_length() const
void inc_line_ptr(T *&p) const
uint8_t _neutral< uint8_t >()
Definition: volumeutil_d.h:110
int8_t _neutral< int8_t >()
Definition: volumeutil_d.h:105
double _neutral< double >()
Definition: volumeutil_d.h:140
uint16_t _neutral< uint16_t >()
Definition: volumeutil_d.h:120
int16_t _neutral< int16_t >()
Definition: volumeutil_d.h:115
int32_t _neutral< int32_t >()
Definition: volumeutil_d.h:125
float _neutral< float >()
Definition: volumeutil_d.h:135
uint32_t _neutral< uint32_t >()
Definition: volumeutil_d.h:130
Volume< T > copy(const Volume< T > &src)
Performs a copy of the data (not only a reference copy) Only the data inside the view is copied.
Definition: volumeutil.h:993
T min(const Volume< T > &vol)
Returns the minimum value of the volume.
Definition: volumeutil.h:1133
T max(const Volume< T > &vol)
Returns the maximum value of the volume.
Definition: volumeutil.h:1153
VolumeRef< T > matrix_product(const Volume< T > &v1, const Volume< T > &v2)
matrix product
Definition: volumeutil_d.h:384
VolumeRef< T > transpose(const Volume< T > &v)
transpose
Definition: volumeutil_d.h:416