aimsdata 6.0.0
Neuroimaging data handling
fssurfformatreader_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_SOMA_FSSURFFORMATREADER_D_H
35#define AIMS_IO_SOMA_FSSURFFORMATREADER_D_H
36
37//-------------------------------------------------------------------
39#include <aims/mesh/surface.h>
41#include <soma-io/datasourceinfo/datasourceinfoloader.h>
43#include <cartobase/stream/stringutil.h>
46//--- debug ------------------------------------------------------------------
47#include <cartobase/config/verbose.h>
48#define localMsg( message ) cartoCondMsg( 4, message, "FSSURFFORMATREADER" )
49// localMsg must be undef at end of file
50//----------------------------------------------------------------------------
51
52
53// from http://www.grahamwideman.com/gw/brain/fs/surfacefileformats.htm
54
55namespace soma
56{
57
58 template <int D>
60 FsSurfFormatReader<D>::createAndRead( rc_ptr<DataSourceInfo> dsi,
61 const AllocatorContext & context,
62 Object options )
63 {
64 carto::rc_ptr<soma::DataSource> ds = dsi->list().dataSource();
65 localMsg( "createAndRead " + ds->url() );
67 try
68 {
69 read( *mesh, dsi, context, options );
70 }
71 catch( ... )
72 {
73 delete mesh;
74 throw;
75 }
76 mesh->header().copyProperties( dsi->header() );
77 return mesh;
78 }
79
80
81 template <int D>
83 rc_ptr<DataSourceInfo> dsi,
84 const AllocatorContext & /* context */,
85 Object options )
86 {
87 // std::cout << "FsSurfFormatReader::read " << dsi->list().dataSource()->url() << std::endl;
88 carto::rc_ptr<DataSource> ds = dsi->list().dataSource();
89
90 if( !ds->isOpen() )
91 {
92 std::cout << "WARNING: reopening freesurfer surf file at beginning\n";
93 ds->open( DataSource::Read ); // FIXME recover offset
94 }
95 if( !ds->isOpen() )
96 throw file_not_found_error( ds->url() );
97
98 carto::Object hdr = dsi->header();
99
100 int asciii = 0;
101 int bswapi = 0;
102 hdr->getProperty( "ascii", asciii );
103 bool ascii = bool( asciii );
104 hdr->getProperty( "byte_swapping", bswapi );
105 bool bswap = bool( bswapi );
106 int nv = 0, np = 0, ps;
107 hdr->getProperty( "vertex_number", nv );
108 hdr->getProperty( "polygon_number", np );
109 // hdr->getProperty( "polygon_dimension", ps );
110
111 if( !readVertices( ds, obj, nv, ascii, bswap ) )
112 throw carto::invalid_format_error( ds->url() );
113 if( !readPolygons( ds, obj, np, ascii, bswap ) )
114 throw carto::invalid_format_error( ds->url() );
115 readAdditions( ds, obj, ascii, bswap );
116
118 rc_ptr<DataSource> mds( 0 );
119 try
120 {
121 mds = dsi->list().dataSource( "minf" );
122 if( mds.get() )
123 DataSourceInfoLoader::readMinf( *mds, hdr, options );
124 }
125 catch( ... )
126 {
127 }
128
129 obj.header().copyProperties( hdr );
130 if( dsi->header().get() )
131 obj.header().copyProperties( dsi->header() );
132
133 // std::cout << "read FSSURF OK\n";
134 }
135
136
137 template <int D>
140 {
141 return new FsSurfFormatReader;
142 }
143
144
145 template <int D>
148 int nv, bool ascii,
149 bool bswap ) const
150 {
151 // std::cout << "readVertices: " << nv << ", " << ascii << ", " << bswap << std::endl;
152
154 std::unique_ptr<ItemReader<float> > itemr;
155 itemr.reset( dir.reader( !ascii, bswap ) );
156
157 std::vector<Point3df> & vert = obj.vertex();
158 vert.resize( nv );
159
160 long n = itemr->read( *ds, (float *) &vert[0], nv * 3 );
161 if( n != nv * 3 )
162 return false;
163
164 return true;
165 }
166
167
168 template <int D>
171 int np, bool ascii,
172 bool bswap ) const
173 {
174 // std::cout << "readPolygons: " << np << ", " << ascii << ", " << bswap << std::endl;
175
177 std::unique_ptr<ItemReader<uint32_t> > itemr;
178 itemr.reset( dir.reader( !ascii, bswap ) );
179
180 std::vector<AimsVector<uint32_t, D> > & poly = obj.polygon();
181 poly.resize( np );
182
183 long n = itemr->read( *ds, (uint32_t *) &poly[0], np * D );
184 if( n != np * D )
185 return false;
186
187 return true;
188 }
189
190
191 template <int D>
194 bool ascii, bool bswap ) const
195 {
196 // std::cout << "readAdditions: " << ascii << ", " << bswap << std::endl;
197
199 std::unique_ptr<ItemReader<uint32_t> > itemr;
200 itemr.reset( dir.reader( !ascii, bswap ) );
201
202 std::vector<uint32_t> dat( 3 );
203
204 long n = itemr->read( *ds, &dat[0], 3 );
205 // 0: should be 3 (magic number), 2: should be 0x14 (magic num)
206 if( n != 3 || dat[0] != 2 || dat[2] != 0x14 )
207 return false;
208 bool using_old_real_ras = bool( dat[1] );
209 obj.header().setProperty( "using_old_real_ras",
210 int( using_old_real_ras ) );
211
212 int i;
213 bool r;
214 std::vector<std::string> lines( 8 );
216 bool has_trans = false;
217
218 for( i=0; i<8; ++i )
219 {
220 r = StreamUtil::getline( *ds, lines[i] );
221 if( !r )
222 return false;
223 lines[i] = StringUtil::strip( lines[i] );
224 std::vector<std::string> val = StringUtil::split( lines[i], "=", 1 );
225 if( val.size() == 2 )
226 {
227 val[0] = StringUtil::strip( val[0] );
228 val[1] = StringUtil::strip( val[1] );
229 if( val[0] == "valid" )
230 continue;
231 if( val[0] == "volume" )
232 {
233 std::vector<std::string> sdims = StringUtil::split( val[1], " " );
234 std::vector<int> dims( sdims.size() );
235 for( int j=0; j<sdims.size(); ++j )
236 {
237 std::stringstream s( sdims[j] );
238 s >> dims[j];
239 }
240 obj.header().setProperty( "volume_dimension", dims );
241 }
242 else if( val[0] == "filename" )
243 obj.header().setProperty( "freesurfer_filename", val[1] );
244 else if( val[0] == "voxelsize" )
245 {
246 std::vector<std::string> svs = StringUtil::split( val[1], " " );
247 std::vector<float> vs( svs.size() );
248 for( int j=0; j<svs.size(); ++j )
249 {
250 std::stringstream s( svs[j] );
251 s >> vs[j];
252 }
253 obj.header().setProperty( "voxel_size", vs );
254 }
255 else if( val[0] == "xras" || val[0] == "yras" || val[0] == "zras"
256 || val[0] == "cras" )
257 {
258 int c = 0;
259 if( val[0][0] == 'x' )
260 c = 0;
261 else if( val[0][0] == 'y' )
262 c = 1;
263 else if( val[0][0] == 'z' )
264 c = 2;
265 else
266 c = 3;
267 std::vector<std::string> sv = StringUtil::split( val[1], " " );
268 for( int j=0; j<sv.size(); ++j )
269 {
270 std::stringstream s( sv[j] );
271 s >> tr.matrix()( j, c );
272 }
273 has_trans = true;
274 }
275 }
276 }
277 if( has_trans )
278 {
279 std::vector<std::vector<float> > trvec(2);
280 // the matrix content seem to go to another orientation (mni305?)
282 tr2.setTranslation( tr.translation() );
283 trvec[0] = tr2.toVector();
284 trvec[1] = tr.toVector();
285 obj.header().setProperty( "transformations", trvec );
286 std::vector<std::string> sref(2);
288 obj.header().setProperty( "referentials", sref );
289 sref[1] = "mni305?";
290 obj.header().setProperty( "referentials", sref );
291 }
292
293 n = itemr->read( *ds, &dat[0], 3 );
294 // should be 3 (magic number)
295 if( n != 3 || dat[0] != 3 )
296 return false;
297 unsigned len = dat[2];
298 std::string line;
299 r = StreamUtil::getline( *ds, line );
300 if( !r )
301 return false;
302 obj.header().setProperty( "freesurfer_cmdline", line );
303
304 return true;
305 }
306
307}
308
309#undef localMsg
310
311#endif
The template class to manage a mesh with time if needed.
Definition surface.h:317
const aims::PythonHeader & header() const
Get the header.
Definition surface.h:332
const std::vector< AimsVector< uint, D > > & polygon() const
Get a const reference to the vector of polygons of the 0 surface.
Definition surface.h:366
const std::vector< Point3df > & vertex() const
Get a const reference to the vector of verteces of the surface of index 0.
Definition surface.h:348
static std::string commonScannerBasedReferential()
virtual void copyProperties(Object source)
static Object value()
virtual void setProperty(const std::string &, Object)
void setTranslation(Point3df trans)
std::vector< float > toVector() const
static carto::Object readMinf(DataSource &ds, carto::Object base=carto::none(), carto::Object options=carto::none())
virtual ItemReader< T > * reader(bool binary=true, bool bswap=false) const
Freesurfer surface format for a mesh.
virtual AimsTimeSurface< D, Void > * createAndRead(carto::rc_ptr< DataSourceInfo > dsi, const AllocatorContext &context, carto::Object options)
virtual FormatReader< AimsTimeSurface< D, Void > > * clone() const
virtual void read(AimsTimeSurface< D, Void > &obj, carto::rc_ptr< DataSourceInfo > dsi, const AllocatorContext &context, carto::Object options)
bool readVertices(carto::rc_ptr< DataSource > ds, AimsTimeSurface< D, Void > &obj, int nv, bool ascii, bool bswap) const
bool readPolygons(carto::rc_ptr< DataSource > ds, AimsTimeSurface< D, Void > &obj, int np, bool ascii, bool bswap) const
bool readAdditions(carto::rc_ptr< DataSource > ds, AimsTimeSurface< D, Void > &obj, bool ascii, bool bswap) const
static bool getline(DataSource &ds, std::string &)
#define localMsg(message)
Definition reader_d.h:48