OpenWalnut  1.5.0dev
WMPartition2Mesh.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 //---------------------------------------------------------------------------
26 //
27 // This file is also part of the
28 // Whole-Brain Connectivity-Based Hierarchical Parcellation Project
29 // David Moreno-Dominguez
30 // Ralph Schurade
31 // moreno@cbs.mpg.de
32 // www.cbs.mpg.de/~moreno
33 //
34 //---------------------------------------------------------------------------
35 
36 #include <fstream>
37 #include <memory>
38 #include <string>
39 #include <vector>
40 
41 #include <boost/foreach.hpp>
42 #include <boost/format.hpp>
43 #include <boost/unordered_map.hpp>
44 
45 #include "WMPartition2Mesh.h"
46 #include "core/common/WIOTools.h"
47 #include "core/common/WStringUtils.h"
48 #include "core/graphicsEngine/WGEUtils.h"
49 #include "core/kernel/WKernel.h"
50 
51 WMPartition2Mesh::WMPartition2Mesh():
52  WModule()
53 {
54 }
55 
56 WMPartition2Mesh::~WMPartition2Mesh()
57 {
58  // Cleanup!
59 }
60 
61 std::shared_ptr< WModule > WMPartition2Mesh::factory() const
62 {
63  // See "src/modules/template/" for an extensively documented example.
64  return std::shared_ptr< WModule >( new WMPartition2Mesh() );
65 }
66 
67 const std::string WMPartition2Mesh::getName() const
68 {
69  // Specify your module name here. This name must be UNIQUE!
70  return "Partition To Mesh";
71 }
72 
73 const std::string WMPartition2Mesh::getDescription() const
74 {
75  // Specify your module description here. Be detailed. This text is read by the user.
76  // See "src/modules/template/" for an extensively documented example.
77  return "Colors freesurfer meshes with results from clustering";
78 }
79 
81 {
82  m_colorInput = WModuleInputData < WDataSetVector >::createAndAdd( shared_from_this(), "colors", "The color vector." );
83  m_coordInput = WModuleInputData < WDataSetScalar >::createAndAdd( shared_from_this(), "coords", "The coordinate vector." );
84  m_meshInput1 = WModuleInputData< WTriangleMesh >::createAndAdd( shared_from_this(), "mesh1", "The reference mesh" );
85  m_meshInput2 = WModuleInputData< WTriangleMesh >::createAndAdd( shared_from_this(), "mesh2", "The mesh to color" );
86 
87  m_meshOutput = WModuleOutputData<WTriangleMesh>::createAndAdd( shared_from_this(), "mesh3", "The mesh to display" );
88 
90 }
91 
93 {
94  m_propCondition = std::shared_ptr< WCondition >( new WCondition() );
95 
96  // Info properties
97  m_infoTotalVertices = m_infoProperties->addProperty( "Total vertices: ", "", 0 );
98  m_infoUnassignedVertices = m_infoProperties->addProperty( "Unassigned vertices", "", 0 );
99 
100  m_propProjectDistance = m_properties->addProperty
101  ( "Max. project distance", "Maximum distance for projecting colors onto the surface", 2.5, m_propCondition );
102  m_propProjectDistance ->setMin( 0.5 );
103  m_propProjectDistance->setMax( 3.5 );
104  m_propNonActiveColor = m_properties->addProperty( "Inactive color", "color for inactive clusters", WColor( 0.5, 0.5, 0.5, 1 ), m_propCondition );
105  m_propHoleColor = m_properties->addProperty( "Unassigned color", "color for unassigned vertices", WColor( 0.9, 0.9, 0.9, 1 ), m_propCondition );
106 
107 
108  m_propLabelFolder= m_properties->addProperty( "Output folder", "", boost::filesystem::path() );
111  m_propAnnotationFile= m_properties->addProperty( "Output file", "", boost::filesystem::path() );
112  m_monochrome = m_properties->addProperty( "Monochrome", "Uses the non-active color for all partitions", false );
113  m_propWriteTrigger = m_properties->addProperty( "Write Labels", "Press!", WPVBaseTypes::PV_TRIGGER_READY, m_propCondition );
115 
116  m_propAnnotationFile->setHidden( true );
117 }
118 
120 {
121  // Put the code for your requirements here. See "src/modules/template/" for an extensively documented example.
122 }
123 
125 {
126  m_moduleState.setResetable( true, true );
127  m_moduleState.add( m_coordInput->getDataChangedCondition() );
128  m_moduleState.add( m_colorInput->getDataChangedCondition() );
129  m_moduleState.add( m_meshInput1->getDataChangedCondition() );
130  m_moduleState.add( m_meshInput2->getDataChangedCondition() );
131  m_moduleState.add( m_active->getUpdateCondition() );
133  m_blankOutMesh = false;
134 
135  ready();
136 
137  // wait for a dataset to be connected, most likely an anatomy dataset
138  while( !m_shutdownFlag() )
139  {
141 
142  std::shared_ptr< WDataSetScalar > newCoordVector = m_coordInput->getData();
143  bool coordsChanged = ( m_coordinateVector != newCoordVector );
144  bool coordsValid = ( newCoordVector != NULL );
145 
146  if( coordsValid )
147  {
148  if( coordsChanged )
149  {
150  infoLog() << "Partition2Mesh: coords changed";
151  m_coordinateVector = newCoordVector;
152  }
153  }
154 
155  std::shared_ptr< WDataSetVector > newColorVector = m_colorInput->getData();
156  bool colorsChanged = ( m_colorVector != newColorVector );
157  bool colorsValid = ( newColorVector != NULL );
158 
159  if( colorsValid )
160  {
161  if( colorsChanged )
162  {
163  //infoLog() << "Partition2Mesh: colors changed";
164  m_colorVector = newColorVector;
165  }
166  }
167 
168  std::shared_ptr< WTriangleMesh > newRefMesh = m_meshInput1->getData();
169  bool refMeshChanged = ( m_referenceMesh != newRefMesh );
170  bool refMeshValid = ( newRefMesh != NULL );
171 
172  if( refMeshValid )
173  {
174  if( refMeshChanged )
175  {
176  infoLog() << "Partition2Mesh: ref mesh changed";
177  m_referenceMesh = newRefMesh;
178  m_infoTotalVertices->set( m_referenceMesh->vertSize() );
179  }
180  }
181 
182  std::shared_ptr< WTriangleMesh > newOutMesh = m_meshInput2->getData();
183  bool outMeshChanged = ( m_outMesh != newOutMesh );
184  bool outMeshValid = ( newOutMesh != NULL );
185 
186  if( outMeshValid )
187  {
188  if( outMeshChanged )
189  {
190  //infoLog() << "Partition2Mesh: out mesh changed";
191  m_outMesh = newOutMesh;
192  m_meshOutput->updateData( m_outMesh );
193  m_blankOutMesh = true;
194  }
195  }
196 
197  bool allInputsValid = ( coordsValid && refMeshValid );
198  bool canRecalc = ( coordsChanged || refMeshChanged || m_propProjectDistance->changed() ) && allInputsValid;
199 
200  //if( m_propRefTrigger->get( true ) == WPVBaseTypes::PV_TRIGGER_TRIGGERED )
201 
202  if( canRecalc )
203  {
204  infoLog() << "Partition2Mesh: start recalc refs";
205 
206  m_datasetSizeX = std::dynamic_pointer_cast< WGridRegular3D >( m_colorInput->getData()->getGrid() )->getNbCoordsX();
207  m_datasetSizeY = std::dynamic_pointer_cast< WGridRegular3D >( m_colorInput->getData()->getGrid() )->getNbCoordsY();
208  m_datasetSizeZ = std::dynamic_pointer_cast< WGridRegular3D >( m_colorInput->getData()->getGrid() )->getNbCoordsZ();
209  std::vector<size_t>volume( m_datasetSizeX * m_datasetSizeY * m_datasetSizeZ, 0 );
210  std::cout << "color volume size " << m_datasetSizeX * m_datasetSizeY * m_datasetSizeZ << std::endl;
211 
212  std::shared_ptr<WValueSet<int> > coords;
213  coords = std::dynamic_pointer_cast<WValueSet<int> >( ( *m_coordinateVector ).getValueSet() );
214 
215  std::cout << "fill volume" << std::endl;
216  for( size_t i = 0; i < m_coordinateVector->getGrid()->size() / 3; ++i )
217  {
218  const size_t id1( coords->getScalar( i*3 ) );
219  const size_t id2( coords->getScalar( i*3 + 1 ) * m_datasetSizeX );
220  const size_t id3( coords->getScalar( i*3 + 2 ) * m_datasetSizeX * m_datasetSizeY );
221  size_t id = id1 + id2 + id3;
222  if( id < volume.size() )
223  {
224  volume[ id ] = i+1;
225  }
226  else
227  {
228  std::cout << "error" << std::endl;
229  }
230  }
231 
232  m_refs.resize( m_referenceMesh->vertSize() );
233  std::shared_ptr<WGridRegular3D> grid = std::dynamic_pointer_cast< WGridRegular3D >( m_colorInput->getData()->getGrid() );
234  float xs = grid->getOffsetX() / 2.0;
235  float ys = grid->getOffsetY() / 2.0;
236  float zs = grid->getOffsetZ() / 2.0;
237  for( size_t i = 0; i < m_referenceMesh->vertSize(); ++i )
238  {
239  osg::Vec3 vert = m_referenceMesh->getVertex( i );
240  int xd = static_cast<int>( vert.x() );
241  int yd = static_cast<int>( vert.y() );
242  int zd = static_cast<int>( vert.z() );
243  size_t loc = xd + yd * m_datasetSizeX + zd * m_datasetSizeX * m_datasetSizeY;
244  m_refs[i] = volume[loc];
245  std::vector<size_t>candidates;
246 
247  if( m_refs[i] == 0 ) // didn't find a voxel have to keep looking
248  {
249  if( ( m_propProjectDistance->get( true ) > 0.5 ) && ( m_propProjectDistance->get( true ) <= 1.5 ) )
250  {
251  // look in the 26 nbhood (3x3x3 voxels)
252 
253  std::vector< size_t> neighbours = grid->getNeighbours27( loc );
254  for( size_t k = 0; k < neighbours.size(); ++k )
255  {
256  if( volume[neighbours[k]] != 0 )
257  {
258  candidates.push_back( neighbours[k] );
259  }
260  }
261 
262  std::vector<float>dists;
263  for( size_t l = 0; l < candidates.size(); ++l )
264  {
265  WPosition voxPos = grid->getPosition( candidates[l] );
266  float dist = sqrt( ( vert.x() - voxPos.x() - xs ) * ( vert.x() - voxPos.x() - xs ) +
267  ( vert.y() - voxPos.y() - ys ) * ( vert.y() - voxPos.y() - ys ) +
268  ( vert.z() - voxPos.z() - zs ) * ( vert.z() - voxPos.z() - zs ) );
269  dists.push_back( dist );
270  }
271  float curDist = 10;
272  for( size_t l = 0; l < candidates.size(); ++l )
273  {
274  if( dists[l] < curDist )
275  {
276  m_refs[i] = volume[candidates[l]];
277  curDist = dists[l];
278  }
279  }
280  // discard if distance is bigger than specified
281  if( curDist > m_propProjectDistance->get( true ) )
282  {
283  m_refs[i]=0;
284  }
285  }
286  else if( ( m_propProjectDistance->get( true ) > 1.5 ) && ( m_propProjectDistance->get( true ) <= 2.5 ) )
287  {
288  // look in the 124 nbhood (5x5x5 voxels)
289 
290  std::vector< size_t> neighbours = grid->getNeighboursRange( loc, 2 );
291  for( size_t k = 0; k < neighbours.size(); ++k )
292  {
293  if( volume[neighbours[k]] != 0 )
294  {
295  candidates.push_back( neighbours[k] );
296  }
297  }
298 
299  std::vector<float>dists;
300  for( size_t l = 0; l < candidates.size(); ++l )
301  {
302  WPosition voxPos = grid->getPosition( candidates[l] );
303  float dist = sqrt( ( vert.x() - voxPos.x() - xs ) * ( vert.x() - voxPos.x() - xs ) +
304  ( vert.y() - voxPos.y() - ys ) * ( vert.y() - voxPos.y() - ys ) +
305  ( vert.z() - voxPos.z() - zs ) * ( vert.z() - voxPos.z() - zs ) );
306  dists.push_back( dist );
307  }
308  float curDist = 10;
309  for( size_t l = 0; l < candidates.size(); ++l )
310  {
311  if( dists[l] < curDist )
312  {
313  m_refs[i] = volume[candidates[l]];
314  curDist = dists[l];
315  }
316  }
317  // discard if distance is bigger than specified
318  if( curDist > m_propProjectDistance->get( true ) )
319  {
320  m_refs[i]=0;
321  }
322  }
323  else if( m_propProjectDistance->get( true ) > 2.5 )
324  {
325  // look in the 342 nbhood (7x7x7 voxels)
326 
327  std::vector< size_t> neighbours = grid->getNeighboursRange( loc, 3 );
328  for( size_t k = 0; k < neighbours.size(); ++k )
329  {
330  if( volume[neighbours[k]] != 0 )
331  {
332  candidates.push_back( neighbours[k] );
333  }
334  }
335 
336  std::vector<float>dists;
337  for( size_t l = 0; l < candidates.size(); ++l )
338  {
339  WPosition voxPos = grid->getPosition( candidates[l] );
340  float dist = sqrt( ( vert.x() - voxPos.x() - xs ) * ( vert.x() - voxPos.x() - xs ) +
341  ( vert.y() - voxPos.y() - ys ) * ( vert.y() - voxPos.y() - ys ) +
342  ( vert.z() - voxPos.z() - zs ) * ( vert.z() - voxPos.z() - zs ) );
343  dists.push_back( dist );
344  }
345  float curDist = 10;
346  for( size_t l = 0; l < candidates.size(); ++l )
347  {
348  if( dists[l] < curDist )
349  {
350  m_refs[i] = volume[candidates[l]];
351  curDist = dists[l];
352  }
353  }
354  // discard if distance is bigger than specified
355  if( curDist > m_propProjectDistance->get( true ) )
356  {
357  m_refs[i]=0;
358  }
359  }
360  }
361  }
362  m_infoUnassignedVertices->set( std::count( m_refs.begin(), m_refs.end(), 0 ) );
363  infoLog() << "Partition2Mesh: end recalc refs";
364  }
365 
366  bool canRecolor = colorsValid && outMeshValid && ( m_refs.size() == m_outMesh->vertSize() );
367  if( ( colorsChanged || m_propNonActiveColor->changed( true ) || m_propHoleColor->changed( true ) || m_blankOutMesh ) && canRecolor )
368  {
369  m_blankOutMesh = false;
370  //infoLog() << "Partition2Mesh: write colors to out mesh";
371 #if 1
372  std::shared_ptr< WTriangleMesh > triMesh( new WTriangleMesh( m_outMesh->vertSize(), m_outMesh->triangleSize() ) );
373  for( size_t i = 0; i < m_outMesh->vertSize(); ++i )
374  {
375  triMesh->addVertex( m_outMesh->getVertex( i ) );
376  }
377  for( size_t i = 0; i < m_outMesh->triangleSize(); ++i )
378  {
379  triMesh->addTriangle( m_outMesh->getTriVertId0( i ), m_outMesh->getTriVertId1( i ), m_outMesh->getTriVertId2( i ) );
380  }
381  triMesh->getNormal( 0 );
382 
383  int dimx = std::dynamic_pointer_cast< WGridRegular3D >( m_colorInput->getData()->getGrid() )->getNbCoordsX();
384  int dimy = std::dynamic_pointer_cast< WGridRegular3D >( m_colorInput->getData()->getGrid() )->getNbCoordsY();
385  //int dimz = std::dynamic_pointer_cast< WGridRegular3D >( m_colorInput->getData()->getGrid() )->getNbCoordsZ();
386 
387  std::shared_ptr<WValueSet<unsigned char> > colors;
388  colors = std::dynamic_pointer_cast<WValueSet<unsigned char> >( ( *m_colorVector ).getValueSet() );
389  std::shared_ptr<WValueSet<int> > coords;
390  coords = std::dynamic_pointer_cast<WValueSet<int> >( ( *m_coordinateVector ).getValueSet() );
391 
392  WColor col1( m_propHoleColor->get( true ) );
393  for( size_t i = 0; i < triMesh->vertSize(); ++i )
394  {
395  triMesh->setVertexColor( i, col1 );
396  }
397  for( size_t i = 0; i < triMesh->vertSize(); ++i )
398  {
399  size_t id = m_refs[i];
400  if( id > 0 )
401  {
402  id = id - 1;
403  int x = coords->getScalar( id * 3 );
404  int y = coords->getScalar( id * 3 + 1 );
405  int z = coords->getScalar( id * 3 + 2 );
406 
407  size_t loc = x + y * dimx + z * dimx * dimy;
408 
409  WColor col( colors->getScalar( loc * 3 )/255.0,
410  colors->getScalar( loc * 3 + 1 )/255.0,
411  colors->getScalar( loc * 3 + 2 )/255.0,
412  1.0 );
413  if( col == WColor( 0, 0, 0, 1 ) )
414  {
415  col = m_propNonActiveColor->get( true );
416  }
417 
418  triMesh->setVertexColor( i, col );
419  }
420  }
421 
422  m_outMesh = triMesh;
423 
424  // this code shouold work to recolor the mesh, for some reason it does not,
425  // and so a new output mesh has to be crated every time colors change
426 #else
427  int dimx = std::dynamic_pointer_cast< WGridRegular3D >( m_colorInput->getData()->getGrid() )->getNbCoordsX();
428  int dimy = std::dynamic_pointer_cast< WGridRegular3D >( m_colorInput->getData()->getGrid() )->getNbCoordsY();
429  //int dimz = std::dynamic_pointer_cast< WGridRegular3D >( m_colorInput->getData()->getGrid() )->getNbCoordsZ();
430 
431  std::shared_ptr<WValueSet<unsigned char> > colors;
432  colors = std::dynamic_pointer_cast<WValueSet<unsigned char> >( ( *m_colorVector ).getValueSet() );
433  std::shared_ptr<WValueSet<int> > coords;
434  coords = std::dynamic_pointer_cast<WValueSet<int> >( ( *m_coordinateVector ).getValueSet() );
435 
436  WColor col1( 0.9, 0.9, 0.9, 1.0 );
437  for( size_t i = 0; i < m_outMesh->vertSize(); ++i )
438  {
439  m_outMesh->setVertexColor( i, col1 );
440  }
441  for( size_t i = 0; i < m_outMesh->vertSize(); ++i )
442  {
443  size_t id = m_refs[i];
444  if( id > 0 )
445  {
446  id = id - 1;
447  int x = coords->getScalar( id * 3 );
448  int y = coords->getScalar( id * 3 + 1 );
449  int z = coords->getScalar( id * 3 + 2 );
450 
451  size_t loc = x + y * dimx + z * dimx * dimy;
452 
453  WColor col( colors->getScalar( loc * 3 )/255.0,
454  colors->getScalar( loc * 3 + 1 )/255.0,
455  colors->getScalar( loc * 3 + 2 )/255.0,
456  1.0 );
457 
458  m_outMesh->setVertexColor( i, col );
459  }
460  }
461 #endif
462  m_meshOutput->updateData( m_outMesh );
463  }
464 
466  {
467  //writeAnnotation();
468  writeLabels();
470  }
471  }
472 }
473 
475 {
476  std::vector<std::vector<size_t> > labels;
477  std::vector<osg::Vec4> colormap;
478 
479  // create label indexes
480  {
481  boost::unordered_map<std::string, int> id_hash;
482  boost::unordered_map<std::string, osg::Vec4> color_hash;
483  std::vector<std::string>keys;
484  int id = 0;
485  std::vector<size_t> vertexLabels( m_outMesh->vertSize(), 0 );
486 
487 
488  for( size_t i = 0; i < m_outMesh->vertSize(); ++i )
489  {
490  osg::Vec4 color = m_outMesh->getVertColor( i );
491  std::string key = string_utils::toString( static_cast<unsigned char>( color.r() * 255 ) ) +
492  string_utils::toString( static_cast<unsigned char>( color.g() * 255 ) ) +
493  string_utils::toString( static_cast<unsigned char>( color.b() * 255 ) );
494  if( id_hash.find( key ) == id_hash.end() )
495  {
496  id_hash[key] = id;
497  color_hash[key] = color;
498  keys.push_back( key );
499  ++id;
500  std::vector<size_t> temp;
501  labels.push_back( temp );
502  colormap.push_back( color );
503  }
504  vertexLabels[i] = id_hash.at( key );
505  labels[vertexLabels[i]].push_back( i );
506  }
507  }
508 
509  // ========== Write freesurfer labels ==========
510 
511  std::string currentPath( m_propLabelFolder->getAsString() );
512  currentPath.erase( currentPath.begin() );
513  currentPath.erase( currentPath.end()-1 );
514 
515  infoLog() << "Partition2Mesh: Writing out labels for " << labels.size() << " cluster partition in: " << currentPath;
516 
517 
518  std::string tclFilePath( currentPath + "/get_labels.tcl" );
519 
520  std::ofstream tclFile( tclFilePath.c_str() );
521  tclFile << "# " << labels.size() << " labels loading file. Use: >> tksurfer 'subject' 'hemisphere' 'surface' -tcl get_labels.tcl" << std::endl;
522 
523  std::string load_command( "labl_load " );
524  std::string color_command( "labl_set_color " );
525 
526  for( size_t i = 0; i < labels.size(); ++i )
527  {
528  std::string labelnumstring = ( str( boost::format( "%04d" ) % i ) );
529  std::string labelFileName( "pclust"+labelnumstring+".label" );
530 
531  std::string labelFilepath( currentPath + "/" + labelFileName );
532 
533  std::ofstream labelFile( labelFilepath.c_str() );
534  labelFile << "#!ascii label " << labelFileName << " , out of a " << labels.size() << " labels partition" << std::endl << std::endl;
535  labelFile << labels[i].size() << std::endl;
536 
537  for( size_t j = 0; j < labels[i].size(); ++j )
538  {
539  size_t vID( labels[i][j] );
540  labelFile << vID << " ";
541  labelFile << m_outMesh->getVertex( vID ).x()-( m_datasetSizeX*0.5 ) << " ";
542  labelFile << m_outMesh->getVertex( vID ).y()-( m_datasetSizeY*0.5 ) << " ";
543  labelFile << m_outMesh->getVertex( vID ).z()-( m_datasetSizeZ*0.5 ) << " 0.0" << std::endl;
544  }
545 
546  tclFile << load_command << labelFileName << std::endl;
547  tclFile << color_command << i << " ";
548  if( m_monochrome->get( true ) )
549  {
550  tclFile << static_cast<unsigned int>( ( m_propNonActiveColor->get( true ).r() *255 ) ) << " ";
551  tclFile << static_cast<unsigned int>( ( m_propNonActiveColor->get( true ).g() *255 ) ) << " ";
552  tclFile << static_cast<unsigned int>( ( m_propNonActiveColor->get( true ).b() *255 ) ) << std::endl;
553  }
554  else
555  {
556  tclFile << static_cast<unsigned int>( ( colormap[i].r() *255 ) ) << " ";
557  tclFile << static_cast<unsigned int>( ( colormap[i].g() *255 ) ) << " ";
558  tclFile << static_cast<unsigned int>( ( colormap[i].b() *255 ) ) << std::endl;
559  }
560  }
561 
562  // ========== Write freesurfer tcl file ==========
563 
564  tclFile << "set gaLinkedVars(offset) 0.6" << std::endl;
565  tclFile << "set gaLinkedVars(light0 ) 0.6" << std::endl;
566  tclFile << "SendLinkedVarGroup scene" << std::endl;
567  tclFile << "rotate_brain_y 90" << std::endl;
568  tclFile << "rotate_brain_x -90" << std::endl;
569  tclFile << "labl_select -1" << std::endl;
570  tclFile << "redraw" << std::endl;
571 } // end writeLabels()
572 
573 #if 0
574 void WMPartition2Mesh::writeAnnotation()
575 {
576  // create label indexes
577  boost::unordered_map<std::string, int> id_hash;
578  boost::unordered_map<std::string, osg::Vec4> color_hash;
579  std::vector<std::string>keys;
580  int intVar( 0 );
581  int id( 0 );
582 
583  int* vno = new int[ m_outMesh->vertSize() ];
584  int* label = new int[ m_outMesh->vertSize() ];
585 
586  for( size_t i = 0; i < m_outMesh->vertSize(); ++i )
587  {
588  vno[i] = i;
589  }
590  for( size_t i = 0; i < m_outMesh->vertSize(); ++i )
591  {
592  osg::Vec4 color = m_outMesh->getVertColor( i );
593  std::string key = string_utils::toString( ( unsigned char )( color.r() * 255 ) ) +
594  string_utils::toString( ( unsigned char )( color.g() * 255 ) ) +
595  string_utils::toString( ( unsigned char )( color.b() * 255 ) );
596  if( id_hash.find( key ) == id_hash.end() )
597  {
598  id_hash[key] = id;
599  color_hash[key] = color;
600  keys.push_back( key );
601  ++id;
602  }
603  label[i] = id_hash.at( key );
604  }
605  std::cout << "num labels: " << id_hash.size() << std::endl;
606 
607  int fileSize = 0;
608  fileSize += m_outMesh->vertSize() * 2 * sizeof( intVar );
609  fileSize += 6 * sizeof( intVar );
610  fileSize += 10; // string filename
611  fileSize += ( 6 * sizeof( intVar ) + 5 ) * id_hash.size();
612 
613  size_t counter = 0;
614  char* buffer = new char[fileSize];
615 
616  int* intBuffer = new int[4];
617  intBuffer[0] = m_outMesh->vertSize();
618  switchByteOrderOfArray( intBuffer, 1 );
619  char* charintbuffer = reinterpret_cast< char* >( intBuffer );
620  for( size_t i = 0; i < sizeof( intVar ) ; ++i )
621  {
622  buffer[counter] = charintbuffer[i];
623  ++counter;
624  }
625  switchByteOrderOfArray( vno, m_outMesh->vertSize() );
626  char* charvno = reinterpret_cast< char* >( vno );
627  for( size_t i = 0; i < m_outMesh->vertSize() * sizeof( intVar ); ++i )
628  {
629  buffer[counter] = charvno[i];
630  ++counter;
631  }
632  switchByteOrderOfArray( label, m_outMesh->vertSize() );
633  char* charlabel = reinterpret_cast< char* >( label );
634  for( size_t i = 0; i < m_outMesh->vertSize() * sizeof( intVar ); ++i )
635  {
636  buffer[counter] = charlabel[i];
637  ++counter;
638  }
639 
640  intBuffer[0] = 0; // Tag "TAG_OLD_COLORTABLE" indicating a color table comes next
641  intBuffer[1] = -1; // >0 means "old format", <0 means "new format" (new shown below)
642  intBuffer[2] = id_hash.size(); // Max structure index (could be more than actual entries, since some may be omitted)
643  intBuffer[3] = 10; // Length of subsequent string
644 
645  switchByteOrderOfArray( intBuffer, 4 );
646  charintbuffer = reinterpret_cast< char* >( intBuffer );
647  for( size_t i = 0; i < 4 * sizeof( intVar ); ++i )
648  {
649  buffer[counter] = charintbuffer[i];
650  ++counter;
651  }
652  for( size_t i = 0; i < 10; ++i )
653  {
654  buffer[counter] = 'a';
655  ++counter;
656  }
657  intBuffer[0] = id_hash.size();
658  switchByteOrderOfArray( intBuffer, 1 );
659  charintbuffer = reinterpret_cast< char* >( intBuffer );
660  for( size_t i = 0; i < sizeof( intVar ); ++i )
661  {
662  buffer[counter] = charintbuffer[i];
663  ++counter;
664  }
665  for( size_t k = 0; k < keys.size(); ++k )
666  {
667  //std::cout << keys[k] << " " << id_hash.at( keys[k] ) << " " << color_hash.at( keys[k] ) << std::endl;
668  intBuffer[0] = id_hash.at( keys[k] );
669  std::string label = "label" + string_utils::toString( k );
670  intBuffer[1] = label.length();
671  switchByteOrderOfArray( intBuffer, 2 );
672  charintbuffer = reinterpret_cast< char* >( intBuffer );
673  for( size_t i = 0; i < 2 * sizeof( intVar ); ++i )
674  {
675  buffer[counter] = charintbuffer[i];
676  ++counter;
677  }
678  for( size_t i = 0; i < label.length(); ++i )
679  {
680  buffer[counter] = label.at( i );
681  ++counter;
682  }
683  osg::Vec4 col = color_hash.at( keys[k] );
684 
685  intBuffer[0] = static_cast<unsigned int>( col.r() * 255 );
686  intBuffer[1] = static_cast<unsigned int>( col.g() * 255 );
687  intBuffer[2] = static_cast<unsigned int>( col.b() * 255 );
688  intBuffer[3] = 0;
689 
690  switchByteOrderOfArray( intBuffer, 4 );
691  charintbuffer = reinterpret_cast< char* >( intBuffer );
692  for( size_t i = 0; i < 4 * sizeof( intVar ); ++i )
693  {
694  buffer[counter] = charintbuffer[i];
695  ++counter;
696  }
697  std::ofstream outfile( m_propAnnotationFile->getAsString().c_str(), std::ofstream::binary );
698  outfile.write( buffer, fileSize );
699  outfile.close();
700  }
701 }
702 #endif
virtual void wait() const
Wait for the condition.
void setResetable(bool resetable=true, bool autoReset=true)
Sets the resetable flag.
virtual void add(std::shared_ptr< WCondition > condition)
Adds another condition to the set of conditions to wait for.
Class to encapsulate boost::condition_variable_any.
Definition: WCondition.h:42
This module projects a clustering partition result onto a (freesurfer) mesh Meant to work with hierch...
virtual const std::string getDescription() const
Gives back a description of this module.
std::vector< size_t > m_refs
a vector holding the cluster id corresponding to each vertex
unsigned int m_datasetSizeZ
Size of the dataset (Z)
std::shared_ptr< WModuleInputData< WDataSetVector > > m_colorInput
This is a pointer to the color input dataset.
virtual void connectors()
Initialize the connectors this module is using.
std::shared_ptr< WModuleInputData< WTriangleMesh > > m_meshInput2
An input connector for the mesh.
std::shared_ptr< WDataSetVector > m_colorVector
This is a pointer to the color vector.
virtual std::shared_ptr< WModule > factory() const
Due to the prototype design pattern used to build modules, this method returns a new instance of this...
std::shared_ptr< WDataSetScalar > m_coordinateVector
This is a pointer to the coord vector.
unsigned int m_datasetSizeX
Size of the dataset (X)
WPropBool m_monochrome
if used all labels will have m_propNonActiveColor
std::shared_ptr< WCondition > m_propCondition
A condition used to notify about changes in several properties.
std::shared_ptr< WTriangleMesh > m_outMesh
A pointer to the currently processed tri mesh.
virtual void moduleMain()
Entry point after loading the module.
void writeLabels()
writes a freesurfer set of labels and tcl loading file
virtual void requirements()
Initialize requirements for this module.
unsigned int m_datasetSizeY
Size of the dataset (Y)
WPropFilename m_propLabelFolder
folder where the labels will be written
std::shared_ptr< WModuleInputData< WDataSetScalar > > m_coordInput
An input connector that accepts order 1 datasets.
WPropInt m_infoUnassignedVertices
Info property: number of vertices without match.
WPropColor m_propNonActiveColor
color for the non labeled texture voxels
std::shared_ptr< WModuleInputData< WTriangleMesh > > m_meshInput1
An input connector for the reference mesh.
WPropInt m_infoTotalVertices
Info property: number of vertices.
WPropTrigger m_propWriteTrigger
trigger the writing of the labels
WPropDouble m_propProjectDistance
maximum distance to project the voxels
virtual void properties()
Initialize the properties for this module.
WPropFilename m_propAnnotationFile
filename for the annotation file
std::shared_ptr< WTriangleMesh > m_referenceMesh
A pointer to the currently processed tri mesh.
WPropColor m_propHoleColor
color for the non labeled texture voxels
std::shared_ptr< WModuleOutputData< WTriangleMesh > > m_meshOutput
Output connector provided by this module.
bool m_blankOutMesh
if set mesh colors must be initialized
virtual const std::string getName() const
Gives back the name of this module.
Class offering an instantiate-able data connection between modules.
static PtrType createAndAdd(std::shared_ptr< WModule > module, std::string name="", std::string description="")
Convenience method to create a new instance of this in data connector with proper type and add it to ...
static PtrType createAndAdd(std::shared_ptr< WModule > module, std::string name="", std::string description="")
Convenience method to create a new instance of this out data connector with proper type and add it to...
Class representing a single module of OpenWalnut.
Definition: WModule.h:72
virtual void properties()
Initialize properties in this function.
Definition: WModule.cpp:212
std::shared_ptr< WProperties > m_properties
The property object for the module.
Definition: WModule.h:640
std::shared_ptr< WProperties > m_infoProperties
The property object for the module containing only module whose purpose is "PV_PURPOSE_INFORMNATION".
Definition: WModule.h:647
void ready()
Call this whenever your module is ready and can react on property changes.
Definition: WModule.cpp:505
WConditionSet m_moduleState
The internal state of the module.
Definition: WModule.h:703
WPropBool m_active
True whenever the module should be active.
Definition: WModule.h:723
wlog::WStreamedLogger infoLog() const
Logger instance for comfortable info logging.
Definition: WModule.cpp:565
virtual void connectors()
Initialize connectors in this function.
Definition: WModule.cpp:208
This only is a 3d double vector.
WBoolFlag m_shutdownFlag
Condition getting fired whenever the thread should quit.
Triangle mesh data structure allowing for convenient access of the elements.
Definition: WTriangleMesh.h:46
@ PV_TRIGGER_TRIGGERED
Trigger property: got triggered.
@ PV_TRIGGER_READY
Trigger property: is ready to be triggered (again)
void addTo(WPropFilename prop)
Add the PC_PATHEXISTS constraint to the property.
void addTo(WPropFilename prop)
Add the PC_PATHEXISTS constraint to the property.
std::string toString(const T &value)
Convert a given value to a string.
Definition: WStringUtils.h:120