aimsdata  5.0.5
Neuroimaging data handling
converter_volume.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 /*
35  * Converter between the different A.I.M.S. types
36  */
37 #ifndef AIMS_UTILITY_CONVERTER_VOLUME_H
38 #define AIMS_UTILITY_CONVERTER_VOLUME_H
39 
40 #include <aims/data/data.h>
41 #include <aims/data/pheader.h>
43 
44 namespace std
45 {
46 
47  template<typename _Tp>
48  struct numeric_limits<AimsData<_Tp> > : public numeric_limits<_Tp>
49  {
50  public:
51  };
52 
53 
54  template<typename _Tp>
55  struct numeric_limits<carto::Volume<_Tp> > : public numeric_limits<_Tp>
56  {
57  public:
58  };
59 
60 
61  template<typename _Tp>
62  struct numeric_limits<carto::VolumeRef<_Tp> > : public numeric_limits<_Tp>
63  {
64  public:
65  };
66 
67 }
68 
69 namespace carto
70 {
71 
72  template <typename INP,typename OUTP>
73  class RawConverter<AimsData<INP>, AimsData<OUTP> >
74  {
75  public:
76  void convert( const AimsData<INP> &in, AimsData<OUTP> & out ) const;
77  };
78 
79 
80  template <typename INP,typename OUTP>
82  {
83  public:
84  void convert( const carto::VolumeRef<INP> &in,
85  carto::VolumeRef<OUTP> & out ) const;
86  };
87 
88 
90  template<typename INP, typename OUTP>
91  class Rescaler<AimsData<INP>, AimsData<OUTP> >
92  {
93  public:
94  Rescaler();
95  Rescaler( const RescalerInfo & info );
96 
97  void convert( const AimsData<INP> &in, AimsData<OUTP> & out ) const;
98 
99  private:
100  RescalerInfo _info;
101  };
102 
103 
104  template<typename INP, typename OUTP>
106  {
107  public:
108  Rescaler();
109  Rescaler( const RescalerInfo & info );
110 
111  void convert( const carto::VolumeRef<INP> &in,
112  carto::VolumeRef<OUTP> & out ) const;
113 
114  private:
115  RescalerInfo _info;
116  };
117 
118  // special case of same input and output types
119 
120  template <typename INP>
121  class RawConverter<AimsData<INP>, AimsData<INP> >
122  {
123  public:
124  RawConverter( bool shallowcopy = false ) : _shallowcopy( shallowcopy ) {}
125  void convert( const AimsData<INP> &in, AimsData<INP> & out ) const;
126 
127  private:
128  bool _shallowcopy;
129  };
130 
131 
132  template <typename INP>
134  {
135  public:
136  RawConverter( bool shallowcopy = false ) : _shallowcopy( shallowcopy ) {}
137  void convert( const carto::VolumeRef<INP> &in, carto::VolumeRef<INP> & out ) const;
138 
139  private:
140  bool _shallowcopy;
141  };
142 
143 
144  template <typename INP>
145  class ShallowConverter<AimsData<INP>, AimsData<INP> >
146  : public Converter<AimsData<INP>, AimsData<INP> >
147  {
148  public:
149  ShallowConverter( bool rescale = false )
150  : Converter<AimsData<INP>, AimsData<INP> >( rescale ) {}
151  ShallowConverter( bool rescale, const RescalerInfo & info )
152  : Converter<AimsData<INP>, AimsData<INP> >( rescale, info ) {}
153  virtual void convert( const AimsData<INP> &in, AimsData<INP> & out ) const;
154  };
155 
156  template <typename INP>
158  : public Converter<carto::VolumeRef<INP>, carto::VolumeRef<INP> >
159  {
160  public:
161  ShallowConverter( bool rescale = false )
162  : Converter<carto::VolumeRef<INP>, carto::VolumeRef<INP> >( rescale ) {}
163  ShallowConverter( bool rescale, const RescalerInfo & info )
164  : Converter<carto::VolumeRef<INP>, carto::VolumeRef<INP> >( rescale, info ) {}
165  virtual void convert( const carto::VolumeRef<INP> &in, carto::VolumeRef<INP> & out ) const;
166  };
167 
168  template <class INP,class OUTP>
170  {
171  public:
172  static AimsData<OUTP>* alloc( const AimsData<INP> &in );
173  };
174 
175 
176  template <class INP,class OUTP>
178  carto::VolumeRef<OUTP> >
179  {
180  public:
181  static carto::VolumeRef<OUTP>* alloc( const carto::VolumeRef<INP> &in );
182  };
183 
184 
185  template <class INP>
187  {
188  public:
189  static AimsData<INP>* alloc( const AimsData<INP> &in );
190  };
191 
192 
193  template <class INP>
195  {
196  public:
197  static carto::VolumeRef<INP>* alloc( const carto::VolumeRef<INP> &in );
198  };
199 
200 
201  // implementation
202 
203  template <class INP,class OUTP> inline
205  ( const AimsData<INP> &in )
206  {
207  return new AimsData<OUTP>( in.dimX(), in.dimY(), in.dimZ(),
208  in.dimT(), in.borderWidth() );
209  }
210 
211 
212  template <class INP> inline
213  AimsData<INP>* ConverterAllocator<AimsData<INP>,AimsData<INP> >::alloc
214  ( const AimsData<INP> & )
215  {
216  return new AimsData<INP>( 0 );
217  }
218 
219 
220  // inline is a bit abusive here...
221  template<class INP,class OUTP> inline
223  ( const AimsData<INP> &in, AimsData<OUTP> &out ) const
224  {
225  out.setSizeX( in.sizeX() );
226  out.setSizeY( in.sizeY() );
227  out.setSizeZ( in.sizeZ() );
228  out.setSizeT( in.sizeT() );
229 
230  if( in.header() )
231  out.setHeader( in.header()->cloneHeader( true ) );
232 
233  int x, y, z, t, dx = out.dimX(), dy = out.dimY(), dz = out.dimZ(),
234  dt = out.dimT(), ox = dx, oy = dy, oz = dz, ot = dt;
235  if( in.dimX() < dx )
236  dx = in.dimX();
237  if( in.dimY() < dy )
238  dy = in.dimY();
239  if( in.dimZ() < dz )
240  dz = in.dimZ();
241  if( in.dimT() < dt )
242  dt = in.dimT();
243 
244  RawConverter<INP,OUTP> itemconv;
245 
246  for( t=0; t<dt; ++t )
247  {
248  for( z=0; z<dz; ++z )
249  {
250  for( y=0; y<dy; ++y )
251  {
252  for( x=0; x<dx; ++x )
253  itemconv.convert( in( x, y, z, t ), out( x, y, z, t ) );
254  for( ; x<ox; ++x )
255  out( x, y, z, t ) = OUTP(0);
256  }
257  for( ; y<oy; ++y )
258  for( x=0; x<ox; ++x )
259  out( x, y, z, t ) = OUTP(0);
260  }
261  for( ; z<oz; ++z )
262  for( y=0; y<oy; ++y )
263  for( x=0; x<ox; ++x )
264  out( x, y, z, t ) = OUTP(0);
265  }
266 
267  for( ; t<ot; ++t )
268  for( z=0; z<oz; ++z )
269  for( y=0; y<oy; ++y )
270  for( x=0; x<ox; ++x )
271  out( x, y, z, t ) = OUTP(0);
272 
274  = dynamic_cast<aims::PythonHeader *>( out.header() );
275  if( ph )
276  {
277  ph->setProperty( "data_type", DataTypeCode<OUTP>::dataType() );
278  if( ph->hasProperty( "disk_data_type" ) )
279  ph->removeProperty( "disk_data_type" );
280  }
281  }
282 
283 
284  // inline is a bit abusive here...
285  template<class INP,class OUTP> inline
286  void Rescaler<AimsData<INP>,AimsData<OUTP> >::convert
287  ( const AimsData<INP> &in, AimsData<OUTP> &out ) const
288  {
289  // Accommodate the case where out is allocated with zero size by
290  // AllocatorConverter. This happens when the INP and OUTP types are equal.
291  if( out.dimX() == 0 )
292  out = AimsData<OUTP>( in.dimX(), in.dimY(), in.dimZ(),
293  in.dimT(), in.borderWidth() );
294 
295  out.setSizeX( in.sizeX() );
296  out.setSizeY( in.sizeY() );
297  out.setSizeZ( in.sizeZ() );
298  out.setSizeT( in.sizeT() );
299 
300  if( in.header() )
301  out.setHeader( in.header()->cloneHeader( true ) );
302 
303  RescalerInfo info( _info );
304  if( std::isnan( info.vmin ) ) {
305  if ( ! info.usevtypelimits ) {
306  info.vmin = (double) in.minimum();
307  }
308  }
309 
310  if( std::isnan( info.vmax ) ) {
311  if ( ! info.usevtypelimits ) {
312  info.vmax = (double) in.maximum();
313  }
314  }
315 
316  DefaultedRescalerInfo<INP, OUTP> defaultedinfo( info );
317 
318  int x, y, z, t, dx = out.dimX(), dy = out.dimY(), dz = out.dimZ(),
319  dt = out.dimT(), ox = dx, oy = dy, oz = dz, ot = dt;
320  if( in.dimX() < dx )
321  dx = in.dimX();
322  if( in.dimY() < dy )
323  dy = in.dimY();
324  if( in.dimZ() < dz )
325  dz = in.dimZ();
326  if( in.dimT() < dt )
327  dt = in.dimT();
328 
329  for( t=0; t<dt; ++t )
330  {
331  for( z=0; z<dz; ++z )
332  {
333  for( y=0; y<dy; ++y )
334  {
335  for( x=0; x<dx; ++x )
336  out( x, y, z, t ) =
337  defaultedinfo.getScaledValue( in( x, y, z, t ) );
338  for( ; x<ox; ++x )
339  out( x, y, z, t ) = OUTP(0);
340  }
341  for( ; y<oy; ++y )
342  for( x=0; x<ox; ++x )
343  out( x, y, z, t ) = OUTP(0);
344  }
345  for( ; z<oz; ++z )
346  for( y=0; y<oy; ++y )
347  for( x=0; x<ox; ++x )
348  out( x, y, z, t ) = OUTP(0);
349  }
350 
351  for( ; t<ot; ++t )
352  for( z=0; z<oz; ++z )
353  for( y=0; y<oy; ++y )
354  for( x=0; x<ox; ++x )
355  out( x, y, z, t ) = OUTP(0);
356 
357  float scf = 1.;
359  *h = dynamic_cast<aims::PythonHeader *>( out.header() );
360  if( !h )
361  h = new aims::PythonHeader;
362  h->getProperty( "scale_factor", scf );
363  scf *= defaultedinfo.getScale();
364  h->setProperty( "scale_factor", scf );
365  h->setProperty( "data_type", DataTypeCode<OUTP>::dataType() );
366  if( h->hasProperty( "disk_data_type" ) )
367  h->removeProperty( "disk_data_type" );
368  }
369 
370 
371  template<class INP> inline
372  void RawConverter<AimsData<INP>,AimsData<INP> >::convert
373  ( const AimsData<INP> &in, AimsData<INP> &out ) const
374  {
375  if( out.dimX() == 0
376  || ( in.dimX() == out.dimX() && in.dimY() == out.dimY()
377  && in.dimZ() == out.dimZ() && in.dimT() == out.dimT()
378  && in.borders() == out.borders() ) )
379  {
380  if( this->_shallowcopy )
381  out = in;
382  else
383  {
384  // using deep-copy to be consistent with other cases
385  out = in.clone();
386  // keep the same UUID
387  out.volume()->copyUuid( *in.volume() );
388  }
389  }
390  else
391  {
392  if( in.header() )
393  out.setHeader( in.header()->cloneHeader( true ) );
394 
395  out.setSizeXYZT( in.sizeX(), in.sizeY(), in.sizeZ(), in.sizeT() );
396  int x, y, z, t, dx = out.dimX(), dy = out.dimY(), dz = out.dimZ(),
397  dt = out.dimT(), ox = dx, oy = dy, oz = dz, ot = dt;
398  if( in.dimX() < dx )
399  dx = in.dimX();
400  if( in.dimY() < dy )
401  dy = in.dimY();
402  if( in.dimZ() < dz )
403  dz = in.dimZ();
404  if( in.dimT() < dt )
405  dt = in.dimT();
406 
407  for( t=0; t<dt; ++t )
408  {
409  for( z=0; z<dz; ++z )
410  {
411  for( y=0; y<dy; ++y )
412  {
413  for( x=0; x<dx; ++x )
414  out( x, y, z, t ) = in( x, y, z, t );
415  for( ; x<ox; ++x )
416  out( x, y, z, t ) = INP(0);
417  }
418  for( ; y<oy; ++y )
419  for( x=0; x<ox; ++x )
420  out( x, y, z, t ) = INP(0);
421  }
422  for( ; z<oz; ++z )
423  for( y=0; y<oy; ++y )
424  for( x=0; x<ox; ++x )
425  out( x, y, z, t ) = INP(0);
426  }
427 
428  for( ; t<ot; ++t )
429  for( z=0; z<oz; ++z )
430  for( y=0; y<oy; ++y )
431  for( x=0; x<ox; ++x )
432  out( x, y, z, t ) = INP(0);
433  }
434  }
435 
436  template<typename INP, typename OUTP>
437  inline
438  Rescaler<AimsData<INP>, AimsData<OUTP> >::Rescaler() : _info()
439  {
440  }
441 
442  template<typename INP, typename OUTP>
443  inline
444  Rescaler<AimsData<INP>, AimsData<OUTP> >::Rescaler(const RescalerInfo & info)
445  : _info(info)
446  {
447  }
448 
449  template<typename INP>
450  class ConverterSwitch<AimsData<INP>,AimsData<INP>,false>
451  : public RawConverter<AimsData<INP>,AimsData<INP> >
452  {
453  public:
454  ConverterSwitch( bool shallowcopy = false )
455  : RawConverter<AimsData<INP>,AimsData<INP> >( shallowcopy ) {}
456  ConverterSwitch( const RescalerInfo&, bool shallowcopy = false )
457  : RawConverter<AimsData<INP>,AimsData<INP> >( shallowcopy ) {}
458  };
459 
460 
461  template<typename INP>
463  : public RawConverter<carto::VolumeRef<INP>,carto::VolumeRef<INP> >
464  {
465  public:
466  ConverterSwitch( bool shallowcopy = false )
467  : RawConverter<carto::VolumeRef<INP>,carto::VolumeRef<INP> >( shallowcopy ) {}
468  ConverterSwitch( const RescalerInfo&, bool shallowcopy = false )
469  : RawConverter<carto::VolumeRef<INP>,carto::VolumeRef<INP> >( shallowcopy ) {}
470  };
471 
472 
473  template<typename INP>
474  class ConverterSwitch<AimsData<INP>,AimsData<INP>,true>
475  : public Rescaler<AimsData<INP>,AimsData<INP> >
476  {
477  public:
478  ConverterSwitch( bool = false )
479  : Rescaler<AimsData<INP>,AimsData<INP> >() {}
480  ConverterSwitch( const RescalerInfo& info, bool )
481  : Rescaler<AimsData<INP>,AimsData<INP> >(info) {}
482  };
483 
484 
485  template<typename INP>
487  : public Rescaler<carto::VolumeRef<INP>,carto::VolumeRef<INP> >
488  {
489  public:
490  ConverterSwitch( bool = false )
491  : Rescaler<carto::VolumeRef<INP>,carto::VolumeRef<INP> >() {}
492  ConverterSwitch( const RescalerInfo& info, bool )
493  : Rescaler<carto::VolumeRef<INP>,carto::VolumeRef<INP> >(info) {}
494  };
495 
496 
497  template<typename INP>
498  class SmartConverter<AimsData<INP>, AimsData<INP> >
499  : public ConverterSwitch<AimsData<INP>, AimsData<INP>,
500  std::numeric_limits<INP>::is_specialized
501  && std::numeric_limits<INP>::is_bounded >
502  {
503  public:
504  SmartConverter( bool shallowcopy = false )
505  : ConverterSwitch<AimsData<INP>, AimsData<INP>,
506  std::numeric_limits<INP>::is_specialized
507  && std::numeric_limits<INP>::is_bounded >( shallowcopy ) {}
508  SmartConverter( const RescalerInfo& info, bool shallowcopy = false )
509  : ConverterSwitch<AimsData<INP>, AimsData<INP>,
510  std::numeric_limits<INP>::is_specialized
511  && std::numeric_limits<INP>::is_bounded >( info, shallowcopy ) {}
512  };
513 
514 
515  template<typename INP>
517  : public ConverterSwitch<carto::VolumeRef<INP>, carto::VolumeRef<INP>,
518  std::numeric_limits<INP>::is_specialized
519  && std::numeric_limits<INP>::is_bounded >
520  {
521  public:
522  SmartConverter( bool shallowcopy = false )
524  std::numeric_limits<INP>::is_specialized
525  && std::numeric_limits<INP>::is_bounded >( shallowcopy ) {}
526  SmartConverter( const RescalerInfo& info, bool shallowcopy = false )
528  std::numeric_limits<INP>::is_specialized
529  && std::numeric_limits<INP>::is_bounded >( info, shallowcopy ) {}
530  };
531 
532 
533  template<class INP>
534  inline void
536  ( const AimsData<INP> &in, AimsData<INP> & out ) const
537  {
538  if( this->_rescale )
539  {
540  SmartConverter<AimsData<INP>,AimsData<INP> > sc( this->_info, true );
541  sc.convert( in, out );
542  }
543  else
544  {
545  RawConverter<AimsData<INP>,AimsData<INP> > rc( true );
546  rc.convert( in, out );
547  }
548  }
549 
550 
551  // VolumeRef implementation
552 
553  template<class INP>
554  inline void
556  ( const carto::VolumeRef<INP> &in, carto::VolumeRef<INP> & out ) const
557  {
558  if( this->_rescale )
559  {
561  sc( this->_info, true );
562  sc.convert( in, out );
563  }
564  else
565  {
567  rc.convert( in, out );
568  }
569  }
570 
571 
572  template <typename INP,typename OUTP>
575  {
576  AimsData<OUTP> data( out );
577  RawConverter<AimsData<INP>, AimsData<OUTP> > c;
578  c.convert( in, data );
579  out = data.volume(); // vol in data may have changed
580  }
581 
582 
583  template<typename INP, typename OUTP>
585  : _info()
586  {
587  }
588 
589 
590  template<typename INP, typename OUTP>
592  ( const RescalerInfo & info )
593  : _info( info )
594  {
595  }
596 
597 
598  template<typename INP, typename OUTP>
601  {
602  AimsData<OUTP> data( out );
603  Rescaler<AimsData<INP>,AimsData<OUTP> > c( _info );
604  c.convert( in, data );
605  out = data.volume(); // vol in data may have changed
606  }
607 
608  template <class INP,class OUTP>
611  ( const carto::VolumeRef<INP> &in )
612  {
613  return new VolumeRef<OUTP>( in.getSizeX(), in.getSizeY(), in.getSizeZ(),
614  in.getSizeT() );
615  }
616 
617 
618  template <class INP> inline
620  ConverterAllocator<carto::VolumeRef<INP>, carto::VolumeRef<INP> >::alloc
622  {
623  return new carto::VolumeRef<INP>( 0 );
624  }
625 
626 
627  template<class INP> inline
628  void RawConverter<carto::VolumeRef<INP>,carto::VolumeRef<INP> >::convert
630  {
631  AimsData<INP> datain( in );
632  AimsData<INP> dataout( out );
633  RawConverter<AimsData<INP>, AimsData<INP> > conv( _shallowcopy );
634  conv.convert( datain, dataout );
635  out = dataout.volume(); // vol in dataout may have changed
636  }
637 
638 }
639 
640 #endif
void setSizeT(float sizet)
void convert(const INP &in, OUTP &out) const
int dimZ() const
virtual bool getProperty(const std::string &, Object &) const
int getSizeX() const
int getSizeY() const
int getSizeZ() const
Attributed python-like header, stores all needed information about an object, currently used for volu...
Definition: pheader.h:51
int getSizeT() const
float sizeZ() const
const std::vector< int > & borders() const
Sizes of the border.
ShallowConverter(bool rescale, const RescalerInfo &info)
STL namespace.
int dimY() const
float sizeT() const
void setSizeX(float sizex)
virtual bool removeProperty(const std::string &)
void setSizeY(float sizey)
OUTP getScaledValue(INP value) const
void setHeader(aims::Header *hdr)
float sizeX() const
virtual Header * cloneHeader(bool keepUuid=false) const =0
SmartConverter(const RescalerInfo &info, bool shallowcopy=false)
AimsData< T > clone() const
const aims::Header * header() const
ConverterSwitch(const RescalerInfo &, bool shallowcopy=false)
float sizeY() const
carto::rc_ptr< carto::Volume< T > > volume()
int dimT() const
T minimum() const
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)
virtual bool hasProperty(const std::string &) const
void setSizeZ(float sizez)
void convert(const INP &in, OUTP &out) const
T maximum() const
SmartConverter(const RescalerInfo &info, bool shallowcopy=false)
int dimX() const
int borderWidth() const
Usefull offsets for A.I.M.S.
Definition: border.h:200