33 #include "WReaderVTK.h"
34 #include "core/common/WAssert.h"
35 #include "core/common/WIOTools.h"
36 #include "core/common/WLimits.h"
37 #include "core/common/WLogger.h"
38 #include "core/common/WStringUtils.h"
39 #include "core/dataHandler/WDataSet.h"
40 #include "core/dataHandler/WDataSetDTI.h"
41 #include "core/dataHandler/WDataSetRawHARDI.h"
42 #include "core/dataHandler/WDataSetScalar.h"
43 #include "core/dataHandler/WDataSetVector.h"
44 #include "core/dataHandler/WGridRegular3D.h"
45 #include "core/dataHandler/exceptions/WDHIOFailure.h"
46 #include "core/dataHandler/exceptions/WDHNoSuchFile.h"
47 #include "core/dataHandler/exceptions/WDHParseError.h"
60 std::shared_ptr< WDataSet > ds;
62 m_ifs = std::shared_ptr< std::ifstream >(
new std::ifstream() );
63 m_ifs->open(
m_fname.c_str(), std::ifstream::in | std::ifstream::binary );
66 throw WDHIOFailure( std::string(
"internal error while opening" ) );
75 std::shared_ptr< WGridRegular3D > grid;
95 std::shared_ptr< WValueSetBase > values =
readData( grid );
107 ds = std::shared_ptr< WDataSet >(
new WDataSetScalar( values, grid ) );
110 ds = std::shared_ptr< WDataSet >(
new WDataSetVector( values, grid ) );
113 ds = std::shared_ptr< WDataSet >(
new WDataSetDTI( values, grid ) );
116 if( values->dimension() > 6 )
118 std::shared_ptr< std::vector< WVector3d > > grads =
readGradients();
119 ds = std::shared_ptr< WDataSet >(
new WDataSetRawHARDI( values, grid, grads ) );
123 ds = std::shared_ptr< WDataSet >(
new WDataSetDTI( values, grid ) );
136 typedef std::vector< WVector3d > GradVec;
138 std::string gradientFileName =
m_fname;
139 std::string suffix = getSuffix(
m_fname );
141 WAssert( suffix ==
".vtk",
"Input file is not a vtk file." );
143 WAssert( gradientFileName.length() > 4,
"" );
144 gradientFileName.resize( gradientFileName.length() - 4 );
145 gradientFileName +=
".bvec";
148 std::ifstream i( gradientFileName.c_str() );
149 if( i.bad() || !i.is_open() )
160 std::vector< double > values;
165 values.push_back( d );
169 if( values.size() % 3 != 0 )
171 values.resize( values.size() / 3 );
174 std::shared_ptr< GradVec > newGradients(
new GradVec( values.size() / 3 ) );
176 for( std::size_t j = 0; j < values.size() / 3; ++j )
178 ( *newGradients )[ j ] =
WVector3d( values[ 3 * j + 0 ], values[ 3 * j + 1 ], values[ 3 * j + 2 ] );
183 return std::shared_ptr< GradVec >();
188 for(
int i = 0; i < 4; ++i )
194 if( (
m_header.at( 0 ) !=
"# vtk DataFile Version 3.0" )
195 && (
m_header.at( 0 ) !=
"# vtk DataFile Version 2.0" ) )
197 wlog::error(
"WReaderVTK" ) <<
"Unsupported format version string in VTK file: "
205 wlog::warn(
"WReaderVTK" ) <<
"Invalid header size of VTK file: "
207 <<
", max. 256 but got: "
211 if( ( su::toUpper( su::trim(
m_header.at( 2 ) ) ) !=
"BINARY" )
212 &&( su::toUpper( su::trim(
m_header.at( 2 ) ) ) !=
"ASCII" ) )
214 wlog::error(
"WReaderVTK" ) <<
"VTK files in '" <<
m_header.at( 2 ) <<
"' format are not yet supported. Must be BINARY or ASCII";
220 if( su::tokenize(
m_header.at( 3 ) ).size() == 2 )
222 if( su::toUpper( su::tokenize(
m_header.at( 3 ) )[1] ) ==
"STRUCTURED_POINTS" )
226 else if( su::toUpper( su::tokenize(
m_header.at( 3 ) )[1] ) ==
"RECTILINEAR_GRID" )
232 wlog::error(
"WReaderVTK" ) <<
"Cannot read this VTK DATASET type: " << su::tokenize(
m_header.back() )[1];
238 wlog::error(
"WReaderVTK" ) <<
"Cannot read this VTK DATASET type: " << su::tokenize(
m_header.back() )[1];
247 std::string line =
getLine(
"reading DIMENSIONS" );
249 if( ( dimensions_line.size() != 4 ) &&
string_utils::toLower( dimensions_line.at( 0 ) ) !=
"dimensions" )
251 throw WDHParseError( std::string(
"invalid DIMENSIONS token: " + line +
", expected DIMENSIONS." ) );
254 size_t dimensions[ 3 ];
255 dimensions[ 0 ] = getLexicalCast< size_t >( dimensions_line.at( 1 ),
"" );
256 dimensions[ 1 ] = getLexicalCast< size_t >( dimensions_line.at( 2 ),
"" );
257 dimensions[ 2 ] = getLexicalCast< size_t >( dimensions_line.at( 3 ),
"" );
259 line =
getLine(
"reading ORIGIN" );
263 throw WDHParseError( std::string(
"invalid ORIGIN token: " + line +
", expected ORIGIN." ) );
267 origin[ 0 ] = getLexicalCast< float >( origin_line.at( 1 ),
"" );
268 origin[ 1 ] = getLexicalCast< float >( origin_line.at( 2 ),
"" );
269 origin[ 2 ] = getLexicalCast< float >( origin_line.at( 3 ),
"" );
271 line =
getLine(
"reading SPACING" );
275 throw WDHParseError( std::string(
"invalid DIMENSIONS token: " + line +
", expected DIMENSIONS." ) );
278 double spacings[ 3 ];
279 spacings[ 0 ] = getLexicalCast< float >( spacings_line.at( 1 ),
"" );
280 spacings[ 1 ] = getLexicalCast< float >( spacings_line.at( 2 ),
"" );
281 spacings[ 2 ] = getLexicalCast< float >( spacings_line.at( 3 ),
"" );
286 return std::shared_ptr< WGridRegular3D >(
new WGridRegular3D( dimensions[ 0 ], dimensions[ 1 ], dimensions[ 2 ], transform ) );
291 std::string line =
getLine(
"reading DIMENSIONS" );
293 if( ( dimensions_line.size() != 4 ) &&
string_utils::toLower( dimensions_line.at( 0 ) ) !=
"dimensions" )
295 throw WDHParseError( std::string(
"invalid DIMENSIONS token: " + line +
", expected DIMENSIONS." ) );
298 size_t dimensions[ 3 ];
299 dimensions[ 0 ] = getLexicalCast< size_t >( dimensions_line.at( 1 ),
"" );
300 dimensions[ 1 ] = getLexicalCast< size_t >( dimensions_line.at( 2 ),
"" );
301 dimensions[ 2 ] = getLexicalCast< size_t >( dimensions_line.at( 3 ),
"" );
303 std::vector< float > xcoords;
304 readCoords(
"X_COORDINATES", dimensions[ 0 ], xcoords );
305 std::vector< float > ycoords;
306 readCoords(
"Y_COORDINATES", dimensions[ 1 ], ycoords );
307 std::vector< float > zcoords;
308 readCoords(
"Z_COORDINATES", dimensions[ 2 ], zcoords );
310 wlog::warn(
"WReaderVTK" ) <<
"Assuming evenly spaced rectilinear grid! This may not adhere to the domain data in the file!";
312 WGridTransformOrtho transform( xcoords.at( 1 ) - xcoords.at( 0 ), ycoords.at( 1 ) - ycoords.at( 0 ), zcoords.at( 1 ) - zcoords.at( 0 ) );
313 return std::shared_ptr< WGridRegular3D >(
new WGridRegular3D( dimensions[ 0 ], dimensions[ 1 ], dimensions[ 2 ], transform ) );
318 std::string line =
getLine( std::string(
"reading " ) + name );
322 throw WDHParseError( std::string(
"invalid " ) + name +
" token: " + line +
", expected " + name +
"!" );
336 std::string line =
getLine(
"Data" );
340 while( point < numValues )
342 for(
size_t token = 0; token < tokens.size(); ++token )
344 values.push_back( getLexicalCast< float >( tokens.at( token ),
"invalid data point" ) );
346 if( point > numValues )
348 throw WDHException( std::string(
"Too many points in file" ) );
351 if( point < numValues )
361 m_ifs->read(
reinterpret_cast<char*
>( &values[ 0 ] ), values.size() *
sizeof( values[ 0 ] ) );
370 std::size_t pos =
m_ifs->tellg();
372 std::string line =
getLine(
"LookupTableOrData" );
376 pos =
m_ifs->tellg();
379 m_ifs->seekg( pos, std::ios::beg );
381 std::shared_ptr< std::vector< float > > data(
new std::vector< float >() );
385 return std::shared_ptr< WValueSetBase >(
new WValueSet< float >( 0, 1, data, W_DT_FLOAT ) );
390 int pos =
m_ifs->tellg();
393 std::string line =
getLine(
"LookupTableOrData" );
399 pos =
m_ifs->tellg();
402 m_ifs->seekg( pos, std::ios::beg );
407 const size_t dimension = 3;
408 std::shared_ptr< std::vector< float > > data(
new std::vector< float >( nbPoints * dimension ) );
412 return std::shared_ptr< WValueSetBase >(
new WValueSet< float >( 1, 3, data, W_DT_FLOAT ) );
420 int pos =
m_ifs->tellg();
423 std::string line =
getLine(
"LookupTableOrData" );
427 pos =
m_ifs->tellg();
430 m_ifs->seekg( pos, std::ios::beg );
432 std::size_t dimension = 9;
438 std::shared_ptr< std::vector< float > > data(
new std::vector< float >( nbPoints * dimension ) );
445 for( std::size_t k = 0; k < data->size(); ++k )
447 std::size_t m = k % 9;
448 if( m != 3 && m != 6 && m != 7 )
450 ( *data )[ idx ] = ( *data )[ k ];
454 data->resize( nbPoints * 6 );
457 return std::shared_ptr< WValueSetBase >(
new WValueSet< float >( 1, 6, data, W_DT_FLOAT ) );
463 std::shared_ptr< WValueSetBase >
WReaderVTK::readHARDI( std::size_t nbPoints, std::size_t nbGradients,
const std::string& )
465 int pos =
m_ifs->tellg();
468 std::string line =
getLine(
"LookupTableOrData" );
474 pos =
m_ifs->tellg();
477 m_ifs->seekg( pos, std::ios::beg );
482 std::shared_ptr< std::vector< float > > data(
new std::vector< float >( nbPoints * nbGradients ) );
486 return std::shared_ptr< WValueSetBase >(
new WValueSet< float >( 1, nbGradients, data, W_DT_FLOAT ) );
495 std::string line =
getLine(
"POINT_DATA declaration" );
500 throw WDHException( std::string(
"Invalid SCALARS tag" ) );
503 size_t nbPoints = getLexicalCast< size_t >( tokens.at( 1 ),
"parsing number of points" );
505 line =
getLine(
"SCALARS declaration" );
508 std::string name =
"Default";
509 if( tokens.size() >= 2 )
511 name = tokens.at( 1 );
528 else if( tokens.size() == 4 &&
string_utils::toUpper( tokens.at( 0 ) ) ==
"ARRAYS" && tokens.at( 2 ) ==
"6" )
533 else if( tokens.size() == 4 &&
string_utils::toUpper( tokens.at( 0 ) ) ==
"ARRAYS" && getLexicalCast< std::size_t >( tokens.at( 2 ),
"" ) > 6 )
536 std::size_t k = getLexicalCast< std::size_t >( tokens.at( 2 ),
"" );
541 throw WDHException( std::string(
"Invalid SCALARS or VECTORS tag" ) );
552 std::getline( *
m_ifs, line,
'\n' );
554 catch(
const std::ios_base::failure &e )
556 throw WDHIOFailure( std::string(
"IO error while " + desc +
" of VTK fiber file: " +
m_fname +
", " + e.what() ) );
General purpose exception and therefore base class for all DataHandler related exceptions.
Use this for IO error handling.
Use this for IO error handling.
Represents a Diffusion-Tensor-Image dataset.
This data set type contains raw HARDI and its gradients.
This data set type contains scalars as values.
This data set type contains vectors as values.
A grid that has parallelepiped cells which all have the same proportion.
std::shared_ptr< WValueSetBase > readVectors(size_t nbVectors, const std::string &name)
Read VTK SCALARS field.
std::shared_ptr< std::ifstream > m_ifs
Pointer to the input file stream reader.
WReaderVTK(std::string fname)
Constructs and makes a new VTK reader for separate thread start.
void readCoords(std::string const &name, std::size_t dim, std::vector< float > &coords)
Read the coordinates of the dataset's domain.
std::shared_ptr< WGridRegular3D > readStructuredPoints()
Read VTK Domain specification and create a matching grid.
bool readHeader()
Read VTK header from file.
std::shared_ptr< WValueSetBase > readTensors(size_t nbTensors, const std::string &name)
Read VTK TENSORS field.
@ RECTILINEAR_GRID
rectilinear grid
@ STRUCTURED_POINTS
structured points
std::shared_ptr< WGridRegular3D > readRectilinearGrid()
Read VTK Domain specification and create a matching grid.
void readValuesFromFile(std::vector< float > &values, std::size_t numValues)
Read values from the file.
AttributeType m_attributeType
The type of the attributes first read from the file.
bool m_isASCII
internal flag whether we read ascii or binary
std::shared_ptr< WValueSetBase > readHARDI(std::size_t nbPoints, std::size_t nbGradients, const std::string &)
Read HARDI data from the file.
std::shared_ptr< std::vector< WVector3d > > readGradients()
Read gradients from a gradients file which has the same basename as the data file and ends in ....
std::shared_ptr< WValueSetBase > readScalars(size_t nbScalars, const std::string &name)
Read VTK SCALARS field.
DomainType m_domainType
The type of domain specified in the file.
virtual std::shared_ptr< WDataSet > read()
Reads the data file and creates a dataset out of it.
virtual ~WReaderVTK()
Destroys this instance and closes the file.
std::shared_ptr< WValueSetBase > readData(std::shared_ptr< WGridRegular3D > const &grid)
Read domain information for structured points.
std::string getLine(const std::string &desc)
Reads the next line from current position in stream of the fiber VTK file.
std::vector< std::string > m_header
VTK header of the read file.
Read some data from a given file.
std::string m_fname
Absolute path of the file to read from.
Base Class for all value set types.
Some utilities for string manipulation and output operations.
std::string toLower(const std::string &source)
Transforms all characters in the given string into lower case characters.
std::string toUpper(const std::string &source)
Transforms all characters in the given string into upper case characters.
std::vector< std::string > tokenize(const std::string &source, const std::string &delim=WHITESPACE, bool compress=true)
Splits the given string into a vector of strings (so called tokens).
WStreamedLogger debug(const std::string &source)
Logging a debug message.
WStreamedLogger warn(const std::string &source)
Logging a warning message.
WStreamedLogger error(const std::string &source)
Logging an error message.