cartodata 6.0.0
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
44#include <cartobase/type/datatypetraits.h>
45#include <cartobase/exception/assert.h>
46#include <cartobase/containers/nditerator.h>
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
56namespace
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
70namespace 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 ),
288 for( ; x<nx2; ++x )
289 res->at( x, y, z, t ) = f( 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>
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<long> 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
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
std::vector< long > getStrides() const
const PropertySet & header() 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.
static void selfApply(UnaryFunction f, VolumeRef< T > &o)
applies a binary function to each voxel of a pair of volumes
static VolumeRef< T > apply(UnaryFunction f, const VolumeRef< T > &o)
applies a unary function to each voxel of a volume
N-D Volume main class.
Definition volumebase.h:120
std::vector< int > getBorders() const
Get borders for the volume.
std::vector< long > getStrides() const
Get strides for the volume.
const T & at(long x, long y=0, long z=0, long t=0) const
std::ptrdiff_t line_length() const
void inc_line_ptr(const T *&p) const
std::ptrdiff_t line_length() const
void inc_line_ptr(T *&p) const
uint8_t _neutral< uint8_t >()
int8_t _neutral< int8_t >()
double _neutral< double >()
uint16_t _neutral< uint16_t >()
int16_t _neutral< int16_t >()
int32_t _neutral< int32_t >()
float _neutral< float >()
uint32_t _neutral< uint32_t >()
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:994
VolumeRef< T > matrix_product(const Volume< T > &v1, const Volume< T > &v2)
matrix product
VolumeRef< T > transpose(const Volume< T > &v)
transpose
T min_limit()
static _Tp max()