cant update matplotlib canvas with new data
-
i want to plot a graph when an image is clicked, so i have to get the coordinate of the clicked image, but when i try to update the graph, nothing happens, i have tried alot of things no success. here is my code
import numpy as np from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton, QAction, QMenu, QFileDialog, QVBoxLayout, \ QHBoxLayout, QSplitter, QWidget, QFrame from PyQt5.QtGui import QMouseEvent, QImage from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.figure import Figure from utils import * import matplotlib import matplotlib.pyplot as plt matplotlib.use("QtAgg") class SnapProcessor(QWidget): def __init__(self): super().__init__() self.wavelengths = None self.image_paths = '' # List to store the paths of the images self.current_image_index = 0 # Index of the currently displayed image self.images_list = [] # List toF store the images self.current_image = None self.cube = None self.initUI() def initUI(self): # Create a QPushButton for previous image self.prev_button = QPushButton("Previous", self) self.prev_button.clicked.connect(self.show_previous_image) # Connect the button to the slot # Create a QLabel to display the image self.image_canvas = SnapCanvas(self) # Create a QPushButton for next image self.next_button = QPushButton("Next", self) self.next_button.clicked.connect(self.show_next_image) # Connect the button to the slot # Create a QHBoxLayout for the buttons button_layout = QHBoxLayout() button_layout.addWidget(self.prev_button) button_layout.addWidget(self.next_button) # Create a QVBoxLayout for the main layout main_layout = QVBoxLayout() main_layout.addLayout(button_layout) main_layout.addWidget(self.image_canvas) # Set the main layout for the widget self.setLayout(main_layout) # Update the UI self.update_ui() def open_file(self): file_paths, _ = QFileDialog.getOpenFileNames(self, "Open Files") # Open file picker dialog if file_paths: self.image_paths = file_paths # Save the selected image paths self.current_image_index = 0 # Reset the current image index self.images_list = self.si_processing() self.update_ui() def si_processing(self): print('si_processing', self.image_paths) snap = create_snapshot(self.image_paths[0]) print('snap', snap) cube = generate_cube(snap) self.cube = cube self.wavelengths = calculate_wavelength(cube) return get_cube_images(snap) def clear_image(self): self.image_paths = [] # Clear the image paths list self.current_image_index = 0 # Reset the current image index self.wavelengths = None self.images_list = [] self.current_image = None self.update_ui() def show_previous_image(self): if self.current_image_index > 0: self.current_image_index -= 1 else: self.current_image_index = len(self.images_list) - 1 self.update_ui() def show_next_image(self): if self.current_image_index < len(self.images_list) - 1: self.current_image_index += 1 else: self.current_image_index = 0 self.update_ui() def update_ui(self): print('update_ui') if len(self.images_list) > 0: self.image_canvas.set_image(self.images_list[self.current_image_index]) self.current_image = self.images_list[self.current_image_index] print('current image', self.current_image) else: self.image_canvas.clear_image() def image_label_clicked(self, event: QMouseEvent): # Get the x and y coordinates of the click event x = event.x() y = event.y() print(f"Clicked on image at ({x}, {y})") def get_variables(self): self.snapinstance = SnapCanvas(self) class SnapCanvas(FigureCanvas): def __init__(self, sp): self.fig = Figure(figsize=(5, 4), dpi=100) super().__init__(self.fig) self.ax = self.fig.add_subplot(111) self.ax.axis('off') self.image = None self.sp = sp self.fig.canvas.mpl_connect('button_press_event', self.on_canvas_click) def set_image(self, image): self.image = image self.ax.imshow(image) self.draw() def clear_image(self): self.image = None self.ax.clear() self.draw() def on_canvas_click(self, event): if event.inaxes: x = int(event.xdata) y = int(event.ydata) print(f"Clicked on image at ({x}, {y})") plot_canvas = PlotCanvas() snap_processor = SnapProcessor() print('wave', self.sp.wavelengths) print('current image', self.sp.current_image) plot_canvas.plot_graph(self.sp.wavelengths, self.sp.cube.data[y, x]) class PlotCanvas(FigureCanvas): def __init__(self, parent=None): self.fig = Figure(figsize=(5, 1), dpi=100) super().__init__(self.fig) self.ax = self.fig.add_subplot(111) self.line, = self.ax.plot([], []) # Initialize with empty line def plot_graph(self, wavelength, other): self.line.set_data(wavelength, other) # Update line data self.ax.relim() # Adjust the limits of the axes self.ax.autoscale_view(True, True, True) # Autoscale the axes self.fig.canvas.draw() class UI(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("ToolKit") # Set the window title self.initUI() def initUI(self): self.setGeometry(0, 300, 1100, 800) menubar = self.menuBar() file_menu = menubar.addMenu("Options") help_menu = menubar.addMenu("Help") open_action = QAction("Load Snap", self) open_action.triggered.connect(self.open_file) save_action = QAction("Save", self) clear_action = QAction("Clear", self) clear_action.triggered.connect(self.clear_image) exit_action = QAction("Exit", self) exit_action.triggered.connect(self.close) file_menu.addAction(open_action) file_menu.addAction(save_action) file_menu.addAction(clear_action) file_menu.addSeparator() file_menu.addAction(exit_action) about_action = QAction("About", self) help_menu.addAction(about_action) self.snap_slider = SnapProcessor() self.setCentralWidget(self.snap_slider) self.plot_canvas = PlotCanvas() self.snap_slider.layout().addWidget(self.plot_canvas) def open_file(self): self.snap_slider.open_file() def clear_image(self): self.snap_slider.clear_image()
when the image is clicked nothing changes on the matplotlb canvas
-
S SGaist moved this topic from General and Desktop on
-
Hi,
Please reduce the code to the minimal amount required to reproduce your issue.
-
i want to plot a graph when an image is clicked, so i have to get the coordinate of the clicked image, but when i try to update the graph, nothing happens, i have tried alot of things no success. here is my code
import numpy as np from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton, QAction, QMenu, QFileDialog, QVBoxLayout, \ QHBoxLayout, QSplitter, QWidget, QFrame from PyQt5.QtGui import QMouseEvent, QImage from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.figure import Figure from utils import * import matplotlib import matplotlib.pyplot as plt matplotlib.use("QtAgg") class SnapProcessor(QWidget): def __init__(self): super().__init__() self.wavelengths = None self.image_paths = '' # List to store the paths of the images self.current_image_index = 0 # Index of the currently displayed image self.images_list = [] # List toF store the images self.current_image = None self.cube = None self.initUI() def initUI(self): # Create a QPushButton for previous image self.prev_button = QPushButton("Previous", self) self.prev_button.clicked.connect(self.show_previous_image) # Connect the button to the slot # Create a QLabel to display the image self.image_canvas = SnapCanvas(self) # Create a QPushButton for next image self.next_button = QPushButton("Next", self) self.next_button.clicked.connect(self.show_next_image) # Connect the button to the slot # Create a QHBoxLayout for the buttons button_layout = QHBoxLayout() button_layout.addWidget(self.prev_button) button_layout.addWidget(self.next_button) # Create a QVBoxLayout for the main layout main_layout = QVBoxLayout() main_layout.addLayout(button_layout) main_layout.addWidget(self.image_canvas) # Set the main layout for the widget self.setLayout(main_layout) # Update the UI self.update_ui() def open_file(self): file_paths, _ = QFileDialog.getOpenFileNames(self, "Open Files") # Open file picker dialog if file_paths: self.image_paths = file_paths # Save the selected image paths self.current_image_index = 0 # Reset the current image index self.images_list = self.si_processing() self.update_ui() def si_processing(self): print('si_processing', self.image_paths) snap = create_snapshot(self.image_paths[0]) print('snap', snap) cube = generate_cube(snap) self.cube = cube self.wavelengths = calculate_wavelength(cube) return get_cube_images(snap) def clear_image(self): self.image_paths = [] # Clear the image paths list self.current_image_index = 0 # Reset the current image index self.wavelengths = None self.images_list = [] self.current_image = None self.update_ui() def show_previous_image(self): if self.current_image_index > 0: self.current_image_index -= 1 else: self.current_image_index = len(self.images_list) - 1 self.update_ui() def show_next_image(self): if self.current_image_index < len(self.images_list) - 1: self.current_image_index += 1 else: self.current_image_index = 0 self.update_ui() def update_ui(self): print('update_ui') if len(self.images_list) > 0: self.image_canvas.set_image(self.images_list[self.current_image_index]) self.current_image = self.images_list[self.current_image_index] print('current image', self.current_image) else: self.image_canvas.clear_image() def image_label_clicked(self, event: QMouseEvent): # Get the x and y coordinates of the click event x = event.x() y = event.y() print(f"Clicked on image at ({x}, {y})") def get_variables(self): self.snapinstance = SnapCanvas(self) class SnapCanvas(FigureCanvas): def __init__(self, sp): self.fig = Figure(figsize=(5, 4), dpi=100) super().__init__(self.fig) self.ax = self.fig.add_subplot(111) self.ax.axis('off') self.image = None self.sp = sp self.fig.canvas.mpl_connect('button_press_event', self.on_canvas_click) def set_image(self, image): self.image = image self.ax.imshow(image) self.draw() def clear_image(self): self.image = None self.ax.clear() self.draw() def on_canvas_click(self, event): if event.inaxes: x = int(event.xdata) y = int(event.ydata) print(f"Clicked on image at ({x}, {y})") plot_canvas = PlotCanvas() snap_processor = SnapProcessor() print('wave', self.sp.wavelengths) print('current image', self.sp.current_image) plot_canvas.plot_graph(self.sp.wavelengths, self.sp.cube.data[y, x]) class PlotCanvas(FigureCanvas): def __init__(self, parent=None): self.fig = Figure(figsize=(5, 1), dpi=100) super().__init__(self.fig) self.ax = self.fig.add_subplot(111) self.line, = self.ax.plot([], []) # Initialize with empty line def plot_graph(self, wavelength, other): self.line.set_data(wavelength, other) # Update line data self.ax.relim() # Adjust the limits of the axes self.ax.autoscale_view(True, True, True) # Autoscale the axes self.fig.canvas.draw() class UI(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("ToolKit") # Set the window title self.initUI() def initUI(self): self.setGeometry(0, 300, 1100, 800) menubar = self.menuBar() file_menu = menubar.addMenu("Options") help_menu = menubar.addMenu("Help") open_action = QAction("Load Snap", self) open_action.triggered.connect(self.open_file) save_action = QAction("Save", self) clear_action = QAction("Clear", self) clear_action.triggered.connect(self.clear_image) exit_action = QAction("Exit", self) exit_action.triggered.connect(self.close) file_menu.addAction(open_action) file_menu.addAction(save_action) file_menu.addAction(clear_action) file_menu.addSeparator() file_menu.addAction(exit_action) about_action = QAction("About", self) help_menu.addAction(about_action) self.snap_slider = SnapProcessor() self.setCentralWidget(self.snap_slider) self.plot_canvas = PlotCanvas() self.snap_slider.layout().addWidget(self.plot_canvas) def open_file(self): self.snap_slider.open_file() def clear_image(self): self.snap_slider.clear_image()
when the image is clicked nothing changes on the matplotlb canvas
@Allaye not sure if it helps, but maybe you can check other examples, like https://doc.qt.io/qtforpython-6/examples/example_external_matplotlib_widget3d.html to get an idea of the missing connection to update the data.