aimsdata  4.7.0
Neuroimaging data handling
cartodatavolume.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 AIMS_DATA_CARTODATAVOLUME_H
35 #define AIMS_DATA_CARTODATAVOLUME_H
36 
39 #include <aims/vector/vector.h>
40 #include <aims/border/border.h>
41 #include <aims/rgb/rgb.h>
42 #include <cartobase/smart/rcptr.h>
44 #include <aims/data/pheader.h>
45 
46 #include <algorithm>
47 
48 
49 template<typename T>
50 class AimsData : public carto::RCObject, public aims::Border
51 {
52  public:
53  typedef T value_type;
55  typedef T* pointer;
57  typedef T**** pointer4d;
59  typedef T* iterator;
61  typedef const T* const_iterator;
63  typedef T& reference;
65  typedef const T& const_reference;
67  typedef size_t size_type;
69  typedef ptrdiff_t difference_type;
70 
71  iterator begin();
72  const_iterator begin() const;
73  iterator end();
74  const_iterator end() const;
75  bool empty() const;
76 
77  AimsData( int dimx = 1, int dimy = 1, int dimz = 1, int dimt = 1,
78  int borderw = 0 );
79  AimsData( int dimx, int dimy, int dimz, int dimt,
80  int borderw, const carto::AllocatorContext & al );
81  AimsData( const AimsData<T>& other );
82  AimsData( const AimsData<T>& other, int borderw );
83  virtual ~AimsData();
84 
85  // conversions with carto::Volume
88 
89  AimsData<T> & operator = ( const AimsData<T> & );
90  AimsData<T> & operator = ( const T & );
91 
95  operator carto::rc_ptr<carto::Volume<T> >();
96  operator const carto::rc_ptr<carto::Volume<T> >() const;
97 
98  const carto::AllocatorContext & allocator() const;
99  int dimX() const;
100  int dimY() const;
101  int dimZ() const;
102  int dimT() const;
103  float sizeX() const;
104  float sizeY() const;
105  float sizeZ() const;
106  float sizeT() const;
107  void setSizeX( float sizex );
108  void setSizeY( float sizey );
109  void setSizeZ( float sizez );
110  void setSizeT( float sizet );
111  void setSizeXYZT( float sizex = 1.0f, float sizey = 1.0f,
112  float sizez = 1.0f, float sizet = 1.0f );
113  void setSizeXYZT( const AimsData<T>& other );
114  const aims::Header* header() const;
115  aims::Header* header();
116  void setHeader( aims::Header* hdr );
117  reference operator [] ( size_type n );
118  const_reference operator [] ( size_type n ) const;
119  reference operator () ( size_type x = 0, size_type y = 0,
120  size_type z = 0, size_type t = 0 );
121  const_reference operator () ( size_type x = 0, size_type y = 0,
122  size_type z = 0, size_type t = 0 ) const;
123  reference operator () ( const Point4d& pt );
124  const_reference operator () ( const Point4d& pt ) const;
125  reference operator () ( const Point4dl& pt );
126  const_reference operator () ( const Point4dl& pt ) const;
127  reference operator () ( const Point3d& pt );
128  const_reference operator () ( const Point3d& pt ) const;
129  reference operator () ( const Point3dl& pt );
130  const_reference operator () ( const Point3dl& pt ) const;
131  reference operator () ( const Point2d& pt );
132  const_reference operator () ( const Point2d& pt ) const;
133  reference operator () ( const Point2dl& pt );
134  const_reference operator () ( const Point2dl& pt ) const;
135 
136  T minimum() const;
137  T maximum() const;
138  T minIndex( int* x, int* y, int* z, int* t ) const;
139  T maxIndex( int* x, int* y, int* z, int* t ) const;
140  void fillBorder( const T& val );
141  AimsData<T> clone () const;
142  AimsData<T> cross( const AimsData<T>& other );
144 
145  private:
146  struct Private;
147 
149  Private *d;
150 };
151 
152 
153 #ifndef DOXYGEN_HIDE_INTERNAL_CLASSES
154 
155 namespace carto
156 {
157 
158  template<class T> class DataTypeCode<AimsData<T> >
159  {
160  public:
161  static std::string objectType()
162  { return "Volume"; }
163  static std::string dataType()
164  { return DataTypeCode<T>::dataType(); }
165  static std::string name()
166  {
167  return std::string("volume of ") + DataTypeCode< T >::name();
168  }
169  };
170 
171  template <typename T>
173  {
174  return carto::Object::reference( obj.volume()->header() );
175  }
176 
177 }
178 
179 #endif // DOXYGEN_HIDE_INTERNAL_CLASSES
180 
181 // private struct
182 
183 template<typename T>
184 struct AimsData<T>::Private
185 {
186  Private();
187  ~Private();
188 
189  static int borderWidth( carto::rc_ptr<carto::Volume<T> > vol );
190 
192 };
193 
194 
195 // inline methods definition
196 
197 // Private struct methods
198 
199 template<typename T>
200 inline
202  : header( 0 )
203 {
204 }
205 
206 
207 template<typename T>
208 inline
210 {
211  if( header )
212  delete header;
213 }
214 
215 
216 template<typename T>
217 inline
219 {
220  if( !vol->refVolume().isNull() ) // is a view to another volume
221  if (vol->refVolume()->allocatorContext().isAllocated()) {
222  // AimsData is not able to deal with different border sizes, so we get the
223  // minimum border through dimensions
224  const std::vector<int> vborders = vol->getBorders();
225 
226  // Borders are not defined for T dimension so we must only deal with
227  // X, Y and Z dimensions
228  std::vector<int>::const_iterator vbordersend = (vborders.size() > 6
229  ? vborders.begin() + 6
230  : vborders.end());
231  if(vborders.begin() != vbordersend) {
232  std::vector<int>::const_iterator minit = std::min_element(vborders.begin(),
233  vbordersend);
234  return (minit == vbordersend ? 0 : *minit);
235  }
236  }
237  return 0;
238 }
239 
240 
241 // AimsData methods
242 
243 template <typename T>
245 {
246  return volume();
247 }
248 
249 
250 template <typename T>
252 {
253  return volume();
254 }
255 
256 
257 template<typename T>
258 inline
260 {
261  return &*_volume->begin();
262 }
263 
264 
265 template<typename T>
266 inline
268 {
269  return &*_volume->begin();
270 }
271 
272 
273 template<typename T>
274 inline
276 {
277  // &*_volume->end() may return 0 with some versions of blitz++
278  // do does not make a valid pointer for end
279  return &_volume->at( _volume->getSizeX() - 1, _volume->getSizeY() - 1,
280  _volume->getSizeZ() - 1, _volume->getSizeT() - 1 ) + 1;
281 }
282 
283 
284 template<typename T>
285 inline
287 {
288  // &*_volume->end() may return 0 with some versions of blitz++
289  // do does not make a valid pointer for end
290  return &_volume->at( _volume->getSizeX() - 1, _volume->getSizeY() - 1,
291  _volume->getSizeZ() - 1, _volume->getSizeT() - 1 ) + 1;
292 }
293 
294 
295 template<typename T>
296 inline
297 bool AimsData<T>::empty() const
298 {
299  return _volume->begin() == _volume->end();
300 }
301 
302 
303 template<typename T>
304 inline
305 AimsData<T>::AimsData( int dimx, int dimy, int dimz, int dimt, int borderw )
306  : carto::RCObject(), aims::Border( dimx, dimy, dimz, borderw ),
307  _volume( new carto::Volume<T>( dimx + borderw * 2, dimy + borderw * 2,
308  dimz + borderw * 2, dimt ) ),
309  d( new Private )
310 {
311  if( borderw != 0 )
312  _volume.reset( new carto::Volume<T>(
313  _volume,
314  typename carto::Volume<T>::Position4Di( borderw, borderw, borderw, 0 ),
315  typename carto::Volume<T>::Position4Di( dimx, dimy, dimz, dimt ) ) );
316  _oFirstPoint = 0;
317  d->header = new aims::PythonHeader( *_volume );
318 }
319 
320 
321 template < typename T >
322 inline
323 AimsData<T>::AimsData( int dimx, int dimy, int dimz, int dimt,
324  int borderw, const carto::AllocatorContext & al )
325  : carto::RCObject(), aims::Border( dimx, dimy, dimz, borderw ),
326  _volume( new carto::Volume<T>( dimx + borderw * 2, dimy + borderw * 2,
327  dimz + borderw * 2, dimt, al ) ),
328  d( new Private )
329 {
330  if( borderw != 0 )
331  _volume.reset( new carto::Volume<T>(
332  _volume,
333  typename carto::Volume<T>::Position4Di( borderw, borderw, borderw, 0 ),
334  typename carto::Volume<T>::Position4Di( dimx, dimy, dimz, dimt ), al ) );
335  _oFirstPoint = 0;
336  d->header = new aims::PythonHeader( *_volume );
337 }
338 
339 
340 template < typename T >
341 inline
343  : carto::RCObject(), aims::Border( other.dimX(), other.dimY(),
344  other.dimZ(), other.borderWidth() ),
345  _volume( other._volume ),
346  d( new Private )
347 {
348  _oFirstPoint = 0;
349  _oLine = &_volume->at( 0, 1 ) - &_volume->at( 0 );
350  _oPointBetweenLine = &_volume->at( 0, 1 ) - &_volume->at( dimX() );
351  _oSlice = &_volume->at( 0, 0, 1 ) - &_volume->at( 0 );
352  _oLineBetweenSlice = &_volume->at( 0, 0, 1 ) - &_volume->at( 0, dimY() );
353  _oVolume = &_volume->at( 0, 0, 0, 1 ) - &_volume->at( 0 );
354  _oSliceBetweenVolume = &_volume->at( 0, 0, 0, 1 )
355  - &_volume->at( 0, 0, dimZ() );
356  d->header = new aims::PythonHeader( *_volume );
357 }
358 
359 
360 template < typename T >
361 inline
362 AimsData<T>::AimsData( const AimsData<T>& other, int borderw )
363  : carto::RCObject(), aims::Border( other.dimX(), other.dimY(), other.dimZ(),
364  borderw ), _volume( new carto::Volume<T>( other.dimX() + borderw * 2,
365  other.dimY() + borderw * 2, other.dimZ() + borderw * 2, other.dimT() ) ),
366  d( new Private )
367 {
368  _volume->copyHeaderFrom( other.volume()->header() );
369 
370  if( borderw != 0 )
371  _volume.reset( new carto::Volume<T>(
372  _volume,
373  typename carto::Volume<T>::Position4Di( borderw, borderw, borderw, 0 ),
374  typename carto::Volume<T>::Position4Di( other.dimX(), other.dimY(),
375  other.dimZ(), other.dimT() ) ) );
376  _oFirstPoint = 0;
377 
378  long x, xm = dimX(), y, ym = dimY(), z, zm = dimZ(), t, tm = dimT();
379  for ( t = 0; t < tm; t++ )
380  for ( z = 0; z < zm; z++ )
381  for ( y = 0; y < ym; y++ )
382  for ( x = 0; x < xm; x++ )
383  (*this)( x, y, z, t ) = other( x, y, z, t );
384  d->header = new aims::PythonHeader( *_volume );
385 }
386 
387 
388 template < typename T >
389 inline
391 {
392  delete d;
393 }
394 
395 
396 template < typename T >
397 inline
399  : carto::RCObject(),
400  aims::Border( vol->getSizeX(),
401  vol->getSizeY(),
402  vol->getSizeZ(),
403  Private::borderWidth( vol ) ),
404  _volume( vol ),
405  d( new Private )
406 {
407  _oFirstPoint = 0;
408  _oLine = &_volume->at( 0, 1 ) - &_volume->at( 0 );
409  _oPointBetweenLine = &_volume->at( 0, 1 ) - &_volume->at( dimX() );
410  _oSlice = &_volume->at( 0, 0, 1 ) - &_volume->at( 0 );
411  _oLineBetweenSlice = &_volume->at( 0, 0, 1 ) - &_volume->at( 0, dimY() );
412  _oVolume = &_volume->at( 0, 0, 0, 1 ) - &_volume->at( 0 );
413  _oSliceBetweenVolume = &_volume->at( 0, 0, 0, 1 )
414  - &_volume->at( 0, 0, dimZ() );
415  d->header = new aims::PythonHeader( *_volume );
416 }
417 
418 
419 template < typename T >
420 inline
422 {
423  if( _volume.get() == vol.get() )
424  return *this;
425 
426  int border = Private::borderWidth( vol );
427 
428  _setBorder( vol->getSizeX(), vol->getSizeY(),
429  vol->getSizeZ(), border );
430  delete d->header;
431  _volume = vol;
432  _oFirstPoint = 0;
433  d->header = new aims::PythonHeader( *_volume );
434 
435  return *this;
436 }
437 
438 
439 template < typename T >
440 inline
442 {
443  if ( &other == this )
444  return *this;
445 
446  _setBorder( other.dimX(), other.dimY(), other.dimZ(), other.borderWidth() );
447  delete d->header;
448  _volume = other._volume;
449  *d = *other.d;
450  _oFirstPoint = 0;
451  _oLine = &_volume->at( 0, 1 ) - &_volume->at( 0 );
452  _oPointBetweenLine = &_volume->at( 0, 1 ) - &_volume->at( dimX() );
453  _oSlice = &_volume->at( 0, 0, 1 ) - &_volume->at( 0 );
454  _oLineBetweenSlice = &_volume->at( 0, 0, 1 ) - &_volume->at( 0, dimY() );
455  _oVolume = &_volume->at( 0, 0, 0, 1 ) - &_volume->at( 0 );
456  _oSliceBetweenVolume = &_volume->at( 0, 0, 0, 1 )
457  - &_volume->at( 0, 0, dimZ() );
458  d->header = new aims::PythonHeader( *_volume );
459  return *this;
460 }
461 
462 
463 template < typename T >
464 inline
466 {
467  iterator it = begin() + oFirstPoint();
468  long x, xm = dimX(), y, ym = dimY(), z, zm = dimZ(), t, tm = dimT();
469 
470  for ( t = 0; t < tm; t++ )
471  {
472  for ( z = 0; z < zm; z++ )
473  {
474  for ( y = 0; y < ym; y++ )
475  {
476  for ( x = 0; x < xm; x++ )
477  *it++ = val;
478  it += oPointBetweenLine();
479  }
480  it += oLineBetweenSlice();
481  }
482  it += oSliceBetweenVolume();
483  }
484  return *this;
485 }
486 
487 
488 template<typename T>
489 inline
491 {
492  return _volume;
493 }
494 
495 
496 template<typename T>
497 inline
499 {
500  return _volume;
501 }
502 
503 
504 template<typename T>
505 inline
506 int AimsData<T>::dimX() const
507 {
508  return _volume->getSizeX();
509 }
510 
511 
512 template<typename T>
513 inline
514 int AimsData<T>::dimY() const
515 {
516  return _volume->getSizeY();
517 }
518 
519 
520 template<typename T>
521 inline
522 int AimsData<T>::dimZ() const
523 {
524  return _volume->getSizeZ();
525 }
526 
527 
528 template<typename T>
529 inline
530 int AimsData<T>::dimT() const
531 {
532  return _volume->getSizeT();
533 }
534 
535 
536 template < typename T >
537 inline
538 float AimsData<T>::sizeX() const
539 {
540  if( !d->header )
541  return 1;
542  aims::PythonHeader *ph = dynamic_cast<aims::PythonHeader *>( d->header );
543  if( !ph )
544  return 1;
545  try
546  {
547  carto::Object vs = ph->getProperty( "voxel_size" );
548  if( !vs.isNull() && vs->size() >= 1 )
549  return (float) vs->getArrayItem( 0 )->getScalar();
550  }
551  catch( ... )
552  {
553  }
554  return 1;
555 }
556 
557 
558 template < typename T >
559 inline
560 float AimsData<T>::sizeY() const
561 {
562  if( !d->header )
563  return 1;
564  aims::PythonHeader *ph = dynamic_cast<aims::PythonHeader *>( d->header );
565  if( !ph )
566  return 1;
567  try
568  {
569  carto::Object vs = ph->getProperty( "voxel_size" );
570  if( !vs.isNull() && vs->size() >= 2 )
571  return (float) vs->getArrayItem( 1 )->getScalar();
572  }
573  catch( ... )
574  {
575  }
576  return 1;
577 }
578 
579 
580 template < typename T >
581 inline
582 float AimsData<T>::sizeZ() const
583 {
584  if( !d->header )
585  return 1;
586  aims::PythonHeader *ph = dynamic_cast<aims::PythonHeader *>( d->header );
587  if( !ph )
588  return 1;
589  try
590  {
591  carto::Object vs = ph->getProperty( "voxel_size" );
592  if( !vs.isNull() && vs->size() >= 3 )
593  return (float) vs->getArrayItem( 2 )->getScalar();
594  }
595  catch( ... )
596  {
597  }
598  return 1;
599 }
600 
601 
602 template < typename T >
603 inline
604 float AimsData<T>::sizeT() const
605 {
606  if( !d->header )
607  return 1;
608  aims::PythonHeader *ph = dynamic_cast<aims::PythonHeader *>( d->header );
609  if( !ph )
610  return 1;
611  try
612  {
613  carto::Object vs = ph->getProperty( "voxel_size" );
614  if( !vs.isNull() && vs->size() >= 4 )
615  return (float) vs->getArrayItem( 3 )->getScalar();
616  }
617  catch( ... )
618  {
619  }
620  return 1;
621 }
622 
623 
624 template < typename T >
625 inline
626 void AimsData<T>::setSizeX( float sizex )
627 {
628  if( !d->header )
630  aims::PythonHeader *ph = dynamic_cast<aims::PythonHeader *>( d->header );
631  if( ph )
632  {
633  try
634  {
635  carto::Object vs = ph->getProperty( "voxel_size" );
636  if( !vs.isNull() )
637  if( vs->size() >= 1 )
638  vs->setArrayItem( 0, carto::Object::value( sizex ) );
639  }
640  catch( ... )
641  {
642  std::vector<float> vs( 4, 1. );
643  vs[0] = sizex;
644  ph->setProperty( "voxel_size", vs );
645  }
646  }
647 }
648 
649 
650 template < typename T >
651 inline
652 void AimsData<T>::setSizeY( float sizey )
653 {
654  if( !d->header )
656  aims::PythonHeader *ph = dynamic_cast<aims::PythonHeader *>( d->header );
657  if( ph )
658  {
659  std::vector<float> vs( 4, 1. );
660  try
661  {
662  carto::Object vso = ph->getProperty( "voxel_size" );
663  if( !vso.isNull() )
664  {
665  if( vso->size() >= 2 )
666  {
667  vso->setArrayItem( 1, carto::Object::value( sizey ) );
668  return;
669  }
670  else
671  {
672  if( vso->size() >= 1 )
673  vs[0] = vso->getArrayItem(0)->getScalar();
674  }
675  }
676  }
677  catch( ... )
678  {
679  }
680  vs[1] = sizey;
681  ph->setProperty( "voxel_size", vs );
682  }
683 }
684 
685 
686 template < typename T >
687 inline
688 void AimsData<T>::setSizeZ( float sizez )
689 {
690  if( !d->header )
692  aims::PythonHeader *ph = dynamic_cast<aims::PythonHeader *>( d->header );
693  if( ph )
694  {
695  std::vector<float> vs( 4, 1. );
696  try
697  {
698  carto::Object vso = ph->getProperty( "voxel_size" );
699  if( !vso.isNull() )
700  {
701  if( vso->size() >= 3 )
702  {
703  vso->setArrayItem( 2, carto::Object::value( sizez ) );
704  return;
705  }
706  else
707  {
708  carto::Object it;
709  int i;
710  for( i=0, it=vso->objectIterator();
711  it->isValid() && i<3; ++i, it->next() )
712  vs[i] = it->currentValue()->getScalar();
713  }
714  }
715  }
716  catch( ... )
717  {
718  }
719  vs[2] = sizez;
720  ph->setProperty( "voxel_size", vs );
721  }
722 }
723 
724 
725 template < typename T >
726 inline
727 void AimsData<T>::setSizeT( float sizet )
728 {
729  if( !d->header )
731  aims::PythonHeader *ph = dynamic_cast<aims::PythonHeader *>( d->header );
732  if( ph )
733  {
734  std::vector<float> vs( 4, 1. );
735  try
736  {
737  carto::Object vso = ph->getProperty( "voxel_size" );
738  if( !vso.isNull() )
739  {
740  if( vso->size() >= 4 )
741  {
742  vso->setArrayItem( 3, carto::Object::value( sizet ) );
743  return;
744  }
745  else
746  {
747  carto::Object it;
748  int i;
749  for( i=0, it=vso->objectIterator();
750  it->isValid() && i<4; ++i, it->next() )
751  vs[i] = it->currentValue()->getScalar();
752  }
753  }
754  }
755  catch( ... )
756  {
757  }
758  vs[3] = sizet;
759  ph->setProperty( "voxel_size", vs );
760  }
761 }
762 
763 
764 template < typename T >
765 inline
766 void
767 AimsData<T>::setSizeXYZT( float sizex, float sizey, float sizez, float sizet )
768 {
769  if( !d->header )
771  aims::PythonHeader *ph = dynamic_cast<aims::PythonHeader *>( d->header );
772  if( ph )
773  {
774  std::vector<float> vs( 4 );
775  vs[0] = sizex;
776  vs[1] = sizey;
777  vs[2] = sizez;
778  vs[3] = sizet;
779  ph->setProperty( "voxel_size", vs );
780  }
781 }
782 
783 
784 template < typename T >
785 inline
787 {
788  if( !d->header )
790  aims::PythonHeader *ph = dynamic_cast<aims::PythonHeader *>( d->header );
791  if( ph )
792  {
793  std::vector<float> vs( 4 );
794  vs[0] = other.sizeX();
795  vs[1] = other.sizeY();
796  vs[2] = other.sizeZ();
797  vs[3] = other.sizeT();
798  ph->setProperty( "voxel_size", vs );
799  }
800 }
801 
802 
803 template < typename T >
804 inline
805 const carto::AllocatorContext & AimsData<T>::allocator() const
806 {
807  return _volume->allocatorContext();
808 }
809 
810 
811 template < typename T >
812 inline
814 {
815  return d->header;
816 }
817 
818 
819 template < typename T >
820 inline
822 {
823  return d->header;
824 }
825 
826 
827 template<typename T>
828 inline
830 {
831  if( hdr != d->header )
832  {
833  aims::PythonHeader *mh;
834  if( !d->header )
835  {
836  d->header = mh = new aims::PythonHeader( *_volume );
837  }
838  else
839  {
840  mh = static_cast<aims::PythonHeader *>( d->header );
841  carto::Object oldvs;
842  try
843  {
844  // retreive old voxel size (if any)
845  oldvs = mh->getProperty( "voxel_size" );
846  }
847  catch( ... )
848  {
849  }
850  mh->clearProperties();
851  if( !oldvs.isNull() )
852  /* keep old voxel size which was not part of the dynamic header
853  in the old AimsData */
854  mh->setProperty( "voxel_size", oldvs );
855  }
856  const aims::PythonHeader
857  *ph = dynamic_cast<const aims::PythonHeader *>( hdr );
858  if( ph )
859  mh->copy( *ph, 1 );
860  // hdr used to transfor ownership to me
861  delete hdr;
862  }
863 }
864 
865 
866 template < typename T >
867 inline
868 typename AimsData<T>::reference
870 {
871  return *( begin() + n );
872 }
873 
874 
875 template < typename T >
876 inline
879 {
880  return *( begin() + n );
881 }
882 
883 
884 template < typename T >
885 inline
886 typename AimsData<T>::reference
889 {
890  return (*_volume)( x, y, z, t );
891 }
892 
893 
894 template < typename T >
895 inline
899  AimsData<T>::size_type t ) const
900 {
901  return (*_volume)( x, y, z, t );
902 }
903 
904 
905 template < typename T >
906 inline
907 typename AimsData<T>::reference
909 {
910  return (*this)( pt[0], pt[1], pt[2], pt[3] );
911 }
912 
913 
914 template < typename T >
915 inline
918 {
919  return (*this)( pt[0], pt[1], pt[2], pt[3] );
920 }
921 
922 
923 template < typename T >
924 inline
925 typename AimsData<T>::reference
927 {
928  return (*this)( pt[0], pt[1], pt[2], pt[3] );
929 }
930 
931 
932 template < typename T >
933 inline
936 {
937  return (*this)( pt[0], pt[1], pt[2], pt[3] );
938 }
939 
940 
941 template < typename T >
942 inline
943 typename AimsData<T>::reference
945 {
946  return (*this)( pt[0], pt[1], pt[2] );
947 }
948 
949 
950 template < typename T >
951 inline
954 {
955  return (*this)( pt[0], pt[1], pt[2] );
956 }
957 
958 
959 template < typename T >
960 inline
961 typename AimsData<T>::reference
963 {
964  return (*this)( pt[0], pt[1], pt[2] );
965 }
966 
967 
968 template < typename T >
969 inline
972 {
973  return (*this)( pt[0], pt[1], pt[2] );
974 }
975 
976 
977 template < typename T >
978 inline
979 typename AimsData<T>::reference
981 {
982  return (*this)( pt[0], pt[1] );
983 }
984 
985 
986 template < typename T >
987 inline
990 {
991  return (*this)( pt[0], pt[1] );
992 }
993 
994 
995 template < typename T >
996 inline
997 typename AimsData<T>::reference
999 {
1000  return (*this)( pt[0], pt[1] );
1001 }
1002 
1003 
1004 template < typename T >
1005 inline
1008 {
1009  return (*this)( pt[0], pt[1] );
1010 }
1011 
1012 
1013 template < typename T >
1014 inline
1016 {
1017  return volume()->min();
1018 }
1019 
1020 
1021 template < typename T >
1022 inline
1024 {
1025  return volume()->max();
1026 }
1027 
1028 
1029 template < typename T >
1030 inline
1031 T AimsData<T>::minIndex( int* xx, int* yy, int* zz, int* tt ) const
1032 {
1033  int minxind = 0,minyind = 0,minzind = 0,mintind = 0;
1034  T mini;
1035  const_iterator it = begin() + oFirstPoint();
1036 
1037  mini = *it;
1038  int x, xm = dimX(), y, ym = dimY(), z, zm = dimZ(), t, tm = dimT();
1039 
1040  for ( t = 0; t < tm; t++ )
1041  {
1042  for ( z = 0; z < zm; z++ )
1043  {
1044  for ( y = 0; y < ym; y++ )
1045  {
1046  for ( x = 0; x < xm; x++ )
1047  {
1048  if ( *it < mini )
1049  {
1050  mini = *it;
1051  minxind = x;
1052  minyind = y;
1053  minzind = z;
1054  mintind = t;
1055  }
1056  it++;
1057  }
1058  it += oPointBetweenLine();
1059  }
1060  it += oLineBetweenSlice();
1061  }
1062  it += oSliceBetweenVolume();
1063  }
1064  if ( xx )
1065  *xx = minxind;
1066  if ( yy )
1067  *yy = minyind;
1068  if ( zz )
1069  *zz = minzind;
1070  if ( tt )
1071  *tt = mintind;
1072 
1073  return mini;
1074 }
1075 
1076 
1077 template < typename T >
1078 inline
1079 T AimsData<T>::maxIndex( int* xx, int* yy, int* zz, int* tt ) const
1080 {
1081  int maxxind = 0,maxyind = 0,maxzind = 0,maxtind = 0;
1082  T maxi;
1083  const_iterator it = begin() + oFirstPoint();
1084 
1085  maxi = *it;
1086  int x, xm = dimX(), y, ym = dimY(), z, zm = dimZ(), t, tm = dimT();
1087 
1088  for ( t = 0; t < tm; t++ )
1089  {
1090  for ( z = 0; z < zm; z++ )
1091  {
1092  for ( y = 0; y < ym; y++ )
1093  {
1094  for ( x = 0; x < xm; x++ )
1095  {
1096  if ( *it > maxi )
1097  {
1098  maxi = *it;
1099  maxxind = x;
1100  maxyind = y;
1101  maxzind = z;
1102  maxtind = t;
1103  }
1104  it++;
1105  }
1106  it += oPointBetweenLine();
1107  }
1108  it += oLineBetweenSlice();
1109  }
1110  it += oSliceBetweenVolume();
1111  }
1112  if ( xx )
1113  *xx = maxxind;
1114  if ( yy )
1115  *yy = maxyind;
1116  if ( zz )
1117  *zz = maxzind;
1118  if ( tt )
1119  *tt = maxtind;
1120 
1121  return maxi;
1122 }
1123 
1124 
1125 template < typename T >
1126 inline
1127 void AimsData<T>::fillBorder( const T& val )
1128 {
1129  carto::VolumeRef<T> bigger = _volume->refVolume();
1130  if( bigger.isNull() )
1131  return;
1132  T *it;
1133  long x, xm = dimX(), y, ym = dimY(), z, zm = dimZ(), t, tm = dimT();
1134  long of = &_volume->at( 0, 0, 0, 0 ) - &bigger->at( 0, 0, 0, 0 ),
1135  op = &_volume->at( 0, 1, 0, 0 ) - &_volume->at( xm, 0, 0, 0 ),
1136  ol = &_volume->at( 0, 0, 1, 0 ) - &_volume->at( 0, ym, 0, 0 );
1137 
1138  for ( t = 0; t < tm; t++ )
1139  {
1140  it = &bigger->at( 0, 0, 0, t );
1141  for ( x = 0; x < of; x++ )
1142  *it++ = val;
1143  for ( z = 0; z < zm; z++ )
1144  {
1145  for ( y = 0; y < ym; y++ )
1146  {
1147  it += xm;
1148  for ( x = 0; x < op; x++ )
1149  *it++ = val;
1150  }
1151  for ( x = 0; x < ol; x++ )
1152  *it++ = val;
1153  }
1154  for ( x = 0; x < of - op - ol; x++ )
1155  *it++ = val;
1156  }
1157 }
1158 
1159 
1160 template<typename T>
1162 {
1163  AimsData<T> dat( *this );
1164  if( !_volume->refVolume().isNull() )
1165  {
1166  // border has to be copied
1168  new carto::Volume<T>( *_volume->refVolume() ) );
1169  dat._volume.reset( new carto::Volume<T>( rvol, _volume->posInRefVolume(),
1170  typename carto::Volume<T>::Position4Di( _volume->getSizeX(),
1171  _volume->getSizeY(),
1172  _volume->getSizeZ(),
1173  _volume->getSizeT() ) ) );
1174  dat._volume->header().copyProperties(
1175  carto::Object::reference( _volume->header() ) );
1176  }
1177  else
1178  dat._volume.reset( new carto::Volume<T>( *_volume ) );
1179  delete dat.d->header;
1180  dat.d->header = new aims::PythonHeader( *dat._volume );
1181  return dat;
1182 }
1183 
1184 
1185 template < typename T >
1186 inline
1188 {
1189  ASSERT( dimT() == 1 && other.dimT() == 1 &&
1190  dimZ() == 1 && other.dimZ() == 1 );
1191  ASSERT( dimY() == other.dimX() );
1192 
1193  AimsData<T> prod( dimX(), other.dimY(), 1, 1,
1194  std::max( borderWidth(), other.borderWidth() ) );
1195  for ( long y = 0; y < other.dimY(); y++ )
1196  for ( long x = 0; x < dimX(); x++ )
1197  {
1198  prod( x, y ) = T( 0 );
1199  for ( long k = 0; k < dimY(); k++ )
1200  prod( x, y ) += (*this)( x, k ) * other( k, y );
1201  }
1202 
1203  return prod;
1204 }
1205 
1206 
1207 template < typename T >
1208 inline
1210 {
1211  AimsData<T> tmp( dimY(), dimX(), dimZ(), dimT(), borderWidth() );
1213  *ph = dynamic_cast<aims::PythonHeader *>( header() );
1214  if( ph )
1215  {
1216  ph = static_cast<aims::PythonHeader *>( ph->cloneHeader() );
1217  if( ph->hasProperty( "volume_dimension" ) )
1218  ph->removeProperty( "volume_dimension" );
1219  if( ph->hasProperty( "voxel_size" ) )
1220  ph->removeProperty( "voxel_size" );
1221  tmp.setHeader( ph );
1222  }
1223  tmp.setSizeXYZT( sizeY(), sizeX(), sizeZ(), sizeT() );
1224  tmp.fillBorder( T( 0 ) );
1225 
1226  long x, xm = dimX(), y, ym = dimY(), z, zm = dimZ(), t, tm = dimT();
1227 
1228  for ( t = 0; t < tm; t++ )
1229  for ( z = 0; z < zm; z++ )
1230  for ( y = 0; y < ym; y++ )
1231  for ( x = 0; x < xm; x++ )
1232  tmp( y, x, z, t ) = (*this)( x, y, z, t );
1233 
1234  *this = tmp;
1235  return *this;
1236 }
1237 
1238 
1239 template < typename T >
1240 inline
1242  const AimsData<T>& secondThing )
1243 {
1245  v += carto::VolumeRef<T>(secondThing.volume());
1246  return v;
1247 }
1248 
1249 
1250 template < typename T >
1251 inline
1253  const AimsData<T>& secondThing )
1254 {
1256  v -= carto::VolumeRef<T>(secondThing.volume());
1257  return v;
1258 }
1259 
1260 template < typename T >
1261 inline
1262 AimsData<T> operator * ( const AimsData<T>& firstThing, float scale )
1263 {
1265  v *= scale;
1266  return v;
1267 }
1268 
1269 
1270 // macros
1271 
1272 #define ForEach4d( thing , x , y , z , t) \
1273  for ( t = 0; t < thing.dimT(); t++ ) \
1274  for ( z = 0; z < thing.dimZ(); z++ ) \
1275  for ( y = 0; y < thing.dimY(); y++ ) \
1276  for ( x = 0; x < thing.dimX(); x++ )
1277 
1278 #define ForEach3d( thing , x , y , z) \
1279  for ( z = 0; z < thing.dimZ(); z++ ) \
1280  for ( y = 0; y < thing.dimY(); y++ ) \
1281  for ( x = 0; x < thing.dimX(); x++ )
1282 
1283 #define ForEach2d( thing , x , y) \
1284  for ( y = 0; y < thing.dimY(); y++ ) \
1285  for ( x = 0; x < thing.dimX(); x++ )
1286 
1287 #define ForEach1d( thing , x) \
1288  for ( x = 0; x < thing.dimX(); x++ )
1289 
1290 
1291 #define ForEach4dp( thing , x , y , z , t) \
1292  for ( t = 0; t < thing->dimT(); t++ ) \
1293  for ( z = 0; z < thing->dimZ(); z++ ) \
1294  for ( y = 0; y < thing->dimY(); y++ ) \
1295  for ( x = 0; x < thing->dimX(); x++ )
1296 
1297 #define ForEach3dp( thing , x , y , z) \
1298  for ( z = 0; z < thing->dimZ(); z++ ) \
1299  for ( y = 0; y < thing->dimY(); y++ ) \
1300  for ( x = 0; x < thing->dimX(); x++ )
1301 
1302 #define ForEach2dp( thing , x , y) \
1303  for ( y = 0; y < thing->dimY(); y++ ) \
1304  for ( x = 0; x < thing->dimX(); x++ )
1305 
1306 #define ForEach1dp( thing , x) \
1307  for ( x = 0; x < thing->dimX(); x++ )
1308 
1309 
1310 class DtiTensor;
1311 
1312 namespace carto
1313 {
1314  // instanciations of Volume classes
1315 
1316  extern template class VolumeProxy<DtiTensor*>;
1317  extern template class Volume<DtiTensor*>;
1318 
1319 }
1320 
1321 
1322 #endif
1323 
int oLineBetweenSlice() const
Number of lines between 2 consecutive slices.
Definition: border.h:177
void setSizeT(float sizet)
T & reference
basic reference
reference operator()(size_type x=0, size_type y=0, size_type z=0, size_type t=0)
AimsData< T > & transpose()
const T * const_iterator
basic constant iterator
int dimZ() const
virtual bool getProperty(const std::string &, Object &) const
T **** pointer4d
4D-pointer
AimsData(int dimx=1, int dimy=1, int dimz=1, int dimt=1, int borderw=0)
Attributed python-like header, stores all needed information about an object, currently used for volu...
Definition: pheader.h:51
int _oSlice
Length of a slice.
Definition: border.h:102
int oPointBetweenLine() const
Offset between the end of a line and the start of the consecutive line.
Definition: border.h:163
void _setBorder(int dimx, int dimy, int dimz, int width)
Function that sets up all protected datas.
iterator begin()
static int borderWidth(carto::rc_ptr< carto::Volume< T > > vol)
T * iterator
basic iterator
float sizeZ() const
The base class to manage borders on data containers.
Definition: border.h:47
ptrdiff_t difference_type
difference type
int dimY() const
virtual void copy(const PythonHeader &, bool keepUuid=false)
float sizeT() const
The class for EcatSino data write operation.
Definition: border.h:42
size_t size_type
size of the basic type
AimsData< T > operator+(const AimsData< T > &firstThing, const AimsData< T > &secondThing)
AimsData< T > operator-(const AimsData< T > &firstThing, const AimsData< T > &secondThing)
static Object reference(T &value)
void setSizeX(float sizex)
virtual bool removeProperty(const std::string &)
void setSizeY(float sizey)
void setHeader(aims::Header *hdr)
int _oPointBetweenLine
Offset between two consecutive lines.
Definition: border.h:100
virtual Header * cloneHeader(bool keepUuid=false) const
float sizeX() const
const T & at(long x, long y=0, long z=0, long t=0) const
int _oSliceBetweenVolume
Offset between two consecutive volumes.
Definition: border.h:108
int _oFirstPoint
Offset up to first point.
Definition: border.h:94
void fillBorder(const T &val)
bool empty() const
carto::Object getObjectHeader(AimsData< T > &obj)
virtual ~AimsData()
virtual void clearProperties()
T * pointer
basic pointer
AimsData< T > & operator=(carto::rc_ptr< carto::Volume< T > > vol)
AimsData< T > clone() const
T minIndex(int *x, int *y, int *z, int *t) const
const aims::Header * header() const
Volume< T > deepcopy(const Volume< T > &src)
AimsData< T > operator*(const AimsData< T > &firstThing, float scale)
AimsData< T > cross(const AimsData< T > &other)
int _oLineBetweenSlice
Offset between two consecutive slices.
Definition: border.h:104
Border(int dimx, int dimy, int dimz, int width=0)
The constructor precalculates offsets to speed-up access to data during loops.
Definition: border.h:122
float sizeY() const
static Object value()
carto::rc_ptr< carto::Volume< T > > volume()
int _oVolume
Length of a volume.
Definition: border.h:106
T maxIndex(int *x, int *y, int *z, int *t) const
const carto::AllocatorContext & allocator() const
T * get() const
int dimT() const
int oSliceBetweenVolume() const
Number of slices between 2 consecutive volumes.
Definition: border.h:191
T minimum() const
int _oLine
Length of a line.
Definition: border.h:98
virtual void setProperty(const std::string &, Object)
void setSizeXYZT(float sizex=1.0f, float sizey=1.0f, float sizez=1.0f, float sizet=1.0f)
const T & const_reference
basic constant reference
iterator end()
void reset(T *p=NULL)
virtual bool hasProperty(const std::string &) const
#define ASSERT(EX)
void setSizeZ(float sizez)
aims::Header * header
int oFirstPoint() const
Offset from the start of the allocated memory to the first point.
Definition: border.h:142
T maximum() const
reference operator[](size_type n)
int dimX() const
int borderWidth() const
Usefull offsets for A.I.M.S.
Definition: border.h:135