Medical Imaging Interaction Toolkit  2018.4.99-c7ee88da
Medical Imaging Interaction Toolkit
mitkPythonService.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include "mitkPythonService.h"
14 #include <Python.h>
15 #include <mitkIOUtil.h>
16 #include <QFile>
17 #include <QDir>
18 #include <PythonQt.h>
19 #include "PythonPath.h"
20 #include <vtkPolyData.h>
21 #include <mitkRenderingManager.h>
22 #include <mitkImageReadAccessor.h>
23 #include <mitkImageWriteAccessor.h>
24 #include <QFileInfo>
25 #include <QCoreApplication>
26 #include <itksys/SystemTools.hxx>
27 
28 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
29 #include <numpy/arrayobject.h>
30 
31 #include <mitkExceptionMacro.h>
32 
33 #ifndef WIN32
34 #include <dlfcn.h>
35 #endif
36 
37 typedef itksys::SystemTools ist;
38 
40  : m_ItkWrappingAvailable( true )
41  , m_OpenCVWrappingAvailable( true )
42  , m_VtkWrappingAvailable( true )
43  , m_ErrorOccured( false )
44 {
45  bool pythonInitialized = static_cast<bool>( Py_IsInitialized() ); //m_PythonManager.isPythonInitialized() );
46 
47  // due to strange static var behaviour on windows Py_IsInitialized() returns correct value while
48  // m_PythonManager.isPythonInitialized() does not because it has been constructed and destructed again
49  if( !pythonInitialized )
50  {
51  MITK_INFO << "Initializing python service";
52  //TODO a better way to do this
53 #ifndef WIN32
54  dlerror();
55  if(dlopen(PYTHON_LIBRARY, RTLD_NOW | RTLD_GLOBAL) == nullptr )
56  {
57  mitkThrow() << "Python runtime could not be loaded: " << dlerror();
58  }
59 #endif
60 
61  std::string programPath = QCoreApplication::applicationDirPath().toStdString() + "/";
62 
63  QString pythonCommand;
64  pythonCommand.append( QString("import site, sys\n") );
65  pythonCommand.append( QString("import SimpleITK as sitk\n") );
66  pythonCommand.append( QString("import SimpleITK._SimpleITK as _SimpleITK\n") );
67  pythonCommand.append( QString("import numpy\n") );
68 
69  pythonCommand.append( QString("sys.path.append('')\n") );
70  pythonCommand.append( QString("sys.path.append('%1')\n").arg(programPath.c_str()) );
71  pythonCommand.append( QString("sys.path.append('%1')\n").arg(EXTERNAL_DIST_PACKAGES) );
72  pythonCommand.append( QString("\nsite.addsitedir('%1')").arg(EXTERNAL_SITE_PACKAGES) );
73 
74  if( pythonInitialized )
75  m_PythonManager.setInitializationFlags(PythonQt::RedirectStdOut|PythonQt::PythonAlreadyInitialized);
76  else
77  m_PythonManager.setInitializationFlags(PythonQt::RedirectStdOut);
78  m_PythonManager.initialize();
79 
80  m_PythonManager.executeString( pythonCommand, ctkAbstractPythonManager::FileInput );
81  }
82 }
83 
85 {
86  MITK_DEBUG("mitk::PythonService") << "destructing PythonService";
87 }
88 
89 void mitk::PythonService::AddRelativeSearchDirs(std::vector< std::string > dirs)
90 {
91  std::string programPath = QCoreApplication::applicationDirPath().toStdString() + "/";
92  std::string cwd = ist::GetCurrentWorkingDirectory() + "/";
93 
94  for (auto dir : dirs)
95  {
96  m_PythonManager.executeString(QString("sys.path.append('%1')").arg((programPath + dir).c_str()), ctkAbstractPythonManager::SingleInput );
97  m_PythonManager.executeString(QString("sys.path.append('%1')").arg((cwd + dir).c_str()), ctkAbstractPythonManager::SingleInput );
98  }
99 }
100 
101 void mitk::PythonService::AddAbsoluteSearchDirs(std::vector< std::string > dirs)
102 {
103  for (auto dir : dirs)
104  {
105  m_PythonManager.executeString(QString("sys.path.append('%1')").arg(dir.c_str()), ctkAbstractPythonManager::SingleInput );
106  }
107 }
108 
109 std::string mitk::PythonService::Execute(const std::string &stdpythonCommand, int commandType)
110 {
111  QString pythonCommand = QString::fromStdString(stdpythonCommand);
112  QVariant result;
113 
114  bool commandIssued = true;
115  if(commandType == IPythonService::SINGLE_LINE_COMMAND )
116  result = m_PythonManager.executeString(pythonCommand, ctkAbstractPythonManager::SingleInput );
117  else if(commandType == IPythonService::MULTI_LINE_COMMAND )
118  result = m_PythonManager.executeString(pythonCommand, ctkAbstractPythonManager::FileInput );
119  else if(commandType == IPythonService::EVAL_COMMAND )
120  result = m_PythonManager.executeString(pythonCommand, ctkAbstractPythonManager::EvalInput );
121  else
122  commandIssued = false;
123 
124  if(commandIssued)
125  {
126  this->NotifyObserver(pythonCommand.toStdString());
127  m_ErrorOccured = PythonQt::self()->hadError();
128  }
129 
130  return result.toString().toStdString();
131 }
132 
133 void mitk::PythonService::ExecuteScript( const std::string& pythonScript )
134 {
135  std::ifstream t(pythonScript.c_str());
136  std::string str((std::istreambuf_iterator<char>(t)),
137  std::istreambuf_iterator<char>());
138  t.close();
139 
140  m_PythonManager.executeString(QString::fromStdString(str));
141 }
142 
143 std::vector<mitk::PythonVariable> mitk::PythonService::GetVariableStack() const
144 {
145  std::vector<mitk::PythonVariable> list;
146 
147  PyObject* dict = PyImport_GetModuleDict();
148  PyObject* object = PyDict_GetItemString(dict, "__main__");
149  PyObject* dirMain = PyObject_Dir(object);
150  PyObject* tempObject = nullptr;
151  //PyObject* strTempObject = 0;
152 
153  if(dirMain)
154  {
155  std::string name, attrValue, attrType;
156 
157  for(int i = 0; i<PyList_Size(dirMain); i++)
158  {
159  tempObject = PyList_GetItem(dirMain, i);
160  name = PyString_AsString(tempObject);
161  tempObject = PyObject_GetAttrString( object, name.c_str() );
162  attrType = tempObject->ob_type->tp_name;
163 
164  if(tempObject && ( PyUnicode_Check(tempObject) || PyString_Check(tempObject) ) )
165  attrValue = PyString_AsString(tempObject);
166  else
167  attrValue = "";
168 
170  var.m_Name = name;
171  var.m_Value = attrValue;
172  var.m_Type = attrType;
173  list.push_back(var);
174  }
175  }
176 
177  return list;
178 }
179 
180 std::string mitk::PythonService::GetVariable(const std::string& name) const
181 {
182  std::vector<mitk::PythonVariable> allVars = this->GetVariableStack();
183  for(unsigned int i = 0; i< allVars.size(); i++)
184  {
185  if( allVars.at(i).m_Name == name )
186  return allVars.at(i).m_Value;
187  }
188 
189  return "";
190 }
191 
192 bool mitk::PythonService::DoesVariableExist(const std::string& name) const
193 {
194  bool varExists = false;
195 
196  std::vector<mitk::PythonVariable> allVars = this->GetVariableStack();
197  for(unsigned int i = 0; i< allVars.size(); i++)
198  {
199  if( allVars.at(i).m_Name == name )
200  {
201  varExists = true;
202  break;
203  }
204  }
205 
206  return varExists;
207 }
208 
210 {
211  if(!m_Observer.contains(observer))
212  m_Observer.append(observer);
213 }
214 
216 {
217  m_Observer.removeOne(observer);
218 }
219 
220 void mitk::PythonService::NotifyObserver(const std::string &command)
221 {
222  MITK_DEBUG("mitk::PythonService") << "number of observer " << m_Observer.size();
223  for( int i=0; i< m_Observer.size(); ++i )
224  {
225  m_Observer.at(i)->CommandExecuted(command);
226  }
227 }
228 
230 {
231  QString varName = QString::fromStdString( stdvarName );
232  QString command;
233  unsigned int* imgDim = image->GetDimensions();
234  int npy_nd = 1;
235 
236  // access python module
237  PyObject *pyMod = PyImport_AddModule("__main__");
238  // global dictionary
239  PyObject *pyDict = PyModule_GetDict(pyMod);
240  const mitk::Vector3D spacing = image->GetGeometry()->GetSpacing();
241  const mitk::Point3D origin = image->GetGeometry()->GetOrigin();
242  mitk::PixelType pixelType = image->GetPixelType();
243  itk::ImageIOBase::IOPixelType ioPixelType = image->GetPixelType().GetPixelType();
244  PyObject* npyArray = nullptr;
245  mitk::ImageReadAccessor racc(image);
246  void* array = const_cast<void*>(racc.GetData());
247 
248  mitk::Vector3D xDirection;
249  mitk::Vector3D yDirection;
250  mitk::Vector3D zDirection;
251  const vnl_matrix_fixed<ScalarType, 3, 3> &transform =
252  image->GetGeometry()->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix();
253 
254  mitk::Vector3D s = image->GetGeometry()->GetSpacing();
255 
256  // ToDo: Check if this is a collumn or row vector from the matrix.
257  // right now it works but not sure for rotated geometries
258  mitk::FillVector3D(xDirection, transform[0][0]/s[0], transform[0][1]/s[1], transform[0][2]/s[2]);
259  mitk::FillVector3D(yDirection, transform[1][0]/s[0], transform[1][1]/s[1], transform[1][2]/s[2]);
260  mitk::FillVector3D(zDirection, transform[2][0]/s[0], transform[2][1]/s[1], transform[2][2]/s[2]);
261 
262  // save the total number of elements here (since the numpy array is one dimensional)
263  npy_intp* npy_dims = new npy_intp[1];
264  npy_dims[0] = imgDim[0];
265 
271  QString dimensionString;
272  dimensionString.append(QString("["));
273  dimensionString.append(QString::number(imgDim[0]));
274  for (unsigned i = 1; i < 3; ++i)
275  // always three because otherwise the 3d-geometry gets destroyed
276  // (relevant for backtransformation of simple itk image to mitk.
277  {
278  dimensionString.append(QString(","));
279  dimensionString.append(QString::number(imgDim[i]));
280  npy_dims[0] *= imgDim[i];
281  }
282  dimensionString.append("]");
283 
284 
285  // the next line is necessary for vectorimages
286  npy_dims[0] *= pixelType.GetNumberOfComponents();
287 
288  // default pixeltype: unsigned short
289  NPY_TYPES npy_type = NPY_USHORT;
290  std::string sitk_type = "sitkUInt8";
291  if( ioPixelType == itk::ImageIOBase::SCALAR )
292  {
293  if( pixelType.GetComponentType() == itk::ImageIOBase::DOUBLE ) {
294  npy_type = NPY_DOUBLE;
295  sitk_type = "sitkFloat64";
296  } else if( pixelType.GetComponentType() == itk::ImageIOBase::FLOAT ) {
297  npy_type = NPY_FLOAT;
298  sitk_type = "sitkFloat32";
299  } else if( pixelType.GetComponentType() == itk::ImageIOBase::SHORT) {
300  npy_type = NPY_SHORT;
301  sitk_type = "sitkInt16";
302  } else if( pixelType.GetComponentType() == itk::ImageIOBase::CHAR ) {
303  npy_type = NPY_BYTE;
304  sitk_type = "sitkInt8";
305  } else if( pixelType.GetComponentType() == itk::ImageIOBase::INT ) {
306  npy_type = NPY_INT;
307  sitk_type = "sitkInt32";
308  } else if( pixelType.GetComponentType() == itk::ImageIOBase::LONG ) {
309  npy_type = NPY_LONG;
310  sitk_type = "sitkInt64";
311  } else if( pixelType.GetComponentType() == itk::ImageIOBase::UCHAR ) {
312  npy_type = NPY_UBYTE;
313  sitk_type = "sitkUInt8";
314  } else if( pixelType.GetComponentType() == itk::ImageIOBase::UINT ) {
315  npy_type = NPY_UINT;
316  sitk_type = "sitkUInt32";
317  } else if( pixelType.GetComponentType() == itk::ImageIOBase::ULONG ) {
318  npy_type = NPY_LONG;
319  sitk_type = "sitkUInt64";
320  } else if( pixelType.GetComponentType() == itk::ImageIOBase::USHORT ) {
321  npy_type = NPY_USHORT;
322  sitk_type = "sitkUInt16";
323  }
324  }
325  else if ( ioPixelType == itk::ImageIOBase::VECTOR ||
326  ioPixelType == itk::ImageIOBase::RGB ||
327  ioPixelType == itk::ImageIOBase::RGBA
328  )
329  {
330  if( pixelType.GetComponentType() == itk::ImageIOBase::DOUBLE ) {
331  npy_type = NPY_DOUBLE;
332  sitk_type = "sitkVectorFloat64";
333  } else if( pixelType.GetComponentType() == itk::ImageIOBase::FLOAT ) {
334  npy_type = NPY_FLOAT;
335  sitk_type = "sitkVectorFloat32";
336  } else if( pixelType.GetComponentType() == itk::ImageIOBase::SHORT) {
337  npy_type = NPY_SHORT;
338  sitk_type = "sitkVectorInt16";
339  } else if( pixelType.GetComponentType() == itk::ImageIOBase::CHAR ) {
340  npy_type = NPY_BYTE;
341  sitk_type = "sitkVectorInt8";
342  } else if( pixelType.GetComponentType() == itk::ImageIOBase::INT ) {
343  npy_type = NPY_INT;
344  sitk_type = "sitkVectorInt32";
345  } else if( pixelType.GetComponentType() == itk::ImageIOBase::LONG ) {
346  npy_type = NPY_LONG;
347  sitk_type = "sitkVectorInt64";
348  } else if( pixelType.GetComponentType() == itk::ImageIOBase::UCHAR ) {
349  npy_type = NPY_UBYTE;
350  sitk_type = "sitkVectorUInt8";
351  } else if( pixelType.GetComponentType() == itk::ImageIOBase::UINT ) {
352  npy_type = NPY_UINT;
353  sitk_type = "sitkVectorUInt32";
354  } else if( pixelType.GetComponentType() == itk::ImageIOBase::ULONG ) {
355  npy_type = NPY_LONG;
356  sitk_type = "sitkVectorUInt64";
357  } else if( pixelType.GetComponentType() == itk::ImageIOBase::USHORT ) {
358  npy_type = NPY_USHORT;
359  sitk_type = "sitkVectorUInt16";
360  }
361  }
362  else {
363  MITK_WARN << "not a recognized pixeltype";
364  return false;
365  }
366 
367  // creating numpy array
368  import_array1 (true);
369  npyArray = PyArray_SimpleNewFromData(npy_nd,npy_dims,npy_type,array);
370 
371  // add temp array it to the python dictionary to access it in python code
372  const int status = PyDict_SetItemString( pyDict,QString("%1_numpy_array")
373  .arg(varName).toStdString().c_str(),
374  npyArray );
375 
376 
377  // sanity check
378  if ( status != 0 )
379  return false;
380 
381 
382  command.append( QString("%1 = sitk.Image(%2,sitk.%3,%4)\n").arg(varName)
383  .arg(dimensionString)
384  .arg(QString(sitk_type.c_str())).arg(QString::number(pixelType.GetNumberOfComponents())) );
385  command.append( QString("%1.SetSpacing([%2,%3,%4])\n").arg(varName)
386  .arg(QString::number(spacing[0]))
387  .arg(QString::number(spacing[1]))
388  .arg(QString::number(spacing[2])) );
389  command.append( QString("%1.SetOrigin([%2,%3,%4])\n").arg(varName)
390  .arg(QString::number(origin[0]))
391  .arg(QString::number(origin[1]))
392  .arg(QString::number(origin[2])) );
393  command.append( QString("%1.SetDirection([%2,%3,%4,%5,%6,%7,%8,%9,%10])\n").arg(varName)
394  .arg(QString::number(xDirection[0]))
395  .arg(QString::number(xDirection[1]))
396  .arg(QString::number(xDirection[2]))
397  .arg(QString::number(yDirection[0]))
398  .arg(QString::number(yDirection[1]))
399  .arg(QString::number(yDirection[2]))
400  .arg(QString::number(zDirection[0]))
401  .arg(QString::number(zDirection[1]))
402  .arg(QString::number(zDirection[2]))
403  );
404  // directly access the cpp api from the lib
405  command.append( QString("_SimpleITK._SetImageFromArray(%1_numpy_array,%1)\n").arg(varName) );
406  command.append( QString("del %1_numpy_array").arg(varName) );
407 
408  MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString();
409 
410 
411  this->Execute( command.toStdString(), IPythonService::MULTI_LINE_COMMAND );
412 
413  return true;
414 }
415 
416 
417 mitk::PixelType DeterminePixelType(const std::string& pythonPixeltype, unsigned long nrComponents, int dimensions)
418 {
419  typedef itk::RGBPixel< unsigned char > UCRGBPixelType;
420  typedef itk::RGBPixel< unsigned short > USRGBPixelType;
421  typedef itk::RGBPixel< float > FloatRGBPixelType;
422  typedef itk::RGBPixel< double > DoubleRGBPixelType;
423  typedef itk::Image< UCRGBPixelType > UCRGBImageType;
424  typedef itk::Image< USRGBPixelType > USRGBImageType;
425  typedef itk::Image< FloatRGBPixelType > FloatRGBImageType;
426  typedef itk::Image< DoubleRGBPixelType > DoubleRGBImageType;
427  typedef itk::RGBAPixel< unsigned char > UCRGBAPixelType;
428  typedef itk::RGBAPixel< unsigned short > USRGBAPixelType;
429  typedef itk::RGBAPixel< float > FloatRGBAPixelType;
430  typedef itk::RGBAPixel< double > DoubleRGBAPixelType;
431  typedef itk::Image< UCRGBAPixelType > UCRGBAImageType;
432  typedef itk::Image< USRGBAPixelType > USRGBAImageType;
433  typedef itk::Image< FloatRGBAPixelType > FloatRGBAImageType;
434  typedef itk::Image< DoubleRGBAPixelType > DoubleRGBAImageType;
435 
436  auto pixelType = mitk::MakePixelType<char, char >(nrComponents);
437 
438  if (nrComponents == 1)
439  {
440  if( pythonPixeltype.compare("float64") == 0 ) {
441  pixelType = mitk::MakePixelType<double, double >(nrComponents);
442  } else if( pythonPixeltype.compare("float32") == 0 ) {
443  pixelType = mitk::MakePixelType<float, float >(nrComponents);
444  } else if( pythonPixeltype.compare("int16") == 0) {
445  pixelType = mitk::MakePixelType<short, short >(nrComponents);
446  } else if( pythonPixeltype.compare("int8") == 0 ) {
447  pixelType = mitk::MakePixelType<char, char >(nrComponents);
448  } else if( pythonPixeltype.compare("int32") == 0 ) {
449  pixelType = mitk::MakePixelType<int, int >(nrComponents);
450  } else if( pythonPixeltype.compare("int64") == 0 ) {
451  pixelType = mitk::MakePixelType<long, long >(nrComponents);
452  } else if( pythonPixeltype.compare("uint8") == 0 ) {
453  pixelType = mitk::MakePixelType<unsigned char, unsigned char >(nrComponents);
454  } else if( pythonPixeltype.compare("uint32") == 0 ) {
455  pixelType = mitk::MakePixelType<unsigned int, unsigned int >(nrComponents);
456  } else if( pythonPixeltype.compare("uint64") == 0 ) {
457  pixelType = mitk::MakePixelType<unsigned long, unsigned long >(nrComponents);
458  } else if( pythonPixeltype.compare("uint16") == 0 ) {
459  pixelType = mitk::MakePixelType<unsigned short, unsigned short >(nrComponents);
460  }
461  else
462  {
463  mitkThrow()<< "unknown scalar PixelType";
464  }
465  } else if(nrComponents == 3 && dimensions == 2) {
466  if( pythonPixeltype.compare("float64") == 0 ) {
467  pixelType = mitk::MakePixelType<DoubleRGBImageType>();
468  } else if( pythonPixeltype.compare("float32") == 0 ) {
469  pixelType = mitk::MakePixelType<FloatRGBImageType>();
470  } else if( pythonPixeltype.compare("uint8") == 0 ) {
471  pixelType = mitk::MakePixelType<UCRGBImageType>();
472  } else if( pythonPixeltype.compare("uint16") == 0 ) {
473  pixelType = mitk::MakePixelType<USRGBImageType>();
474  }
475  } else if( (nrComponents == 4) && dimensions == 2 ) {
476  if( pythonPixeltype.compare("float64") == 0 ) {
477  pixelType = mitk::MakePixelType<DoubleRGBAImageType>();
478  } else if( pythonPixeltype.compare("float32") == 0 ) {
479  pixelType = mitk::MakePixelType<FloatRGBAImageType>();
480  } else if( pythonPixeltype.compare("uint8") == 0 ) {
481  pixelType = mitk::MakePixelType<UCRGBAImageType>();
482  } else if( pythonPixeltype.compare("uint16") == 0 ) {
483  pixelType = mitk::MakePixelType<USRGBAImageType>();
484  }
485  }
486  else {
487  if( pythonPixeltype.compare("float64") == 0 ) {
488  pixelType = mitk::MakePixelType<double, itk::Vector<double,3> >(nrComponents);
489  } else if( pythonPixeltype.compare("float32") == 0 ) {
490  pixelType = mitk::MakePixelType<float, itk::Vector<float,3> >(nrComponents);
491  } else if( pythonPixeltype.compare("int16") == 0) {
492  pixelType = mitk::MakePixelType<short, itk::Vector<short,3> >(nrComponents);
493  } else if( pythonPixeltype.compare("int8") == 0 ) {
494  pixelType = mitk::MakePixelType<char, itk::Vector<char,3> >(nrComponents);
495  } else if( pythonPixeltype.compare("int32") == 0 ) {
496  pixelType = mitk::MakePixelType<int, itk::Vector<int,3> >(nrComponents);
497  } else if( pythonPixeltype.compare("int64") == 0 ) {
498  pixelType = mitk::MakePixelType<long, itk::Vector<long,3> >(nrComponents);
499  } else if( pythonPixeltype.compare("uint8") == 0 ) {
500  pixelType = mitk::MakePixelType<unsigned char, itk::Vector<unsigned char,3> >(nrComponents);
501  } else if( pythonPixeltype.compare("uint16") == 0 ) {
502  pixelType = mitk::MakePixelType<unsigned short, itk::Vector<unsigned short,3> >(nrComponents);
503  } else if( pythonPixeltype.compare("uint32") == 0 ) {
504  pixelType = mitk::MakePixelType<unsigned int, itk::Vector<unsigned int,3> >(nrComponents);
505  } else if( pythonPixeltype.compare("uint64") == 0 ) {
506  pixelType = mitk::MakePixelType<unsigned long, itk::Vector<unsigned long,3> >(nrComponents);
507  } else {
508  mitkThrow()<< "unknown vectorial PixelType";
509  }
510  }
511 
512  return pixelType;
513 }
514 
516 {
517  double*ds = nullptr;
518  // access python module
519  PyObject *pyMod = PyImport_AddModule("__main__");
520  // global dictionarry
521  PyObject *pyDict = PyModule_GetDict(pyMod);
523  mitk::Vector3D spacing;
524  mitk::Point3D origin;
525  QString command;
526  QString varName = QString::fromStdString( stdvarName );
527 
528  command.append( QString("%1_numpy_array = sitk.GetArrayFromImage(%1)\n").arg(varName) );
529  command.append( QString("%1_spacing = numpy.asarray(%1.GetSpacing())\n").arg(varName) );
530  command.append( QString("%1_origin = numpy.asarray(%1.GetOrigin())\n").arg(varName) );
531  command.append( QString("%1_dtype = %1_numpy_array.dtype.name\n").arg(varName) );
532  command.append( QString("%1_direction = numpy.asarray(%1.GetDirection())\n").arg(varName) );
533  command.append( QString("%1_nrComponents = numpy.asarray(%1.GetNumberOfComponentsPerPixel())\n").arg(varName));
534  command.append( QString("%1_dtype = %1_numpy_array.dtype.name\n").arg(varName) );
535 
536 
537  MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString();
538  this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND );
539 
540  PyObject* py_dtype = PyDict_GetItemString(pyDict,QString("%1_dtype").arg(varName).toStdString().c_str() );
541  std::string dtype = PyString_AsString(py_dtype);
542  PyArrayObject* py_data = (PyArrayObject*) PyDict_GetItemString(pyDict,QString("%1_numpy_array").arg(varName).toStdString().c_str() );
543  PyArrayObject* py_spacing = (PyArrayObject*) PyDict_GetItemString(pyDict,QString("%1_spacing").arg(varName).toStdString().c_str() );
544  PyArrayObject* py_origin = (PyArrayObject*) PyDict_GetItemString(pyDict,QString("%1_origin").arg(varName).toStdString().c_str() );
545  PyArrayObject* py_direction = (PyArrayObject*) PyDict_GetItemString(pyDict,QString("%1_direction").arg(varName).toStdString().c_str() );
546 
547  PyArrayObject* py_nrComponents = (PyArrayObject*) PyDict_GetItemString(pyDict,QString("%1_nrComponents").arg(varName).toStdString().c_str() );
548 
549  unsigned int nr_Components = *(reinterpret_cast<unsigned int*>(PyArray_DATA(py_nrComponents)));
550 
551  unsigned int nr_dimensions = PyArray_NDIM(py_data);
552  if (nr_Components > 1) // for VectorImages the last dimension in the numpy array are the vector components.
553  {
554  --nr_dimensions;
555  }
556 
557  mitk::PixelType pixelType = DeterminePixelType(dtype, nr_Components, nr_dimensions);
558 
559  unsigned int* dimensions = new unsigned int[nr_dimensions];
560  // fill backwards , nd data saves dimensions in opposite direction
561  for( unsigned i = 0; i < nr_dimensions; ++i )
562  {
563  dimensions[i] = PyArray_DIMS(py_data)[nr_dimensions - 1 - i];
564  }
565 
566  mitkImage->Initialize(pixelType, nr_dimensions, dimensions);
567 
568 
569  mitkImage->SetChannel(PyArray_DATA(py_data));
570 
571 
572  ds = reinterpret_cast<double*>(PyArray_DATA(py_spacing));
573  spacing[0] = ds[0];
574  spacing[1] = ds[1];
575  spacing[2] = ds[2];
576 
577  mitkImage->GetGeometry()->SetSpacing(spacing);
578 
579 
580  ds = reinterpret_cast<double*>(PyArray_DATA(py_origin));
581  origin[0] = ds[0];
582  origin[1] = ds[1];
583  origin[2] = ds[2];
584  mitkImage->GetGeometry()->SetOrigin(origin);
585 
586 
587  itk::Matrix<double,3,3> py_transform;
588 
589  ds = reinterpret_cast<double*>(PyArray_DATA(py_direction));
590  py_transform[0][0] = ds[0];
591  py_transform[0][1] = ds[1];
592  py_transform[0][2] = ds[2];
593 
594  py_transform[1][0] = ds[3];
595  py_transform[1][1] = ds[4];
596  py_transform[1][2] = ds[5];
597 
598  py_transform[2][0] = ds[6];
599  py_transform[2][1] = ds[7];
600  py_transform[2][2] = ds[8];
601 
602  mitk::AffineTransform3D::Pointer affineTransform = mitkImage->GetGeometry()->GetIndexToWorldTransform();
603 
604  itk::Matrix<double,3,3> transform = py_transform * affineTransform->GetMatrix();
605 
606  affineTransform->SetMatrix(transform);
607 
608  mitkImage->GetGeometry()->SetIndexToWorldTransform(affineTransform);
609 
610  // mitk::AffineTransform3D::New();
611  //mitkImage->GetGeometry()->SetIndexToWorldTransform();
612 
613  // cleanup
614  command.clear();
615  command.append( QString("del %1_numpy_array\n").arg(varName) );
616  command.append( QString("del %1_dtype\n").arg(varName) );
617  command.append( QString("del %1_spacing\n").arg(varName) );
618  command.append( QString("del %1_origin\n").arg(varName) );
619  command.append( QString("del %1_direction\n").arg(varName) );
620  command.append( QString("del %1_nrComponents\n").arg(varName) );
621  MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString();
622  this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND );
623 
624  delete[] dimensions;
625 
626 
627  return mitkImage;
628 }
629 
630 bool mitk::PythonService::CopyToPythonAsCvImage( mitk::Image* image, const std::string& stdvarName )
631 {
632  QString varName = QString::fromStdString( stdvarName );
633  QString command;
634  unsigned int* imgDim = image->GetDimensions();
635  int npy_nd = 1;
636 
637  // access python module
638  PyObject *pyMod = PyImport_AddModule((char*)"__main__");
639  // global dictionary
640  PyObject *pyDict = PyModule_GetDict(pyMod);
641  mitk::PixelType pixelType = image->GetPixelType();
642  PyObject* npyArray = nullptr;
643  mitk::ImageReadAccessor racc(image);
644  void* array = (void*) racc.GetData();
645 
646  // save the total number of elements here (since the numpy array is one dimensional)
647  npy_intp* npy_dims = new npy_intp[1];
648  npy_dims[0] = imgDim[0];
649 
655  QString dimensionString;
656  dimensionString.append(QString("["));
657  dimensionString.append(QString::number(imgDim[0]));
658  // ToDo: check if we need this
659  for (unsigned i = 1; i < 3; ++i)
660  // always three because otherwise the 3d-geometry gets destroyed
661  // (relevant for backtransformation of simple itk image to mitk.
662  {
663  dimensionString.append(QString(","));
664  dimensionString.append(QString::number(imgDim[i]));
665  npy_dims[0] *= imgDim[i];
666  }
667  dimensionString.append("]");
668 
669 
670  // the next line is necessary for vectorimages
671  npy_dims[0] *= pixelType.GetNumberOfComponents();
672 
673  // default pixeltype: unsigned short
674  NPY_TYPES npy_type = NPY_USHORT;
675  if( pixelType.GetComponentType() == itk::ImageIOBase::DOUBLE ) {
676  npy_type = NPY_DOUBLE;
677  } else if( pixelType.GetComponentType() == itk::ImageIOBase::FLOAT ) {
678  npy_type = NPY_FLOAT;
679  } else if( pixelType.GetComponentType() == itk::ImageIOBase::SHORT) {
680  npy_type = NPY_SHORT;
681  } else if( pixelType.GetComponentType() == itk::ImageIOBase::CHAR ) {
682  npy_type = NPY_BYTE;
683  } else if( pixelType.GetComponentType() == itk::ImageIOBase::INT ) {
684  npy_type = NPY_INT;
685  } else if( pixelType.GetComponentType() == itk::ImageIOBase::LONG ) {
686  npy_type = NPY_LONG;
687  } else if( pixelType.GetComponentType() == itk::ImageIOBase::UCHAR ) {
688  npy_type = NPY_UBYTE;
689  } else if( pixelType.GetComponentType() == itk::ImageIOBase::UINT ) {
690  npy_type = NPY_UINT;
691  } else if( pixelType.GetComponentType() == itk::ImageIOBase::ULONG ) {
692  npy_type = NPY_LONG;
693  } else if( pixelType.GetComponentType() == itk::ImageIOBase::USHORT ) {
694  npy_type = NPY_USHORT;
695  }
696  else {
697  MITK_WARN << "not a recognized pixeltype";
698  return false;
699  }
700 
701  // creating numpy array
702  import_array1 (true);
703  npyArray = PyArray_SimpleNewFromData(npy_nd,npy_dims,npy_type,array);
704 
705  // add temp array it to the python dictionary to access it in python code
706  const int status = PyDict_SetItemString( pyDict,QString("%1_numpy_array")
707  .arg(varName).toStdString().c_str(),
708  npyArray );
709  // sanity check
710  if ( status != 0 )
711  return false;
712 
713  command.append( QString("import numpy as np\n"));
714  //command.append( QString("if '%1' in globals():\n").arg(varName));
715  //command.append( QString(" del %1\n").arg(varName));
716  command.append( QString("%1_array_tmp=%1_numpy_array.copy()\n").arg(varName));
717  command.append( QString("%1_array_tmp=%1_array_tmp.reshape(%2,%3,%4)\n").arg( varName,
718  QString::number(imgDim[1]),
719  QString::number(imgDim[0]),
720  QString::number(pixelType.GetNumberOfComponents())));
721 
722  command.append( QString("%1 = %1_array_tmp[:,...,::-1]\n").arg(varName));
723  command.append( QString("del %1_numpy_array\n").arg(varName) );
724  command.append( QString("del %1_array_tmp").arg(varName) );
725 
726  MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString();
727 
728  this->Execute( command.toStdString(), IPythonService::MULTI_LINE_COMMAND );
729 
730  return true;
731 }
732 
733 
735 {
736 
737  // access python module
738  PyObject *pyMod = PyImport_AddModule((char*)"__main__");
739  // global dictionarry
740  PyObject *pyDict = PyModule_GetDict(pyMod);
742  QString command;
743  QString varName = QString::fromStdString( stdvarName );
744 
745  command.append( QString("import numpy as np\n"));
746  command.append( QString("%1_dtype=%1.dtype.name\n").arg(varName) );
747  command.append( QString("%1_shape=np.asarray(%1.shape)\n").arg(varName) );
748  command.append( QString("%1_np_array=%1[:,...,::-1]\n").arg(varName));
749  command.append( QString("%1_np_array=np.reshape(%1_np_array,%1.shape[0] * %1.shape[1] * %1.shape[2])").arg(varName) );
750 
751  MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString();
752  this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND );
753 
754  PyObject* py_dtype = PyDict_GetItemString(pyDict,QString("%1_dtype").arg(varName).toStdString().c_str() );
755  std::string dtype = PyString_AsString(py_dtype);
756  PyArrayObject* py_data = (PyArrayObject*) PyDict_GetItemString(pyDict,QString("%1_np_array").arg(varName).toStdString().c_str() );
757  PyArrayObject* shape = (PyArrayObject*) PyDict_GetItemString(pyDict,QString("%1_shape").arg(varName).toStdString().c_str() );
758 
759  size_t* d = reinterpret_cast<size_t*>(PyArray_DATA(shape));
760 
761  unsigned int dimensions[3];
762  dimensions[0] = d[1];
763  dimensions[1] = d[0];
764  dimensions[2] = d[2];
765 
766  unsigned int nr_dimensions = 2;
767 
768  // get number of components
769  unsigned int nr_Components = (unsigned int) d[2];
770 
771  auto pixelType = DeterminePixelType(dtype, nr_Components, nr_dimensions);
772 
773  mitkImage->Initialize(pixelType, nr_dimensions, dimensions);
774  //mitkImage->SetChannel(py_data->data);
775 
776  {
777  mitk::ImageWriteAccessor ra(mitkImage);
778  char* data = (char*)(ra.GetData());
779  memcpy(data, PyArray_DATA(py_data), dimensions[0] * dimensions[1] * pixelType.GetSize());
780  }
781 
782  command.clear();
783 
784  command.append( QString("del %1_shape\n").arg(varName) );
785  command.append( QString("del %1_dtype\n").arg(varName) );
786  command.append( QString("del %1_np_array").arg(varName));
787 
788  MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString();
789  this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND );
790 
791  return mitkImage;
792 }
793 
794 ctkAbstractPythonManager *mitk::PythonService::GetPythonManager()
795 {
796  return &m_PythonManager;
797 }
798 
800 {
801  // access python module
802  PyObject *pyMod = PyImport_AddModule((char*)"__main__");
803  // global dictionarry
804  PyObject *pyDict = PyModule_GetDict(pyMod);
805  // python memory address
806  PyObject *pyAddr = nullptr;
807  // cpp address
808  size_t addr = 0;
810  QString command;
811  QString varName = QString::fromStdString( stdvarName );
812 
813  command.append( QString("%1_addr_str = %1.GetAddressAsString(\"vtkPolyData\")\n").arg(varName) );
814  // remove 0x from the address
815  command.append( QString("%1_addr = int(%1_addr_str[5:],16)").arg(varName) );
816 
817  MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString();
818  this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND );
819 
820  // get address of the object
821  pyAddr = PyDict_GetItemString(pyDict,QString("%1_addr").arg(varName).toStdString().c_str());
822 
823  // convert to long
824  addr = PyInt_AsLong(pyAddr);
825 
826  MITK_DEBUG << "Python object address: " << addr;
827 
828  // get the object
829  vtkPolyData* poly = (vtkPolyData*)((void*)addr);
830  surface->SetVtkPolyData(poly);
831 
832  // delete helper variables from python stack
833  command = "";
834  command.append( QString("del %1_addr_str\n").arg(varName) );
835  command.append( QString("del %1_addr").arg(varName) );
836 
837  MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString();
838  this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND );
839 
840  return surface;
841 }
842 
843 bool mitk::PythonService::CopyToPythonAsVtkPolyData( mitk::Surface* surface, const std::string& stdvarName )
844 {
845  QString varName = QString::fromStdString( stdvarName );
846  std::ostringstream oss;
847  std::string addr = "";
848  QString command;
849  QString address;
850 
851  oss << (void*) ( surface->GetVtkPolyData() );
852 
853  // get the address
854  addr = oss.str();
855 
856  // remove "0x"
857  address = QString::fromStdString(addr.substr(2));
858 
859  command.append( QString("%1 = vtk.vtkPolyData(\"%2\")\n").arg(varName).arg(address) );
860 
861  MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString();
862  this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND );
863 
864  return true;
865 }
866 
868 {
869  this->Execute( "import SimpleITK as sitk\n", IPythonService::SINGLE_LINE_COMMAND );
870  // directly access cpp lib
871  this->Execute( "import SimpleITK._SimpleITK as _SimpleITK\n", IPythonService::SINGLE_LINE_COMMAND );
872  m_ItkWrappingAvailable = !this->PythonErrorOccured();
873 
874  // check for numpy
875  this->Execute( "import numpy\n", IPythonService::SINGLE_LINE_COMMAND );
876 
877  if ( this->PythonErrorOccured() )
878  MITK_ERROR << "Numpy not found.";
879 
880  m_ItkWrappingAvailable = !this->PythonErrorOccured();
881 
882  return m_ItkWrappingAvailable;
883 }
884 
886 {
887  this->Execute( "import cv2\n", IPythonService::SINGLE_LINE_COMMAND );
888  m_OpenCVWrappingAvailable = !this->PythonErrorOccured();
889 
890  return m_OpenCVWrappingAvailable;
891 }
892 
894 {
895  this->Execute( "import vtk", IPythonService::SINGLE_LINE_COMMAND );
896  //this->Execute( "print \"Using VTK version \" + vtk.vtkVersion.GetVTKVersion()\n", IPythonService::SINGLE_LINE_COMMAND );
897  m_VtkWrappingAvailable = !this->PythonErrorOccured();
898 
899  return m_VtkWrappingAvailable;
900 }
901 
903 {
904  return m_ErrorOccured;
905 }
906 
bool CopyToPythonAsVtkPolyData(mitk::Surface *surface, const std::string &varName) override
Class for storing surfaces (vtkPolyData).
Definition: mitkSurface.h:28
virtual vtkPolyData * GetVtkPolyData(unsigned int t=0) const
bool CopyToPythonAsSimpleItkImage(mitk::Image *image, const std::string &varName) override
#define MITK_INFO
Definition: mitkLogMacros.h:18
const mitk::PixelType GetPixelType(int n=0) const
Returns the PixelType of channel n.
Definition: mitkImage.cpp:101
#define MITK_ERROR
Definition: mitkLogMacros.h:20
vcl_size_t GetNumberOfComponents() const
Get the number of components of which each element consists.
unsigned int * GetDimensions() const
Get the sizes of all dimensions as an integer-array.
Definition: mitkImage.cpp:1309
#define MITK_DEBUG
Definition: mitkLogMacros.h:22
void RemovePythonCommandObserver(PythonCommandObserver *observer) override
void AddRelativeSearchDirs(std::vector< std::string > dirs) override
void * GetData()
Gives full data access.
static const int MULTI_LINE_COMMAND
void NotifyObserver(const std::string &command) override
#define PYTHON_LIBRARY
Definition: PythonPath.h:7
void FillVector3D(Tout &out, mitk::ScalarType x, mitk::ScalarType y, mitk::ScalarType z)
Definition: mitkArray.h:106
bool IsSimpleItkPythonWrappingAvailable() override
bool CopyToPythonAsCvImage(mitk::Image *image, const std::string &varName) override
int GetComponentType() const
Get the component type (the scalar (!) type). Each element may contain m_NumberOfComponents (more tha...
mitk::Image::Pointer CopySimpleItkImageFromPython(const std::string &varName) override
std::string GetVariable(const std::string &name) const override
mitk::Image::Pointer CopyCvImageFromPython(const std::string &varName) override
bool DoesVariableExist(const std::string &name) const override
#define MITK_WARN
Definition: mitkLogMacros.h:19
ctkAbstractPythonManager * GetPythonManager() override
#define EXTERNAL_SITE_PACKAGES
Definition: PythonPath.h:14
static const int SINGLE_LINE_COMMAND
bool PythonErrorOccured() const override
#define mitkThrow()
Image class for storing images.
Definition: mitkImage.h:72
void ExecuteScript(const std::string &pathToPythonScript) override
itk::ImageIOBase::IOPixelType GetPixelType() const
void AddAbsoluteSearchDirs(std::vector< std::string > dirs) override
mitk::Image::Pointer image
mitk::Surface::Pointer CopyVtkPolyDataFromPython(const std::string &varName) override
const Point3D GetOrigin() const
Get the origin, e.g. the upper-left corner of the plane.
static Pointer New()
void AddPythonCommandObserver(PythonCommandObserver *observer) override
std::string Execute(const std::string &pythonCommand, int commandType=SINGLE_LINE_COMMAND) override
std::vector< PythonVariable > GetVariableStack() const override
bool IsOpenCvPythonWrappingAvailable() override
const mitk::Vector3D GetSpacing() const
Get the spacing (size of a pixel).
~PythonService() override
empty implementation...
ImageWriteAccessor class to get locked write-access for a particular image part.
mitk::PixelType DeterminePixelType(const std::string &pythonPixeltype, unsigned long nrComponents, int dimensions)
static const int EVAL_COMMAND
itksys::SystemTools ist
ImageReadAccessor class to get locked read access for a particular image part.
bool IsVtkPythonWrappingAvailable() override
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
Definition: mitkBaseData.h:138
PythonService()
instantiate python manager here
static Pointer New()
const void * GetData() const
Gives const access to the data.
Class for defining the data type of pixels.
Definition: mitkPixelType.h:51
mitk::AffineTransform3D * GetIndexToWorldTransform()
Get the transformation used to convert from index to world coordinates.
#define EXTERNAL_DIST_PACKAGES
Definition: PythonPath.h:15