I am currently working on creating a Qt window with 3 matplotlib colormaps.
The process is something like this:
- The user will input the x and y values of the plots into a GUI (each plot will have the same x and y values).
- These values will be converted and then sent to a microprocessor which will communicate with both a DAC and ADC (Instrument "stuff" happens on the "backend" between the DAC and ADC, i.e. a spectrum analyzer takes noise measurements).
- For each x and y point, we will receive one z value for each colormap. To emphasize: This means that each subplot will need to update simultaneously.
I am currently working on the script that will real-time graph these colormaps in a Qt window as the data is being taken. I can find readily accessible resources on how to real-time plot line graphs; however, I am unable to find anything for colormaps. Here is the code I have so far:
import sys
import time
import random
import numpy as np
from matplotlib.backends.qt_compat import QtWidgets
from matplotlib.backends.backend_qt5agg import (
FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
from matplotlib.figure import Figure
from matplotlib.colors import ListedColormap, LinearSegmentedColormap
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
# Quick note, this will need to be a widget class in the final version so it can be run from the kalamari main window
# but I think that will just change how the class is initalized
class ApplicationWindow(QtWidgets.QMainWindow):
def __init__(self):
# set up the window
super().__init__()
self._main = QtWidgets.QWidget()
self.setCentralWidget(self._main)
# It seems as though this layout is what is going to allow me to
# orient all 3 subplots onto the same y axis
layout = QtWidgets.QVBoxLayout(self._main)
# create seperate canvas objects
first_canvas = FigureCanvas(Figure(figsize=(9, 6)))
layout.addWidget(NavigationToolbar(first_canvas, self))
layout.addWidget(first_canvas)
second_canvas = FigureCanvas(Figure(figsize=(9, 3)))
layout.addWidget(second_canvas)
layout.addWidget(NavigationToolbar(second_canvas, self))
# add subplots to the first canvas
self._first_axs = first_canvas.figure.subplots(1, 3)
# create data and colormap
# Here I replace X and Y with coordinate vectors which are just np.linspace
x = np.linspace(0, 10, 10)
y = np.linspace(0, 10, 10)
# For the final version you can use x for flux and y for biases and then have
# each row of z be the voltages, such that:
# z[i,j] is V(bias[j], flux[i])
# Then here is the data I will use to determine the color,
# this needs to have the same dimension as the coordinates
z = np.random.rand(10, 10)
custom_cmap = mpl.colors.LinearSegmentedColormap.from_list(
"custom", ["#00008B", "blue", "cyan", "green", "yellow", "orange", "red", "#8B0000"])
# access each subplot using regular indexing
self._first_axs[0].set_title(
'I' + u'\u209B' + u'\u2092' + u'\u209C', size=40)
self._first_axs[1].set_title(
'dI' + u'\u209B' + u'\u2092' + u'\u209C' + '/dt', size=40)
self._first_axs[2].set_title('Noise', size=40)
# plot data and create colorbars
self.plot1 = self._first_axs[0].contourf(
x, y, z, levels=20, cmap=custom_cmap)
self.plot2 = self._first_axs[1].contourf(
x, y, z, levels=20, cmap=custom_cmap)
self.plot3 = self._first_axs[2].contourf(
x, y, z, levels=20, cmap=custom_cmap)
self.cbar1 = first_canvas.figure.colorbar(
self.plot1, ax=self._first_axs[0], orientation='horizontal')
self.cbar2 = first_canvas.figure.colorbar(
self.plot2, ax=self._first_axs[1], orientation='horizontal')
self.cbar3 = first_canvas.figure.colorbar(
self.plot3, ax=self._first_axs[2], orientation='horizontal')
# make the second canvas a dynamic plot
self._second_ax = second_canvas.figure.subplots()
t = list(range(50))
self.yData = [random.randint(0, 10) for i in range(50)]
# Set up a Line2D.
self._line, = self._second_ax.plot(t, self.yData)
self._timer = second_canvas.new_timer(50)
self._timer.add_callback(self._update_canvas)
self._timer.start()
def _update_canvas(self):
t = list(range(50))
self.yData = self.yData[1:] + [random.randint(0, 10)]
# set line data
self._line.set_data(t, self.yData)
self._line.figure.canvas.draw()
if __name__ == "__main__":
# Check for open QApplication.instance()
qapp = QtWidgets.QApplication.instance()
if not qapp:
qapp = QtWidgets.QApplication(sys.argv)
# run it!
app = ApplicationWindow()
app.show()
app.activateWindow()
app.raise_()
qapp.exec()
This code currently produces 1 Qt window with 2 separate "canvases". The first canvas is the 3 colormaps, the second is a line plot that real-time graphs.
Top Plots
- These are static, but I would like them to be dynamic.
- Would anybody be able to help me determine how to real-time plot these colormaps as I am collecting data?
Bottom Plot
- This runs in real-time
- I do not need the line graph for my purposes. It is just there as a reference to real-time plotting methods.