OpenWalnut  1.5.0dev
WReaderFiberVTK.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <cstdlib>
26 #include <fstream>
27 #include <memory>
28 #include <stdint.h>
29 #include <string>
30 #include <vector>
31 
32 
33 #include "WReaderFiberVTK.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/WDataSetFibers.h"
40 #include "core/dataHandler/exceptions/WDHIOFailure.h"
41 #include "core/dataHandler/exceptions/WDHNoSuchFile.h"
42 #include "core/dataHandler/exceptions/WDHParseError.h"
43 
45  : WReader( fname )
46 {
47 }
48 
50 {
51 }
52 
53 std::shared_ptr< WDataSetFibers > WReaderFiberVTK::read()
54 {
55  m_ifs = std::shared_ptr< std::ifstream >( new std::ifstream() );
56  m_ifs->open( m_fname.c_str(), std::ifstream::in | std::ifstream::binary );
57  if( !m_ifs || m_ifs->bad() )
58  {
59  throw WDHIOFailure( std::string( "internal error while opening file" ) );
60  }
61  readHeader();
62  readPoints();
63  readLines();
64  readValues();
65 
66  std::shared_ptr< WDataSetFibers > fibers( new WDataSetFibers( m_points, m_fiberStartIndices,
68 
69  fibers->setFilename( m_fname );
70 
71  m_ifs->close();
72  return fibers;
73 }
74 
76 {
77  for( int i = 0; i < 4; ++i ) // strip first four lines
78  {
79  m_header.push_back( getLine( "reading first 4 lines (aka header)" ) );
80  }
81 
82  // check if the header may be valid for the .fib format
83  if( m_header.at( 0 ) != "# vtk DataFile Version 3.0" )
84  {
85  wlog::error( "WReaderFiberVTK" ) << "Unsupported format version string in VTK fiber file: "
86  << m_fname
87  << ", "
88  << m_header.at( 0 );
89  }
90  if( m_header.at( 1 ).size() > 256 )
91  {
92  wlog::warn( "WReaderFiberVTK" ) << "Invalid header size of VTK fiber file: "
93  << m_fname
94  << ", max. 256 but got: "
95  << string_utils::toString( m_header.at( 1 ).size() );
96  }
97  namespace su = string_utils;
98  if( su::toUpper( su::trim( m_header.at( 2 ) ) ) != "BINARY" )
99  {
100  wlog::error( "WReaderFiberVTK" ) << "VTK files in '" << m_header.at( 2 ) << "' format are not yet supported";
101  }
102  if( su::tokenize( m_header.at( 3 ) ).size() < 2 || su::toUpper( su::tokenize( m_header.at( 3 ) )[1] ) != "POLYDATA" )
103  {
104  wlog::error( "WReaderFiberVTK" ) << "Invalid fiber VTK DATASET type: " << su::tokenize( m_header.back() )[1];
105  }
106 }
107 
109 {
110  std::string line = getLine( "reading POINTS declaration" );
111 
112  std::vector< std::string > tokens = string_utils::tokenize( line );
113  if( tokens.size() != 3 || string_utils::toLower( tokens.at( 2 ) ) != "float" )
114  {
115  throw WDHParseError( std::string( "Invalid POINTS declaration: " + line + ", expected float." ) );
116  }
117 
118  size_t numPoints = getLexicalCast< size_t >( tokens.at( 1 ), "Invalid number of points" );
119 
120  float *pointData = new float[ 3 * numPoints ];
121  m_ifs->read( reinterpret_cast< char* >( pointData ), 3 * sizeof( float ) * numPoints );
122 
123  switchByteOrderOfArray( pointData, 3 * numPoints ); // all 4 bytes of each float are in wrong order we need to reorder them
124 
125  m_points = std::shared_ptr< std::vector< float > >( new std::vector< float >( pointData, pointData + 3 * numPoints ) );
126 
127  WAssert( m_points->size() % 3 == 0, "Number of floats for coordinates not dividable by three." );
128  delete[] pointData;
129 
130  // since we know here the size of the vector we may allocate it right here
131  m_pointFiberMapping = std::shared_ptr< std::vector< size_t > >( new std::vector< size_t > );
132  m_pointFiberMapping->reserve( numPoints );
133 
134  line = getLine( "also eat the remaining newline after points declaration" );
135  WAssert( std::string( "" ) == line, "Found characters in file where nothing was expected." );
136 }
137 
139 {
140  std::string line = getLine( "LINES declaration" );
141 
142  std::vector< std::string > tokens = string_utils::tokenize( line );
143  if( tokens.size() != 3 || string_utils::toUpper( tokens.at( 0 ) ) != "LINES" )
144  {
145  throw WDHException( std::string( "Invalid VTK LINES declaration: " + line ) );
146  }
147  size_t numLines = getLexicalCast< size_t >( tokens.at( 1 ), "Invalid number of lines in LINES delclaration" );
148  size_t linesSize = getLexicalCast< size_t >( tokens.at( 2 ), "Invalid size of lines in LINES delclaration" );
149 
150  uint32_t *lineData = new uint32_t[ linesSize ];
151  m_ifs->read( reinterpret_cast<char*>( lineData ), linesSize * sizeof( uint32_t ) );
152 
153  switchByteOrderOfArray( lineData, linesSize );
154 
155  m_fiberStartIndices = std::shared_ptr< std::vector< size_t > >( new std::vector< size_t > );
156  m_fiberLengths = std::shared_ptr< std::vector< size_t > >( new std::vector< size_t > );
157  m_fiberStartIndices->reserve( numLines );
158  m_fiberLengths->reserve( numLines );
159 
160  // now convert lines with point numbers to real fibers
161  size_t linesSoFar = 0;
162  size_t pos = 0;
163  size_t posInVerts = 0;
164  while( linesSoFar < numLines )
165  {
166  m_fiberStartIndices->push_back( posInVerts );
167  size_t fiberLength = lineData[pos];
168  m_fiberLengths->push_back( fiberLength );
169  ++pos;
170  for( size_t i = 0; i < fiberLength; ++i, ++pos, ++posInVerts )
171  {
172  m_pointFiberMapping->push_back( linesSoFar ); // space was reserved in the readPoints member function
173  }
174  ++linesSoFar;
175  }
176 
177  delete[] lineData;
178 
179  line = getLine( "also eat the remaining newline after lines declaration" );
180  WAssert( std::string( "" ) == line, "Found characters in file where nothing was expected." );
181 }
182 
184 {
185  if( !m_ifs->good() )
186  {
187  return;
188  }
189  std::string line = getLine( "reading VALUES declaration" );
190 
191  std::vector< std::string > tokens = string_utils::tokenize( line );
192  if( tokens.size() != 3 || string_utils::toLower( tokens.at( 2 ) ) != "double" )
193  {
194  // do not throw an error. this is a custom extension.
195  return;
196  }
197 
198  size_t numValues = getLexicalCast< size_t >( tokens.at( 1 ), "Invalid number of values" );
199 
200  wlog::debug( "ReaderFiberVTK" ) << "Found " << numValues << " values.";
201 
202  double *valueData = new double[ numValues ];
203  m_ifs->read( reinterpret_cast< char* >( valueData ), sizeof( double ) * numValues );
204 
205  switchByteOrderOfArray( valueData, numValues ); // all 4 bytes of each double are in wrong order we need to reorder them
206 
207  m_fiberParameters = WDataSetFibers::VertexParemeterArray( new std::vector< double > );
208  m_fiberParameters->reserve( numValues );
209  for( size_t i = 0; i < numValues; ++i )
210  {
211  m_fiberParameters->push_back( valueData[i] );
212  }
213 
214  delete[] valueData;
215 
216  line = getLine( "also eat the remaining newline after values declaration" );
217  WAssert( std::string( "" ) == line, "Found characters in file where nothing was expected." );
218 }
219 
220 std::string WReaderFiberVTK::getLine( const std::string& desc )
221 {
222  std::string line;
223  try
224  {
225  // we use '\n' as line termination under every platform so our files (which are most likely to be generated on Unix systems)
226  // can be read from all platforms not having those line termination symbols like e.g. windows ('\r\n').
227  std::getline( *m_ifs, line, '\n' );
228  }
229  catch( const std::ios_base::failure &e )
230  {
231  throw WDHIOFailure( std::string( "IO error while " + desc + " of VTK fiber file: " + m_fname + ", " + e.what() ) );
232  }
233  return line;
234 }
General purpose exception and therefore base class for all DataHandler related exceptions.
Definition: WDHException.h:40
Use this for IO error handling.
Definition: WDHIOFailure.h:38
Use this for IO error handling.
Definition: WDHParseError.h:38
Represents a simple set of WFibers.
std::shared_ptr< std::vector< double > > VertexParemeterArray
Parameter storage for each vertex.
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.
virtual ~WReaderFiberVTK()
Destroys this instance and closes the file.
WDataSetFibers::VertexParemeterArray m_fiberParameters
additional colors if found in file.
void readValues()
Read VTK VALUES field from input stream.
std::shared_ptr< std::ifstream > m_ifs
Pointer to the input file stream reader.
std::shared_ptr< std::vector< float > > m_points
Stores for every point its x,y and z float value successivley.
std::shared_ptr< std::vector< size_t > > m_fiberStartIndices
Stores the start indices (in the point array) for every fiber.
std::shared_ptr< std::vector< size_t > > m_fiberLengths
Stores the length of every fiber.
void readPoints()
Read VTK POINTS field from input stream.
WReaderFiberVTK(std::string fname)
Constructs and makes a new VTK reader for separate thread start.
virtual std::shared_ptr< WDataSetFibers > read()
Reads the fiber file and creates a dataset out of it.
void readHeader()
Read VTK header from file.
std::shared_ptr< std::vector< size_t > > m_pointFiberMapping
Stores for every point the fiber where it belongs to.
void readLines()
Read VTK LINES field from input stream.
Read some data from a given file.
Definition: WReader.h:40
std::string m_fname
Absolute path of the file to read from.
Definition: WReader.h:68
Some utilities for string manipulation and output operations.
Definition: WStringUtils.h:59
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).
std::string toString(const T &value)
Convert a given value to a string.
Definition: WStringUtils.h:120
WStreamedLogger debug(const std::string &source)
Logging a debug message.
Definition: WLogger.h:331
WStreamedLogger warn(const std::string &source)
Logging a warning message.
Definition: WLogger.h:309
WStreamedLogger error(const std::string &source)
Logging an error message.
Definition: WLogger.h:298