python_view.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. r"""python_view is a module providing access to a PythonView. It is
  2. possible to use the PythonView API directly, but this module provides
  3. convenience classes in Python.
  4. """
  5. #==============================================================================
  6. #
  7. # Program: ParaView
  8. # Module: python_view.py
  9. #
  10. # Copyright (c) Kitware, Inc.
  11. # All rights reserved.
  12. # See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
  13. #
  14. # This software is distributed WITHOUT ANY WARRANTY without even
  15. # the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  16. # PURPOSE. See the above copyright notice for more information.
  17. #
  18. #==============================================================================
  19. import paraview
  20. from vtkmodules.vtkCommonDataModel import vtkImageData
  21. def numpy_to_image(numpy_array):
  22. """Convert a numpy 2D or 3D array to a vtkImageData object.
  23. numpy_array
  24. 2D or 3D numpy array containing image data
  25. return
  26. vtkImageData with the numpy_array content
  27. """
  28. try:
  29. import numpy
  30. except:
  31. paraview.print_error("Error: Cannot import numpy")
  32. shape = numpy_array.shape
  33. if len(shape) < 2:
  34. raise Exception('numpy array must have dimensionality of at least 2')
  35. h, w = shape[0], shape[1]
  36. c = 1
  37. if len(shape) == 3:
  38. c = shape[2]
  39. # Reshape 2D image to 1D array suitable for conversion to a
  40. # vtkArray with numpy_support.numpy_to_vtk()
  41. linear_array = numpy.reshape(numpy_array, (w*h, c))
  42. try:
  43. from vtkmodules.util import numpy_support
  44. except:
  45. paraview.print_error("Error: Cannot import vtkmodules.util.numpy_support")
  46. vtk_array = numpy_support.numpy_to_vtk(linear_array)
  47. image = vtkImageData()
  48. image.SetDimensions(w, h, 1)
  49. image.AllocateScalars(vtk_array.GetDataType(), 4)
  50. image.GetPointData().GetScalars().DeepCopy(vtk_array)
  51. return image
  52. def figure_to_data(figure):
  53. """Convert a Matplotlib figure to a numpy 2D array with RGBA uint8 channels
  54. and return it.
  55. figure
  56. A matplotlib figure.
  57. return
  58. A numpy 2D array of RGBA values.
  59. """
  60. # Draw the renderer
  61. try:
  62. import matplotlib
  63. except:
  64. paraview.print_error("Error: Cannot import matplotlib")
  65. figure.canvas.draw()
  66. # Get the RGBA buffer from the figure
  67. w, h = figure.canvas.get_width_height()
  68. try:
  69. import numpy
  70. except:
  71. paraview.print_error("Error: Cannot import numpy")
  72. buf = numpy.fromstring(figure.canvas.tostring_argb(), dtype=numpy.uint8)
  73. buf.shape = (h, w, 4)
  74. # canvas.tostring_argb gives pixmap in ARGB mode. Roll the alpha channel to have it in RGBA mode
  75. buf = numpy.roll(buf, 3, axis=2)
  76. return buf
  77. def figure_to_image(figure):
  78. """Convert a Matplotlib figure to a vtkImageData with RGBA unsigned char
  79. channels.
  80. figure
  81. A matplotlib figure.
  82. return
  83. A vtkImageData with the Matplotlib figure content.
  84. """
  85. buf = figure_to_data(figure)
  86. # Flip rows to be suitable for vtkImageData.
  87. buf = buf[::-1,:,:].copy()
  88. return numpy_to_image(buf)
  89. def matplotlib_figure(width, height):
  90. """Create a Matplotlib figure with specified width and height for rendering.
  91. w
  92. Width of desired plot.
  93. h
  94. Height of desired plot.
  95. return
  96. A Matplotlib figure.
  97. """
  98. try:
  99. from matplotlib.backends.backend_agg import FigureCanvasAgg
  100. except:
  101. paraview.print_error("Error: Cannot import matplotlib.backends.backend_agg.FigureCanvasAgg")
  102. try:
  103. from matplotlib.figure import Figure
  104. except:
  105. paraview.print_error("Error: Cannot import matplotlib.figure.Figure")
  106. figure = Figure()
  107. figureCanvas = FigureCanvasAgg(figure)
  108. figure.set_dpi(72)
  109. figure.set_size_inches(float(width)/72.0, float(height)/72.0)
  110. return figure
  111. def call_render(render_function, view, width, height):
  112. """Utility function to call the user-defined render function. This is called
  113. by the C++ side of the vtkPythonView class.
  114. view
  115. vtkPythonView object
  116. width
  117. Width of view
  118. height
  119. Height of view
  120. """
  121. if render_function == None:
  122. return
  123. # Check how many parameters it takes.
  124. num_args = render_function.__code__.co_argcount
  125. image = None
  126. if (num_args == 3):
  127. # Current-style render() function
  128. image = render_function(view, width, height)
  129. elif (num_args == 2):
  130. # Old-style render() function introduced in ParaView 4.1
  131. figure = matplotlib_figure(width, height)
  132. render_function(view, figure)
  133. image = figure_to_image(figure)
  134. view.SetImageData(image)