OpenWalnut  1.5.0dev
WFiberCluster.h
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 #ifndef WFIBERCLUSTER_H
26 #define WFIBERCLUSTER_H
27 
28 #include <list>
29 #include <memory>
30 #include <shared_mutex>
31 #include <string>
32 #include <vector>
33 
34 #include <boost/thread.hpp>
35 
36 #include "../../common/WColor.h"
37 #include "../../common/WTransferable.h"
38 #include "../WDataSetFiberVector.h"
39 
40 
41 /**
42  * Represents a cluster of indices of a WDataSetFiberVector.
43  */
44 class WFiberCluster: public WTransferable // NOLINT
45 {
46 friend class WFiberClusterTest; //!< Access for test class.
47 public:
48  /**
49  * Shared pointer abbreviation.
50  */
51  typedef std::shared_ptr< WFiberCluster > SPtr;
52 
53  /**
54  * Const shared pointer abbreviation.
55  */
56  typedef std::shared_ptr< const WFiberCluster > ConstSPtr;
57 
58  /**
59  * This is the list of indices of fibers.
60  */
61  typedef std::list< size_t > IndexList;
62 
63  /**
64  * Const iterator on the index list.
65  */
66  typedef IndexList::const_iterator IndexListConstIterator;
67 
68  /**
69  * Constructs an cluster with one fiber and a reference to the fiber dataset
70  * to compute the intercluster distance.
71  *
72  * \param index The index of the first fiber belonging to this cluster
73  */
74  explicit WFiberCluster( size_t index );
75 
76  /**
77  * Constructs a cluster with the specified set of indices and the given color.
78  *
79  * \param indices the indices initially used for this clustering
80  * \param color the color of this cluster
81  * \param annotation an optional annotation string
82  */
83  WFiberCluster( const IndexList& indices, const WColor& color = WColor(), std::string const& annotation = std::string() );
84 
85  /**
86  * Constructs a clustering with the given set of indices. The indexlist is generated using the given iterators. It copies the elements in
87  * [indicesBegin,indicesEnd).
88  *
89  * \param indicesBegin begin iterator in the predefined index set
90  * \param indicesEnd end iterator in the predefined index set
91  * \param color the color of this cluster
92  * \param annotation an optional annotation string
93  */
95  const WColor& color = WColor(), std::string const& annotation = std::string() );
96 
97  /**
98  * Copies the specified \ref WFiberCluster Instance. The copy does not contain a valid centerline or longest line.
99  *
100  * \param other the other instance to clone.
101  */
102  WFiberCluster( const WFiberCluster& other );
103 
104  /**
105  * Constructs an empty cluster.
106  */
107  WFiberCluster();
108 
109  /**
110  * Destructs. Frees used locks/mutex.
111  */
112  virtual ~WFiberCluster();
113 
114  /**
115  * Returns true if there are no fibers in that cluster, false otherwise.
116  *
117  * \return true if empty
118  */
119  bool empty() const;
120 
121  /**
122  * Merge the fibers of the other cluster with the fibers of this cluster.
123  * Afterwards the other cluster is empty.
124  *
125  * \param other The other WFiberCluster which should merged into this one
126  */
127  void merge( WFiberCluster &other ); // NOLINT
128 
129  /**
130  * Copy the elements denoted by the two iterators to this cluster. In contrast to the other merge() methods, this will not clean the source
131  * list.
132  *
133  * \param indicesBegin begin iterator in the predefined index set
134  * \param indicesEnd end iterator in the predefined index set
135  */
136  void merge( IndexListConstIterator indicesBegin, IndexListConstIterator indicesEnd );
137 
138  /**
139  * Returns a const reference of all indices inside this cluster
140  *
141  * \return the index list
142  */
143  const IndexList& getIndices() const;
144 
145  /**
146  * Reset the indices belonging to that cluster
147  *
148  * \param indices list of indices
149  */
150  void setIndices( const IndexList& indices );
151 
152  /**
153  * Sort the indices of fibers associated with this cluster in ascending
154  * order.
155  */
156  void sort();
157 
158  /**
159  * \return Number of fibers associated with this cluster.
160  */
161  size_t size() const;
162 
163  /**
164  * Make this cluster empty. Note: The real fibers from fiber dataset are
165  * not deleted.
166  */
167  void clear();
168 
169  /**
170  * Sets the color of which all fibers of this clusters should be painted
171  * with.
172  *
173  * \param color The color for all fibers of this cluster.
174  */
175  void setColor( WColor color );
176 
177  /**
178  * Gets the color of which all fibers of this clusters should be painted
179  * with.
180  *
181  * \return cluster color.
182  */
183  WColor getColor() const;
184 
185  /**
186  * Set the annotation for this fiber cluster.
187  *
188  * \param anno The new annotation.
189  */
190  void setAnnotation( std::string const& anno );
191 
192  /**
193  * Get the annotation string.
194  *
195  * \return The annotation string.
196  */
197  std::string const& getAnnotation() const;
198 
199  /**
200  * Sets the main direction of the cluster
201  *
202  * \param mainDirection the cluster's main direction
203  */
204  void setMainDirection( osg::Vec3 mainDirection );
205 
206  /**
207  * Gets the main direction of the cluster ( if set )
208  *
209  * \return the cluster's main direction
210  */
211  osg::Vec3 getMainDirection() const;
212 
213  /**
214  * The name of this transferable. This is useful information for the users.
215  *
216  * \return the name.
217  */
218  virtual const std::string getName() const;
219 
220  /**
221  *
222  * The description of this transferable. This is useful information for the users.
223  *
224  * \return A description
225  */
226  virtual const std::string getDescription() const;
227 
228  /**
229  * \param other The other fiber which should be compared
230  * \return true If both clusters having same fibers IN SAME ORDER!
231  */
232  bool operator==( const WFiberCluster& other ) const;
233 
234  /**
235  * The opposite of the operator==
236  *
237  * \param other The other fiber which should be compared
238  * \return false If both clusters having same fibers IN SAME ORDER!
239  */
240  bool operator!=( const WFiberCluster& other ) const;
241 
242  /**
243  * Copy assignment operator which does NOT copy the mutex's!!!
244  *
245  * \param other The instance to copy.
246  *
247  * \return itself
248  */
250  {
251  WTransferable::operator=( other );
253  m_fibs = other.m_fibs;
254  m_color = other.m_color;
255  m_centerLineCreationLock = new std::shared_mutex();
256  m_longestLineCreationLock = new std::shared_mutex();
257  // copy them only if they exist
258  if( other.m_centerLine )
259  {
260  m_centerLine = std::shared_ptr< WFiber >( new WFiber( *other.m_centerLine.get() ) );
261  }
262  if( other.m_longestLine )
263  {
264  m_longestLine = std::shared_ptr< WFiber >( new WFiber( *other.m_longestLine.get() ) );
265  }
266  return *this;
267  }
268 
269  // TODO(math): The only reason why we store here a Reference to the fiber
270  // dataset is, we need it in the WMVoxelizer module as well as the clustering
271  // information. Since we don't have the possibility of multiple
272  // InputConnectors we must agglomerate those into one object. Please remove this.
273  // \cond Suppress_Doxygen
274  void setDataSetReference( std::shared_ptr< const WDataSetFiberVector > fibs );
275  std::shared_ptr< const WDataSetFiberVector > getDataSetReference() const;
276  // \endcond
277 
278  /**
279  * Returns a prototype instantiated with the true type of the deriving class.
280  *
281  * \return the prototype.
282  */
283  static std::shared_ptr< WPrototyped > getPrototype();
284 
285  /**
286  * Returns the center line of this cluster. The centerline gets calculated during the first call of this method.
287  *
288  * \return Reference to the center line
289  */
290  std::shared_ptr< WFiber > getCenterLine() const;
291 
292  /**
293  * Returns the center line of this cluster. The longest line gets calculated during the first call if this method.
294  *
295  * \return Reference to the longest line
296  */
297  std::shared_ptr< WFiber > getLongestLine() const;
298 
299  /**
300  * Makes the hard work to compute the center line.
301  */
302  void generateCenterLine() const;
303 
304  /**
305  * Makes the hard work to find the longest line.
306  */
307  void generateLongestLine() const;
308 
309  /**
310  * Recomputes on every call the axis aligned bounding box incorporating all tracts in this cluster.
311  *
312  * \return AABB as WBoundingBox.
313  */
315 
316 protected:
317  /**
318  * Prototype for this dataset
319  */
320  static std::shared_ptr< WPrototyped > m_prototype;
321 
322  /**
323  * Alings all fibers within the given dataset to be in one main direction. But Alignment only may swap the ordering of the fibers
324  * but not the positions or something similar. We need this only for the centerline generation.
325  *
326  * \param fibs The dataset
327  */
328  void unifyDirection( std::shared_ptr< WDataSetFiberVector > fibs ) const;
329 
330 private:
331  /**
332  * The centerline may be shortened due to the averaging of outliers. To
333  * nevertheless color almost the whole bundle surface we need a surface
334  * parameterization (given via the centerline) upto the endings of the
335  * bundle. Therefore the centerline is stepwise elongated with the last
336  * known direction, until no perpendicular plane intersects any of the
337  * tracts inside of the bundle.
338  */
339  void elongateCenterLine() const;
340 
341  /**
342  * All indices in this set are members of this cluster
343  */
345 
346  // TODO(math): The only reason why we store here a Reference to the fiber
347  // dataset is, we need it in the WMVoxelizer module as well as the clustering
348  // information. Since we don't have the possibility of multiple
349  // InputConnectors we must agglomerate those into one object. Please remove this.
350  /**
351  * Reference to the real fibers of the brain this cluster belongs to.
352  */
353  std::shared_ptr< const WDataSetFiberVector > m_fibs;
354 
355  /**
356  * Color which is used to paint the members of this cluster.
357  */
358  WColor m_color;
359 
360  /**
361  * An annotation for the bundle, usually a name.
362  */
363  std::string m_annotation;
364 
365  /**
366  * The cluster's main direction
367  */
368  osg::Vec3 m_mainDirection;
369 
370  /**
371  * Lock the modification in the m_centerLine mutable. The lock is stored as pointer to avoid copy construction problems.
372  */
373  std::shared_mutex* m_centerLineCreationLock;
374 
375  /**
376  * Lock the modification in the m_longestLine mutable. The lock is stored as pointer to avoid copy construction problems.
377  */
378  std::shared_mutex* m_longestLineCreationLock;
379 
380  /**
381  * Average fiber for this cluster representing the main direction and curvature of this cluster.
382  *
383  * \note This member is mutable as it needs to be modified during a const getter.
384  */
385  mutable std::shared_ptr< WFiber > m_centerLine;
386 
387  /**
388  * The longest fiber in the dataset.
389  *
390  * \note This member is mutable as it needs to be modified during a const getter.
391  */
392  mutable std::shared_ptr< WFiber > m_longestLine;
393 };
394 
395 inline bool WFiberCluster::empty() const
396 {
397  return m_memberIndices.empty();
398 }
399 
400 inline void WFiberCluster::sort()
401 {
402  m_memberIndices.sort();
403 }
404 
405 inline size_t WFiberCluster::size() const
406 {
407  return m_memberIndices.size();
408 }
409 
410 inline void WFiberCluster::clear()
411 {
412  m_memberIndices.clear();
413 }
414 
415 inline void WFiberCluster::setColor( WColor color )
416 {
417  m_color = color;
418 }
419 
420 inline WColor WFiberCluster::getColor() const
421 {
422  return m_color;
423 }
424 
425 inline void WFiberCluster::setAnnotation( std::string const& anno )
426 {
427  m_annotation = anno;
428 }
429 
430 inline std::string const& WFiberCluster::getAnnotation() const
431 {
432  return m_annotation;
433 }
434 
435 inline void WFiberCluster::setMainDirection( osg::Vec3 mainDirection )
436 {
437  m_mainDirection = mainDirection;
438 }
439 
440 inline osg::Vec3 WFiberCluster::getMainDirection() const
441 {
442  return m_mainDirection;
443 }
444 
445 inline const std::string WFiberCluster::getName() const
446 {
447  return "FiberCluster";
448 }
449 
450 inline const std::string WFiberCluster::getDescription() const
451 {
452  return "A collection of indices for fibers representing a fiber cluster";
453 }
454 
455 inline bool WFiberCluster::operator==( const WFiberCluster& other ) const
456 {
457  return m_memberIndices == other.m_memberIndices;
458 }
459 
460 inline bool WFiberCluster::operator!=( const WFiberCluster& other ) const
461 {
462  return m_memberIndices != other.m_memberIndices;
463 }
464 
466 {
467  return m_memberIndices;
468 }
469 
471 {
472  m_memberIndices = indices;
473 }
474 
475 inline std::ostream& operator<<( std::ostream& os, const WFiberCluster& c )
476 {
477  using string_utils::operator<<;
478  return os << c.getIndices();
479 }
480 
481 #endif // WFIBERCLUSTER_H
Unit test the WFiberCluster class.
Represents a cluster of indices of a WDataSetFiberVector.
Definition: WFiberCluster.h:45
bool operator==(const WFiberCluster &other) const
std::shared_ptr< WFiberCluster > SPtr
Shared pointer abbreviation.
Definition: WFiberCluster.h:51
std::shared_ptr< WFiber > m_centerLine
Average fiber for this cluster representing the main direction and curvature of this cluster.
std::shared_ptr< WFiber > m_longestLine
The longest fiber in the dataset.
IndexList m_memberIndices
All indices in this set are members of this cluster.
void elongateCenterLine() const
The centerline may be shortened due to the averaging of outliers.
WFiberCluster & operator=(const WFiberCluster &other)
Copy assignment operator which does NOT copy the mutex's!!!
virtual const std::string getName() const
The name of this transferable.
WColor m_color
Color which is used to paint the members of this cluster.
static std::shared_ptr< WPrototyped > m_prototype
Prototype for this dataset.
void clear()
Make this cluster empty.
void setMainDirection(osg::Vec3 mainDirection)
Sets the main direction of the cluster.
IndexList::const_iterator IndexListConstIterator
Const iterator on the index list.
Definition: WFiberCluster.h:66
virtual ~WFiberCluster()
Destructs.
std::shared_ptr< WFiber > getCenterLine() const
Returns the center line of this cluster.
WColor getColor() const
Gets the color of which all fibers of this clusters should be painted with.
std::list< size_t > IndexList
This is the list of indices of fibers.
Definition: WFiberCluster.h:61
osg::Vec3 getMainDirection() const
Gets the main direction of the cluster ( if set )
bool empty() const
Returns true if there are no fibers in that cluster, false otherwise.
virtual const std::string getDescription() const
The description of this transferable.
std::string const & getAnnotation() const
Get the annotation string.
void generateLongestLine() const
Makes the hard work to find the longest line.
std::shared_ptr< WFiber > getLongestLine() const
Returns the center line of this cluster.
std::shared_ptr< const WDataSetFiberVector > m_fibs
Reference to the real fibers of the brain this cluster belongs to.
static std::shared_ptr< WPrototyped > getPrototype()
Returns a prototype instantiated with the true type of the deriving class.
void setAnnotation(std::string const &anno)
Set the annotation for this fiber cluster.
std::string m_annotation
An annotation for the bundle, usually a name.
void setColor(WColor color)
Sets the color of which all fibers of this clusters should be painted with.
const IndexList & getIndices() const
Returns a const reference of all indices inside this cluster.
void merge(WFiberCluster &other)
Merge the fibers of the other cluster with the fibers of this cluster.
WFiberCluster()
Constructs an empty cluster.
void setIndices(const IndexList &indices)
Reset the indices belonging to that cluster.
void sort()
Sort the indices of fibers associated with this cluster in ascending order.
void unifyDirection(std::shared_ptr< WDataSetFiberVector > fibs) const
Alings all fibers within the given dataset to be in one main direction.
void generateCenterLine() const
Makes the hard work to compute the center line.
osg::Vec3 m_mainDirection
The cluster's main direction.
bool operator!=(const WFiberCluster &other) const
The opposite of the operator==.
size_t size() const
std::shared_mutex * m_centerLineCreationLock
Lock the modification in the m_centerLine mutable.
std::shared_ptr< const WFiberCluster > ConstSPtr
Const shared pointer abbreviation.
Definition: WFiberCluster.h:56
std::shared_mutex * m_longestLineCreationLock
Lock the modification in the m_longestLine mutable.
WBoundingBox getBoundingBox() const
Recomputes on every call the axis aligned bounding box incorporating all tracts in this cluster.
Represents a neural pathway.
Definition: WFiber.h:40
Class building the interface for classes that might be transferred using WModuleConnector.
Definition: WTransferable.h:38