# Qt with VTK and Loading Files

**URL:** https://discourse.vtk.org/t/qt-with-vtk-and-loading-files/6569
**Category:** Support
**Created:** [September 6, 2021, 8:51pm UTC](https://discourse.vtk.org/t/qt-with-vtk-and-loading-files/6569 "2021-09-06T20:51:59Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![Adam\_Hendry](https://discourse.vtk.org/user_avatar/discourse.vtk.org/adam_hendry/32/5571_2.png) [@Adam\_Hendry](https://discourse.vtk.org/u/Adam_Hendry)
#### Post date: [September 6, 2021, 8:51pm UTC](https://discourse.vtk.org/t/qt-with-vtk-and-loading-files/6569/1 "2021-09-06T20:51:59Z")

</div>

I’ve seen some `pyvista` questions posted here, so I’m posting my question. I am trying to create a Qt GUI with `pyvista` and would like to implement Progress Bars when loading large file stacks. I have succeeded with the code below, but it is much slower than ParaView.

Does my implementation need improvement, or could it be that ParaView is somehow loading files in parallel? I have a folder of 1,174 DICOM files, each 5.96 MB. These are simply raw DICOM files (`*.dcm`), so they have not been preprocessed in any way.

Below are the times using my code vs. ParaView (including rendering it as a volume). I used `time.time` for my code and my stopwatch for ParaView:

```auto
My Code: ~13 minutes, 9 seconds
ParaView 5.9.1 (installed pre-built binary): ~24 seconds

```

This may not be related to the progress bar code at all, so if anyone can tell me how to make my load times on par with ParaView, that’s what I want! Thanks in advance!

#### Setup

**OS:** Windows 10 Professional x64-bit, Build 1909  
**Python:** 3.8.10 x64-bit  
**PyQt:** 5.15.4  
**pyvista:** 0.31.3  
**IDE:** VSCode 1.59.0

#### Project Directory

```auto
gui/
├───gui/
│ │ main.py
│ │ __init__.py
│ │   
│ ├───controller/
│ │ controller.py
│ │ __init__.py
│ │
│ ├───model/
│ │ model.py
│ │ __init__.py
│ │
│ └───view/
│ view.py
│ __init__.py
├───resources/
│ │ __init__.py
│ │   
│ └───icons
│ │ main.ico
│ │ __init__.py
│ │   
│ └───toolbar
│ new.png
│ __init__.py
└───tests/
    │ conftest.py
    │ __init__.py
    │
    └───unit_tests
            test_view.py
            __init__.py

```

#### Code

**`gui/main.py`:**

```python
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication

from gui.controller.controller import Controller
from gui.model.model import Model
from gui.view.view import View

class MainApp:
    def __init__ (self) -> None:
        self.controller = Controller()
        self.model = self.controller.model
        self.view = self.controller.view

    def show(self) -> None:
        self.view.showMaximized()

if __name__ == " __main__":
    app = QApplication([])
    app.setStyle("fusion")
    app.setAttribute(Qt.AA_DontShowIconsInMenus, True)
    root = MainApp()
    root.show()
    app.exec_()

```

**`gui/view.py`:**

```python
import os
import threading
from typing import Any

import numpy as np
import pyvista as pv
import SimpleITK as sitk
from PyQt5.QtCore import QObject, QPoint, QSize, Qt, pyqtSignal
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import (QAction, QDialog, QDockWidget, QFileDialog,
                             QFrame, QHBoxLayout, QMainWindow, QProgressBar,
                             QSplitter, QStatusBar, QTabWidget, QToolBar,
                             QTreeWidget, QTreeWidgetItem, QVBoxLayout,
                             QWidget)
from pyvistaqt import MainWindow, QtInteractor
from resources import icons
from resources.icons import project_explorer, toolbar
from SimpleITK import ImageFileReader, ImageSeriesReader

class FileSeriesWorker(QObject):
    started = pyqtSignal()
    finished = pyqtSignal()
    result = pyqtSignal(dict)

    def __init__ (self, folder, plotter):
        super(). __init__ ()
        self.folder = folder
        self.plotter = plotter
        self.thread = threading.Thread(target=self._load_files, daemon=True)

    def execute(self):
        self.thread.start()

    def _load_files(self):
        self.started.emit()

        dicom_reader = ImageSeriesReader()
        dicom_files = dicom_reader.GetGDCMSeriesFileNames(self.folder)
        dicom_reader.SetFileNames(dicom_files)
        scan = dicom_reader.Execute()

        origin = scan.GetOrigin()
        spacing = scan.GetSpacing()
        direction = scan.GetDirection()

        data = sitk.GetArrayFromImage(scan)
        data = (data // 256).astype(np.uint8)

        data_values = data[data > 0]
        pct_low, pct_high = np.percentile(data_values, [1, 99])
        clim = [pct_low, pct_high]

        volume = pv.UniformGrid(data.shape)

        volume.origin = origin
        volume.spacing = spacing
        volume.direction = direction

        volume.point_arrays["Values"] = data.flatten(order="F")
        volume.set_active_scalars("Values")

        self.plotter.add_volume(
            volume,
            clim=clim,
            opacity="sigmoid",
            reset_camera=True,
        )

        self.finished.emit()

        self.result.emit(
            {
                "origin": origin,
                "spacing": spacing,
                "direction": direction,
                "data": data,
                "volume": volume,
            }
        )

class ProgressBarDialog(QDialog):
    def __init__ (self, parent=None, message=None):
        super(). __init__ (parent)

        self.setWindowTitle(message)

        self.progressbar = QProgressBar()

        layout = QVBoxLayout(self)
        layout.addWidget(self.progressbar)

        self.setLayout(layout)

class View(MainWindow):
    def __init__ (
        self, controller, parent: QWidget = None, *args: Any, **kwargs: Any
    ) -> None:
        super(). __init__ (parent, *args, **kwargs)
        self.controller = controller

        # Set the window name
        self.setWindowTitle("Demo")

        # Create the container frame
        self.container = QFrame()

        # Create the layout
        self.layout = QGridLayout()
        self.layout.setContentsMargins(0, 0, 0, 0)

        # Set the layout
        self.container.setLayout(self.layout)
        self.setCentralWidget(self.container)

        # Set project variables
        self.project_is_open = False

        # Create and position widgets
        self._create_actions()
        self._create_menubar()
        self._create_toolbar()
        self._create_progressbar()

    def _create_actions(self):
        # New
        self.new_action = QAction(QIcon(toolbar.NEW_ICO), "&New Project...", self)
        self.new_action.setShortcut("Ctrl+N")
        self.new_action.setStatusTip("Create a new project...")
        self.new_action.triggered.connect(self._create_new_project)

        # Open Folder
        self.open_folder_action = QAction(
            QIcon(toolbar.OPEN_FOLDER_ICO), "&Open Folder...", self
        )
        self.open_folder_action.setShortcut("Ctrl+Shift+O")
        self.open_folder_action.setStatusTip("Open folder...")
        self.open_folder_action.triggered.connect(self._open_folder)

    def _create_menubar(self):
        self.menubar = self.menuBar()

        # File menu
        self.file_menu = self.menubar.addMenu("&File")

        self.file_menu.addAction(self.new_action)
        self.file_menu.addAction(self.open_folder_action)

    def _create_toolbar(self):
        self.toolbar = QToolBar("Main Toolbar")
        self.toolbar.setIconSize(QSize(16, 16))

        self.addToolBar(self.toolbar)

        self.toolbar.addAction(self.new_action)

    def _create_progressbar(self):
        self.progressbar_dialog = ProgressBarDialog(parent=self)

        self.progressbar_dialog.setGeometry(25, 250, 400, 50)
        self.progressbar_dialog.hide()

    def _open_folder(self):
        if not self.project_is_open:
            self.interactor_layout = QHBoxLayout()
            
            self.plotter = QtInteractor()

            self.plotter.add_axes()
            self.plotter.reset_camera()
            self.signal_close.connect(self.plotter.close)

            self.layout.addLayout(self.interactor_layout)

            self.container.setLayout(self.layout)
            self.setCentralWidget(self.container)

            self.project_is_open = True

        # Create "Open Folder..." Dialog
        dialog = QFileDialog()

        filters = ["DICOM Files (*.dcm)",]

        dialog.setFileMode(QFileDialog.Directory)
        dialog.setWindowTitle("Open Folder...")
        dialog.setNameFilters(filters)
        dialog.setLabelText(dialog.FileName, "Folder: ")
        dialog.setOptions(QFileDialog.DontUseNativeDialog)

        dialog.exec_()

        root = dialog.directory().path()
        directory = dialog.selectedFiles()[0]

        if directory:
            folder = os.path.join(root, directory)

            self.file_series_worker = FileSeriesWorker(folder, self.plotter)

            self.file_series_worker.started.connect(self._on_import_start)
            self.file_series_worker.finished.connect(self._on_import_finish)
            self.file_series_worker.result.connect(self._on_import_result)

            self.file_series_worker.execute()

    def _on_import_start(self):
        self.progressbar_dialog.setWindowTitle("Loading data...")

        x = self.x() + (self.width() - self.progressbar_dialog.width()) // 2
        y = self.y() + (self.height() - self.progressbar_dialog.height()) // 2

        self.progressbar_dialog.move(QPoint(x, y))
        self.progressbar_dialog.progressbar.setRange(0, 0)

        self.progressbar_dialog.setModal(True)
        self.progressbar_dialog.show()

    def _on_import_finish(self):
        pass

    def _on_import_result(self, result):
        self.origin = result["origin"]
        self.spacing = result["spacing"]
        self.direction = result["direction"]
        self.data = result["data"]
        self.volume = result["volume"]

        self.progressbar_dialog.hide()
        self.progressbar_dialog.progressbar.setRange(0, 1)
        self.progressbar_dialog.setModal(False)

```

**`gui/model.py`:**

```python
from typing import Any

class Model(object):
    def __init__ (self, controller, *args: Any, **kwargs: Any):
        self.controller = controller

```

**`gui/controller.py`:**

```python
from typing import Any

from gui.model.model import Model
from gui.view.view import View

class Controller(object):
    def __init__ (self, *args: Any, **kwargs: Any):
        self.model = Model(controller=self, *args, **kwargs)
        self.view = View(controller=self, *args, **kwargs)

```

---

<div class="post-metadata">

### Author: ![Adam\_Hendry](https://discourse.vtk.org/user_avatar/discourse.vtk.org/adam_hendry/32/5571_2.png) [@Adam\_Hendry](https://discourse.vtk.org/u/Adam_Hendry)
#### Post date: [September 6, 2021, 8:55pm UTC](https://discourse.vtk.org/t/qt-with-vtk-and-loading-files/6569/2 "2021-09-06T20:55:04Z")

</div>

Cc @banesullivan

---

<div class="post-metadata">

### Author: ![Adam\_Hendry](https://discourse.vtk.org/user_avatar/discourse.vtk.org/adam_hendry/32/5571_2.png) [@Adam\_Hendry](https://discourse.vtk.org/u/Adam_Hendry)
#### Post date: [September 6, 2021, 9:58pm UTC](https://discourse.vtk.org/t/qt-with-vtk-and-loading-files/6569/3 "2021-09-06T21:58:05Z")

</div>

**Update: 06-SEP-2021**

I’ve added a helper function `print_time` to my module `view.py` and broke down the time each function takes to execute. From this, it is clear volume plotting takes the longest. Why is volume plotting so much slower than in ParaView?

**New Code:**

```python
def print_time(msg, start, finish):
    total_time = finish - start
    hours = int(total_time // 3600)
    total_time -= 3600 * hours
    minutes = int(total_time // 60)
    total_time -= 60 * minutes
    seconds = int(total_time)

    print(f"{msg} - Run Time: {hours}::{minutes}::{seconds} (hrs::mins::sec)")

class FileSeriesWorker(QObject):
    started = pyqtSignal()
    finished = pyqtSignal()
    result = pyqtSignal(dict)

    def __init__ (self, folder, plotter):
        super(). __init__ ()
        self.folder = folder
        self.plotter = plotter
        self.thread = threading.Thread(target=self._load_files, daemon=True)

    def execute(self):
        self.thread.start()

    def _load_files(self):
        self.started.emit()

        start = time.time()

        dicom_reader = ImageSeriesReader()
        dicom_files = dicom_reader.GetGDCMSeriesFileNames(self.folder)
        dicom_reader.SetFileNames(dicom_files)
        scan = dicom_reader.Execute()

        finish = time.time()

        print_time("ImageSeriesReader Execute", start, finish)

        origin = scan.GetOrigin()
        spacing = scan.GetSpacing()
        direction = scan.GetDirection()

        start = time.time()

        data = sitk.GetArrayFromImage(scan)

        data = (data // 256).astype(np.uint8)

        finish = time.time()

        print_time("GetArrayFromImage", start, finish)

        data_values = data[data > 0]
        pct_low, pct_high = np.percentile(data_values, [1, 99])
        clim = [pct_low, pct_high]

        start = time.time()

        volume = pv.UniformGrid(data.shape)

        finish = time.time()

        print_time("Create UniformGrid", start, finish)

        volume.origin = origin
        volume.spacing = spacing
        volume.direction = direction

        volume.point_arrays["Attenuation Coefficients"] = data.flatten(order="F")

        volume.set_active_scalars("Attenuation Coefficients")

        start = time.time()

        self.plotter.add_volume(
            volume,
            clim=clim,
            opacity="sigmoid",
            reset_camera=True,
        )

        finish = time.time()

        print_time("Plot Volume", start, finish)

        self.finished.emit()

        self.result.emit(
            {
                "origin": origin,
                "spacing": spacing,
                "direction": direction,
                "data": data,
                "volume": volume,
            }
        )

```

**Output:**

From this, it is quite clear now that plotting is taking the longest amount of time

```bash
WARNING: In d:\a\1\sitk-build\itk-prefix\include\itk-5.2\itkImageSeriesReader.hxx, line 480
ImageSeriesReader (0000017376F972B0): Non uniform sampling or missing slices detected, maximum nonuniformity:7.39539e-07

ImageSeriesReader Execute - Run Time: 0::0::24 (hrs::mins::sec)
GetArrayFromImage - Run Time: 0::0::10 (hrs::mins::sec)
Create UniformGrid - Run Time: 0::0::0 (hrs::mins::sec)
2021-09-06 14:30:57.308 ( 761.842s) []vtkWin32OpenGLRenderWin:217 ERR| vtkWin32OpenGLRenderWindow (000001736C95CDC0): wglMakeCurrent failed in MakeCurrent(), error: The requested resource is in use.

ERROR:root:wglMakeCurrent failed in MakeCurrent(), error: The requested resource is in use.
Plot Volume - Run Time: 0::10::49 (hrs::mins::sec)

```

---

<div class="post-metadata">

### Author: ![Adam\_Hendry](https://discourse.vtk.org/user_avatar/discourse.vtk.org/adam_hendry/32/5571_2.png) [@Adam\_Hendry](https://discourse.vtk.org/u/Adam_Hendry)
#### Post date: [September 7, 2021, 4:48am UTC](https://discourse.vtk.org/t/qt-with-vtk-and-loading-files/6569/4 "2021-09-07T04:48:59Z")

</div>

**Update #2: 06-SEP-2021**

I used `cProfile` to break down issues in the plotting (see [Profiling and optimizing your Python code | Python tricks by Sebastiaan Mathôt](https://www.youtube.com/watch?v=8qEnExGLZfY) for details.

I pulled plotting into the `View` class `_on_import_result` method and added a top level decorator function `profile` in `view.py`

**Code:**

```python
def profile(fnc):
    """Wrapper for cProfile"""
    def inner(*args, **kwargs):
        pr = cProfile.Profile()
        pr.enable()
        retval = fnc(*args, **kwargs)
        pr.disable()
        s = io.StringIO()
        sortby = "cumulative"
        ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
        ps.print_stats()
        print(s.getvalue())
        return retval

    return inner

```

```python
@profile
def _on_import_result(self, result):
    self.origin = result["origin"]
    self.spacing = result["spacing"]
    self.direction = result["direction"]
    self.data = result["data"]
    self.volume = result["volume"]

    data_values = self.data[self.data > 0]
    pct_low, pct_high = np.percentile(data_values, [1, 99])
    clim = [pct_low, pct_high]

    start = time.time()

    self.plotter.add_volume(
        self.volume,
        clim=clim,
        opacity="linear",
        reset_camera=True,
    )

    self.progressbar_dialog.hide()
    self.progressbar_dialog.progressbar.setRange(0, 1)
    self.progressbar_dialog.setModal(False)

```

### Output:

```auto
WARNING: In d:\a\1\sitk-build\itk-prefix\include\itk-5.2\itkImageSeriesReader.hxx, line 480
ImageSeriesReader (00000206D88B8100): Non uniform sampling or missing slices detected, maximum nonuniformity:7.40137e-07

ImageSeriesReader Execute - Run Time: 0::1::18 (hrs::mins::sec)
GetArrayFromImage - Run Time: 0::0::10 (hrs::mins::sec)
Create UniformGrid - Run Time: 0::0::0 (hrs::mins::sec)
         8284 function calls (7945 primitive calls) in 714.899 seconds

   Ordered by: cumulative time

   ncalls tottime percall cumtime percall filename:lineno(function)
        1 8.142 8.142 714.899 714.899 gui\view\view.py:571(_on_import_result)
        1 96.223 96.223 693.131 693.131 .venv\lib\site-packages\pyvista\plotting\plotting.py:1817(add_volume)        
        1 0.001 0.001 394.513 394.513 .venv\lib\site-packages\pyvista\core\filters.py:1483(cell_data_to_point_data)
        2 392.239 196.119 392.239 196.119 {method 'Update' of 'vtkmodules.vtkCommonExecutionModel.vtkAlgorithm' objects}
   121/38 9.357 0.077 137.771 3.626 {built-in method numpy.core._multiarray_umath.implement_array_function}
        3 19.357 6.452 103.425 34.475 .venv\lib\site-packages\numpy\lib\nanfunctions.py:68(_replace_nan)
      272 82.231 0.302 82.231 0.302 {built-in method numpy.array}
        2 0.001 0.000 77.979 38.990 < __array_function__ internals>:2(nanmin)
        2 0.941 0.471 72.894 36.447 .venv\lib\site-packages\numpy\lib\nanfunctions.py:228(nanmin)
        1 0.000 0.000 46.175 46.175 < __array_function__ internals>:2(nanmax)
        1 0.274 0.274 43.740 43.740 .venv\lib\site-packages\numpy\lib\nanfunctions.py:343(nanmax)
       24 37.062 1.544 37.062 1.544 {method 'astype' of 'numpy.ndarray' objects}
        2 0.000 0.000 27.030 13.515 .venv\lib\site-packages\pyvista\core\datasetattributes.py:171(append)        
        6 0.000 0.000 24.055 4.009 .venv\lib\site-packages\pyvista\utilities\helpers.py:83(convert_array)       
        3 0.001 0.000 24.055 8.018 .venv\lib\site-packages\vtkmodules\util\numpy_support.py:104(numpy_to_vtk)   
        1 23.339 23.339 23.339 23.339 {method 'DeepCopy' of 'vtkmodules.vtkCommonCore.vtkDataArray' objects}
        1 0.000 0.000 13.616 13.616 < __array_function__ internals>:2(percentile)
        1 0.000 0.000 13.616 13.616 .venv\lib\site-packages\numpy\lib\function_base.py:3724(percentile)
        1 0.000 0.000 13.616 13.616 .venv\lib\site-packages\numpy\lib\function_base.py:3983(_quantile_unchecked)
        1 0.450 0.450 13.616 13.616 .venv\lib\site-packages\numpy\lib\function_base.py:3513(_ureduce)
        1 0.000 0.000 13.166 13.166 .venv\lib\site-packages\numpy\lib\function_base.py:4018(_quantile_ureduce_func)
       29 0.000 0.000 11.994 0.414 .venv\lib\site-packages\numpy\core\fromnumeric.py:69(_wrapreduction)
       30 11.993 0.400 11.994 0.400 {method 'reduce' of 'numpy.ufunc' objects}
        2 0.000 0.000 11.450 5.725 .venv\lib\site-packages\pyvista\plotting\plotting.py:477(add_actor)
        2 0.000 0.000 11.450 5.725 .venv\lib\site-packages\pyvista\plotting\renderer.py:342(add_actor)
        2 0.000 0.000 11.449 5.724 .venv\lib\site-packages\pyvistaqt\plotting.py:336(render)
        2 0.000 0.000 11.449 5.724 {method 'emit' of 'PyQt5.QtCore.pyqtBoundSignal' objects}
        2 0.000 0.000 11.449 5.724 .venv\lib\site-packages\pyvistaqt\plotting.py:331(_render)
        2 0.000 0.000 11.449 5.724 .venv\lib\site-packages\pyvista\plotting\plotting.py:808(render)
        2 11.449 5.724 11.449 5.724 {method 'Render' of 'vtkmodules.vtkRenderingOpenGL2.vtkOpenGLRenderWindow' objects}
        1 0.000 0.000 11.405 11.405 .venv\lib\site-packages\pyvista\plotting\renderer.py:1362(reset_camera)
        1 11.236 11.236 11.236 11.236 {method 'partition' of 'numpy.ndarray' objects}
        2 0.000 0.000 6.644 3.322 < __array_function__ internals>:2(amin)
        2 0.000 0.000 6.644 3.322 .venv\lib\site-packages\numpy\core\fromnumeric.py:2763(amin)
        2 0.000 0.000 6.644 3.322 {method 'min' of 'numpy.ndarray' objects}
        2 0.000 0.000 6.644 3.322 .venv\lib\site-packages\numpy\core\_methods.py:42(_amin)
        1 0.000 0.000 4.964 4.964 < __array_function__ internals>:2(amax)
        1 0.000 0.000 4.964 4.964 .venv\lib\site-packages\numpy\core\fromnumeric.py:2638(amax)
        1 0.000 0.000 4.964 4.964 {method 'max' of 'numpy.ndarray' objects}
        1 0.000 0.000 4.964 4.964 .venv\lib\site-packages\numpy\core\_methods.py:38(_amax)
        1 0.000 0.000 3.330 3.330 .venv\lib\site-packages\pyvista\core\dataset.py:637( __setitem__ )
        1 0.000 0.000 3.330 3.330 .venv\lib\site-packages\pyvista\core\datasetattributes.py:55( __setitem__ )
        2 2.974 1.487 2.974 1.487 {method 'AddArray' of 'vtkmodules.vtkCommonDataModel.vtkFieldData' objects}
        2 2.648 1.324 2.648 1.324 .venv\lib\site-packages\pyvista\core\pyvista_ndarray.py:50( __setitem__ )
        1 0.000 0.000 2.273 2.273 .venv\lib\site-packages\pyvista\core\filters.py:51(_get_output)
        1 0.000 0.000 2.272 2.272 .venv\lib\site-packages\pyvista\utilities\helpers.py:528(wrap)
        1 0.000 0.000 2.272 2.272 .venv\lib\site-packages\pyvista\core\grid.py:281( __init__ )
        1 0.000 0.000 2.272 2.272 .venv\lib\site-packages\pyvista\core\dataobject.py:44(deep_copy)
        1 2.271 2.271 2.271 2.271 {method 'DeepCopy' of 'vtkmodules.vtkCommonDataModel.vtkImageData' objects}
        1 1.929 1.929 1.929 1.929 {method 'flatten' of 'numpy.ndarray' objects}
        6 0.000 0.000 1.837 0.306 < __array_function__ internals>:2(copyto)
        3 0.609 0.203 0.609 0.203 {method 'SetVoidArray' of 'vtkmodules.vtkCommonCore.vtkAbstractArray' objects}
        3 0.000 0.000 0.386 0.129 < __array_function__ internals>:2(all)
        3 0.000 0.000 0.386 0.129 .venv\lib\site-packages\numpy\core\fromnumeric.py:2367(all)
        3 0.000 0.000 0.385 0.128 {method 'all' of 'numpy.ndarray' objects}
        3 0.000 0.000 0.385 0.128 .venv\lib\site-packages\numpy\core\_methods.py:60(_all)
        3 0.105 0.035 0.105 0.035 {method 'SetNumberOfTuples' of 'vtkmodules.vtkCommonCore.vtkAbstractArray' objects}
        1 0.000 0.000 0.046 0.046 .venv\lib\site-packages\pyvista\plotting\plotting.py:2317(add_scalar_bar)
        1 0.001 0.001 0.046 0.046 .venv\lib\site-packages\pyvista\plotting\scalar_bars.py:115(add_scalar_bar)
        1 0.037 0.037 0.037 0.037 .venv\lib\site-packages\pyvista\plotting\mapper.py:4(make_mapper)
        1 0.010 0.010 0.010 0.010 {built-in method hide}
      257 0.003 0.000 0.005 0.000 .venv\lib\site-packages\matplotlib\colors.py:588( __call__ )
        1 0.000 0.000 0.004 0.004 .venv\lib\site-packages\pyvista\plotting\colors.py:393(get_cmap_safe)
        2 0.000 0.000 0.003 0.002 <frozen importlib._bootstrap>:986(_find_and_load)
        2 0.000 0.000 0.003 0.002 <frozen importlib._bootstrap>:956(_find_and_load_unlocked)
        2 0.000 0.000 0.003 0.002 <frozen importlib._bootstrap>:890(_find_spec)
        2 0.000 0.000 0.003 0.002 <frozen importlib._bootstrap_external>:1399(find_spec)
        2 0.000 0.000 0.003 0.002 <frozen importlib._bootstrap_external>:1367(_get_spec)
       22 0.001 0.000 0.003 0.000 <frozen importlib._bootstrap_external>:1498(find_spec)
        1 0.000 0.000 0.002 0.002 .venv\lib\site-packages\pyvista\plotting\tools.py:239(opacity_transfer_function)
        7 0.000 0.000 0.001 0.000 .venv\lib\site-packages\pyvista\core\dataset.py:98(active_scalars_info)
       22 0.000 0.000 0.001 0.000 <frozen importlib._bootstrap_external>:135(_path_stat)
        9 0.000 0.000 0.001 0.000 .venv\lib\site-packages\pyvista\core\dataset.py:46(_namedtuple)
       22 0.001 0.000 0.001 0.000 {built-in method nt.stat}
       28 0.000 0.000 0.001 0.000 .venv\lib\site-packages\pyvista\core\pyvista_ndarray.py:31( __array_finalize__ )
        8 0.000 0.000 0.001 0.000 .venv\lib\site-packages\pyvista\core\dataset.py:52( __iter__ )
      110 0.001 0.000 0.001 0.000 <frozen importlib._bootstrap_external>:91(_path_join)
        9 0.001 0.000 0.001 0.000 C:\Program Files\Python38\lib\collections\ __init__.py:313(namedtuple)
      371 0.000 0.000 0.001 0.000 {built-in method builtins.isinstance}
        1 0.000 0.000 0.001 0.001 .venv\lib\site-packages\pyvista\core\dataset.py:413(active_scalars)
        9 0.000 0.000 0.001 0.000 C:\Program Files\Python38\lib\abc.py:96( __instancecheck__ )
        9 0.000 0.000 0.001 0.000 {built-in method _abc._abc_instancecheck}
    131/3 0.000 0.000 0.001 0.000 C:\Program Files\Python38\lib\abc.py:100( __subclasscheck__ )
    131/3 0.001 0.000 0.001 0.000 {built-in method _abc._abc_subclasscheck}
       12 0.000 0.000 0.001 0.000 < __array_function__ internals>:2(linspace)
        5 0.000 0.000 0.001 0.000 .venv\lib\site-packages\pyvista\core\pyvista_ndarray.py:14( __new__ )
       12 0.000 0.000 0.001 0.000 .venv\lib\site-packages\numpy\core\function_base.py:23(linspace)
        1 0.000 0.000 0.001 0.001 .venv\lib\site-packages\pyvista\core\dataset.py:516(copy_meta_from)
       22 0.000 0.000 0.001 0.000 < __array_function__ internals>:2(any)
        1 0.000 0.000 0.001 0.001 .venv\lib\site-packages\pyvista\core\datasetattributes.py:48( __getitem__ )
        1 0.000 0.000 0.001 0.001 .venv\lib\site-packages\pyvista\core\datasetattributes.py:142(get_array)
        3 0.000 0.000 0.001 0.000 .venv\lib\site-packages\pyvista\core\dataset.py:179(active_scalars_name)
       22 0.000 0.000 0.001 0.000 .venv\lib\site-packages\numpy\core\fromnumeric.py:2268(any)
        1 0.000 0.000 0.001 0.001 .venv\lib\site-packages\matplotlib\colors.py:1052(_init)
        2 0.000 0.000 0.001 0.000 < __array_function__ internals>:2(geomspace)
        1 0.000 0.000 0.001 0.001 .venv\lib\site-packages\matplotlib\colors.py:302(to_rgba_array)
        2 0.000 0.000 0.000 0.000 .venv\lib\site-packages\numpy\core\function_base.py:286(geomspace)
        9 0.000 0.000 0.000 0.000 {built-in method builtins.exec}
      257 0.000 0.000 0.000 0.000 .venv\lib\site-packages\numpy\ma\core.py:6566(is_masked)
        1 0.000 0.000 0.000 0.000 .venv\lib\site-packages\pyvista\core\dataset.py:326(set_active_scalars)
       28 0.000 0.000 0.000 0.000 .venv\lib\site-packages\vtkmodules\numpy_interface\dataset_adapter.py:275( __array_finalize__ )
        2 0.000 0.000 0.000 0.000 .venv\lib\site-packages\pyvista\plotting\renderer.py:1231(remove_actor)
        1 0.000 0.000 0.000 0.000 .venv\lib\site-packages\pyvista\core\dataset.py:119(active_vecto

```

---

<div class="post-metadata">

### Author: ![Paulo\_Carvalho](https://discourse.vtk.org/user_avatar/discourse.vtk.org/paulo_carvalho/32/370_2.png) [@Paulo\_Carvalho](https://discourse.vtk.org/u/Paulo_Carvalho)
#### Post date: [September 8, 2021, 12:44pm UTC](https://discourse.vtk.org/t/qt-with-vtk-and-loading-files/6569/5 "2021-09-08T12:44:59Z")

</div>

Make sure you’re not updating the progress bar too often. I have a large file loader too in which I had to update the progress bar just once every 1MB or so in it’s file reading loop. GUI updating takes quite a while and should be done very sparingly from inside performance critical loops.
