cartodata  5.0.5
volumeformatwriter_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_VOLUMEFORMATWRITER_D_H
35 #define CARTODATA_IO_VOLUMEFORMATWRITER_D_H
36 //--- cartodata --------------------------------------------------------------
37 #include <cartodata/io/volumeformatwriter.h> // class declaration
38 #include <cartodata/volume/volume.h> // manipulate sizes
39 //--- soma-io ----------------------------------------------------------------
41 #include <soma-io/datasourceinfo/datasourceinfo.h> // function's argument
42 #include <soma-io/image/imagewriter.h> // use of member functions
43 #include <soma-io/utilities/minfutil.h> // used by filterProperties()
44 //--- cartobase --------------------------------------------------------------
45 #include <cartobase/smart/rcptr.h>
46 #include <cartobase/object/object.h> // header & options
47 #include <cartobase/object/property.h> // header & options
48 #include <cartobase/exception/ioexcept.h> // exceptions
49 //--- system -----------------------------------------------------------------
50 #include <vector>
51 #include <iostream>
52 #include <string>
53 //--- debug ------------------------------------------------------------------
55 #define localMsg( message ) cartoCondMsg( 4, message, "VOLUMEFORMATWRITER" )
56 // localMsg must be undef at end of file
57 //----------------------------------------------------------------------------
58 
59 namespace soma
60 {
64 
65  //==========================================================================
66  // C O N S T R U C T O R S
67  //==========================================================================
68  template <typename T>
70  {
71  }
72 
73  //==========================================================================
74  // F I L T E R M E T H O D S
75  //==========================================================================
76  template <typename T>
78  carto::Object options)
79  {
80  // Filter minf to remove irrelevant properties
81  soma::MinfUtil::filter(header, options);
82 
83  return true;
84  }
85 
86  //==========================================================================
87  // W R I T E M E T H O D S
88  //==========================================================================
89  template <typename T>
92  carto::Object options )
93  {
94  localMsg( "writing: " + dsi->url() );
95  //=== memory mapping =====================================================
96  localMsg( "checking for memory mapping..." );
98  return true;
99 
100  //=== multiresolution level ==============================================
101  localMsg( "reading resolution level..." );
102  int level = 0;
103  if( options->hasProperty( "resolution_level" ) ) {
104  options->getProperty( "resolution_level", level );
105  if (level < 0) {
106  try {
107  // Try to solve negative level values
108  level += dsi->header()->getProperty( "resolutions_dimension" )
109  ->size();
110  }
111  catch(...){}
112  }
113  }
114  localMsg( " -> level to write : " + carto::toString( level ) );
115 
116  //=== partial reading ====================================================
117  localMsg( "checking for partial writing..." );
118  bool partial = false;
119  if( options->hasProperty( "partial_writing" ) )
120  partial = true;
121  if( partial )
122  {
123  localMsg( " -> partial writing enabled." );
124  }
125 
126  size_t dim, ndim = obj.getSize().size();
127  std::vector<int> position( ndim, 0 );
128  std::vector<int> view( ndim, 0 );
129  std::vector<int> size( ndim, 1 );
130 
131  //=== checking if obj is a view ==========================================
132  localMsg( "checking if object is a view..." );
133  carto::Volume<T> *parent1 = 0;
134  carto::Volume<T> *parent2 = 0;
135  parent1 = obj.refVolume().get();
136  if( parent1 )
137  parent2 = parent1->refVolume().get();
138  localMsg( std::string("object ") + ( parent1 ? "is" : "isn't" ) + " a view and "
139  + ( obj.allocatorContext().isAllocated() ? "is" : "isn't" )
140  + " allocated." );
141  if( parent1 )
142  {
143  localMsg( std::string("parent1 exists and ")
144  + ( parent1->allocatorContext().isAllocated() ? "is" : "isn't" )
145  + " allocated." );
146  }
147  if( parent2 )
148  {
149  localMsg( std::string("parent2 exists and ")
150  + ( parent2->allocatorContext().isAllocated() ? "is" : "isn't" )
151  + " allocated." );
152  }
153 
154  //=== view size ==========================================================
155  localMsg( "reading view size..." );
156  view = obj.getSize();
157 
158  //=== full volume size ===================================================
159  localMsg( "reading full volume size and view position..." );
160  if( parent1 && !parent1->allocatorContext().isAllocated() ) {
161  localMsg( " -> from parent1" )
162  size = parent1->getSize();
163  position = obj.posInRefVolume();
164  } else if( parent2 ) {
165  localMsg( " -> from parent2" )
166  size = parent2->getSize();
167  position = obj.posInRefVolume();
168  size_t i, ndim = parent1->posInRefVolume().size();
169  for( i=0; i<ndim; ++i )
170  position[ i ] += parent1->posInRefVolume()[ i ];
171  } else {
172  localMsg( " -> from self" )
173  size = view;
174  }
175 
176  if( !partial ) {
177  // we treat the view as a pure Volume
178  localMsg( " -> from self (no partial writing)" )
179  size = view;
180  position = std::vector<int>( ndim, 0 );
181  }
182 
183  localMsg( " -> Full volume size : ( "
184  + carto::toString( size[0] ) + ", "
185  + carto::toString( size[1] ) + ", "
186  + carto::toString( size[2] ) + ", "
187  + carto::toString( size[3] ) + " )" );
188  localMsg( " -> View size : ( "
189  + carto::toString( view[0] ) + ", "
190  + carto::toString( view[1] ) + ", "
191  + carto::toString( view[2] ) + ", "
192  + carto::toString( view[3] ) + " )" );
193  localMsg( " -> View position : ( "
194  + carto::toString( position[0] ) + ", "
195  + carto::toString( position[1] ) + ", "
196  + carto::toString( position[2] ) + ", "
197  + carto::toString( position[3] ) + " )" );
198 
199  //=== checking for borders ===============================================
200  localMsg( "checking for borders..." );
201  bool withborders = false;
202  if( parent1 && parent1->allocatorContext().isAllocated() )
203  withborders = true;
204  localMsg( std::string(" -> ") + ( withborders ? "with borders" : "without borders" ) );
205  withborders = withborders; // compilation warning
206 
207  //=== header info ========================================================
208  localMsg( "setting header..." );
209  if( !options )
211  if( !parent1 && !obj.allocatorContext().isAllocated() )
212  options->setProperty( "unallocated", true );
213  if( !dsi->header() )
214  {
216  dsi->header()->copyProperties(
217  carto::Object::reference( obj.header() ) );
218  }
219  dsi->header()->setProperty( "volume_dimension", size );
220  dsi->header()->setProperty( "sizeX", size[ 0 ] );
221  dsi->header()->setProperty( "sizeY", size[ 1 ] );
222  dsi->header()->setProperty( "sizeZ", size[ 2 ] );
223  dsi->header()->setProperty( "sizeT", size[ 3 ] );
224  if( !dsi->header()->hasProperty( "voxel_size" ) )
225  {
226  std::vector<float> voxel_size( 4, 1. );
227  dsi->header()->setProperty( "voxel_size", voxel_size );
228  }
229 
230 
231  //=== use optional parameters for partial writing ========================
232  if( partial ) {
233  try {
234  position[0] = (int) rint( options->getProperty( "ox" )->getScalar() );
235  localMsg( "override ox : " + carto::toString(position[0]) );
236  } catch( ... ) {}
237  try {
238  position[1] = (int) rint( options->getProperty( "oy" )->getScalar() );
239  localMsg( "override oy : " + carto::toString(position[1]) );
240  } catch( ... ) {}
241  try {
242  position[2] = (int) rint( options->getProperty( "oz" )->getScalar() );
243  localMsg( "override oz : " + carto::toString(position[2]) );
244 // std::cout << "override oz : " + carto::toString(position[2]) << std::endl;
245  } catch( ... ) {}
246  try {
247  position[3] = (int) rint( options->getProperty( "ot" )->getScalar() );
248  localMsg( "override ot : " + carto::toString(position[3]) );
249 // std::cout << "override ot : " + carto::toString(position[3]) << std::endl;
250  } catch( ... ) {}
251  size_t dim, value;
252  for( dim=0; dim<carto::Volume<T>::DIM_MAX; ++dim )
253  {
254  try
255  {
256  std::stringstream skey;
257  skey << "ox" << dim+1;
258  std::string key = skey.str();
259  value = (int) rint( options->getProperty( key )->getScalar() );
260  options->removeProperty( key );
261  while( position.size() <= dim )
262  position.push_back( 0 );
263  position[ dim ] = value;
264 // std::cout << "override " << key << " : " + carto::toString(value) << std::endl;
265  }
266  catch( ... ) {}
267  }
268  }
269 
270  //=== writing header & creating files ====================================
271  localMsg( "writing header..." );
272  std::vector<long> strides( ndim );
273  for( dim=0; dim<ndim; ++dim )
274  {
275  std::vector<int> pos( ndim, 0 );
276  pos[dim] = 1;
277  strides[dim] = &obj( pos ) - &obj(0,0,0,0);
278  }
279 
280  this->filterProperties(dsi->header(), options);
281 
282 
283  *dsi = _imw->writeHeader( *dsi, (T*) &obj(0,0,0,0), position, view,
284  strides, options );
285 
286  //=== sanity check =======================================================
287  if( partial )
288  {
289  // file sizes may be different from what has been set before (since
290  // the file already exists, its size has been re-read by writeHeader())
291  std::vector<int> file_sz( ndim, 1 );
292  if( !dsi->header()->getProperty( "volume_dimension", file_sz ) )
293  {
294  dsi->header()->getProperty( "sizeX", file_sz[0] );
295  dsi->header()->getProperty( "sizeY", file_sz[1] );
296  dsi->header()->getProperty( "sizeZ", file_sz[2] );
297  dsi->header()->getProperty( "sizeT", file_sz[3] );
298  }
299  for( dim=0; dim<ndim; ++dim )
300  {
301  if( file_sz.size() <= dim )
302  file_sz.push_back( 1 );
303  if( position[dim] + view[dim] > file_sz[dim] )
304  {
305  localMsg( "view is larger than the volume." );
306  throw carto::format_error( "view is larger than the volume." );
307  }
308  }
309  }
310 
311  //=== writing image ======================================================
312  localMsg( "writing volume..." );
313  const T* data = 0;
314  if( parent1 || obj.allocatorContext().isAllocated() )
315  data = reinterpret_cast<const T*>( &obj(0,0,0,0) );
316  // in unallocated case, data is null; this is OK.
317  _imw->write( data, *dsi, position, view, strides, options );
318 // {
319 // // if( !withborders ) {
320 // _imw->write( (T*) &obj(0,0,0,0), *dsi, position, view, strides,
321 // options );
322 // // } else {
323 // // int y, z, t;
324 // // std::vector<int> posline ( position );
325 // // std::vector<int> sizeline ( 4, 1 );
326 // // sizeline[ 0 ] = view[ 0 ];
327 // // for( t=0; t<view[3]; ++t )
328 // // for( z=0; z<view[2]; ++z )
329 // // for( y=0; y<view[1]; ++y ) {
330 // // posline[ 1 ] = position[ 1 ] + y;
331 // // posline[ 2 ] = position[ 2 ] + z;
332 // // posline[ 3 ] = position[ 3 ] + t;
333 // // _imw->write( (T*) &obj(0,y,z,t), *dsi, posline,
334 // // sizeline, options );
335 // // }
336 // // }
337 // }
338  // else we just needed to write the header and reserve file space
339  // no image to write
340 
341  // we reset at 0 the ImageWriter's members (sizes, binary, ...) so that
342  // they are recomputed at the next writing.
343  _imw->resetParams();
344  return true;
345  }
346 
347  template <typename T>
349  {
350  _imw = imw;
351  }
352 
356 
357  template <typename T>
359  {
360  }
361 
362  template <typename T>
364  carto::Object options)
365  {
366  // Filter minf to remove irrelevant properties
367  soma::MinfUtil::filter(header, options);
368 
369  return true;
370  }
371 
372 
373  template <typename T>
376  carto::Object options )
377  {
379  vfw.attach( _imw );
380  return vfw.write( *obj, dsi, options );
381  }
382 
383  template <typename T>
385  {
386  _imw = imw;
387  }
388 
389 }
390 
391 #undef localMsg
392 #endif
const Position & posInRefVolume() const
Get position in parent volume.
Definition: volumebase_d.h:607
N-D Volume main class.
bool isAllocated() const
MappingMode allocatorType() const
FormatWriter specialized for 4D Volume.
std::string url() const
Convenient handle for a Volume - this is normally the entry point for all volumes handling...
virtual bool write(const carto::Volume< T > &obj, carto::rc_ptr< DataSourceInfo > dsi, carto::Object options)
FormatWriter derived function This method understands a volume and calls appropriate ImageWriter meth...
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
virtual bool filterProperties(carto::Object header, carto::Object options=carto::none())
FormatWriter derived function It removes properties that must not be written.
rc_ptr< Volume< T > > refVolume() const
Get parent volume.
Definition: volumebase_d.h:601
#define localMsg(message)
static void filter(carto::Object header, carto::Object options=carto::none())
void attach(carto::rc_ptr< ImageWriter< T > > imw)
Linking to a ImageWriter Allows us to declare only once the ImageWriter.
static Object value()
void attach(carto::rc_ptr< ImageWriter< T > > imw)
Linking to a ImageWriter Allows us to declare only once the ImageWriter.
T * get() const
const PropertySet & header() const
std::string toString(const T &object)
const carto::Object & header() const
virtual bool filterProperties(carto::Object header, carto::Object options=carto::none())
FormatWriter derived function It removes properties that must not be written.
virtual bool write(const carto::VolumeRef< T > &obj, carto::rc_ptr< DataSourceInfo > dsi, carto::Object options)
FormatWriter derived function This method understands a volume and calls appropriate ImageWriter meth...