Widgets¶
The widgets shipped with data-slicer
can be re-combined to create new
applications.
In order to do this, a certain level of familiarity with widget-based GUI
creation is required and some knowledge or experience with Qt or PyQt is
recommended.
Nevertheless, even without said experience, the step-by-step tutorial below may help you figure out how to do such
things.
List of available widgets¶
data_slicer.imageplot.ImagePlot |
A pseudocolor plot of a 2D dataset, similar to matplotlib
pcolormesh . |
data_slicer.imageplot.CrosshairImagePlot |
An ImagePlot with a draggable crosshair. |
data_slicer.imageplot.CursorPlot |
A regular data plot with a draggable line (cursor). |
data_slicer.imageplot.Scalebar |
A draggable scalebar. |
data_slicer.cutline.Cutline |
A line that can be dragged on both ends and added to a
pyqtgraph.PlotWidget to create arbitrary cuts. |
data_slicer.pit.MainWindow |
The full main window of PIT, itself consisting of widgets from this list. |
data_slicer.widgets.ColorSliders |
Gamma and vmax color sliders. Essentially just a pair of
Scalebar objects. |
data_slicer.widgets.ThreeDWidget |
A widget that allows showing xy-slices out of a 3D dataset as a plane in 3D. |
data_slicer.widgets.ThreeDSliceWidget |
Subclass of ThreeDWidget that shows the
xz- and yz-planes in addition to the xy plane. |
data_slicer.widgets.FreeSliceWidget |
Subclass of ThreeDWidget that makes use
of a Cutline on an
ImagePlot to allow creating arbitrary
slice-planes. |
Example¶
In the following we will go through the creation of a simple App that uses a
ThreeDSliceWidget
to display some data that can
be loaded when clicking a Load button.
Step 1: Just a plain ThreeDSliceWidget¶
First, we take a look at what we would need to do in order to just create a
ThreeDSliceWidget
without anything else.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # Import libraries from pyqtgraph.Qt import QtGui from data_slicer.widgets import ThreeDSliceWidget # Create a Qt Window and set its size app = QtGui.QApplication([]) window = QtGui.QMainWindow() window.resize(600, 500) # Create the ThreeDSliceWidget and add it to the window widget = ThreeDSliceWidget() window.setCentralWidget(widget) # Show the window and run the app window.show() app.exec_() |
This should create a window with a
ThreeDSliceWidget
- but there is no data
present inside the widget yet.
Step 2: Adding a Load button¶
In order to add a button, we need to change the structure of our application
a little bit.
Since we need to be able to let Qt know where our different GUI elements
should appear, we are going to work with a QGridLayout
.
We then add a QPushButton
and the
ThreeDSliceWidget
from before to the layout.
In the following code snippets, all new lines are preceded by a comment #
NEW
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | # Import libraries from pyqtgraph.Qt import QtGui from data_slicer.widgets import ThreeDSliceWidget # Create a Qt Window and set its size app = QtGui.QApplication([]) window = QtGui.QMainWindow() window.resize(600, 500) # NEW: Create a "dummy-widget" that just contains the layout layout_widget = QtGui.QWidget() window.setCentralWidget(layout_widget) # NEW: Create the layout and link it to the central widget layout = QtGui.QGridLayout() layout_widget.setLayout(layout) # NEW: Create a QPushButton load_button = QtGui.QPushButton() load_button.setText('Load') # Create the ThreeDSliceWidget and add it to the window widget = ThreeDSliceWidget() # NEW: This is no longer the central widget - thus the following line has to # be removed #window.setCentralWidget(widget) # NEW: Add the widgets to the layout. The syntax for a QGridLayout is # addWidget(widget_to_add, row, column, rowspan, columnspan) layout.addWidget(load_button, 0, 0, 1, 1) layout.addWidget(widget, 1, 0, 1, 1) # Show the window and run the app window.show() app.exec_() |
We now have a button above the ThreeDSliceWidget
!
However, clicking the button does not do anything yet… Let’s change that in
the next step.
Step 3: Making the button do something¶
We can define what happens when the button is clicked by connecting a function to it:
load_button.clicked.connect(my_function)
For my_function
we could put any python
callable, for example:
def my_function() :
print('Button clicked!;)
Try defining my_function
like this before connecting it to the button
and running the example again.
You should now get the message Button clicked!
on the console whenever
you click the button.
This is not yet what we want though.
We would like the click on the Load button to open a file selection
dialog from which we can navigate to a data file, select it and that is then
going to be loaded into the ThreeDSliceWidget
.
This can be achieved with the following function:
def load_data() :
# Open the file selection dialog and store the selected file as *fname*
fname = QtGui.QFileDialog.getOpenFileName(layout_widget, 'Select file')
print(fname[0])
# Load the selected data into the ThreeDSliceWidget
D = dataloading.load_data(fname[0])
widget.set_data(D.data)
Don’t forget to from data_slicer import dataloading
at the start of the
file and to connect this function to our Load button.
The full example code at this stage should look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | # Import libraries from pyqtgraph.Qt import QtGui from data_slicer import dataloading from data_slicer.widgets import ThreeDSliceWidget # Create a Qt Window and set its size app = QtGui.QApplication([]) window = QtGui.QMainWindow() window.resize(600, 500) # Create a "dummy-widget" that just contains the layout layout_widget = QtGui.QWidget() window.setCentralWidget(layout_widget) # Create the layout and link it to the central widget layout = QtGui.QGridLayout() layout_widget.setLayout(layout) # Create a QPushButton load_button = QtGui.QPushButton() load_button.setText('Load') # Create the ThreeDSliceWidget and add it to the window widget = ThreeDSliceWidget() # Add the widgets to the layout. The syntax for a QGridLayout is # addWidget(widget_to_add, row, column, rowspan, columnspan) layout.addWidget(load_button, 0, 0, 1, 1) layout.addWidget(widget, 1, 0, 1, 1) # Define the function that is executed whenever the button is clicked def load_data() : """ Open a Filedialog and use the file selected by the user to load some data into the ThreeDSliceWidget. """ # Open the file selection dialog and store the selected file as *fname* fname = QtGui.QFileDialog.getOpenFileName(layout_widget, 'Select file') print(fname[0]) # Load the selected data into the ThreeDSliceWidget D = dataloading.load_data(fname[0]) widget.set_data(D.data) load_button.clicked.connect(load_data) # Show the window and run the app window.show() app.exec_() |
Conclusion¶
While we have seen how to use the provided widgets in other contexts to
create new applications, it is obvious that a lot could be improved and
tinkered with in our little example.
One could include some ColorSliders
and link
them up to the ThreeDSliceWidget
s colormap to
adjust the colors.
Or one could implement a different way of loading the data that is not
limited to the formats supported by data_slicer.dataloading
, add
error handling when specifying unsupported formats, add more widgets that
show the data from different viewpoints, and so much more (don’t even get me
started on brushing up the layout and look and feel).
For further inspiration it is recommended to check out the source coudes of
the tests, located under the tests
directory in your data_slicer
installation or on the github.
Additionally, a lot can be achieved when combining functionalities from
pyqtgraph.
Check out the rich set of examples they provide by:
python -m pyqtgraph.examples