MeVisLab Toolbox Reference
mlITKSupportToolFunctions.h
Go to the documentation of this file.
1 /*************************************************************************************
2 **
3 ** Copyright 2007, MeVis Medical Solutions AG
4 **
5 ** The user may use this file in accordance with the license agreement provided with
6 ** the Software or, alternatively, in accordance with the terms contained in a
7 ** written agreement between the user and MeVis Medical Solutions AG.
8 **
9 ** For further information use the contact form at https://www.mevislab.de/contact
10 **
11 **************************************************************************************/
12 
13 #pragma once
14 
16 // Include dll-specific settings.
17 #include "mlInitSystemITKSupport.h"
18 
20 #include "mlModuleIncludes.h"
21 
23 #include "mlPointList.h"
24 #include "mlVectorList.h"
25 #include "mlXMarkerList.h"
26 
28 #include <itkImage.h>
29 #include <itkImportImageFilter.h>
30 #include <itkMatrix.h>
31 #include <itkPointSet.h>
32 #include <itkArray.h>
33 #include <itkFixedArray.h>
34 
35 ML_START_NAMESPACE
36 
37 //---------------------------------------------------------------------------
47 //---------------------------------------------------------------------------
48 extern MLITK_SUPPORT_EXPORT void postITKException(const itk::ExceptionObject &e,
49  const Module *module,
50  MLMessageType messageType,
51  const std::string &handling="");
52 
53 
54 
55 //---------------------------------------------------------------------------
61 //------------------------------------------------------------------------------------
63  size_t itkDataTypeSize,
64  const SubImageBox &itkBox,
65  SubImage &outSubImg);
66 
67 
68 //---------------------------------------------------------------------------
78 //---------------------------------------------------------------------------
79 template<typename SIZE_TYPE>
80 SIZE_TYPE ITKSizeFromMLVector(const ImageVector &vec)
81 {
82  SIZE_TYPE sizeObj;
83  if (sizeObj.GetSizeDimension() > static_cast<unsigned int>(vec.dim())){
84  ML_PRINT_FATAL_ERROR("ITKSizeFromMLVector",
86  "Too high ITK dimension. The ML can handle only 6 dimensions.");
87  }
88  else{
89  for (unsigned int i=0; i<sizeObj.GetSizeDimension(); i++){
90  sizeObj[i] = static_cast<typename SIZE_TYPE::SizeValueType>(vec[i]);
91  }
92  }
93  return sizeObj;
94 }
95 
96 //---------------------------------------------------------------------------
106 //---------------------------------------------------------------------------
107 template<typename INDEX_TYPE>
108 INDEX_TYPE ITKIndexFromMLVector(const ImageVector &vec)
109 {
110  INDEX_TYPE sizeObj;
111  if (sizeObj.GetIndexDimension() > static_cast<unsigned int>(vec.dim())){
112  ML_PRINT_FATAL_ERROR("ITKIndexFromMLVector",
114  "Too high ITK dimension. The ML can handle only 6 dimensions.");
115  }
116  else{
117  for (unsigned int i=0; i<sizeObj.GetIndexDimension(); i++){
118  sizeObj[i] = vec[i];
119  }
120  }
121  return sizeObj;
122 }
123 
124 //---------------------------------------------------------------------------
133 //---------------------------------------------------------------------------
134 template<typename INDEX_TYPE>
135 ImageVector MLVectorFromITKSize(const INDEX_TYPE &sizeObj, MLint defaultVal)
136 {
137  ImageVector vec(0);
138  unsigned int sizeDim = sizeObj.GetSizeDimension();
139  unsigned int vecDim = static_cast<unsigned int>(vec.dim());
140  if (sizeDim > vecDim){
141  sizeDim = vecDim;
142  ML_PRINT_WARNING("MLVectorFromITKSize", ML_BAD_DIMENSION, "Too high ITK dimension. Highest dimensions ignored.");
143  }
144 
145  for (unsigned int i=0; i < vecDim; i++){ vec[i] = (i < sizeDim) ? static_cast<MLint>(sizeObj[i]) : defaultVal; }
146  return vec;
147 }
148 
149 //---------------------------------------------------------------------------
160 //---------------------------------------------------------------------------
161 template<typename INDEX_TYPE>
162 ImageVector MLVectorFromITKIndex(const INDEX_TYPE &indexObj, MLint defaultVal)
163 {
164  ImageVector vec(0);
165  unsigned int idxDim = indexObj.GetIndexDimension();
166  unsigned int vecDim = static_cast<unsigned int>(vec.dim());
167  if (idxDim > vecDim){
168  idxDim = vecDim;
169  ML_PRINT_WARNING("MLVectorFromITKIndex", ML_BAD_DIMENSION, "Too high ITK dimension. Highest dimensions ignored.");
170  }
171 
172  for (unsigned int i=0; i < vecDim; i++){ vec[i] = (i < idxDim) ? indexObj[i] : defaultVal; }
173  return vec;
174 }
175 
176 //---------------------------------------------------------------------------
188 //---------------------------------------------------------------------------
189 template<typename VECTOR_TYPE>
190 VECTOR_TYPE ITKVectorFromMLVec3(const Vector3 &vec, MLdouble defaultComp)
191 {
192  VECTOR_TYPE sizeObj;
193  for (unsigned int i=0; i<sizeObj.GetVectorDimension(); i++){
194  sizeObj[i] = i < 3 ? vec[i] : defaultComp;
195  }
196  return sizeObj;
197 }
198 
199 //---------------------------------------------------------------------------
211 //---------------------------------------------------------------------------
212 template<typename VECTOR_TYPE>
213 VECTOR_TYPE ITKVectorFromMLVec4(const Vector4 &vec, MLdouble defaultComp)
214 {
215  VECTOR_TYPE sizeObj;
216  for (unsigned int i=0; i<sizeObj.GetVectorDimension(); i++){
217  sizeObj[i] = i < 4 ? vec[i] : defaultComp;
218  }
219  return sizeObj;
220 }
221 
222 //---------------------------------------------------------------------------
234 //---------------------------------------------------------------------------
235 template<typename POINT_TYPE>
236 POINT_TYPE ITKPointFromMLVec3(const Vector3 &vec, MLdouble defaultComp)
237 {
238  POINT_TYPE sizeObj;
239  for (unsigned int i=0; i<sizeObj.GetPointDimension(); i++){
240  sizeObj[i] = i < 3 ? vec[i] : defaultComp;
241  }
242  return sizeObj;
243 }
244 
245 //---------------------------------------------------------------------------
257 //---------------------------------------------------------------------------
258 template<typename POINT_TYPE>
259 POINT_TYPE ITKPointFromMLVec4(const Vector4 &vec, MLdouble defaultComp)
260 {
261  POINT_TYPE sizeObj;
262  for (unsigned int i=0; i<sizeObj.GetPointDimension(); i++){
263  sizeObj[i] = i < 4 ? vec[i] : defaultComp;
264  }
265  return sizeObj;
266 }
267 
268 
269 //---------------------------------------------------------------------------
279 //---------------------------------------------------------------------------
280 template<typename REGION_PARENT_TYPE>
281 typename REGION_PARENT_TYPE::RegionType ITKRegionFromMLSubImgBox(const SubImageBox &subImgBox)
282 {
283  typename REGION_PARENT_TYPE::RegionType region;
284 
285  // Set ITK region origin to the ML SubImageBox origin.
286  region.SetIndex(ITKIndexFromMLVector<ITKML_TYPENAME REGION_PARENT_TYPE::IndexType>(subImgBox.v1));
287 
288  // Set ITK region extent to the ML SubImageBox extent.
289  region.SetSize(ITKSizeFromMLVector<ITKML_TYPENAME REGION_PARENT_TYPE::SizeType>(subImgBox.getExtent()));
290  return region;
291 }
292 
293 //---------------------------------------------------------------------------
301 //---------------------------------------------------------------------------
302 template<typename REGION_PARENT_TYPE>
303 SubImageBox MLSubImgBoxFromITKRegion(const typename REGION_PARENT_TYPE::RegionType &region)
304 {
305  // Get ITK region origin into the ML SubImageBox origin.
306  // For dimensions not specified by ITK use coordinate 0.
307  SubImageBox box;
308  box.v1 = MLVectorFromITKIndex(region.GetIndex(), 0);
309 
310  // Get ITK region extent into the ML SubImageBox extent.
311  // For dimensions not specified by ITK use extent 1.
312  ImageVector ext = MLVectorFromITKSize(region.GetSize(), 1);
313 
314  // Return the constructed SubImageBox.
315  box.v2 = box.v1 + (ext - ImageVector(1));
316  return box;
317 }
318 
319 //---------------------------------------------------------------------------
322 //---------------------------------------------------------------------------
323 template<typename ARRAY_TYPE, typename STL_VECTOR>
324 ARRAY_TYPE ITKArrayFromSTLVector(const STL_VECTOR &stlVec)
325 {
326  const size_t mFieldSize = stlVec.size();
327  ARRAY_TYPE retArray(mFieldSize);
328  for (size_t i=0; i<mFieldSize; ++i){ retArray[i] = stlVec[i]; }
329  return retArray;
330 }
331 
332 //---------------------------------------------------------------------------
334 //---------------------------------------------------------------------------
335 template<typename ARR_TYP, unsigned int ARR_SIZE>
336 size_t GetSizeOfAnITKArray(const itk::FixedArray<ARR_TYP, ARR_SIZE> &itkArray)
337 {
338  return itkArray.Length;
339 }
340 
341 //---------------------------------------------------------------------------
343 //---------------------------------------------------------------------------
344 template<typename ITK_ARRAY_TYPE>
345 size_t GetSizeOfAnITKArray(const ITK_ARRAY_TYPE &itkArray)
346 {
347  return itkArray.size();
348 }
349 
350 //---------------------------------------------------------------------------
354 //---------------------------------------------------------------------------
355 template<typename STL_CONTAINER, typename ITK_ARRAY_TYPE>
356 const STL_CONTAINER STLVectorFromITKArray(const ITK_ARRAY_TYPE &itkArray)
357 {
358  const size_t itkFieldSize = GetSizeOfAnITKArray(itkArray);
359  STL_CONTAINER stlVector;
360  for (size_t i=0; i<itkFieldSize; ++i){ stlVector.push_back(itkArray[i]); }
361  return stlVector;
362 }
363 
364 //---------------------------------------------------------------------------
376 //---------------------------------------------------------------------------
377 template<typename INDEX_TYPE>
378 INDEX_TYPE ITKIndexFromMLVec6(const Vector6 &vec)
379 {
380  INDEX_TYPE sizeObj;
381  if (sizeObj.GetIndexDimension() > 6){
382  ML_PRINT_FATAL_ERROR("ITKIndexFromMLVec6", ML_BAD_DIMENSION, "Too high ITK dimension. The ML can handle only 6 dimensions.");
383  }
384  else{
385  for (unsigned int i=0; i<sizeObj.GetIndexDimension(); i++){ sizeObj[i] = vec[i]; }
386  }
387  return sizeObj;
388 }
389 
390 
391 //---------------------------------------------------------------------------
397 //---------------------------------------------------------------------------
398 template<class FilterType>
399 typename FilterType::NodeContainer::Pointer ITKNodeContainerFromBasePointer(Base *baseVal)
400 {
401  XMarkerListContainer *xmlc = NULL;
402  XMarkerList *xml = NULL;
403  PointList *pl = NULL;
404  VectorList *vl = NULL;
405 
406  // Get base field.
407  if (baseVal){
408  // Check for different base object types.
409  if (ML_BASE_IS_A(baseVal, XMarkerListContainer)){
410  xmlc = static_cast<XMarkerListContainer*>(baseVal);
411  }
412  else if (ML_BASE_IS_A(baseVal, XMarkerList)){
413  xml = static_cast<XMarkerList*>(baseVal);
414  }
415  else if (ML_BASE_IS_A(baseVal, PointList)){
416  pl = static_cast<PointList*>(baseVal);
417  }
418  else if (ML_BASE_IS_A(baseVal, VectorList)){
419  vl = static_cast<VectorList*>(baseVal);
420  }
421  else{
422  // No valid type in base field. That can happen.
423  }
424  }
425 
426  // Get number of points from list.
427  MLssize_t numVals = (xmlc ? static_cast<MLssize_t>(xmlc->getList()->size()) :
428  (xml ? static_cast<MLssize_t>(xml->size()) :
429  (pl ? pl->getNum() :
430  (vl ? vl->getNum() : 0))));
431 
432 
433  if (numVals > 0){
434  // Create a NodeContainer and initialize it.
435  typename FilterType::NodeContainer::Pointer nc = FilterType::NodeContainer::New();
436  nc->Initialize();
437 
438  // Insert all list elements into the NodeContainer.
439  for (MLssize_t c=0; c < numVals; ++c){
440  // Get point list value if we have such a list.
441  Vector6 plVal(0);
442  if (pl){
443  float px=0, py=0, pz=0;
444  pl->getValue(c, px, py, pz);
445  plVal[0] = px;
446  plVal[1] = py;
447  plVal[2] = pz;
448  }
449 
450  // Get point list value if we have such a list.
451  Vector6 vlVal(0);
452  int vecType=0;
453  if (vl){
454  float px=0, py=0, pz=0;
455  vl->getPoint(c, vecType, px, py, pz);
456  vlVal[0]=px;
457  vlVal[1]=py;
458  vlVal[2]=pz;
459  }
460 
461  // get position from any of the lists.
462  Vector6 mlVec((xmlc ? (static_cast<XMarker*>(xmlc->getList()->getItemAt(c)))->pos :
463  (xml ? (static_cast<XMarker*>(xml->getItemAt(c)))->pos :
464  (pl ? plVal :
465  (vl ? vlVal : Vector6(0))))));
466 
467  typename FilterType::NodeType pnt;
468  pnt.SetValue(0);
469  pnt.SetIndex(ITKIndexFromMLVec6<ITKML_TYPENAME FilterType::NodeType::IndexType>(mlVec));
470  nc->InsertElement(c, pnt);
471  }
472 
473  return nc;
474  }
475  else{
476  return NULL;
477  }
478 }
479 
480 //---------------------------------------------------------------------------
487 //---------------------------------------------------------------------------
488 template<typename DTYPE, unsigned int ROW_DIM, unsigned int COL_DIM>
489 typename itk::Matrix<DTYPE, ROW_DIM, COL_DIM> ITKMatrixFromMLMatrix(const Matrix4 &mat)
490 {
491  // Create default matrix.
492  itk::Matrix<DTYPE, ROW_DIM, COL_DIM> retMat;
493  retMat.SetIdentity();
494 
495  // Do not allow more than four dimensions.
496  unsigned int maxRowDim = ROW_DIM;
497  if (maxRowDim > 4){
498  maxRowDim = 4;
499  ML_PRINT_WARNING("ITKMatrixFromMLMatrix", ML_BAD_DIMENSION,
500  "Too high row dimension of ITK matrix. Only 4 dimensions will be converted.");
501  }
502  unsigned int maxColDim = COL_DIM;
503  if (maxColDim > 4){
504  maxColDim = 4;
505  ML_PRINT_WARNING("ITKMatrixFromMLMatrix", ML_BAD_DIMENSION,
506  "Too high col dimension of ITK matrix. Only 4 dimensions will be converted.");
507  }
508 
509  // Copy elements.
510  for (unsigned int row=0; row < maxRowDim; ++row){
511  for (unsigned int col=0; col < maxColDim; ++col){
512  retMat[row][col] = mat[row][col];
513  }
514  }
515 
516  return retMat;
517 }
518 
519 //---------------------------------------------------------------------------
529 //---------------------------------------------------------------------------
530 template<typename DTYPE, unsigned int ROW_DIM, unsigned int COL_DIM>
531 Matrix4 MLMatrixFromITKMatrix(const ITKML_TYPENAME itk::Matrix<DTYPE, ROW_DIM, COL_DIM> &mat,
532  bool fillWithID=false,
533  bool suppressDimensionWarning=false)
534 {
535  // Do not allow more than four dimensions.
536  unsigned int maxRowDim = ROW_DIM;
537  if (maxRowDim > 4){
538  maxRowDim = 4;
539  if (!suppressDimensionWarning){
540  ML_PRINT_WARNING("MLMatrixFromITKMatrix",
542  "Too high row dimension of ITK matrix. Only 4 dimensions will be converted.");
543  }
544  }
545  unsigned int maxColDim = COL_DIM;
546  if (maxColDim > 4){
547  maxColDim = 4;
548  if (!suppressDimensionWarning){
549  ML_PRINT_WARNING("MLMatrixFromITKMatrix",
551  "Too high col dimension of ITK matrix. Only 4 dimensions will be converted.");
552  }
553  }
554 
555  // Copy elements.
556  Matrix4 retMat;
557  if (fillWithID){ retMat = Matrix4::getIdentity(); } else { retMat.set(0); }
558  for (unsigned int row=0; row < maxRowDim; ++row){
559  for (unsigned int col=0; col < maxColDim; ++col){
560  retMat[row][col] = mat[row][col];
561  }
562  }
563 
564  return retMat;
565 }
566 
567 //---------------------------------------------------------------------------
573 //---------------------------------------------------------------------------
574 template<class POINTSETTYPE>
575 typename POINTSETTYPE::Pointer ITKPointSetFromBasePointer(Base *baseVal)
576 {
577  XMarkerListContainer *xmlc = NULL;
578  XMarkerList *xml = NULL;
579  PointList *pl = NULL;
580  VectorList *vl = NULL;
581 
582  // Get base field.
583  if (baseVal){
584  // Check for different base object types.
585  if (ML_BASE_IS_A(baseVal, XMarkerListContainer)){ xmlc = static_cast<XMarkerListContainer*>(baseVal); }
586  else if (ML_BASE_IS_A(baseVal, XMarkerList)) { xml = static_cast<XMarkerList*>(baseVal); }
587  else if (ML_BASE_IS_A(baseVal, PointList)) { pl = static_cast<PointList*>(baseVal); }
588  else if (ML_BASE_IS_A(baseVal, VectorList)) { vl = static_cast<VectorList*>(baseVal); }
589  else{ /* No valid type in base field. That can happen. */ }
590  }
591 
592  // Get number of points from list.
593  MLssize_t numVals = (xmlc ? static_cast<MLssize_t>(xmlc->getList()->size()) :
594  (xml ? static_cast<MLssize_t>(xml->size()) :
595  (pl ? pl->getNum() :
596  (vl ? vl->getNum() : 0))));
597 
598 
599  // Determine maximum point dimension, clamp it to 6.
600  int maxDim = POINTSETTYPE::PointDimension;
601  if (maxDim > 6){
602  maxDim = 6;
603  ML_PRINT_WARNING("ITKPointSetFromBasePointer",
605  "Too high dimension of ITK PointSet. Only 6 dimensions will be converted.");
606  }
607 
608  if (numVals > 0){
609 
610  // Create point set object.
611  typename POINTSETTYPE::Pointer outputPointSet = POINTSETTYPE::New();
612 
613  typedef typename POINTSETTYPE::PointDataContainer DataContainer;
614  outputPointSet->SetPointData( DataContainer::New());
615  outputPointSet->GetPoints()->Reserve( numVals );
616  outputPointSet->GetPointData()->Reserve( numVals );
617 
618  typename POINTSETTYPE::PointIdentifier pointId = 0;
619  typename POINTSETTYPE::PointType point;
620 
621  // Insert all list elements into the NodeContainer.
622  for (MLssize_t c=0; c < numVals; ++c){
623  // Get point list value if we have such a list.
624  Vector6 plVal(0);
625  if (pl){
626  float px=0, py=0, pz=0;
627  pl->getValue(c, px, py, pz);
628  plVal[0] = px;
629  plVal[1] = py;
630  plVal[2] = pz;
631  }
632 
633  // Get point list value if we have such a list.
634  Vector6 vlVal(0);
635  int vecType=0;
636  if (vl){
637  float px=0, py=0, pz=0;
638  vl->getPoint(c, vecType, px, py, pz);
639  vlVal[0]=px;
640  vlVal[1]=py;
641  vlVal[2]=pz;
642  }
643 
644  // get position from any of the lists.
645  Vector6 mlVec((xmlc ? (static_cast<XMarker*>(xmlc->getList()->getItemAt(c)))->pos :
646  (xml ? (static_cast<XMarker*>(xml->getItemAt(c)))->pos :
647  (pl ? plVal :
648  (vl ? vlVal : Vector6(0))))));
649 
650  // Copy point components.
651  for (int j=0; j < maxDim ;j++){ point[j] = mlVec[j]; }
652  outputPointSet->SetPoint(pointId++, point );
653  }
654 
655  return outputPointSet;
656  }
657  else{
658  // Create and return default (empty) point set object.
659  typename POINTSETTYPE::Pointer outputPointSet = POINTSETTYPE::New();
660  return outputPointSet;
661  }
662 }
663 
664 //---------------------------------------------------------------------------
668 //---------------------------------------------------------------------------
669 template <typename ITK_IMPORT_IMAGE_FILTER_TYPE>
670 void ITKSetOriginFromVec3(itk::ImportImageFilter<typename ITK_IMPORT_IMAGE_FILTER_TYPE::OutputImagePixelType,
671  ITK_IMPORT_IMAGE_FILTER_TYPE::OutputImageType::ImageDimension>* importImageFilter,
672  const Vector3 &orig)
673 {
674  importImageFilter->SetOrigin(ITKPointFromMLVec3<ITKML_TYPENAME ITK_IMPORT_IMAGE_FILTER_TYPE::OriginType>(orig,0));
675 }
676 
677 //---------------------------------------------------------------------------
681 //---------------------------------------------------------------------------
682 template <typename ITK_IMAGE_TYPE>
683 void ITKSetOriginFromVec3(itk::Image<typename ITK_IMAGE_TYPE::PixelType,
684  ITK_IMAGE_TYPE::ImageDimension>* image,
685  const Vector3 &orig)
686 {
687  image->SetOrigin(ITKPointFromMLVec3<ITKML_TYPENAME ITK_IMAGE_TYPE::PointType>(orig,0));
688 }
689 
690 //---------------------------------------------------------------------------
709 //---------------------------------------------------------------------------
710 template <typename ITK_CLASS_TYPE>
712  ITK_CLASS_TYPE *image,
713  bool correctSVS=true)
714 {
715  if (!image){ return; }
716 
717  // Get ML voxel size/scaling.
718  const Vector3 scales(props.getVoxelSize());
719 
720  // Set voxel spacing, origin and direction cosines of output image and use 1 for unknown higher dimensional components.
721  image->SetSpacing(ITKVectorFromMLVec3<ITKML_TYPENAME ITK_CLASS_TYPE::SpacingType>(scales, 1));
722 
723  // Correct the sub voxel position by translating it to the center.
724  // In the ML the voxel coordinate is in the corner, in itk and vtk
725  // it is in the center.
726  if (correctSVS){ props.translateVoxelToWorldMatrix(Vector3( 0.5, 0.5, 0.5)); }
727 
728  Matrix4 mat = props.getVoxelToWorldMatrix();
729 
730  // Determine image origin for itk image:
731  // Extract (sub voxel) corrected translation vector.
732  const Vector3 orig(mat[0][3], mat[1][3], mat[2][3]);
733  ITKSetOriginFromVec3<ITK_CLASS_TYPE>(image, orig);
734 
735  // Image direction/orientation:
736  // Multiply mat with inverse voxel scale factor to get normalized direction cosines/orientation matrix.
737  const Vector3 invScales(MLValueIs0WOM(scales[0]) ? 1 : 1/scales[0],
738  MLValueIs0WOM(scales[1]) ? 1 : 1/scales[1],
739  MLValueIs0WOM(scales[2]) ? 1 : 1/scales[2]);
740 
741  mat[0][0] = mat[0][0]*invScales[0];
742  mat[1][0] = mat[1][0]*invScales[0];
743  mat[2][0] = mat[2][0]*invScales[0];
744  mat[3][0] = 0;
745 
746  mat[0][1] = mat[0][1]*invScales[1];
747  mat[1][1] = mat[1][1]*invScales[1];
748  mat[2][1] = mat[2][1]*invScales[1];
749  mat[3][1] = 0;
750 
751  mat[0][2] = mat[0][2]*invScales[2];
752  mat[1][2] = mat[1][2]*invScales[2];
753  mat[2][2] = mat[2][2]*invScales[2];
754  mat[3][2] = 0;
755 
756  mat[0][3] = 0;
757  mat[1][3] = 0;
758  mat[2][3] = 0;
759  mat[3][3] = 1;
760 
761  typename ITK_CLASS_TYPE::DirectionType dirCosines = ITKMatrixFromMLMatrix<MLdouble,
762  ITK_CLASS_TYPE::DirectionType::RowDimensions,
763  ITK_CLASS_TYPE::DirectionType::ColumnDimensions>(mat);
764  image->SetDirection(dirCosines);
765 }
766 
767 
768 //---------------------------------------------------------------------------
793 //---------------------------------------------------------------------------
794 template <typename ITK_CLASS_TYPE>
795 void setMLWorldFromITKScaleOriginAndOrientation(const ITK_CLASS_TYPE *image,
796  MedicalImageProperties &props,
797  bool correctSVS=true,
798  bool suppressDimensionWarning=false)
799 {
800  if (!image){ return; }
801  if (ITK_CLASS_TYPE::ImageDimension < 2){
802  ML_PRINT_ERROR("setMLWorldFromITKScaleOriginAndOrientation",
804  "1 D itk world matrix conversion is not supported; "
805  "using identity as return value.");
806  props.setVoxelToWorldMatrix(Matrix4::getIdentity());
807  }
808 
809  // Get location, voxel scaling and orientation of itk image or importer.
810  const typename ITK_CLASS_TYPE::SpacingType spacing = image->GetSpacing();
811  const typename ITK_CLASS_TYPE::PointType origin = image->GetOrigin();
812  const typename ITK_CLASS_TYPE::DirectionType direction = image->GetDirection();
813 
814  // Copy 3x3 itk matrix components to corresponding ones in id ML matrix.
815  const Matrix4 dirCosines = MLMatrixFromITKMatrix<double,
816  ITK_CLASS_TYPE::ImageDimension,
817  ITK_CLASS_TYPE::ImageDimension>(direction, true, suppressDimensionWarning);
818 
819  // Create the ML world matrix as id and set up scaling, orientation and origin provided by the itk image or importer.
820  Matrix4 mat = Matrix4::getIdentity();
821 
822  // Compose scale, directionCosines and translation to the new ML world matrix.
823  mat[0][0] = dirCosines[0][0]*spacing[0];
824  mat[1][0] = dirCosines[1][0]*spacing[0];
825  mat[2][0] = dirCosines[2][0]*spacing[0];
826  mat[3][0] = 0;
827 
828  mat[0][1] = dirCosines[0][1]*spacing[1];
829  mat[1][1] = dirCosines[1][1]*spacing[1];
830  mat[2][1] = dirCosines[2][1]*spacing[1];
831  mat[3][1] = 0;
832 
833  // Avoid invalid accesses to spacing if we operate on 2D images.
834  const double spacing2 = (ITK_CLASS_TYPE::ImageDimension > 2) ? spacing[2] : 1;
835  mat[0][2] = dirCosines[0][2]*spacing2;
836  mat[1][2] = dirCosines[1][2]*spacing2;
837  mat[2][2] = dirCosines[2][2]*spacing2;
838  mat[3][2] = 0;
839 
840  mat[0][3] = origin[0];
841  mat[1][3] = origin[1];
842  mat[2][3] = (ITK_CLASS_TYPE::ImageDimension > 2) ? origin[2] : 0;
843  mat[3][3] = 1;
844 
845  props.setVoxelToWorldMatrix(mat);
846 
847  // Subtract half voxel shift - in MedicalImageProperties the matrix considers
848  // voxel positions at the corner and not in the center.
849  if (correctSVS){ props.translateVoxelToWorldMatrix(Vector3(-0.5, -0.5, -0.5)); }
850 }
851 
852 
853 //---------------------------------------------------------------------------
874 //---------------------------------------------------------------------------
875 template <typename ITK_INDATATYPE, unsigned int DIM>
876 typename itk::ImportImageFilter<ITK_INDATATYPE, DIM>::Pointer getITKImportImageFromSubImg(const SubImage &inSubImg,
877  const MedicalImageProperties &props,
878  bool correctSVS=true)
879 {
880  // Create a new ImportImageFilter.
881  typedef itk::ImportImageFilter<ITK_INDATATYPE, DIM> ImportFilterType;
882  typedef typename ImportFilterType::Pointer ImportFilterPointerType;
883 
884  ImportFilterPointerType importer = ImportFilterType::New();
885 
886  // Get box from the input subimage, convert it to a ITK region and
887  // set it as output image region of the image import filter.
888  SubImageBox inSubImgBox(inSubImg.getBox());
889  importer->SetRegion(ITKRegionFromMLSubImgBox<ImportFilterType>(inSubImgBox));
890 
891  // Set voxel spacing, origin and orientation of itk image.
892  setITKWorldFromMedicalImageProperty<ImportFilterType>(props, &(*importer), correctSVS);
893 
894  // Set pointer to the data to be imported by the image import filter.
895  importer->SetImportPointer(static_cast<ITK_INDATATYPE*>(inSubImg.getData()),
896  static_cast<itk::SizeValueType>(inSubImgBox.getNumVoxels()),
897  false); // we don't want to let ITK managing memory
898  importer->Update();
899 
900  // Return the importer object.
901  return importer;
902 }
903 
904 
905  //----------------------------------------------------------------------------------
921  //----------------------------------------------------------------------------------
922  template <typename RETURN_TYPE_PTR, typename FILTER_TYPE, typename VOXEL_TYPE>
924  int inIdx,
925  TSubImage<VOXEL_TYPE> &dataSubImg,
926  bool correctSVS=true)
927  {
928  // Get and load connected image only if it's valid and not a a redirected one
929  // (which may occur in cases of optional mask image inputs).
930  PagedImage* pInImg = op.getUpdatedInputImage(inIdx);
931  if (pInImg){
932  // Get 3D box input image.
933  const ImageVector _inImgExt = pInImg->getImageExtent();
934  const SubImageBox inImgBox(ImageVector(_inImgExt.x, _inImgExt.y, _inImgExt.z,1,1,1));
935 
936  // Check whether TSubImage contains enough memory, if not we need to free and reallocate it.
937  if (dataSubImg.getData() && (dataSubImg.getBox().getExtent() != inImgBox.getExtent())){
938  dataSubImg.free();
939  }
940  // Set up data box and allocate data if still not there.
941  dataSubImg.setBox(inImgBox);
942  if (!dataSubImg.getData()){
944  }
945  if (!dataSubImg.getData()){
946  return NULL;
947  }
948 
949  // Get image data from input.
950  MLErrorCode err = pInImg->getTile(dataSubImg);
951  if (ML_RESULT_OK == err){
952  // Create a new ImportImageFilter.
953  typename FILTER_TYPE::Pointer importer = FILTER_TYPE::New();
954 
955  // Get box from the input subimage, convert it to a ITK region and
956  // set it as output image region of the image import filter.
957  importer->SetRegion(ITKRegionFromMLSubImgBox<FILTER_TYPE>(inImgBox));
958 
959  // Pass world transformation of ML image to world transformation of itk image or importer.
960  setITKWorldFromMedicalImageProperty<FILTER_TYPE>(*pInImg, &(*importer), correctSVS);
961 
962  // Set pointer to the data to be imported by the image import filter.
963  // Pass true to make ITK manage the memory, i.e. if the last import object
964  // disappears the data also disappears.
965  importer->SetImportPointer(static_cast<VOXEL_TYPE*>(dataSubImg.getData()), inImgBox.getNumVoxels(), false);
966  importer->Update();
967  return importer->GetOutput();
968  }
969  else{
970  ML_PRINT_ERROR("mlITKSupportToolFunctions::getInputAsItkImportImageAndSubImg()",
971  err,
972  "Failed to request input image data, probably subsequent operations will fail");
973  }
974  }
975 
976  // Error, no image could be loaded.
977  return NULL;
978  }
979 
980 ML_END_NAMESPACE
BaseItem * getItemAt(MLssize_t index) override
This virtual function is reimplemented from ListBase, where it returns 0 in any case (also in ListTem...
Definition: mlListBase.h:746
Class representing general ML objects that support import/export via strings (setPersistentState() an...
Definition: mlBase.h:62
ImageVector getImageExtent() const
Returns the extent of the (sub)image.
virtual T * getList()
Get pointer to the active list object Use this pointer for list access after testing that it is !...
This class encapsulates basic medical image properties:
Vector3 getVoxelSize() const
Returns the voxel size.
const Matrix4 & getVoxelToWorldMatrix() const
Returns the voxelToWorld matrix.
void setVoxelToWorldMatrix(const Matrix4 &matrix)
Sets the matrix which transforms voxel to world coordinates to matrix.
void translateVoxelToWorldMatrix(const Vector3 &offsetVector)
Translates the voxelToWorld matrix by the offsetVector.
Base class for an image processing module of the ML.
Definition: mlModule.h:156
PagedImage * getUpdatedInputImage(MLint inputIndex, bool getReal=false) const
Convenience method for safe access to the input image at index inputIndex.
Class which represents an image, which manages properties of an image and image data which is located...
Definition: mlPagedImage.h:70
MLEXPORT MLErrorCode getTile(SubImageBox location, MLDataType dataType, void **data, const ScaleShiftData &scaleShiftData=ScaleShiftData(), MLRequestProgressCB *progressCallback=nullptr, void *progressCallbackUserData=nullptr)
See Host::getTile( module, outputIndex, location, dataType, data, scaleShiftData).
Base object class PointList managing a list of points.
Definition: mlPointList.h:29
void getValue(MLssize_t index, Vector3 &vec) const
get point at given index
MLssize_t getNum() const
returns the number of contained points
This class manages/represents a rectangular 6d image region which is organized linearly in memory.
Definition: mlSubImage.h:75
void * getData() const
Returns the memory address of the memory managed by the subimage.
Definition: mlSubImage.h:372
void setBox(const SubImageBox &subImageBox)
Sets a rectangular 6d region of the subimage to subImageBox.
Definition: mlSubImage.h:163
MLEXPORT void allocateAsMemoryBlockHandle(MLMemoryErrorHandling handleFailure=ML_RETURN_NULL)
Allocate data using the ML memory manager. For failure handing, see SubImage::allocate().
MLEXPORT void free()
Frees data pointed to by getData() with MLFree().
const SubImageBox & getBox() const
Returns the box describing the origin/extent of the subimage.
Definition: mlSubImage.h:230
static MLint dim()
Returns the dimension the ML calculates with.
VectorType v1
Corner v1 of the subimage region (included in region).
Definition: mlSubImageBox.h:63
VectorType v2
Corner v2 of the subimage region (also included in region!).
Definition: mlSubImageBox.h:69
intT getNumVoxels() const
Returns number of voxels in the subimage region, i.e., the product of all extents if this is not empt...
VectorType getExtent() const
Returns the extents of the subimage region.
This template class manages/represents a rectangular 6d image region in memory which is organized lin...
Definition: mlTSubImage.h:110
const DATATYPE * getData() const
Returns memory address of image region (Overloads method from SubImage)
Definition: mlTSubImage.h:217
ComponentType z
Z component of the vector.
Definition: mlImageVector.h:63
ComponentType x
X component of the vector.
Definition: mlImageVector.h:59
ComponentType y
Y component of the vector.
Definition: mlImageVector.h:61
void set(const DT val)
Sets all values to double val.
Definition: mlMatrix4.h:277
Base object representing a list of vectors given as Vector4's.
Definition: mlVectorList.h:29
void getPoint(MLssize_t index, int &type, float &x1, float &y1, float &z1) const
returns point of vectors at given point index (NOTE: (0,1 = first vector , 2,3 = second vector))
MLssize_t getNum() const
returns the number of contained points
Base object class XMarkerListContainer (derived from ListContainerTemplate) for XMarkerList objects.
Base object class XMarkerList (derived from BaseListTemplate) specialized for XMarker items.
Base object class XMarker (derived form baseItem) with 6D pos, 3D vec and type int.
Definition: mlXMarkerList.h:52
#define ML_BASE_IS_A(base, type)
This file defines macros, which are inserted in classes to declare and implement additional class mem...
bool MLValueIs0WOM(MLint8 a)
Returns true if value is 0, otherwise false.
#define ML_BAD_PARAMETER
A bad/invalid parameter (or even an inappropriate image) has been passed to a module or an algorithm;...
Definition: mlTypeDefs.h:925
#define ML_BAD_DIMENSION
he image or data structure has wrong extent or dimensions.
Definition: mlTypeDefs.h:937
MLint32 MLErrorCode
Type of an ML Error code.
Definition: mlTypeDefs.h:818
#define ML_RESULT_OK
No error. Everything seems to be okay.
Definition: mlTypeDefs.h:826
#define ML_PRINT_FATAL_ERROR(FUNC_NAME, REASON, HANDLING)
Like ML_PRINT_FATAL_ERROR_DUMP(FUNC_NAME, REASON, HANDLING, RT_OBJ) without a runtime object to be du...
#define ML_PRINT_WARNING(FUNC_NAME, REASON, HANDLING)
Like ML_PRINT_WARNING_DUMP(FUNC_NAME, REASON, HANDLING, RT_OBJ) without a runtime object to be dumped...
#define ML_PRINT_ERROR(FUNC_NAME, REASON, HANDLING)
Like ML_PRINT_ERROR_DUMP(FUNC_NAME, REASON, HANDLING, RT_OBJ) without a runtime object to be dumped.
#define MLITK_SUPPORT_EXPORT
When included by other libraries MLITK_SUPPORT_EXPORT is compiled as import symbol.
#define ITKML_TYPENAME
Define it empty. In some cases VC++6 does not accept "typename" where non WIN32 compilers do.
@ ML_FATAL_MEMORY_ERROR
On allocation failure a fatal error print is done and NULL is returned.
Definition: mlTypeDefs.h:779
double MLdouble
Definition: mlTypeDefs.h:223
MLint64 MLint
A signed ML integer type with at least 64 bits used for index calculations on very large images even ...
Definition: mlTypeDefs.h:578
SSIZE_T MLssize_t
The signed ML size type which is a signed 32 bit size_t on 32 bit platforms and 64 bit one on 64 bit ...
Definition: mlTypeDefs.h:654
MLMessageType
Message types handled by the ErrorOutput class.
Definition: mlTypeDefs.h:798
ImageVector MLVectorFromITKSize(const INDEX_TYPE &sizeObj, MLint defaultVal)
Assign and cast values from an ITK size object to an ML ImageVector.
void setITKWorldFromMedicalImageProperty(MedicalImageProperties props, ITK_CLASS_TYPE *image, bool correctSVS=true)
Takes the world transformation of ML MedicalImageProperties and sets spacing, origin and direction co...
itk::ImportImageFilter< ITK_INDATATYPE, DIM >::Pointer getITKImportImageFromSubImg(const SubImage &inSubImg, const MedicalImageProperties &props, bool correctSVS=true)
Takes a SubImage and returns an object of an itk::ImportImageFilter managing the inSubImg as ITK obje...
const STL_CONTAINER STLVectorFromITKArray(const ITK_ARRAY_TYPE &itkArray)
Returns an STL container object of type STL_CONTAINER which contains cast copies of all elements of t...
FilterType::NodeContainer::Pointer ITKNodeContainerFromBasePointer(Base *baseVal)
Reads a base field and looks for point like data structures (XMarkerLists, XMarkerListContainers,...
size_t GetSizeOfAnITKArray(const ITK_ARRAY_TYPE &itkArray)
Returns the size of an arbitrary itk array.
REGION_PARENT_TYPE::RegionType ITKRegionFromMLSubImgBox(const SubImageBox &subImgBox)
Assign and cast values from an ITK region to an ML SubImageBox object.
POINT_TYPE ITKPointFromMLVec3(const Vector3 &vec, MLdouble defaultComp)
Assign and cast values from an ML Vector3 to an ITK point object; all itk components with index > 3 a...
Matrix4 MLMatrixFromITKMatrix(const ITKML_TYPENAME itk::Matrix< DTYPE, ROW_DIM, COL_DIM > &mat, bool fillWithID=false, bool suppressDimensionWarning=false)
Converts itk::Matrix mat of type itk::Matrix<DTYPE, ROW_DIM, COL_DIM> to the returned ML 4x4 matrix o...
POINTSETTYPE::Pointer ITKPointSetFromBasePointer(Base *baseVal)
Reads the passed baseVal objects and looks for point like data structures (XMarkerLists,...
VECTOR_TYPE ITKVectorFromMLVec4(const Vector4 &vec, MLdouble defaultComp)
Assign and cast values from an ML Vector4 to an ITK size object; all itk components with index > 3 ar...
Tvec3< MLdouble > Vector3
A vector with 3 components of type double.
Definition: mlVector3.h:300
POINT_TYPE ITKPointFromMLVec4(const Vector4 &vec, MLdouble defaultComp)
Assign and cast values from an ML Vector4 to an ITK object of type POINT_TYPE; all itk components wit...
MLITK_SUPPORT_EXPORT void copyITKDataBufferToMLSubImg(void *itkData, size_t itkDataTypeSize, const SubImageBox &itkBox, SubImage &outSubImg)
Unpack ITK data buffer to an ML subimage and convert data formats if necessary.
SIZE_TYPE ITKSizeFromMLVector(const ImageVector &vec)
Assign and cast values from an ML ImageVector to an ITK size object.
RETURN_TYPE_PTR getInputAsItkImportImageAndSubImg(Module &op, int inIdx, TSubImage< VOXEL_TYPE > &dataSubImg, bool correctSVS=true)
Reads and updates an input image from the input number inIdx of Module op and sets up the referenced ...
SubImageBox MLSubImgBoxFromITKRegion(const typename REGION_PARENT_TYPE::RegionType &region)
Assign and cast values from an ITK region to an ML SubImageBox object.
ImageVector MLVectorFromITKIndex(const INDEX_TYPE &indexObj, MLint defaultVal)
Assign and cast values from an ITK index object to an ML ImageVector.
INDEX_TYPE ITKIndexFromMLVector(const ImageVector &vec)
Assign and cast values from an ML ImageVector to an ITK size object.
INDEX_TYPE ITKIndexFromMLVec6(const Vector6 &vec)
Assign and cast values from an ML Vector6 to an ITK index object of type INDEX_TYPE.
void setMLWorldFromITKScaleOriginAndOrientation(const ITK_CLASS_TYPE *image, MedicalImageProperties &props, bool correctSVS=true, bool suppressDimensionWarning=false)
Sets the world transformation of the ML MedicalImageProperties props from the spacing,...
ARRAY_TYPE ITKArrayFromSTLVector(const STL_VECTOR &stlVec)
Returns an object of an ITK array type ARRAY_TYPE which contains cast copies of all elements of stlVe...
void ITKSetOriginFromVec3(itk::Image< typename ITK_IMAGE_TYPE::PixelType, ITK_IMAGE_TYPE::ImageDimension > *image, const Vector3 &orig)
On the given ITK_IMAGE_TYPE the origin orig is set with the SetOrigin method from a point type; the o...
MLITK_SUPPORT_EXPORT void postITKException(const itk::ExceptionObject &e, const Module *module, MLMessageType messageType, const std::string &handling="")
Sends all available information from the ITKException itkException to the ML error handler.
TImageVector< MLint > ImageVector
Defines the standard ImageVector type which is used by the ML for indexing and coordinates.
VECTOR_TYPE ITKVectorFromMLVec3(const Vector3 &vec, MLdouble defaultComp)
Assign and cast values from an ML Vector3 to an ITK size object; all itk components with index > 2 ar...
itk::Matrix< DTYPE, ROW_DIM, COL_DIM > ITKMatrixFromMLMatrix(const Matrix4 &mat)
Converts the ML 4x4 matrix mat function argument to the returned itk::Matrix of type itk::Matrix<DTYP...