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 //---------------------------------------------------------------------------
335 //---------------------------------------------------------------------------
336 template<typename VERSOR_TYPE>
337 VERSOR_TYPE ITKVersorFromMLVector(const ml::Vector4 &mlVec)
338 {
339  VERSOR_TYPE Rotation;
340  Rotation.Set(mlVec[0], mlVec[1], mlVec[2], mlVec[3]);
341  return Rotation;
342 }
343 
344 //---------------------------------------------------------------------------
346 //---------------------------------------------------------------------------
347 template<typename ARR_TYP, unsigned int ARR_SIZE>
348 size_t GetSizeOfAnITKArray(const itk::FixedArray<ARR_TYP, ARR_SIZE> &itkArray)
349 {
350  return itkArray.Length;
351 }
352 
353 //---------------------------------------------------------------------------
355 //---------------------------------------------------------------------------
356 template<typename ITK_ARRAY_TYPE>
357 size_t GetSizeOfAnITKArray(const ITK_ARRAY_TYPE &itkArray)
358 {
359  return itkArray.size();
360 }
361 
362 //---------------------------------------------------------------------------
366 //---------------------------------------------------------------------------
367 template<typename STL_CONTAINER, typename ITK_ARRAY_TYPE>
368 const STL_CONTAINER STLVectorFromITKArray(const ITK_ARRAY_TYPE &itkArray)
369 {
370  const size_t itkFieldSize = GetSizeOfAnITKArray(itkArray);
371  STL_CONTAINER stlVector;
372  for (size_t i=0; i<itkFieldSize; ++i){ stlVector.push_back(itkArray[i]); }
373  return stlVector;
374 }
375 
376 //---------------------------------------------------------------------------
380 //---------------------------------------------------------------------------
381 template<typename ITK_VERSOR_TYPE>
382 const ml::Vector4 MLVectorFromITKVersor(const ITK_VERSOR_TYPE &itkVersor)
383 {
384  ml::Vector4 mlVector(itkVersor.GetX(), itkVersor.GetY(), itkVersor.GetZ(), itkVersor.GetW());
385  return mlVector;
386 }
387 
388 //---------------------------------------------------------------------------
400 //---------------------------------------------------------------------------
401 template<typename INDEX_TYPE>
402 INDEX_TYPE ITKIndexFromMLVec6(const Vector6 &vec)
403 {
404  INDEX_TYPE sizeObj;
405  if (sizeObj.GetIndexDimension() > 6){
406  ML_PRINT_FATAL_ERROR("ITKIndexFromMLVec6", ML_BAD_DIMENSION, "Too high ITK dimension. The ML can handle only 6 dimensions.");
407  }
408  else{
409  for (unsigned int i=0; i<sizeObj.GetIndexDimension(); i++){ sizeObj[i] = vec[i]; }
410  }
411  return sizeObj;
412 }
413 
414 
415 //---------------------------------------------------------------------------
421 //---------------------------------------------------------------------------
422 template<class FilterType>
423 typename FilterType::NodeContainer::Pointer ITKNodeContainerFromBasePointer(Base *baseVal)
424 {
425  XMarkerListContainer *xmlc = nullptr;
426  XMarkerList *xml = nullptr;
427  PointList *pl = nullptr;
428  VectorList *vl = nullptr;
429 
430  // Get base field.
431  if (baseVal){
432  // Check for different base object types.
433  if (ML_BASE_IS_A(baseVal, XMarkerListContainer)){
434  xmlc = static_cast<XMarkerListContainer*>(baseVal);
435  }
436  else if (ML_BASE_IS_A(baseVal, XMarkerList)){
437  xml = static_cast<XMarkerList*>(baseVal);
438  }
439  else if (ML_BASE_IS_A(baseVal, PointList)){
440  pl = static_cast<PointList*>(baseVal);
441  }
442  else if (ML_BASE_IS_A(baseVal, VectorList)){
443  vl = static_cast<VectorList*>(baseVal);
444  }
445  else{
446  // No valid type in base field. That can happen.
447  }
448  }
449 
450  // Get number of points from list.
451  MLssize_t numVals = (xmlc ? static_cast<MLssize_t>(xmlc->getList()->size()) :
452  (xml ? static_cast<MLssize_t>(xml->size()) :
453  (pl ? pl->getNum() :
454  (vl ? vl->getNum() : 0))));
455 
456 
457  if (numVals > 0){
458  // Create a NodeContainer and initialize it.
459  typename FilterType::NodeContainer::Pointer nc = FilterType::NodeContainer::New();
460  nc->Initialize();
461 
462  // Insert all list elements into the NodeContainer.
463  for (MLssize_t c=0; c < numVals; ++c){
464  // Get point list value if we have such a list.
465  Vector6 plVal(0);
466  if (pl){
467  float px=0, py=0, pz=0;
468  pl->getValue(c, px, py, pz);
469  plVal[0] = px;
470  plVal[1] = py;
471  plVal[2] = pz;
472  }
473 
474  // Get point list value if we have such a list.
475  Vector6 vlVal(0);
476  int vecType=0;
477  if (vl){
478  float px=0, py=0, pz=0;
479  vl->getPoint(c, vecType, px, py, pz);
480  vlVal[0]=px;
481  vlVal[1]=py;
482  vlVal[2]=pz;
483  }
484 
485  // get position from any of the lists.
486  Vector6 mlVec((xmlc ? (static_cast<XMarker*>(xmlc->getList()->getItemAt(c)))->pos :
487  (xml ? (static_cast<XMarker*>(xml->getItemAt(c)))->pos :
488  (pl ? plVal :
489  (vl ? vlVal : Vector6(0))))));
490 
491  typename FilterType::NodeType pnt;
492  pnt.SetValue(0);
493  pnt.SetIndex(ITKIndexFromMLVec6<ITKML_TYPENAME FilterType::NodeType::IndexType>(mlVec));
494  nc->InsertElement(c, pnt);
495  }
496 
497  return nc;
498  }
499  else{
500  return nullptr;
501  }
502 }
503 
504 //---------------------------------------------------------------------------
507 //---------------------------------------------------------------------------
509 
510 //---------------------------------------------------------------------------
517 //---------------------------------------------------------------------------
518 template<typename DTYPE, unsigned int ROW_DIM, unsigned int COL_DIM>
519 typename itk::Matrix<DTYPE, ROW_DIM, COL_DIM> ITKMatrixFromMLMatrix(const Matrix4 &mat)
520 {
521  // Create default matrix.
522  itk::Matrix<DTYPE, ROW_DIM, COL_DIM> retMat;
523  retMat.SetIdentity();
524 
525  // Do not allow more than four dimensions.
526  unsigned int maxRowDim = ROW_DIM;
527  if (maxRowDim > 4){
528  maxRowDim = 4;
529  ML_PRINT_WARNING("ITKMatrixFromMLMatrix", ML_BAD_DIMENSION,
530  "Too high row dimension of ITK matrix. Only 4 dimensions will be converted.");
531  }
532  unsigned int maxColDim = COL_DIM;
533  if (maxColDim > 4){
534  maxColDim = 4;
535  ML_PRINT_WARNING("ITKMatrixFromMLMatrix", ML_BAD_DIMENSION,
536  "Too high col dimension of ITK matrix. Only 4 dimensions will be converted.");
537  }
538 
539  // Copy elements.
540  for (unsigned int row=0; row < maxRowDim; ++row){
541  for (unsigned int col=0; col < maxColDim; ++col){
542  retMat[row][col] = mat[row][col];
543  }
544  }
545 
546  return retMat;
547 }
548 
549 //---------------------------------------------------------------------------
559 //---------------------------------------------------------------------------
560 template<typename DTYPE, unsigned int ROW_DIM, unsigned int COL_DIM>
561 Matrix4 MLMatrixFromITKMatrix(const ITKML_TYPENAME itk::Matrix<DTYPE, ROW_DIM, COL_DIM> &mat,
562  bool fillWithID=false,
563  bool suppressDimensionWarning=false)
564 {
565  // Do not allow more than four dimensions.
566  unsigned int maxRowDim = ROW_DIM;
567  if (maxRowDim > 4){
568  maxRowDim = 4;
569  if (!suppressDimensionWarning){
570  ML_PRINT_WARNING("MLMatrixFromITKMatrix",
572  "Too high row dimension of ITK matrix. Only 4 dimensions will be converted.");
573  }
574  }
575  unsigned int maxColDim = COL_DIM;
576  if (maxColDim > 4){
577  maxColDim = 4;
578  if (!suppressDimensionWarning){
579  ML_PRINT_WARNING("MLMatrixFromITKMatrix",
581  "Too high col dimension of ITK matrix. Only 4 dimensions will be converted.");
582  }
583  }
584 
585  // Copy elements.
586  Matrix4 retMat;
587  if (fillWithID){ retMat = Matrix4::getIdentity(); } else { retMat.set(0); }
588  for (unsigned int row=0; row < maxRowDim; ++row){
589  for (unsigned int col=0; col < maxColDim; ++col){
590  retMat[row][col] = mat[row][col];
591  }
592  }
593 
594  return retMat;
595 }
596 
597 //---------------------------------------------------------------------------
603 //---------------------------------------------------------------------------
604 template<class POINTSETTYPE>
605 typename POINTSETTYPE::Pointer ITKPointSetFromBasePointer(Base *baseVal)
606 {
607  XMarkerListContainer *xmlc = nullptr;
608  XMarkerList *xml = nullptr;
609  PointList *pl = nullptr;
610  VectorList *vl = nullptr;
611 
612  // Get base field.
613  if (baseVal){
614  // Check for different base object types.
615  if (ML_BASE_IS_A(baseVal, XMarkerListContainer)){ xmlc = static_cast<XMarkerListContainer*>(baseVal); }
616  else if (ML_BASE_IS_A(baseVal, XMarkerList)) { xml = static_cast<XMarkerList*>(baseVal); }
617  else if (ML_BASE_IS_A(baseVal, PointList)) { pl = static_cast<PointList*>(baseVal); }
618  else if (ML_BASE_IS_A(baseVal, VectorList)) { vl = static_cast<VectorList*>(baseVal); }
619  else{ /* No valid type in base field. That can happen. */ }
620  }
621 
622  // Get number of points from list.
623  MLssize_t numVals = (xmlc ? static_cast<MLssize_t>(xmlc->getList()->size()) :
624  (xml ? static_cast<MLssize_t>(xml->size()) :
625  (pl ? pl->getNum() :
626  (vl ? vl->getNum() : 0))));
627 
628 
629  // Determine maximum point dimension, clamp it to 6.
630  int maxDim = POINTSETTYPE::PointDimension;
631  if (maxDim > 6){
632  maxDim = 6;
633  ML_PRINT_WARNING("ITKPointSetFromBasePointer",
635  "Too high dimension of ITK PointSet. Only 6 dimensions will be converted.");
636  }
637 
638  if (numVals > 0){
639 
640  // Create point set object.
641  typename POINTSETTYPE::Pointer outputPointSet = POINTSETTYPE::New();
642 
643  typedef typename POINTSETTYPE::PointDataContainer DataContainer;
644  outputPointSet->SetPointData( DataContainer::New());
645  outputPointSet->GetPoints()->Reserve( numVals );
646  outputPointSet->GetPointData()->Reserve( numVals );
647 
648  typename POINTSETTYPE::PointIdentifier pointId = 0;
649  typename POINTSETTYPE::PointType point;
650 
651  // Insert all list elements into the NodeContainer.
652  for (MLssize_t c=0; c < numVals; ++c){
653  // Get point list value if we have such a list.
654  Vector6 plVal(0);
655  if (pl){
656  float px=0, py=0, pz=0;
657  pl->getValue(c, px, py, pz);
658  plVal[0] = px;
659  plVal[1] = py;
660  plVal[2] = pz;
661  }
662 
663  // Get point list value if we have such a list.
664  Vector6 vlVal(0);
665  int vecType=0;
666  if (vl){
667  float px=0, py=0, pz=0;
668  vl->getPoint(c, vecType, px, py, pz);
669  vlVal[0]=px;
670  vlVal[1]=py;
671  vlVal[2]=pz;
672  }
673 
674  // get position from any of the lists.
675  Vector6 mlVec((xmlc ? (static_cast<XMarker*>(xmlc->getList()->getItemAt(c)))->pos :
676  (xml ? (static_cast<XMarker*>(xml->getItemAt(c)))->pos :
677  (pl ? plVal :
678  (vl ? vlVal : Vector6(0))))));
679 
680  // Copy point components.
681  for (int j=0; j < maxDim ;j++){ point[j] = mlVec[j]; }
682  outputPointSet->SetPoint(pointId++, point );
683  }
684 
685  return outputPointSet;
686  }
687  else{
688  // Create and return default (empty) point set object.
689  typename POINTSETTYPE::Pointer outputPointSet = POINTSETTYPE::New();
690  return outputPointSet;
691  }
692 }
693 
694 //---------------------------------------------------------------------------
698 //---------------------------------------------------------------------------
699 template <typename ITK_IMPORT_IMAGE_FILTER_TYPE>
700 void ITKSetOriginFromVec3(itk::ImportImageFilter<typename ITK_IMPORT_IMAGE_FILTER_TYPE::OutputImagePixelType,
701  ITK_IMPORT_IMAGE_FILTER_TYPE::OutputImageType::ImageDimension>* importImageFilter,
702  const Vector3 &orig)
703 {
704  importImageFilter->SetOrigin(ITKPointFromMLVec3<ITKML_TYPENAME ITK_IMPORT_IMAGE_FILTER_TYPE::OriginType>(orig,0));
705 }
706 
707 //---------------------------------------------------------------------------
711 //---------------------------------------------------------------------------
712 template <typename ITK_IMAGE_TYPE>
713 void ITKSetOriginFromVec3(itk::Image<typename ITK_IMAGE_TYPE::PixelType,
714  ITK_IMAGE_TYPE::ImageDimension>* image,
715  const Vector3 &orig)
716 {
717  image->SetOrigin(ITKPointFromMLVec3<ITKML_TYPENAME ITK_IMAGE_TYPE::PointType>(orig,0));
718 }
719 
720 //---------------------------------------------------------------------------
739 //---------------------------------------------------------------------------
740 template <typename ITK_CLASS_TYPE>
742  ITK_CLASS_TYPE *image,
743  bool correctSVS=true)
744 {
745  if (!image){ return; }
746 
747  // Get ML voxel size/scaling.
748  const Vector3 scales(props.getVoxelSize());
749 
750  // Set voxel spacing, origin and direction cosines of output image and use 1 for unknown higher dimensional components.
751  image->SetSpacing(ITKVectorFromMLVec3<ITKML_TYPENAME ITK_CLASS_TYPE::SpacingType>(scales, 1));
752 
753  // Correct the sub voxel position by translating it to the center.
754  // In the ML the voxel coordinate is in the corner, in itk and vtk
755  // it is in the center.
756  if (correctSVS){ props.translateVoxelToWorldMatrix(Vector3( 0.5, 0.5, 0.5)); }
757 
758  Matrix4 mat = props.getVoxelToWorldMatrix();
759 
760  // Determine image origin for itk image:
761  // Extract (sub voxel) corrected translation vector.
762  const Vector3 orig(mat[0][3], mat[1][3], mat[2][3]);
763  ITKSetOriginFromVec3<ITK_CLASS_TYPE>(image, orig);
764 
765  // Image direction/orientation:
766  // Multiply mat with inverse voxel scale factor to get normalized direction cosines/orientation matrix.
767  const Vector3 invScales(MLValueIs0WOM(scales[0]) ? 1 : 1/scales[0],
768  MLValueIs0WOM(scales[1]) ? 1 : 1/scales[1],
769  MLValueIs0WOM(scales[2]) ? 1 : 1/scales[2]);
770 
771  mat[0][0] = mat[0][0]*invScales[0];
772  mat[1][0] = mat[1][0]*invScales[0];
773  mat[2][0] = mat[2][0]*invScales[0];
774  mat[3][0] = 0;
775 
776  mat[0][1] = mat[0][1]*invScales[1];
777  mat[1][1] = mat[1][1]*invScales[1];
778  mat[2][1] = mat[2][1]*invScales[1];
779  mat[3][1] = 0;
780 
781  mat[0][2] = mat[0][2]*invScales[2];
782  mat[1][2] = mat[1][2]*invScales[2];
783  mat[2][2] = mat[2][2]*invScales[2];
784  mat[3][2] = 0;
785 
786  mat[0][3] = 0;
787  mat[1][3] = 0;
788  mat[2][3] = 0;
789  mat[3][3] = 1;
790 
791  typename ITK_CLASS_TYPE::DirectionType dirCosines = ITKMatrixFromMLMatrix<MLdouble,
792  ITK_CLASS_TYPE::DirectionType::RowDimensions,
793  ITK_CLASS_TYPE::DirectionType::ColumnDimensions>(mat);
794  image->SetDirection(dirCosines);
795 }
796 
797 
798 //---------------------------------------------------------------------------
823 //---------------------------------------------------------------------------
824 template <typename ITK_CLASS_TYPE>
825 void setMLWorldFromITKScaleOriginAndOrientation(const ITK_CLASS_TYPE *image,
826  MedicalImageProperties &props,
827  bool correctSVS=true,
828  bool suppressDimensionWarning=false)
829 {
830  if (!image){ return; }
831  if (ITK_CLASS_TYPE::ImageDimension < 2){
832  ML_PRINT_ERROR("setMLWorldFromITKScaleOriginAndOrientation",
834  "1 D itk world matrix conversion is not supported; "
835  "using identity as return value.");
836  props.setVoxelToWorldMatrix(Matrix4::getIdentity());
837  }
838 
839  // Get location, voxel scaling and orientation of itk image or importer.
840  const typename ITK_CLASS_TYPE::SpacingType spacing = image->GetSpacing();
841  const typename ITK_CLASS_TYPE::PointType origin = image->GetOrigin();
842  const typename ITK_CLASS_TYPE::DirectionType direction = image->GetDirection();
843 
844  // Copy 3x3 itk matrix components to corresponding ones in id ML matrix.
845  const Matrix4 dirCosines = MLMatrixFromITKMatrix<double,
846  ITK_CLASS_TYPE::ImageDimension,
847  ITK_CLASS_TYPE::ImageDimension>(direction, true, suppressDimensionWarning);
848 
849  // Create the ML world matrix as id and set up scaling, orientation and origin provided by the itk image or importer.
850  Matrix4 mat = Matrix4::getIdentity();
851 
852  // Compose scale, directionCosines and translation to the new ML world matrix.
853  mat[0][0] = dirCosines[0][0]*spacing[0];
854  mat[1][0] = dirCosines[1][0]*spacing[0];
855  mat[2][0] = dirCosines[2][0]*spacing[0];
856  mat[3][0] = 0;
857 
858  mat[0][1] = dirCosines[0][1]*spacing[1];
859  mat[1][1] = dirCosines[1][1]*spacing[1];
860  mat[2][1] = dirCosines[2][1]*spacing[1];
861  mat[3][1] = 0;
862 
863  // Avoid invalid accesses to spacing if we operate on 2D images.
864  const double spacing2 = (ITK_CLASS_TYPE::ImageDimension > 2) ? spacing[2] : 1;
865  mat[0][2] = dirCosines[0][2]*spacing2;
866  mat[1][2] = dirCosines[1][2]*spacing2;
867  mat[2][2] = dirCosines[2][2]*spacing2;
868  mat[3][2] = 0;
869 
870  mat[0][3] = origin[0];
871  mat[1][3] = origin[1];
872  mat[2][3] = (ITK_CLASS_TYPE::ImageDimension > 2) ? origin[2] : 0;
873  mat[3][3] = 1;
874 
875  props.setVoxelToWorldMatrix(mat);
876 
877  // Subtract half voxel shift - in MedicalImageProperties the matrix considers
878  // voxel positions at the corner and not in the center.
879  if (correctSVS){ props.translateVoxelToWorldMatrix(Vector3(-0.5, -0.5, -0.5)); }
880 }
881 
882 
883 //---------------------------------------------------------------------------
904 //---------------------------------------------------------------------------
905 template <typename ITK_INDATATYPE, unsigned int DIM>
906 typename itk::ImportImageFilter<ITK_INDATATYPE, DIM>::Pointer getITKImportImageFromSubImg(const SubImage &inSubImg,
907  const MedicalImageProperties &props,
908  bool correctSVS=true)
909 {
910  // Create a new ImportImageFilter.
911  typedef itk::ImportImageFilter<ITK_INDATATYPE, DIM> ImportFilterType;
912  typedef typename ImportFilterType::Pointer ImportFilterPointerType;
913 
914  ImportFilterPointerType importer = ImportFilterType::New();
915 
916  // Get box from the input subimage, convert it to a ITK region and
917  // set it as output image region of the image import filter.
918  SubImageBox inSubImgBox(inSubImg.getBox());
919  importer->SetRegion(ITKRegionFromMLSubImgBox<ImportFilterType>(inSubImgBox));
920 
921  // Set voxel spacing, origin and orientation of itk image.
922  setITKWorldFromMedicalImageProperty<ImportFilterType>(props, &(*importer), correctSVS);
923 
924  // Set pointer to the data to be imported by the image import filter.
925  importer->SetImportPointer(static_cast<ITK_INDATATYPE*>(inSubImg.getData()),
926  static_cast<itk::SizeValueType>(inSubImgBox.getNumVoxels()),
927  false); // we don't want to let ITK managing memory
928  importer->Update();
929 
930  // Return the importer object.
931  return importer;
932 }
933 
934 
935  //----------------------------------------------------------------------------------
951  //----------------------------------------------------------------------------------
952  template <typename RETURN_TYPE_PTR, typename FILTER_TYPE, typename VOXEL_TYPE>
954  int inIdx,
955  TSubImage<VOXEL_TYPE> &dataSubImg,
956  bool correctSVS=true)
957  {
958  // Get and load connected image only if it's valid and not a a redirected one
959  // (which may occur in cases of optional mask image inputs).
960  PagedImage* pInImg = op.getUpdatedInputImage(inIdx);
961  if (pInImg){
962  // Get 3D box input image.
963  const ImageVector _inImgExt = pInImg->getImageExtent();
964  const SubImageBox inImgBox(ImageVector(_inImgExt.x, _inImgExt.y, _inImgExt.z,1,1,1));
965 
966  // Check whether TSubImage contains enough memory, if not we need to free and reallocate it.
967  if (dataSubImg.getData() && (dataSubImg.getBox().getExtent() != inImgBox.getExtent())){
968  dataSubImg.free();
969  }
970  // Set up data box and allocate data if still not there.
971  dataSubImg.setBox(inImgBox);
972  if (!dataSubImg.getData()){
974  }
975  if (!dataSubImg.getData()){
976  return nullptr;
977  }
978 
979  // Get image data from input.
980  MLErrorCode err = pInImg->getTile(dataSubImg);
981  if (ML_RESULT_OK == err){
982  // Create a new ImportImageFilter.
983  typename FILTER_TYPE::Pointer importer = FILTER_TYPE::New();
984 
985  // Get box from the input subimage, convert it to a ITK region and
986  // set it as output image region of the image import filter.
987  importer->SetRegion(ITKRegionFromMLSubImgBox<FILTER_TYPE>(inImgBox));
988 
989  // Pass world transformation of ML image to world transformation of itk image or importer.
990  setITKWorldFromMedicalImageProperty<FILTER_TYPE>(*pInImg, &(*importer), correctSVS);
991 
992  // Set pointer to the data to be imported by the image import filter.
993  // Pass true to make ITK manage the memory, i.e. if the last import object
994  // disappears the data also disappears.
995  importer->SetImportPointer(static_cast<VOXEL_TYPE*>(dataSubImg.getData()), inImgBox.getNumVoxels(), false);
996  importer->Update();
997  return importer->GetOutput();
998  }
999  else{
1000  ML_PRINT_ERROR("mlITKSupportToolFunctions::getInputAsItkImportImageAndSubImg()",
1001  err,
1002  "Failed to request input image data, probably subsequent operations will fail");
1003  }
1004  }
1005 
1006  // Error, no image could be loaded.
1007  return nullptr;
1008  }
1009 
1010 ML_END_NAMESPACE
Field to encapsulate a pointer to an ML base object.
Definition: mlFields.h:729
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:678
Class representing general ML objects that support import/export via strings (setPersistentState() an...
Definition: mlBase.h:59
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 that 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:151
PagedImage * getUpdatedInputImage(MLint inputIndex, bool getReal=false) const
Convenience method for a safe access to the input image at index inputIndex.
The class PagedImage, representing a fragmented image that manages properties and data of an image lo...
Definition: mlPagedImage.h:66
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
Class to handle Rotations (internally, the rotation is stored as a unit quaternion)
Definition: mlRotation.h:38
This class manages/represents a rectangular 6D image region that 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)
Allocates 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 that is organized line...
Definition: mlTSubImage.h:110
const DATATYPE * getData() const
Returns the memory address of the image region. Overloads methods 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 val.
Definition: mlMatrix4.h:265
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 that are inserted in classes to declare and implement additional class membe...
bool MLValueIs0WOM(MLint8 a)
Returns true if value is 0; otherwise, it returns 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:823
#define ML_BAD_DIMENSION
The image or data structure has wrong extent or dimensions.
Definition: mlTypeDefs.h:835
MLint32 MLErrorCode
Type of an ML Error code.
Definition: mlTypeDefs.h:716
#define ML_RESULT_OK
No error. Everything seems to be okay.
Definition: mlTypeDefs.h:724
#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
@ ML_FATAL_MEMORY_ERROR
On allocation failure, a fatal error print is done and NULL is returned.
Definition: mlTypeDefs.h:677
double MLdouble
Definition: mlTypeDefs.h:217
MLint64 MLint
A signed ML integer type with at least 64 bits used for index calculations on very large images even ...
Definition: mlTypeDefs.h:490
SSIZE_T MLssize_t
The signed ML size type that is a signed 32-bit size_t on 32-bit platforms and 64-bit one on 64-bit p...
Definition: mlTypeDefs.h:566
MLMessageType
Message types handled by the ErrorOutput class.
Definition: mlTypeDefs.h:696
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...
MLITK_SUPPORT_EXPORT void setAllowedTypesForITKNodeContainer(BaseField *field)
Set the allowed types for input Base fields that are converted to ITK NodeContainer objects.
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,...
const ml::Vector4 MLVectorFromITKVersor(const ITK_VERSOR_TYPE &itkVersor)
Returns an STL container object of type STL_CONTAINER which contains cast copies of all elements of t...
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 three components of type double.
Definition: mlVector3.h:286
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 ...
VERSOR_TYPE ITKVersorFromMLVector(const ml::Vector4 &mlVec)
Returns an object of an ITK array type ARRAY_TYPE which contains cast copies of all elements of stlVe...
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 that 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...