41 #include <boost/foreach.hpp>
42 #include <boost/format.hpp>
43 #include <boost/unordered_map.hpp>
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"
51 WMPartition2Mesh::WMPartition2Mesh():
56 WMPartition2Mesh::~WMPartition2Mesh()
70 return "Partition To Mesh";
77 return "Colors freesurfer meshes with results from clustering";
101 (
"Max. project distance",
"Maximum distance for projecting colors onto the surface", 2.5,
m_propCondition );
142 std::shared_ptr< WDataSetScalar > newCoordVector =
m_coordInput->getData();
144 bool coordsValid = ( newCoordVector != NULL );
150 infoLog() <<
"Partition2Mesh: coords changed";
155 std::shared_ptr< WDataSetVector > newColorVector =
m_colorInput->getData();
157 bool colorsValid = ( newColorVector != NULL );
168 std::shared_ptr< WTriangleMesh > newRefMesh =
m_meshInput1->getData();
170 bool refMeshValid = ( newRefMesh != NULL );
176 infoLog() <<
"Partition2Mesh: ref mesh changed";
182 std::shared_ptr< WTriangleMesh > newOutMesh =
m_meshInput2->getData();
183 bool outMeshChanged = (
m_outMesh != newOutMesh );
184 bool outMeshValid = ( newOutMesh != NULL );
197 bool allInputsValid = ( coordsValid && refMeshValid );
198 bool canRecalc = ( coordsChanged || refMeshChanged ||
m_propProjectDistance->changed() ) && allInputsValid;
204 infoLog() <<
"Partition2Mesh: start recalc refs";
212 std::shared_ptr<WValueSet<int> > coords;
213 coords = std::dynamic_pointer_cast<WValueSet<int> >( ( *m_coordinateVector ).getValueSet() );
215 std::cout <<
"fill volume" << std::endl;
218 const size_t id1( coords->getScalar( i*3 ) );
219 const size_t id2( coords->getScalar( i*3 + 1 ) *
m_datasetSizeX );
221 size_t id = id1 + id2 + id3;
222 if(
id < volume.size() )
228 std::cout <<
"error" << std::endl;
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;
240 int xd =
static_cast<int>( vert.x() );
241 int yd =
static_cast<int>( vert.y() );
242 int zd =
static_cast<int>( vert.z() );
245 std::vector<size_t>candidates;
253 std::vector< size_t> neighbours = grid->getNeighbours27( loc );
254 for(
size_t k = 0; k < neighbours.size(); ++k )
256 if( volume[neighbours[k]] != 0 )
258 candidates.push_back( neighbours[k] );
262 std::vector<float>dists;
263 for(
size_t l = 0; l < candidates.size(); ++l )
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 );
272 for(
size_t l = 0; l < candidates.size(); ++l )
274 if( dists[l] < curDist )
276 m_refs[i] = volume[candidates[l]];
290 std::vector< size_t> neighbours = grid->getNeighboursRange( loc, 2 );
291 for(
size_t k = 0; k < neighbours.size(); ++k )
293 if( volume[neighbours[k]] != 0 )
295 candidates.push_back( neighbours[k] );
299 std::vector<float>dists;
300 for(
size_t l = 0; l < candidates.size(); ++l )
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 );
309 for(
size_t l = 0; l < candidates.size(); ++l )
311 if( dists[l] < curDist )
313 m_refs[i] = volume[candidates[l]];
327 std::vector< size_t> neighbours = grid->getNeighboursRange( loc, 3 );
328 for(
size_t k = 0; k < neighbours.size(); ++k )
330 if( volume[neighbours[k]] != 0 )
332 candidates.push_back( neighbours[k] );
336 std::vector<float>dists;
337 for(
size_t l = 0; l < candidates.size(); ++l )
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 );
346 for(
size_t l = 0; l < candidates.size(); ++l )
348 if( dists[l] < curDist )
350 m_refs[i] = volume[candidates[l]];
363 infoLog() <<
"Partition2Mesh: end recalc refs";
366 bool canRecolor = colorsValid && outMeshValid && (
m_refs.size() ==
m_outMesh->vertSize() );
373 for(
size_t i = 0; i <
m_outMesh->vertSize(); ++i )
375 triMesh->addVertex(
m_outMesh->getVertex( i ) );
377 for(
size_t i = 0; i <
m_outMesh->triangleSize(); ++i )
381 triMesh->getNormal( 0 );
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();
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() );
393 for(
size_t i = 0; i < triMesh->vertSize(); ++i )
395 triMesh->setVertexColor( i, col1 );
397 for(
size_t i = 0; i < triMesh->vertSize(); ++i )
403 int x = coords->getScalar(
id * 3 );
404 int y = coords->getScalar(
id * 3 + 1 );
405 int z = coords->getScalar(
id * 3 + 2 );
407 size_t loc = x + y * dimx + z * dimx * dimy;
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,
413 if( col == WColor( 0, 0, 0, 1 ) )
418 triMesh->setVertexColor( i, col );
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();
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() );
436 WColor col1( 0.9, 0.9, 0.9, 1.0 );
437 for(
size_t i = 0; i <
m_outMesh->vertSize(); ++i )
441 for(
size_t i = 0; i <
m_outMesh->vertSize(); ++i )
447 int x = coords->getScalar(
id * 3 );
448 int y = coords->getScalar(
id * 3 + 1 );
449 int z = coords->getScalar(
id * 3 + 2 );
451 size_t loc = x + y * dimx + z * dimx * dimy;
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,
476 std::vector<std::vector<size_t> > labels;
477 std::vector<osg::Vec4> colormap;
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;
485 std::vector<size_t> vertexLabels(
m_outMesh->vertSize(), 0 );
488 for(
size_t i = 0; i <
m_outMesh->vertSize(); ++i )
490 osg::Vec4 color =
m_outMesh->getVertColor( i );
494 if( id_hash.find( key ) == id_hash.end() )
497 color_hash[key] = color;
498 keys.push_back( key );
500 std::vector<size_t> temp;
501 labels.push_back( temp );
502 colormap.push_back( color );
504 vertexLabels[i] = id_hash.at( key );
505 labels[vertexLabels[i]].push_back( i );
512 currentPath.erase( currentPath.begin() );
513 currentPath.erase( currentPath.end()-1 );
515 infoLog() <<
"Partition2Mesh: Writing out labels for " << labels.size() <<
" cluster partition in: " << currentPath;
518 std::string tclFilePath( currentPath +
"/get_labels.tcl" );
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;
523 std::string load_command(
"labl_load " );
524 std::string color_command(
"labl_set_color " );
526 for(
size_t i = 0; i < labels.size(); ++i )
528 std::string labelnumstring = ( str( boost::format(
"%04d" ) % i ) );
529 std::string labelFileName(
"pclust"+labelnumstring+
".label" );
531 std::string labelFilepath( currentPath +
"/" + labelFileName );
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;
537 for(
size_t j = 0; j < labels[i].size(); ++j )
539 size_t vID( labels[i][j] );
540 labelFile << vID <<
" ";
546 tclFile << load_command << labelFileName << std::endl;
547 tclFile << color_command << i <<
" ";
552 tclFile << static_cast<unsigned int>( (
m_propNonActiveColor->get(
true ).b() *255 ) ) << std::endl;
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;
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;
574 void WMPartition2Mesh::writeAnnotation()
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;
583 int* vno =
new int[
m_outMesh->vertSize() ];
584 int* label =
new int[
m_outMesh->vertSize() ];
586 for(
size_t i = 0; i <
m_outMesh->vertSize(); ++i )
590 for(
size_t i = 0; i <
m_outMesh->vertSize(); ++i )
592 osg::Vec4 color =
m_outMesh->getVertColor( i );
596 if( id_hash.find( key ) == id_hash.end() )
599 color_hash[key] = color;
600 keys.push_back( key );
603 label[i] = id_hash.at( key );
605 std::cout <<
"num labels: " << id_hash.size() << std::endl;
608 fileSize +=
m_outMesh->vertSize() * 2 *
sizeof( intVar );
609 fileSize += 6 *
sizeof( intVar );
611 fileSize += ( 6 *
sizeof( intVar ) + 5 ) * id_hash.size();
614 char* buffer =
new char[fileSize];
616 int* intBuffer =
new int[4];
618 switchByteOrderOfArray( intBuffer, 1 );
619 char* charintbuffer =
reinterpret_cast< char*
>( intBuffer );
620 for(
size_t i = 0; i <
sizeof( intVar ) ; ++i )
622 buffer[counter] = charintbuffer[i];
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 )
629 buffer[counter] = charvno[i];
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 )
636 buffer[counter] = charlabel[i];
642 intBuffer[2] = id_hash.size();
645 switchByteOrderOfArray( intBuffer, 4 );
646 charintbuffer =
reinterpret_cast< char*
>( intBuffer );
647 for(
size_t i = 0; i < 4 *
sizeof( intVar ); ++i )
649 buffer[counter] = charintbuffer[i];
652 for(
size_t i = 0; i < 10; ++i )
654 buffer[counter] =
'a';
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 )
662 buffer[counter] = charintbuffer[i];
665 for(
size_t k = 0; k < keys.size(); ++k )
668 intBuffer[0] = id_hash.at( keys[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 )
675 buffer[counter] = charintbuffer[i];
678 for(
size_t i = 0; i < label.length(); ++i )
680 buffer[counter] = label.at( i );
683 osg::Vec4 col = color_hash.at( keys[k] );
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 );
690 switchByteOrderOfArray( intBuffer, 4 );
691 charintbuffer =
reinterpret_cast< char*
>( intBuffer );
692 for(
size_t i = 0; i < 4 *
sizeof( intVar ); ++i )
694 buffer[counter] = charintbuffer[i];
698 outfile.write( buffer, fileSize );
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.
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.
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.
virtual void properties()
Initialize properties in this function.
std::shared_ptr< WProperties > m_properties
The property object for the module.
std::shared_ptr< WProperties > m_infoProperties
The property object for the module containing only module whose purpose is "PV_PURPOSE_INFORMNATION".
void ready()
Call this whenever your module is ready and can react on property changes.
WConditionSet m_moduleState
The internal state of the module.
WPropBool m_active
True whenever the module should be active.
wlog::WStreamedLogger infoLog() const
Logger instance for comfortable info logging.
virtual void connectors()
Initialize connectors in this function.
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.
@ 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.