cartodata  4.5.0
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 //--- cartobase --------------------------------------------------------------
44 #include <cartobase/smart/rcptr.h>
45 #include <cartobase/object/object.h> // header & options
46 #include <cartobase/object/property.h> // header & options
47 #include <cartobase/exception/ioexcept.h> // exceptions
48 //--- system -----------------------------------------------------------------
49 #include <vector>
50 #include <iostream>
51 #include <string>
52 //--- debug ------------------------------------------------------------------
54 #define localMsg( message ) cartoCondMsg( 4, message, "VOLUMEFORMATWRITER" )
55 // localMsg must be undef at end of file
56 //----------------------------------------------------------------------------
57 
58 namespace soma
59 {
63 
64  //==========================================================================
65  // C O N S T R U C T O R S
66  //==========================================================================
67  template <typename T>
69  {
70  }
71 
72  //==========================================================================
73  // W R I T E M E T H O D S
74  //==========================================================================
75  template <typename T>
78  carto::Object options )
79  {
80  localMsg( "writing: " + dsi->url() );
81  //=== memory mapping =====================================================
82  localMsg( "checking for memory mapping..." );
84  return true;
85 
86  //=== multiresolution level ==============================================
87  localMsg( "reading resolution level..." );
88  int level = 0;
89  if( options->hasProperty( "resolution_level" ) ) {
90  options->getProperty( "resolution_level", level );
91  if (level < 0) {
92  try {
93  // Try to solve negative level values
94  level += dsi->header()->getProperty( "resolutions_dimension" )
95  ->size();
96  }
97  catch(...){}
98  }
99  }
100  localMsg( " -> level to write : " + carto::toString( level ) );
101 
102  //=== partial reading ====================================================
103  localMsg( "checking for partial writing..." );
104  bool partial = false;
105  if( options->hasProperty( "partial_writing" ) )
106  partial = true;
107  if( partial )
108  localMsg( " -> partial writing enabled." );
109 
110  std::vector<int> position( 4, 0 );
111  std::vector<int> view( 4, 0 );
112  std::vector<int> size( 4, 0 );
113 
114  //=== checking if obj is a view ==========================================
115  localMsg( "checking if object is a view..." );
116  carto::Volume<T> *parent1 = 0;
117  carto::Volume<T> *parent2 = 0;
118  parent1 = obj.refVolume().get();
119  if( parent1 )
120  parent2 = parent1->refVolume().get();
121  localMsg( std::string("object ") + ( parent1 ? "is" : "isn't" ) + " a view and "
122  + ( obj.allocatorContext().isAllocated() ? "is" : "isn't" )
123  + " allocated." );
124  if( parent1 )
125  localMsg( std::string("parent1 exists and ")
126  + ( parent1->allocatorContext().isAllocated() ? "is" : "isn't" )
127  + " allocated." );
128  if( parent2 )
129  localMsg( std::string("parent2 exists and ")
130  + ( parent2->allocatorContext().isAllocated() ? "is" : "isn't" )
131  + " allocated." );
132 
133  //=== view size ==========================================================
134  localMsg( "reading view size..." );
135  view[ 0 ] = obj.getSizeX();
136  view[ 1 ] = obj.getSizeY();
137  view[ 2 ] = obj.getSizeZ();
138  view[ 3 ] = obj.getSizeT();
139 
140  //=== full volume size ===================================================
141  localMsg( "reading full volume size and view position..." );
142  if( parent1 && !parent1->allocatorContext().isAllocated() ) {
143  localMsg( " -> from parent1" )
144  size[ 0 ] = parent1->getSizeX();
145  size[ 1 ] = parent1->getSizeY();
146  size[ 2 ] = parent1->getSizeZ();
147  size[ 3 ] = parent1->getSizeT();
148  position[ 0 ] = obj.posInRefVolume()[ 0 ];
149  position[ 1 ] = obj.posInRefVolume()[ 1 ];
150  position[ 2 ] = obj.posInRefVolume()[ 2 ];
151  position[ 3 ] = obj.posInRefVolume()[ 3 ];
152  } else if( parent2 ) {
153  localMsg( " -> from parent2" )
154  size[ 0 ] = parent2->getSizeX();
155  size[ 1 ] = parent2->getSizeY();
156  size[ 2 ] = parent2->getSizeZ();
157  size[ 3 ] = parent2->getSizeT();
158  position[ 0 ] = obj.posInRefVolume()[ 0 ] + parent1->posInRefVolume()[ 0 ];
159  position[ 1 ] = obj.posInRefVolume()[ 1 ] + parent1->posInRefVolume()[ 1 ];
160  position[ 2 ] = obj.posInRefVolume()[ 2 ] + parent1->posInRefVolume()[ 2 ];
161  position[ 3 ] = obj.posInRefVolume()[ 3 ] + parent1->posInRefVolume()[ 3 ];
162  } else {
163  localMsg( " -> from self" )
164  size = view;
165  }
166 
167  if( !partial ) {
168  // we treat the view as a pure Volume
169  localMsg( " -> from self (no partial writing)" )
170  size = view;
171  position = std::vector<int>( 4, 0 );
172  }
173 
174  localMsg( " -> Full volume size : ( "
175  + carto::toString( size[0] ) + ", "
176  + carto::toString( size[1] ) + ", "
177  + carto::toString( size[2] ) + ", "
178  + carto::toString( size[3] ) + " )" );
179  localMsg( " -> View size : ( "
180  + carto::toString( view[0] ) + ", "
181  + carto::toString( view[1] ) + ", "
182  + carto::toString( view[2] ) + ", "
183  + carto::toString( view[3] ) + " )" );
184  localMsg( " -> View position : ( "
185  + carto::toString( position[0] ) + ", "
186  + carto::toString( position[1] ) + ", "
187  + carto::toString( position[2] ) + ", "
188  + carto::toString( position[3] ) + " )" );
189 
190  //=== checking for borders ===============================================
191  localMsg( "checking for borders..." );
192  bool withborders = false;
193  if( parent1 && parent1->allocatorContext().isAllocated() )
194  withborders = true;
195  localMsg( std::string(" -> ") + ( withborders ? "with borders" : "without borders" ) );
196 
197  //=== header info ========================================================
198  localMsg( "setting header..." );
199  if( !options )
201  if( !parent1 && !obj.allocatorContext().isAllocated() )
202  options->setProperty( "unallocated", true );
203  if( !dsi->header() )
204  {
206  dsi->header()->copyProperties(
207  carto::Object::reference( obj.header() ) );
208  }
209  dsi->header()->setProperty( "sizeX", size[ 0 ] );
210  dsi->header()->setProperty( "sizeY", size[ 1 ] );
211  dsi->header()->setProperty( "sizeZ", size[ 2 ] );
212  dsi->header()->setProperty( "sizeT", size[ 3 ] );
213  if( !dsi->header()->hasProperty( "voxel_size" ) )
214  {
215  std::vector<float> voxel_size( 4, 1. );
216  dsi->header()->setProperty( "voxel_size", voxel_size );
217  }
218 
219 
220  //=== use optional parameters for partial writing ========================
221  if( partial ) {
222  try {
223  position[0] = (int) rint( options->getProperty( "ox" )->getScalar() );
224 // localMsg( "override ox : " + carto::toString(position[0]) );
225  std::cout << "override ox : " + carto::toString(position[0]) << std::endl;
226  } catch( ... ) {}
227  try {
228  position[1] = (int) rint( options->getProperty( "oy" )->getScalar() );
229 // localMsg( "override oy : " + carto::toString(position[1]) );
230  std::cout << "override oy : " + carto::toString(position[1]) << std::endl;
231  } catch( ... ) {}
232  try {
233  position[2] = (int) rint( options->getProperty( "oz" )->getScalar() );
234 // localMsg( "override oz : " + carto::toString(position[2]) );
235  std::cout << "override oz : " + carto::toString(position[2]) << std::endl;
236  } catch( ... ) {}
237  try {
238  position[3] = (int) rint( options->getProperty( "ot" )->getScalar() );
239 // localMsg( "override ot : " + carto::toString(position[3]) );
240  std::cout << "override ot : " + carto::toString(position[3]) << std::endl;
241  } catch( ... ) {}
242  }
243 
244  //=== writing header & creating files ====================================
245  localMsg( "writing header..." );
246  std::vector<long> strides(4);
247  strides[0] = &obj(1,0,0,0) - &obj(0,0,0,0);
248  strides[1] = &obj(0,1,0,0) - &obj(0,0,0,0);
249  strides[2] = &obj(0,0,1,0) - &obj(0,0,0,0);
250  strides[3] = &obj(0,0,0,1) - &obj(0,0,0,0);
251  *dsi = _imw->writeHeader( *dsi, (T*) &obj(0,0,0,0), position, view,
252  strides, options );
253 
254  //=== sanity check =======================================================
255  if( partial )
256  {
257  // file sizes may be different from what has been set before (since
258  // the file already exists, its size has been re-read by writeHeader())
259  int file_dx, file_dy, file_dz, file_dt;
260  dsi->header()->getProperty( "sizeX", file_dx );
261  dsi->header()->getProperty( "sizeY", file_dy );
262  dsi->header()->getProperty( "sizeZ", file_dz );
263  dsi->header()->getProperty( "sizeT", file_dt );
264  if( position[0] + view[0] > file_dx
265  || position[1] + view[1] > file_dy
266  || position[2] + view[2] > file_dz
267  || position[3] + view[3] > file_dt )
268  {
269  localMsg( "view is larger than the volume." );
270  throw carto::format_error( "view is larger than the volume." );
271  }
272  }
273 
274  //=== writing image ======================================================
275  localMsg( "writing volume..." );
276  const T* data = 0;
277  if( parent1 || obj.allocatorContext().isAllocated() )
278  data = reinterpret_cast<const T*>( &obj(0,0,0,0) );
279  // in unallocated case, data is null; this is OK.
280  _imw->write( data, *dsi, position, view, strides, options );
281 // {
282 // // if( !withborders ) {
283 // _imw->write( (T*) &obj(0,0,0,0), *dsi, position, view, strides,
284 // options );
285 // // } else {
286 // // int y, z, t;
287 // // std::vector<int> posline ( position );
288 // // std::vector<int> sizeline ( 4, 1 );
289 // // sizeline[ 0 ] = view[ 0 ];
290 // // for( t=0; t<view[3]; ++t )
291 // // for( z=0; z<view[2]; ++z )
292 // // for( y=0; y<view[1]; ++y ) {
293 // // posline[ 1 ] = position[ 1 ] + y;
294 // // posline[ 2 ] = position[ 2 ] + z;
295 // // posline[ 3 ] = position[ 3 ] + t;
296 // // _imw->write( (T*) &obj(0,y,z,t), *dsi, posline,
297 // // sizeline, options );
298 // // }
299 // // }
300 // }
301  // else we just needed to write the header and reserve file space
302  // no image to write
303 
304  // we reset at 0 the ImageWriter's members (sizes, binary, ...) so that
305  // they are recomputed at the next writing.
306  _imw->resetParams();
307  return true;
308  }
309 
310  template <typename T>
312  {
313  _imw = imw;
314  }
315 
319 
320  template <typename T>
322  {
323  }
324 
325  template <typename T>
328  carto::Object options )
329  {
331  vfw.attach( _imw );
332  return vfw.write( *obj, dsi, options );
333  }
334 
335  template <typename T>
337  {
338  _imw = imw;
339  }
340 
341 }
342 
343 #undef localMsg
344 #endif
4D Volume main class
const Position4Di posInRefVolume() const
Get position in parent volume.
Definition: volumebase_d.h:451
std::string url() const
virtual bool getProperty(const std::string &key, Object &value) const =0
const AllocatorContext & allocatorContext() const
returns volume's AllocatorContext
Definition: volumebase_d.h:439
int getSizeT() const
Definition: volumeproxy.h:118
FormatWriter specialized for 4D Volume.
virtual bool hasProperty(const std::string &key) const =0
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)
MappingMode allocatorType() const
const PropertySet & header() const
const carto::Object & header() const
T * get() const
#define localMsg(message)
int getSizeZ() const
Definition: volumeproxy.h:108
rc_ptr< Volume< T > > refVolume() const
Get parent volume.
Definition: volumebase_d.h:445
int getSizeX() const
Definition: volumeproxy.h:88
#define soma
virtual void setProperty(const std::string &key, Object value)=0
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.
bool isAllocated() const
std::string toString(const T &object)
virtual void copyProperties(Object source)
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...
int getSizeY() const
Definition: volumeproxy.h:98