cartodata  5.0.5
volumeformatreader_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_IO_VOLUMEFORMATREADER_D_H
35 #define CARTODATA_IO_VOLUMEFORMATREADER_D_H
36 //--- cartodata --------------------------------------------------------------
41 //--- soma io ----------------------------------------------------------------
49 //--- cartobase --------------------------------------------------------------
51 #include <cartobase/smart/rcptr.h>
54 //--- system -----------------------------------------------------------------
55 #include <vector>
56 #include <iostream>
57 #include <string>
58 //--- debug ------------------------------------------------------------------
61 #define localMsg( message ) cartoCondMsg( 4, message, "VOLUMEFORMATREADER" )
62 // localMsg must be undef at end of file
63 //----------------------------------------------------------------------------
64 
65 namespace soma
66 {
70 
71  //==========================================================================
72  // C O N S T R U C T O R S
73  //==========================================================================
74  template <typename T>
76  {
77  }
78 
79  //==========================================================================
80  // U R I O P T I O N S
81  //==========================================================================
82 
83  /**** setupAndRead *********************************************************
84  * Usually it is not necessary to redefine this method, but in the case of
85  * volumes the use of partial reading or borders triggers multiple volume
86  * allocations (see volume philosophy). These complex volumes are
87  * managed in VolumeUtilIO and setupAndRead/createAndRead must call them
88  * when needed.
89  **************************************************************************/
90  template <typename T> void
93  const AllocatorContext & context,
94  carto::Object options )
95  {
96  //=== Reading URI ========================================================
97  std::string uri = dsi->list().dataSource()->url();
98  std::string url = FileUtil::uriFilename( uri );
99  carto::Object urioptions = FileUtil::uriOptions( uri );
100  if( urioptions.get() ) {
101  if( !options.get() )
103  options->copyProperties( urioptions );
104  dsi->list().dataSource().reset( new FileDataSource( url ) );
105  }
106  //=== if no options -> classic reading ===================================
107  if( !options.get() )
108  return FormatReader<Volume<T> >::setupAndRead( obj, dsi, context,
109  options );
110  //=== else, look for known properties ====================================
111  std::set<std::string> prop = VolumeUtilIO<T>::listReadProperties();
112  typename std::set<std::string>::iterator p;
113  typename std::set<std::string>::iterator plast = prop.end();
114  for( p = prop.begin(); p != prop.end(); ++p )
115  {
116  if( options->hasProperty( *p ) )
117  {
118  VolumeUtilIO<T>::read( &obj, dsi, options );
119  bool convert = false;
120  options->getProperty( "convert_to_aims", convert );
121  if( convert )
122  {
124  translator.translate( carto::Object::reference( obj.header() ) );
125  }
126  return;
127  }
128  // for now it's juste unalloc/realloc.
129  // it must be possible to design a nice setup, but then changes are
130  // needed in VolumeUtilIO
131  }
132  //=== if no known property -> classic reading ============================
133  return FormatReader<Volume<T> >::setupAndRead( obj, dsi, context,
134  options );
135  }
136 
137  /**** createAndRead ********************************************************
138  * See setupAndRead
139  **************************************************************************/
140  template <typename T> Volume<T>*
142  const AllocatorContext & context,
143  carto::Object options )
144  {
145  localMsg( "Creating and reading object ( " + dsi->url() + " )" );
146 
147  //=== Reading URI ========================================================
148  std::string uri = dsi->list().dataSource()->url();
149  std::string url = FileUtil::uriFilename( uri );
150  carto::Object urioptions = FileUtil::uriOptions( uri );
151  if( !options.get() )
153  else
154  options = options->clone();
155  if( urioptions.get() ) {
156  options->copyProperties( urioptions );
157  dsi->list().dataSource().reset( new FileDataSource( url ) );
158  }
159  //=== if no options -> classic reading ===================================
160  if( !options.get() )
161  return FormatReader<Volume<T> >::createAndRead( dsi, context, options );
162  //=== else, look for known properties ====================================
163  std::set<std::string> prop = VolumeUtilIO<T>::listReadProperties();
164  typename std::set<std::string>::iterator p;
165  typename std::set<std::string>::iterator plast = prop.end();
166  Volume<T> *volume = 0;
167  for( p = prop.begin(); p != plast; ++p )
168  {
169  if( options->hasProperty( *p ) )
170  {
171  localMsg( "using VolumeUtilIO<T>::read ( " + dsi->url() + " )" );
172  volume = VolumeUtilIO<T>::read( 0, dsi, options );
173  break;
174  }
175  }
176  //=== if no known property -> classic reading ============================
177  if( !volume )
178  {
179  localMsg( "using classical Volume reading ( " + dsi->url() + " )" );
180  volume = FormatReader<Volume<T> >::createAndRead(
181  dsi, context, options );
182  }
183  if( volume )
184  {
185  bool convert = false;
186  options->getProperty( "convert_to_aims", convert );
187  if( convert )
188  {
190  translator.translate( carto::Object::reference( volume->header() ) );
191  }
192  }
193 // localMsg( "-> effective volume size ( "
194 // + carto::toString( volume->getSizeX() ) + ", "
195 // + carto::toString( volume->getSizeY() ) + ", "
196 // + carto::toString( volume->getSizeZ() ) + ", "
197 // + carto::toString( volume->getSizeT() ) + " )"
198 // );
199  return volume;
200  }
201 
202  //==========================================================================
203  // N E W M E T H O D S
204  //==========================================================================
205 
206  /**** Reading to a Volume<T> ***********************************************
207  * This method depends deeply on the data structure (Volume<T>). It is
208  * declared in FormatReader but only defined here.
209  **************************************************************************/
210  template <typename T>
213  const AllocatorContext & /* context */,
214  carto::Object options )
215  {
216  localMsg( "Reading object ( " + dsi->url() + " )" );
217 
218  //=== Test data compability ==============================================
219  std::string otype = dsi->header()->getProperty( "object_type" )->getString();
220  std::string dtype = dsi->header()->getProperty( "data_type" )->getString();
221  std::string ttype = DataTypeCode<T>::dataType();
222  if( otype != "Volume" )
223  throw datatype_format_error( "unsupported data type - " + otype + " != Volume", dsi->url() );
224  if( dtype != ttype )
225  {
226  if( dsi->header()->hasProperty( "possible_data_types" ) )
227  {
228  size_t i;
229  for( i=0;
230  i<dsi->header()->getProperty( "possible_data_types" )->size();
231  ++i )
232  {
233  if( dsi->header()->getProperty( "possible_data_types" )
234  ->getArrayItem( i )->getString()
235  == ttype )
236  break;
237  }
238  if( i == dsi->header()->getProperty( "possible_data_types" )->size() )
239  throw datatype_format_error( dsi->url() );
240  } else
241  throw datatype_format_error( "unsupported data type - " + dtype + " != " + ttype, dsi->url() );
242  }
243 
244  //=== test for memory mapping ============================================
245  localMsg( "checking for memory mapping..." );
246  if( obj.allocatorContext().allocatorType()
248  {
249  localMsg( " -> Memory Mapping : nothing to read." );
250  return;
251  }
252 
253  //=== volume is a view ? =================================================
254  localMsg( "checking if object is a view..." );
255  carto::Volume<T>* parent1( 0 );
256  carto::Volume<T>* parent2( 0 );
257  parent1 = obj.refVolume().get();
258  if( parent1 )
259  parent2 = parent1->refVolume().get();
260  else if( !obj.allocatorContext().isAllocated() ) {
261  localMsg( " -> Unallocated Volume : nothing to read." );
262  return;
263  }
264  localMsg( std::string(" -> object ") + ( parent1 ? "is" : "isn't" )
265  + " a view and "
266  + ( obj.allocatorContext().isAllocated() ? "is" : "isn't" )
267  + " allocated." );
268  if( parent1 )
269  {
270  localMsg( std::string(" -> parent exists and ")
271  + ( parent1->allocatorContext().isAllocated() ? "is" : "isn't" )
272  + " allocated." );
273  }
274  if( parent2 )
275  {
276  localMsg( std::string(" -> grandparent exists and ")
277  + ( parent2->allocatorContext().isAllocated() ? "is" : "isn't" )
278  + " allocated." );
279  }
280 
281  //=== view size ==========================================================
282  localMsg( "reading view size..." );
283  std::vector<int> viewsize = obj.getSize();
284  localMsg( " -> view size ( "
285  + carto::toString( viewsize[ 0 ] ) + ", "
286  + carto::toString( viewsize[ 1 ] ) + ", "
287  + carto::toString( viewsize[ 2 ] ) + ", "
288  + carto::toString( viewsize[ 3 ] ) + " )" );
289 
290  //=== multiresolution level ==============================================
291  localMsg( "reading multiresolution level..." );
292  int level = -1;
293  if( options->hasProperty( "resolution_level" ) ) {
294  options->getProperty( "resolution_level", level );
295  }
296 
297  if (level < 0) {
298  try {
299  // Try to solve negative level values
300  level += dsi->header()->getProperty( "resolutions_dimension" )
301  ->size();
302  }
303  catch(...){
304  level = 0;
305  }
306  }
307  localMsg( " -> level to read : " + carto::toString( level ) );
308 
309  //=== full volume size ===================================================
310  localMsg( "reading full volume size..." );
311  std::vector<int> imagesize( 4, 0 );
312  try
313  {
314  // first we look for "resolutions_dimension" property
315  carto::Object dim
316  = dsi->header()->getProperty( "resolutions_dimension" )->getArrayItem(
317  level );
318  int i, ndim = dim->size();
319  imagesize.resize( std::max( size_t( 4 ), dim->size() ), 1 );
320  for( i=0; i<ndim; ++i )
321  imagesize[ i ] = (int) rint( dim->getArrayItem( i )->getScalar() );
322  localMsg( " -> found \"resolutions_dimension\"." );
323  }
324  catch( ... )
325  {
326  try
327  {
328  // if it doesn't work, we look for "volume_dimension"
329  carto::Object dim = dsi->header()->getProperty( "volume_dimension" );
330  int i, ndim = dim->size();
331  imagesize.resize( std::max( size_t( 4 ), dim->size() ), 1 );
332  for( i=0; i<ndim; ++i )
333  imagesize[ i ] = (int) rint( dim->getArrayItem( i )->getScalar() );
334  localMsg( " -> found \"volume_dimension\"." );
335  }
336  catch( ... )
337  {
338  // if still nothing, we look for parent volumes
339  if( parent1 && !parent1->allocatorContext().isAllocated() ) {
340  imagesize = parent1->getSize();
341  localMsg( " -> found unallocated parent." );
342  } else if( parent2 ) {
343  imagesize = parent2->getSize();
344  localMsg( " -> found grandparent." );
345  } else {
346  imagesize = viewsize;
347  localMsg( " -> full volume is self." );
348  }
349  }
350  }
351  // FIXME: print all dims
352  localMsg( " -> full volume size ( "
353  + carto::toString( imagesize[ 0 ] ) + ", "
354  + carto::toString( imagesize[ 1 ] ) + ", "
355  + carto::toString( imagesize[ 2 ] ) + ", "
356  + carto::toString( imagesize[ 3 ] ) + " )" );
357 
358  //=== allocated volume size ==============================================
359  localMsg( "reading allocated size..." );
360  std::vector<int> allocsize( 4, 0 );
361  if( !parent1 ) {
362  allocsize = viewsize;
363  localMsg( " -> allocated volume is self (full volume)." );
364  } else if( !parent1->allocatorContext().isAllocated() ) {
365  allocsize = viewsize;
366  localMsg( " -> allocated volume is self (partial volume)." );
367  } else {
368  allocsize = parent1->getSize();
369  localMsg( " -> allocated volume is parent "
370  "(borders or partially loading in full volume)." );
371  }
372  localMsg( " -> allocated volume size ( "
373  + carto::toString( allocsize[ 0 ] ) + ", "
374  + carto::toString( allocsize[ 1 ] ) + ", "
375  + carto::toString( allocsize[ 2 ] ) + ", "
376  + carto::toString( allocsize[ 3 ] ) + " )" );
377 
378  //=== strides ============================================================
379  size_t i, ndim = allocsize.size();
380  std::vector<long> strides( ndim );
381  std::vector<int> stride_pos;
382  for( i=0; i<ndim; ++i )
383  {
384  stride_pos = std::vector<int>( ndim, 0 );
385  stride_pos[i] = 1;
386  strides[i] = &obj( stride_pos ) - &obj( 0,0,0,0 );
387  }
388 
389  //=== region's origine ===================================================
390  localMsg( "reading view position in reference to full volume..." );
391  std::vector<int> pos ( ndim, 0 );
392  if( parent1 && !parent1->allocatorContext().isAllocated() ) {
393  pos = obj.posInRefVolume();
394  } else if( parent2 ) {
395  pos = obj.posInRefVolume();
396  for( i=0; i<parent1->posInRefVolume().size(); ++i )
397  pos[i] += parent1->posInRefVolume()[i];
398  }
399  localMsg( " -> view position ( "
400  + carto::toString( pos[ 0 ] ) + ", "
401  + carto::toString( pos[ 1 ] ) + ", "
402  + carto::toString( pos[ 2 ] ) + ", "
403  + carto::toString( pos[ 3 ] ) + " )" );
404 
405  //=== possibilities : with borders, partial reading ======================
406  bool withborders = false;
407  bool partialreading = false;
408  for( i=0; i<ndim; ++i )
409  {
410  if( allocsize[i] > viewsize[i] )
411  withborders = true;
412  if( imagesize[i] > viewsize[i] )
413  partialreading = true;
414  }
415  localMsg( "With Borders : "
416  + std::string( ( withborders ? "yes" : "no" ) ) );
417  localMsg( "Partial Reading : "
418  + std::string( ( partialreading ? "yes" : "no" ) ) );
419  partialreading = partialreading; // compilation warning
420 
421  //=== reading volume =====================================================
422  //int y, z, t;
423  if( !withborders || dsi->capabilities().canHandleStrides() )
424  {
425  localMsg( "reading volume using strides..." );
426  // we can read the volume/region into a contiguous buffer
427  _imr->read( ( T * ) &obj(0,0,0,0), *dsi, pos,
428  viewsize, strides, options );
429  }
430  else
431  {
432  localMsg( "reading volume without strides..." );
433  // we are in a "border" context. The volume/region must be read
434  // line by line
435  std::vector<int> posline ( pos );
436  std::vector<int> sizeline ( ndim, 1 );
437  std::vector<int> volpos( ndim, 0 );
438  volpos[1] = -1;
439  sizeline[ 0 ] = viewsize[ 0 ];
440  size_t dim;
441  bool nextrow = false, ended = false;
442 
443  bool was_open = _imr->isOpen( *dsi );
444 
445  if( !was_open && !_imr->open( *dsi ) )
446  throw carto::open_error( "data source not available", dsi->url() );
447 
448  while( !ended )
449  {
450  nextrow = true;
451  for( dim=1; dim<ndim; ++dim )
452  {
453  if( nextrow )
454  {
455  ++volpos[dim];
456  if( volpos[dim] == viewsize[dim] )
457  {
458  if( dim == ( ndim - 1 ) )
459  ended = true;
460  volpos[dim] = 0;
461  }
462  else
463  nextrow = false;
464  }
465  posline[dim] = pos[dim] + volpos[dim];
466  }
467  if( !ended )
468  {
469  posline[1] = pos[1] + volpos[1];
470  _imr->read( ( T * ) &obj( volpos ), *dsi, posline,
471  sizeline, strides, options );
472  }
473  }
474 
475  if( !was_open )
476  _imr->close( *dsi );
477 
478 // for ( t=0; t<viewsize[ 3 ]; ++t ) {
479 // volpos[ 3 ] = t;
480 // posline[ 3 ] = pos[ 3 ] + t;
481 // for ( z=0; z<viewsize[ 2 ]; ++z ) {
482 // volpos[ 2 ] = z;
483 // posline[ 2 ] = pos[ 2 ] + z;
484 // for ( y=0; y<viewsize[ 1 ]; ++y ) {
485 // volpos[ 1 ] = y;
486 // posline[ 1 ] = pos[ 1 ] + y;
487 // _imr->read( ( T * ) &obj( volpos ), *dsi, posline,
488 // sizeline, strides, options );
489 // }
490 // }
491 // }
492  }
493 
494  // we reset at 0 the ImageReader's members (sizes, binary, ...) so that
495  // they are recomputed at the next reading.
496  _imr->resetParams();
497  }
498 
499 
500  template <typename T>
502  {
504  reader->attach( carto::rc_ptr<ImageReader<T> >( _imr->cloneReader() ) );
505  return reader;
506  }
507 
508  /***************************************************************************
509  * Attaching a specific ImageReader to the FormatReader
510  **************************************************************************/
511  template <typename T>
513  {
514  _imr = imr;
515  }
516 
517 
518  template <typename T>
520  {
521  // delegate to ImageReader
522  if( !_imr )
523  return "";
524  return _imr->formatID();
525  }
526 
530 
531  //==========================================================================
532  // C O N S T R U C T O R S
533  //==========================================================================
534  template <typename T>
536  {
537  }
538 
539  //==========================================================================
540  // U R I O P T I O N S
541  //==========================================================================
542  /*** setupAndRead **********************************************************
543  * see VolumeFormatReader
544  **************************************************************************/
545  template <typename T> void
548  const AllocatorContext & context,
549  carto::Object options )
550  {
551  //=== Reading URI ========================================================
552  std::string uri = dsi->list().dataSource()->url();
553  std::string url = FileUtil::uriFilename( uri );
554  carto::Object urioptions = FileUtil::uriOptions( uri );
555  if( urioptions.get() ) {
556  if( !options.get() )
558  options->copyProperties( urioptions );
559  dsi->list().dataSource().reset( new FileDataSource( url ) );
560  }
561  //=== if no options -> classic reading ===================================
562  if( !options.get() ) {
563  FormatReader<VolumeRef<T> >::setupAndRead( obj, dsi, context,
564  options );
565  return;
566  }
567 
568  //=== else, look for known properties ====================================
569  std::set<std::string> prop = VolumeUtilIO<T>::listReadProperties();
570  typename std::set<std::string>::iterator p;
571  typename std::set<std::string>::iterator plast = prop.end();
572  for( p = prop.begin(); p != plast; ++p )
573  {
574  if( options->hasProperty( *p ) )
575  {
577  vrf.attach( _imr );
578  vrf.setupAndRead( *obj, dsi, context, options );
579  bool convert = false;
580  options->getProperty( "convert_to_aims", convert );
581  if( convert )
582  {
584  translator.translate( carto::Object::reference( obj->header() ) );
585  }
586  return; // return as soon as one read prop has been found.
587  }
588  }
589  //=== if no known property -> classic reading ============================
590  FormatReader<VolumeRef<T> >::setupAndRead( obj, dsi, context,
591  options );
592  }
593 
594  /*** createAndRead *********************************************************
595  * see VolumeFormatReader
596  **************************************************************************/
597  template <typename T> VolumeRef<T>*
599  const AllocatorContext & context,
600  carto::Object options )
601  {
603  vrf.attach( _imr );
604  return new VolumeRef<T>( vrf.createAndRead( dsi, context, options ) );
605  }
606 
607  //==========================================================================
608  // N E W M E T H O D S
609  //==========================================================================
610 
611  /*** Reading to a Volume<T> ************************************************
612  * This method depends deeply on the data structure (Volume<T>). It is
613  * declared in FormatReader but only defined here.
614  **************************************************************************/
615  template <typename T>
618  const AllocatorContext & context,
619  carto::Object options )
620  {
622  vrf.attach( _imr );
623  vrf.read( *obj, dsi, context, options );
624  }
625 
626  /***************************************************************************
627  * Attaching a specific ImageReader to the FormatReader
628  **************************************************************************/
629  template <typename T>
631  {
632  _imr = imr;
633  }
634 
635 
636  template <typename T>
639  {
641  reader->attach( carto::rc_ptr<ImageReader<T> >( _imr->cloneReader() ) );
642  return reader;
643  }
644 
645 
646  template <typename T>
648  {
649  // delegate to ImageReader
650  if( !_imr )
651  return "";
652  return _imr->formatID();
653  }
654 
655 }
656 
657 #undef localMsg
658 #endif
const Position & posInRefVolume() const
Get position in parent volume.
Definition: volumebase_d.h:607
N-D Volume main class.
virtual std::string formatID() const
const carto::rc_ptr< DataSource > & dataSource(const std::string &s="default", int i=0) const
#define localMsg(message)
FormatReader specialized for reference to 4D Volume.
virtual FormatReader< carto::VolumeRef< T > > * clone() const
bool isAllocated() const
virtual std::string formatID() const
virtual void setupAndRead(VolumeRef< T > &obj, carto::rc_ptr< DataSourceInfo > dsi, const AllocatorContext &context, carto::Object options)
Full reading procedure, for an already existing object.
virtual void translate(Object srcheader, Object dstheader=none()) const
T max(const Volume< T > &vol)
Returns the maximum value of the volume.
Definition: volumeutil.h:762
MappingMode allocatorType() const
std::string url() const
void attach(carto::rc_ptr< ImageReader< T > > imr)
Linking to a ImageReader Allows us to declare only once the ImageReader.
const DataSourceCapabilities & capabilities() const
Convenient handle for a Volume - this is normally the entry point for all volumes handling...
virtual void setupAndRead(Volume< T > &obj, carto::rc_ptr< DataSourceInfo > dsi, const AllocatorContext &context, carto::Object options)
Full reading procedure, for an already existing object.
static Object reference(T &value)
std::vector< int > getSize() const
get the 4 dimensions in a vector
Definition: volumeproxy.h:127
const AllocatorContext & allocatorContext() const
returns volume&#39;s AllocatorContext
Definition: volumebase_d.h:595
FormatReader specialized for 4D Volume.
rc_ptr< Volume< T > > refVolume() const
Get parent volume.
Definition: volumebase_d.h:601
static carto::Volume< T > * read(carto::Volume< T > *obj, carto::rc_ptr< DataSourceInfo > dsi, carto::Object options)
Manages all the volumes necessary and returns the final Volume.
virtual Volume< T > * createAndRead(carto::rc_ptr< DataSourceInfo > dsi, const AllocatorContext &context, carto::Object options)
Factory mode: creates an object and reads it.
virtual FormatReader< carto::Volume< T > > * clone() const
virtual VolumeRef< T > * createAndRead(carto::rc_ptr< DataSourceInfo > dsi, const AllocatorContext &context, carto::Object options)
Factory mode: creates an object and reads it.
static Object value()
virtual void read(carto::VolumeRef< T > &obj, carto::rc_ptr< DataSourceInfo > dsi, const AllocatorContext &context, carto::Object options=carto::none())
FormatReader derived function This method understands a volume and calls read( buffer ) with appropri...
void attach(carto::rc_ptr< ImageReader< T > > imr)
Linking to a ImageReader Allows us to declare only once the ImageReader.
static std::set< std::string > listReadProperties()
list of properties triggering partial reading and/or borders
GenericObject * get() const
std::string toString(const T &object)
virtual void read(carto::Volume< T > &obj, carto::rc_ptr< DataSourceInfo > dsi, const AllocatorContext &context, carto::Object options=carto::none())
FormatReader derived function This method understands a volume and calls read( buffer ) with appropri...
const carto::Object & header() const
const DataSourceList & list() const