aimsdata  5.1.2
Neuroimaging data handling
spmR_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 /*
35  * SPM reader template functions
36  */
37 
38 #include <cstdlib>
39 #include <aims/io/spmR.h>
40 #include <aims/io/datatypecode.h>
41 #include <aims/io/defaultItemR.h>
42 #include <aims/io/spmheader.h>
43 #include <aims/utility/flip.h>
44 #include <aims/data/data.h>
49 
50 namespace aims
51 {
52 
53  template< class T >
54  std::string SpmReader< T >::removeExtension(const std::string& name)
55  {
56  std::string res = name;
57  std::string ext="";
58  if ( res.length() > 4 )
59  ext = res.substr( res.length() - 4, 4 );
60  if (ext == ".hdr" || ext == ".img")
61  res = res.substr( 0, res.length() - 4 );
62  return res;
63  }
64 
65 
66  template <typename T>
68  const carto::AllocatorContext & context,
69  carto::Object options )
70  {
71  std::string name = removeExtension( _name );
72 
73  aims::SpmHeader *hdr = new aims::SpmHeader( name + ".hdr" );
74 
75  try
76  {
77  hdr->read();
78  }
79  catch( std::exception & e )
80  {
81  delete hdr;
82  throw e;
83  }
84 
85  std::string type;
86  if ( !hdr->getProperty( "disk_data_type", type ) )
88  hdr->setProperty( "data_type", carto::DataTypeCode<T>().dataType() );
89  hdr->setProperty( "bits_allocated", (int) sizeof( T ) );
90 
91  std::vector<int> dims;
92  std::vector<float> vs;
93  if( ! hdr->getProperty( "volume_dimension", dims ) )
94  throw std::logic_error( "Internal error: getProperty volume_dimension failed" );
95  if( ! hdr->getProperty( "voxel_size", vs ) )
96  throw std::logic_error( "Internal error: getProperty voxel_size failed" );
97 
98  int frame = -1, border = 0;
99  options->getProperty( "frame", frame );
100  options->getProperty( "border", border );
101 
102  int dimt = 1, tmin = 0;
103  if ( frame >= 0 )
104  {
105  if ( frame >= dims[3] )
106  {
107  throw std::domain_error( "Frame number exceeds "
108  "volume time dimension" );
109  }
110  tmin = frame;
111  }
112  else
113  dimt = dims[3];
114 
115  int bswapi = false;
116  hdr->getProperty( "byte_swapping", bswapi );
117  bool bswap = bswapi;
118  std::string filename = name + ".img";
119 
120  bool series = false;
121  std::vector<carto::Object> fnames;
122  std::string bname;
123  if ( tmin > 0 || dimt > 1 )
124  {
125  series = hdr->getProperty( "series_filenames", fnames );
126  if ( series )
127  {
128  if ( fnames.size() < (unsigned) ( dimt + tmin ) )
129  throw std::domain_error( "SPM reader: not enough filenames for "
130  "all frames" );
131  bname = carto::FileUtil::dirname( name )
133  hdr->removeProperty( "series_filenames" );
134  }
135  }
136 
137  carto::AllocatorContext al
138  ( context.accessMode(),
140  ( new carto::FileDataSource( filename, 0, carto::DataSource::Read ) ),
141  false, context.useFactor() );
142 
143  //std::cout << "alloc type: " << al.allocatorType() << std::endl;
144  AimsData<T> data( dims[0], dims[1], dims[2], dimt, border, al );
145  data.setSizeXYZT( vs[0], vs[1] , vs[2], vs[3] );
146 
147  std::ifstream is;
148  if ( !series )
149  {
150  is.open( filename.c_str(), std::ios::in | std::ios::binary );
151  if ( !is )
152  {
154  }
155  is.unsetf( std::ios::skipws );
156  if ( type == "S8")
157  is.seekg( (std::ifstream::pos_type) tmin * data.dimZ() * data.dimY()
158  * data.dimX() * sizeof( int8_t ), std::ios::cur );
159  else if ( type == "U8")
160  is.seekg( (std::ifstream::pos_type) tmin * data.dimZ() * data.dimY()
161  * data.dimX() * sizeof( uint8_t ), std::ios::cur );
162  else if ( type =="S16" )
163  is.seekg( (std::ifstream::pos_type) tmin * data.dimZ() * data.dimY()
164  * data.dimX() * sizeof( int16_t ), std::ios::cur );
165  else if ( type =="U16" )
166  is.seekg( (std::ifstream::pos_type) tmin * data.dimZ() * data.dimY()
167  * data.dimX() * sizeof( uint16_t ), std::ios::cur );
168  else if ( type =="S32" )
169  is.seekg( (std::ifstream::pos_type) tmin * data.dimZ() * data.dimY()
170  * data.dimX() * sizeof( int32_t ), std::ios::cur );
171  else if ( type =="U32" )
172  is.seekg( (std::ifstream::pos_type) tmin * data.dimZ() * data.dimY()
173  * data.dimX() * sizeof( uint32_t ), std::ios::cur );
174  else if ( type == "FLOAT" )
175  is.seekg( (std::ifstream::pos_type) tmin * data.dimZ() * data.dimY()
176  * data.dimX() * sizeof( float ), std::ios::cur );
177  else if ( type == "DOUBLE" )
178  is.seekg( (std::ifstream::pos_type) tmin * data.dimZ() * data.dimY()
179  * data.dimX() * sizeof( double ), std::ios::cur );
180  else
181  is.seekg( (std::ifstream::pos_type) tmin * data.dimZ() * data.dimY()
182  * data.dimX() * sizeof( T ), std::ios::cur );
183  }
184 
185  std::vector<T> buffer ( dims[0] );
186  std::string fnm;
187 
188  std::vector<float> vstom;
190  if( hdr->getProperty( "storage_to_memory", vstom ) )
191  stom = AffineTransformation3d( vstom );
192  else
193  {
194  // standard orientation
195  stom.rotation()(1,1) = -1;
196  stom.rotation()(2,2) = -1;
197  stom.matrix()(1, 3) = data.dimY() - 1;
198  stom.matrix()(2, 3) = data.dimZ() - 1;
199  bool radio = false;
200  try
201  {
202  radio = (bool) hdr->getProperty( "spm_radio_convention" )->getScalar();
203  }
204  catch( std::exception & )
205  {
206  }
207  if( !radio )
208  {
209  stom.rotation()(0,0) = -1;
210  stom.matrix()(0, 3) = data.dimX() - 1;
211  }
212  }
213 
214  for ( int t=0; t<dimt; ++t )
215  {
216  if ( series )
217  {
218  fnm = bname
219  + carto::FileUtil::basename( fnames[t+tmin]->getString() );
220  is.open( ( fnm ).c_str(), std::ios::in | std::ios::binary );
221  if ( !is )
222  {
224  }
225  is.unsetf( std::ios::skipws );
226  }
227  hdr->setProperty( "scale_factor_applied", false ) ;
228  readFrame( is, data, t, type, hdr, bswap, stom );
229  if ( series )
230  is.close();
231  }
232 
233  if ( !series )
234  is.close();
235 
236  thing = data;
237  thing.setHeader( hdr );
238  }
239 
240 
241  template<typename T> void
242  SpmReader<T>::readFrame( std::ifstream & is, AimsData<T> & data, int t,
243  const std::string &, SpmHeader*, bool bswap,
244  const AffineTransformation3d & stom )
245  {
246  DefaultItemReader<T> itemR ;
247  ItemReader<T> *ir
248  = itemR.reader( "binar", bswap );
249 
250  Point3df incf = stom.transform( Point3df( 1, 0, 0 ) )
251  - stom.transform( Point3df( 0, 0, 0 ) );
252  Point4d inc = Point4d( int16_t( rint( incf[0] ) ),
253  int16_t( rint( incf[1] ) ),
254  int16_t( rint( incf[2] ) ), 0 );
255  Point3df d0f;
256  Point4d d0;
257  AffineTransformation3d m2s = stom.inverse();
258  Point3df df = m2s.transform( Point3df( data.dimX(), data.dimY(),
259  data.dimZ() ) )
260  - m2s.transform( Point3df( 0, 0, 0 ) );
261  Point4d tdims = Point4d( short( rint( fabs( df[0] ) ) ),
262  short( rint( fabs( df[1] ) ) ),
263  short( rint( fabs( df[2] ) ) ), (short) data.dimT() );
264  int x, dx = tdims[0];
265  std::vector<T> buffer( dx );
266 
267  for ( int z=0;z<tdims[2];++z)
268  for ( int y=0;y<tdims[1];++y)
269  {
270  d0f = stom.transform( Point3df( 0, y, z ) );
271  d0 = Point4d( int16_t( rint( d0f[0] ) ), int16_t( rint( d0f[1] ) ),
272  int16_t( rint( d0f[2] ) ), t );
273  if( inc == Point4d( 1, 0, 0, 0 ) )
274  ir->read( is, &data( d0 ), dx );
275  else
276  {
277  ir->read( is, &buffer[0], dx );
278  for ( x=0; x<dx; ++x, d0+=inc )
279  data( d0 ) = buffer[ x ];
280  }
281  }
282  delete ir ;
283  }
284 
285 
286  template <typename T> template<typename U>
287  void
288  SpmReader<T>::readScaledFrame( std::ifstream & is, AimsData<T>& data,
289  int t, SpmHeader *hdr, bool bswap,
290  const AffineTransformation3d & stom )
291  {
292  float scaleFactor = 1;
293  bool scaleFactorApplied = false;
294 
295  hdr->getProperty( "scale_factor", scaleFactor );
296  hdr->getProperty( "scale_factor_applied", scaleFactorApplied );
297  if ( scaleFactorApplied || scaleFactor == 0. )
298  scaleFactor = 1. ;
299 
300  DefaultItemReader<U> itemR ;
301  ItemReader<U> *ir
302  = itemR.reader( "binar", bswap );
303 
304  Point3df incf = stom.transform( Point3df( 1, 0, 0 ) )
305  - stom.transform( Point3df( 0, 0, 0 ) );
306  Point4d inc = Point4d( int16_t( rint( incf[0] ) ),
307  int16_t( rint( incf[1] ) ),
308  int16_t( rint( incf[2] ) ), 0 );
309  Point3df d0f;
310  Point4d d0;
311  AffineTransformation3d m2s = stom.inverse();
312  Point3df df = m2s.transform( Point3df( data.dimX(), data.dimY(),
313  data.dimZ() ) )
314  - m2s.transform( Point3df( 0, 0, 0 ) );
315  Point4d tdims = Point4d( short( rint( fabs( df[0] ) ) ),
316  short( rint( fabs( df[1] ) ) ),
317  short( rint( fabs( df[2] ) ) ), data.dimT() );
318  int x, dx = tdims[0];
319  std::vector<U> buffer( dx );
320 
321  for ( int z=0;z<tdims[2];++z)
322  for ( int y=0;y<tdims[1];++y)
323  {
324  d0f = stom.transform( Point3df( 0, y, z ) );
325  d0 = Point4d( int16_t( rint( d0f[0] ) ), int16_t( rint( d0f[1] ) ),
326  int16_t( rint( d0f[2] ) ), t );
327  ir->read( is, &buffer[0] , dx );
328  for ( x=0; x<dx; ++x, d0+=inc )
329  data( d0 ) = (T) ( scaleFactor * buffer[ x ] );
330  }
331  delete ir;
332  hdr->setProperty( "scale_factor_applied", true ) ;
333  }
334 
335 
336  template<> void
337  SpmReader<float>::readFrame( std::ifstream & is, AimsData<float> & data,
338  int t, const std::string & type,
339  SpmHeader* hdr, bool bswap,
340  const AffineTransformation3d & stom )
341  {
342  if ( type == "S8")
343  readScaledFrame<int8_t>( is, data, t, hdr, bswap, stom );
344  else if ( type == "U8")
345  readScaledFrame<uint8_t>( is, data, t, hdr, bswap, stom );
346  else if ( type =="S16" )
347  readScaledFrame<int16_t>( is, data, t, hdr, bswap, stom );
348  else if ( type =="U16" )
349  readScaledFrame<uint16_t>( is, data, t, hdr, bswap, stom );
350  else if ( type =="S32" )
351  readScaledFrame<int32_t>( is, data, t, hdr, bswap, stom );
352  else if ( type =="U32" )
353  readScaledFrame<uint32_t>( is, data, t, hdr, bswap, stom );
354  else if ( type =="FLOAT" )
355  readScaledFrame<float>( is, data, t, hdr, bswap, stom );
356  else if ( type =="DOUBLE" )
357  readScaledFrame<double>( is, data, t, hdr, bswap, stom );
358  else
359  std::cerr << "SPM read not implemented: " << type << " as FLOAT"
360  << std::endl;
361  }
362 
363  template<> void
364  SpmReader<double>::readFrame( std::ifstream & is, AimsData<double>& data,
365  int t, const std::string & type,
366  SpmHeader* hdr, bool bswap,
367  const AffineTransformation3d & stom )
368  {
369  if ( type == "S8")
370  readScaledFrame<int8_t>( is, data, t, hdr, bswap, stom );
371  else if ( type == "U8")
372  readScaledFrame<uint8_t>( is, data, t, hdr, bswap, stom );
373  else if ( type =="S16" )
374  readScaledFrame<int16_t>( is, data, t, hdr, bswap, stom );
375  else if ( type =="U16" )
376  readScaledFrame<uint16_t>( is, data, t, hdr, bswap, stom );
377  else if ( type =="S32" )
378  readScaledFrame<int32_t>( is, data, t, hdr, bswap, stom );
379  else if ( type =="U32" )
380  readScaledFrame<uint32_t>( is, data, t, hdr, bswap, stom );
381  else if ( type =="FLOAT" )
382  readScaledFrame<float>( is, data, t, hdr, bswap, stom );
383  else if ( type =="DOUBLE" )
384  readScaledFrame<double>( is, data, t, hdr, bswap, stom );
385  else
386  std::cerr << "SPM read not implemented: " << type << " as DOUBLE"
387  << std::endl;
388  }
389 
390 }
391 
void setHeader(aims::Header *hdr)
void setSizeXYZT(float sizex=1.0f, float sizey=1.0f, float sizez=1.0f, float sizet=1.0f)
int dimY() const
int dimX() const
int dimT() const
int dimZ() const
carto::VolumeRef< float > rotation()
AffineTransformation3d inverse() const
Default low-levels readers.
Definition: defaultItemR.h:56
virtual ItemReader< T > * reader(const std::string &openmode="binar", bool bswap=false) const
Definition: defaultItemR.h:154
Low-level "small item" reader, used by higher-level file readers.
Definition: itemR.h:99
virtual void read(std::istream &is, T &item) const
Definition: itemR.h:103
virtual ItemReader< T > * reader(const std::string &openmode="binar", bool bswap=false) const =0
SPM Header class.
Definition: spmheader.h:54
The template class for SPM read operation.
Definition: spmR.h:73
void read(AimsData< T > &thing, const carto::AllocatorContext &context, carto::Object options)
Read the data with "name" file name from disk.
Definition: spmR_d.h:67
std::string removeExtension(const std::string &name)
Return a name without .hdr or .img extension.
Definition: spmR_d.h:54
std::string dataType()
static char separator()
static std::string dirname(const std::string &)
static std::string basename(const std::string &)
virtual bool getProperty(const std::string &, Object &) const
virtual bool removeProperty(const std::string &)
virtual void setProperty(const std::string &, Object)
static void launchErrnoExcept(const std::string &filename="")
Point3dd transform(double x, double y, double z) const
The class for EcatSino data write operation.
Definition: borderfiller.h:13