aimsdata 6.0.0
Neuroimaging data handling
spmW_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 AIMS_IO_SPMW_D_H
35#define AIMS_IO_SPMW_D_H
36
37#include <cstdlib>
38#include <aims/io/spmW.h>
40#include <aims/def/settings.h>
41#include <aims/io/spmheader.h>
45#include <cartobase/stream/fileutil.h>
46#include <stdio.h>
47
48namespace aims
49{
50
51 template <class T>
52 void SpmWriter<T>::write( const AimsData<T>& thing )
53 {
55
56 SpmHeader hdr( thing.dimX(), thing.dimY(), thing.dimZ(), thing.dimT(),
57 thing.sizeX(), thing.sizeY(), thing.sizeZ(),
58 thing.sizeT(), _name );
59
60 // Flip if necessary
61 const PythonHeader
62 *ph = dynamic_cast<const PythonHeader *>( thing.header() );
63 if( ph )
64 {
65 hdr.copy( *ph );
66 std::vector<int> dims(4);
67 dims[0] = thing.dimX();
68 dims[1] = thing.dimY();
69 dims[2] = thing.dimZ();
70 dims[3] = thing.dimT();
71 hdr.setProperty( "volume_dimension", dims );
72 std::vector<float> vs(4);
73 vs[0] = thing.sizeX();
74 vs[1] = thing.sizeY();
75 vs[2] = thing.sizeZ();
76 vs[3] = thing.sizeT();
77 hdr.setProperty( "voxel_size", vs );
78 // remove specific attribute that may be incompatible
79 if( hdr.hasProperty( "SPM_data_type" ) )
80 hdr.removeProperty( "SPM_data_type" );
81 if( hdr.hasProperty( "disk_data_type" ) )
82 hdr.removeProperty( "disk_data_type" );
83 if( hdr.hasProperty( "possible_data_types" ) )
84 hdr.removeProperty( "possible_data_types" );
85 }
86
87 std::string code = carto::DataTypeCode<T>().dataType();
88 hdr.setupWriteAttributes( code );
89
90 int y, z, x, dx, f;
91 T vmin = thing( 0 ), vmax = thing( 0 );
92 bool shen = false;
93 float offset = 0, scale = 1;
94
95 if( code == "FLOAT" || code == "DOUBLE" )
96 {
97 double maxm = 0;
98 shen = canEncodeAsScaledS16( *thing.volume(), scale, offset, false,
99 &maxm );
100 if( shen )
101 {
102 std::cout << "16 bit coding possible: scale: " << scale
103 << ", max error: " << maxm << std::endl;
104 hdr.setProperty( "disk_data_type",
106 );
107 hdr.setProperty( "scale_factor_applied", int(0) );
108 hdr.setProperty( "scale_factor", scale );
109 }
110 else
111 std::cout << "matching interval not found. Not 16 bit codable\n";
112 }
113 ForEach4d( thing, x, y, z, f )
114 {
115 if( thing( x, y, z, f ) < vmin )
116 vmin = thing( x, y, z, f );
117 if( thing( x, y, z, f ) > vmax )
118 vmax = thing( x, y, z, f );
119 }
120
121 if( shen )
122 hdr.setProperty( "bits_allocated", (int) 16 );
123 else
124 hdr.setProperty( "bits_allocated", (int) ( sizeof( T ) * 8 ) );
125 hdr.setProperty( "minimum", (int) vmin ) ;
126 hdr.setProperty( "maximum", (int) vmax ) ;
127
128 const Settings sett = Settings::settings();
129 bool write4d = true;
130 try
131 {
132 write4d = (bool)
133 sett.getProperty( "spm_output_4d_volumes" )->getScalar();
134 }
135 catch( std::exception & )
136 {
137 }
138
139 // prepare header without writing it
140 hdr.write( false, write4d );
141
142 std::vector<float> vstom;
143 Motion stom;
144 if( hdr.getProperty( "storage_to_memory", vstom ) )
145 stom = Motion( vstom );
146 else
147 {
148 std::cout << "no storage_to_memory in SPM header\n";
149 // no storage orientation: take a default one
150 stom.rotation()(1,1) = -1;
151 stom.rotation()(2,2) = -1;
152 stom.matrix()(1, 3) = thing.dimY() - 1;
153 stom.matrix()(2, 3) = thing.dimZ() - 1;
154 bool radio = true;
155 try
156 {
157 radio = (bool) hdr.getProperty( "spm_radio_convention" )->getScalar();
158 }
159 catch( std::exception & )
160 {
161 }
162 if( !radio )
163 {
164 stom.rotation()(0,0) = -1;
165 stom.matrix()(0, 3) = thing.dimX() - 1;
166 }
167 }
168
169 std::unique_ptr<AffineTransformation3d> m2s = stom.inverse();
170 Point3df df = m2s->transformVector( Point3df( thing.dimX(), thing.dimY(),
171 thing.dimZ() ) );
172 Point4d tdims = Point4d( short( rint( fabs( df[0] ) ) ),
173 short( rint( fabs( df[1] ) ) ),
174 short( rint( fabs( df[2] ) ) ), thing.dimT() );
175 Point3df incf = stom.transform( Point3df( 1, 0, 0 ) )
176 - stom.transform( Point3df( 0, 0, 0 ) );
177 Point4d inc = Point4d( int16_t( rint( incf[0] ) ),
178 int16_t( rint( incf[1] ) ),
179 int16_t( rint( incf[2] ) ), 0 );
180
181 dx = tdims[0];
182 std::vector<int16_t> datashort;
184 if( shen )
185 datashort.insert( datashort.end(), dx, 0 );
186 std::vector<T> data( dx );
187
188 Point3df d0f;
189 Point4d d0;
190
191 if( write4d || thing.dimT() == 1 )
192 {
193 std::string fname = removeExtension( _name );
194 hdr.setName( fname );
195 hdr.write();
196
197 std::string name = removeExtension( fname ) + ".img";
198 _os.open( name.c_str(), std::ios::out | std::ios::binary );
199 _os.unsetf( std::ios::skipws );
200
201 for ( f=0; f < tdims[3]; f++)
202 for ( z=0;z<tdims[2];z++)
203 {
204 for ( y=0;y<tdims[1];y++)
205 {
206 d0f = stom.transform( Point3df( 0, y, z ) );
207 d0 = Point4d( int16_t( rint( d0f[0] ) ), int16_t( rint( d0f[1] ) ),
208 int16_t( rint( d0f[2] ) ), f );
209 if( shen )
210 {
211 for( x=0; x < dx; ++x, d0+=inc )
212 datashort[ x ] = (int16_t) rint( thing( d0 ) / scale );
213 itemWs.write( _os, &datashort[0] , dx );
214 }
215 else if( inc == Point4d( 1, 0, 0, 0 ) )
216 itemW.write( _os, &thing( d0 ) , dx );
217 else
218 {
219 for( x=0; x < dx; ++x, d0+=inc )
220 data[ x ] = thing( d0 );
221 itemW.write( _os, &data[0] , dx );
222 }
223 }
224 }
225
226 _os.close();
227 }
228 else
229 {
230 char sequence[16];
231 int f, nt = thing.dimT();
232 std::vector<std::string> fnames;
233 std::string dname, bname;
234 dname = carto::FileUtil::dirname( _name )
236 bname = carto::FileUtil::basename( removeExtension( _name ) );
237
238 fnames.reserve( nt );
239 for( f=0; f<nt; ++f )
240 {
241 sprintf( sequence, "%04d", f );
242 fnames.push_back( bname + std::string( sequence ) + ".img" );
243 }
244 hdr.setProperty( "series_filenames", fnames );
245
246 // Do the job for each frame
247 for( f=0; f < nt; ++f )
248 {
249 std::string name = dname + fnames[f];
250 hdr.setName( name );
251 hdr.write( f == 0, false );
252
253 _os.open( name.c_str(), std::ios::out | std::ios::binary );
254 _os.unsetf( std::ios::skipws );
255
256 for (int z=0;z<tdims[2];z++)
257 for (int y=0;y<tdims[1];y++)
258 {
259 d0f = stom.transform( Point3df( 0, y, z ) );
260 d0 = Point4d( int16_t( rint( d0f[0] ) ), int16_t( rint( d0f[1] ) ),
261 int16_t( rint( d0f[2] ) ), f );
262 if( shen )
263 {
264 for( x=0; x < dx; ++x, d0+=inc )
265 datashort[ x ] = (int16_t) rint( thing( d0 ) / scale );
266 itemWs.write( _os, &datashort[0] , dx );
267 }
268 else if( inc == Point4d( 1, 0, 0, 0 ) )
269 itemW.write( _os, &thing( d0 ) , dx );
270 else
271 {
272 for( x=0; x < dx; ++x, d0+=inc )
273 data[ x ] = thing( d0 );
274 itemW.write( _os, &data[0] , dx );
275 }
276 }
277
278 _os.close();
279 }
280 }
281 }
282
283}
284
285#endif
#define ForEach4d(thing, x, y, z, t)
carto::VolumeRef< T > & volume()
float sizeX() const
float sizeT() const
int dimY() const
int dimX() const
int dimT() const
float sizeZ() const
float sizeY() const
int dimZ() const
const aims::Header * header() const
std::unique_ptr< AffineTransformation3d > inverse() const
carto::VolumeRef< float > rotation()
Default low-levels writers.
virtual void write(std::ostream &os, const T &item) const
Attributed python-like header, stores all needed information about an object, currently used for volu...
Definition pheader.h:52
virtual void copy(const PythonHeader &, bool keepUuid=false)
static Settings & settings()
SPM Header class.
Definition spmheader.h:54
void setName(const std::string &fname)
Definition spmheader.h:62
void setupWriteAttributes(const std::string &datatypecode)
bool write(bool writeMinf=true, bool allow4d=true)
void write(const AimsData< T > &thing)
Write the data with "name" file name to disk.
Definition spmW_d.h:52
std::string removeExtension(const std::string &name)
Return a name without .hdr or .img extension.
Definition spmW.h:87
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)
virtual bool hasProperty(const std::string &) const
Point3dd transform(double x, double y, double z) const
The class for EcatSino data write operation.
bool canEncodeAsScaledS16(const carto::Volume< T > &vol, float &slope, float &offset, bool enableoffset=true, double *maxerr=0)
Checks if a volume can be encoded as 16 bit signed ints with a scale factor and optionally an offset.
aims::AffineTransformation3d Motion
Definition spmR.h:52
AimsVector< float, 3 > Point3df
AimsVector< int16_t, 4 > Point4d