Module Widefield-Imaging-Acquisition.gui.scout
Expand source code
import sys
import time
import os
import matplotlib.pyplot as plt
from PyQt5.QtCore import Qt, QLocale
import numpy as np
from PyQt5.QtWidgets import (
QVBoxLayout,
QWidget,
QGridLayout,
QLabel,
QHBoxLayout,
QLineEdit,
QCheckBox,
QPushButton,
QStackedLayout,
QComboBox,
QMessageBox,
QFileDialog,
QApplication,
QSlider,
)
from PyQt5.QtGui import QIntValidator, QDoubleValidator, QFont, QIcon, QBrush, QColor
from matplotlib.widgets import RectangleSelector
from threading import Thread
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
from src.controls import DAQ, Instrument, Camera
from src.blocks import Experiment
from src.tree import Tree
from src.plot import PlotWindow
from src.calculations import (
get_dictionary,
shrink_array,
frames_acquired_from_camera_signal,
get_baseline_frame_indices,
average_baseline,
get_timecourse,
separate_images,
)
class App(QWidget):
def __init__(self):
"""Initialize the application"""
super().__init__()
self.cwd = os.path.dirname(os.path.dirname(__file__))
self.roi_extent = None
self.image_index = 0
self.previous_index = 0
self.files_to_read = True
self.live_preview_light_index = 0
self.initUI()
def closeEvent(self, *args, **kwargs):
"""Stop all processes when closing the application"""
self.files_to_read = False
def initUI(self):
"""Initialize the user interface"""
self.setWindowTitle("Brain Scout")
self.setGeometry(10, 10, 640, 480)
self.grid_layout = QGridLayout()
self.grid_layout.setAlignment(Qt.AlignLeft)
self.grid_layout.setAlignment(Qt.AlignTop)
# self.grid_layout.setContentsMargins(0, 0, 0, 0)
self.setLayout(self.grid_layout)
self.settings_window = QVBoxLayout()
self.settings_window.setAlignment(Qt.AlignLeft)
self.settings_window.setAlignment(Qt.AlignTop)
self.grid_layout.addLayout(self.settings_window, 0, 0)
self.settings_window2 = QVBoxLayout()
self.settings_window2.setAlignment(Qt.AlignLeft)
self.settings_window2.setAlignment(Qt.AlignTop)
self.grid_layout.addLayout(self.settings_window2, 0, 1)
# ----
self.directory_window = QHBoxLayout()
self.directory_window.setAlignment(Qt.AlignLeft)
self.directory_window.setAlignment(Qt.AlignTop)
self.choose_directory_button = QPushButton("Select Directory")
self.choose_directory_button.setIcon(
QIcon(os.path.join(self.cwd, "gui", "icons", "folder-plus.png"))
)
self.choose_directory_button.clicked.connect(self.choose_directory)
self.directory_window.addWidget(self.choose_directory_button)
self.directory_cell = QLineEdit("")
self.directory_cell.setReadOnly(True)
self.directory_window.addWidget(self.directory_cell)
self.settings_window.addLayout(self.directory_window)
# ----
self.light_channel_layout = QHBoxLayout()
self.preview_light_label = QLabel("Light Channel Preview")
self.light_channel_layout.addWidget(self.preview_light_label)
self.preview_light_combo = QComboBox()
self.preview_light_combo.setEnabled(False)
self.preview_light_combo.currentIndexChanged.connect(
self.change_preview_light_channel
)
self.light_channel_layout.addWidget(self.preview_light_combo)
self.settings_window.addLayout(self.light_channel_layout)
# self.import_window = QHBoxLayout()
# self.import_progress = QLabel("0% Imported")
# self.import_window.addWidget(self.import_progress)
# self.settings_window.addLayout(self.import_window)
# --
# -------------
self.index_window = QVBoxLayout()
self.current_index_window = QHBoxLayout()
self.current_index_label = QLabel("Current Index:")
self.current_index_window.addWidget(self.current_index_label)
self.current_index = QLineEdit("0")
self.current_index.textChanged.connect(self.adjust_index)
self.current_index_window.addWidget(self.current_index)
self.index_window.addLayout(self.current_index_window)
self.start_index_window = QHBoxLayout()
self.start_index_label = QLabel("Start Index:")
self.start_index_window.addWidget(self.start_index_label)
self.start_index = QLineEdit("0")
self.start_index_window.addWidget(self.start_index)
self.index_window.addLayout(self.start_index_window)
self.end_index_window = QHBoxLayout()
self.end_index_label = QLabel("End Index:")
self.end_index_window.addWidget(self.end_index_label)
self.end_index = QLineEdit("0")
self.end_index_window.addWidget(self.end_index)
self.index_window.addLayout(self.end_index_window)
self.settings_window2.addLayout(self.index_window)
# self.settings_window.addStretch()
self.make_time_course_button = QPushButton("Generate Time Course")
self.make_time_course_button.setIcon(
QIcon(os.path.join(self.cwd, "gui", "icons", "chart-line.png"))
)
self.make_time_course_button.clicked.connect(self.make_time_course)
self.make_time_course_layout = QHBoxLayout()
self.make_time_course_layout.setAlignment(Qt.AlignLeft)
self.make_time_course_layout.setAlignment(Qt.AlignTop)
self.make_time_course_layout.addWidget(self.make_time_course_button)
self.make_time_course_container = QWidget()
self.make_time_course_container.setLayout(self.make_time_course_layout)
self.grid_layout.addWidget(self.make_time_course_container, 2, 1)
# -------
self.slider_layout = QHBoxLayout()
self.slider_layout.setAlignment(Qt.AlignLeft)
self.slider_layout.setAlignment(Qt.AlignTop)
# self.slider_layout.setContentsMargins(0, 0, 0, 0)
self.slider_layout.addWidget(QLabel("Start"))
self.time_slider = QSlider(Qt.Horizontal, self)
self.time_slider.setRange(0, 0)
self.time_slider.setValue(0)
self.time_slider.valueChanged.connect(self.adjust_time)
self.slider_layout.addWidget(self.time_slider)
self.slider_layout.addWidget(QLabel("End"))
self.settings_window.addLayout(self.slider_layout)
# -------------
# self.graphics_layout =QHBoxLayout()
# self.graphics_layout.addWidget(self.image_view)
self.time_course = PlotWindow(subplots=False)
self.time_course.plot([1, 2, 3], [1, 2, 3], root=False)
self.grid_layout.addWidget(self.time_course, 1, 1)
# self.grid_layout.addLayout(self.graphics_layout, 1, 0)
# -------------
self.show()
def initialize_roi(self):
self.roi_buttons = QStackedLayout()
self.roi_buttons.setAlignment(Qt.AlignLeft)
self.roi_buttons.setAlignment(Qt.AlignTop)
# self.roi_buttons.setContentsMargins(0, 0, 0, 0)
self.roi_layout1 = QHBoxLayout()
self.roi_layout1.setAlignment(Qt.AlignLeft)
self.roi_layout1.setAlignment(Qt.AlignTop)
# self.roi_layout1.setContentsMargins(0, 0, 0, 0)
self.reset_roi_button = QPushButton("Reset ROI")
self.reset_roi_button.setIcon(
QIcon(os.path.join(self.cwd, "gui", "icons", "zoom-out-area.png"))
)
self.reset_roi_button.setEnabled(False)
self.reset_roi_button.clicked.connect(self.reset_roi)
self.roi_layout1.addWidget(self.reset_roi_button)
self.set_roi_button = QPushButton("Set ROI")
self.set_roi_button.setIcon(
QIcon(os.path.join(self.cwd, "gui", "icons", "zoom-in-area.png"))
)
self.set_roi_button.clicked.connect(self.set_roi)
self.roi_layout1.addWidget(self.set_roi_button)
self.roi_layout1_container = QWidget()
self.roi_layout1_container.setLayout(self.roi_layout1)
self.roi_layout2 = QHBoxLayout()
self.roi_layout2.setAlignment(Qt.AlignLeft)
self.roi_layout2.setAlignment(Qt.AlignTop)
# self.roi_layout2.setContentsMargins(0, 0, 0, 0)
self.cancel_roi_button = QPushButton("Cancel")
self.cancel_roi_button.setIcon(
QIcon(os.path.join(self.cwd, "gui", "icons", "zoom-cancel.png"))
)
self.cancel_roi_button.clicked.connect(self.cancel_roi)
self.roi_layout2.addWidget(self.cancel_roi_button)
self.save_roi_button = QPushButton("Save ROI")
self.save_roi_button.setIcon(
QIcon(os.path.join(self.cwd, "gui", "icons", "zoom-check.png"))
)
self.save_roi_button.clicked.connect(self.save_roi)
self.roi_layout2.addWidget(self.save_roi_button)
self.roi_layout2_container = QWidget()
self.roi_layout2_container.setLayout(self.roi_layout2)
self.roi_buttons.addWidget(self.roi_layout1_container)
self.roi_buttons.addWidget(self.roi_layout2_container)
self.grid_layout.addLayout(self.roi_buttons, 2, 0)
def change_preview_light_channel(self):
"""Change the light channel for the live preview"""
self.live_preview_light_index = self.preview_light_combo.currentIndex()
self.adjust_time()
def actualize_lights(self):
"""Update the lights list in the combo box"""
self.preview_light_combo.clear()
if len(self.dictionary["Lights"]) == 0:
self.preview_light_combo.setEnabled(False)
else:
self.preview_light_combo.setEnabled(True)
for light in self.dictionary["Lights"]:
self.preview_light_combo.addItem(light)
self.preview_light_combo.setCurrentIndex(0)
def choose_directory(self):
"""Choose the directory where to save the files"""
self.directory = str(QFileDialog.getExistingDirectory(self, "Select Directory"))
self.directory_cell.setText(self.directory)
self.frames = []
potential_dic = os.listdir(self.directory)
for file in potential_dic:
if ".json" in file:
self.dictionary = get_dictionary(os.path.join(self.directory, file))
self.dimensions = self.dictionary["Dimensions"]
self.initialize_plot()
self.initialize_roi()
self.open_import_thread()
def initialize_plot(self):
try:
self.image_view
except Exception:
self.image_view = PlotWindow()
self.grid_layout.addWidget(self.image_view, 1, 0)
self.plot_image = plt.imshow(
np.zeros((self.dimensions[1], self.dimensions[0])),
cmap="binary_r",
vmin=0,
vmax=4096,
origin="lower",
)
self.plot_image.axes.get_xaxis().set_visible(False)
self.plot_image.axes.axes.get_yaxis().set_visible(False)
def open_import_thread(self):
"""Open the thread that will import the frames"""
self.import_thread = Thread(target=self.import_frames)
self.import_thread.start()
def import_frames(self):
try:
self.frames = []
self.time_slider.setEnabled(False)
potential_data = os.listdir(os.path.join(self.directory, "data"))
for file in potential_data:
if ".npy" in file:
self.concatenate_frames(file)
self.frame_number = self.frames.shape[0]
self.split_frames = separate_images(self.dictionary["Lights"], self.frames)
self.end_index.setText(f"{self.frame_number-1}")
self.time_slider.setRange(0, self.frame_number - 1)
self.time_slider.setEnabled(True)
self.actualize_lights()
except Exception as err:
print(err)
pass
def concatenate_frames(self, file):
"""Concatenate the frames in the directory"""
if len(self.frames) == 0:
self.frames = np.load(os.path.join(self.directory, "data", file))
else:
self.frames = np.concatenate(
(self.frames, np.load(os.path.join(self.directory, "data", file)))
)
def set_roi(self):
"""Set the ROI"""
self.roi_buttons.setCurrentIndex(1)
self.cancel_roi_button.setEnabled(True)
self.save_roi_button.setEnabled(False)
def onselect_function(eclick, erelease):
"""Save the ROI dimensions as attributes"""
self.roi_extent = self.rect_selector.extents
self.save_roi_button.setEnabled(True)
self.rect_selector = RectangleSelector(
self.plot_image.axes,
onselect_function,
drawtype="box",
useblit=True,
button=[1, 3],
minspanx=5,
minspany=5,
spancoords="pixels",
interactive=True,
)
def reset_roi(self):
"""Reset the ROI"""
plt.figure(self.image_view.figure.number)
plt.ion()
plt.xlim(0, self.dimensions[0])
plt.ylim(0, self.dimensions[1])
self.roi_extent = None
self.reset_roi_button.setEnabled(False)
self.set_roi_button.setEnabled(True)
self.reset_roi_button.setEnabled(False)
def cancel_roi(self):
"""Cancel the ROI selection"""
# self.activate_buttons(buttons=self.enabled_buttons)
self.roi_buttons.setCurrentIndex(0)
self.rect_selector.clear()
self.rect_selector = None
def save_roi(self):
"""Save the ROI"""
# self.activate_buttons(buttons=self.enabled_buttons)
self.roi_buttons.setCurrentIndex(0)
plt.figure(self.image_view.figure.number)
plt.ion()
plt.xlim(self.roi_extent[0], self.roi_extent[1])
plt.ylim(self.roi_extent[2], self.roi_extent[3])
self.rect_selector.clear()
self.rect_selector = None
self.reset_roi_button.setEnabled(True)
self.set_roi_button.setEnabled(True)
def adjust_index(self):
"""Adjust the index"""
try:
self.time_slider.setValue(int(self.current_index.text()))
except Exception:
pass
def adjust_time(self):
plt.ion()
try:
self.image_index = self.time_slider.value()
self.current_index.setText(str(self.image_index))
self.open_live_preview_thread()
except Exception as err:
print(err)
pass
def open_live_preview_thread(self):
"""Open the thread that will show the live preview"""
self.live_preview_thread = Thread(target=self.live_preview)
self.live_preview_thread.start()
def live_preview(self):
self.plot_image.set(
array=self.split_frames[self.live_preview_light_index][
self.image_index // len(self.dictionary["Lights"])
]
)
def make_time_course(self):
try:
if self.roi_extent:
print(
shrink_array(
self.split_frames[self.live_preview_light_index],
self.roi_extent,
)
)
y_values = get_timecourse(
shrink_array(
self.split_frames[self.live_preview_light_index],
self.roi_extent,
),
int(self.start_index.text()) // len(self.dictionary["Lights"]),
int(self.end_index.text()) // len(self.dictionary["Lights"]),
)
else:
y_values = get_timecourse(
self.split_frames[self.live_preview_light_index],
int(self.start_index.text()) // len(self.dictionary["Lights"]),
int(self.end_index.text()) // len(self.dictionary["Lights"]),
)
plt.figure(self.time_course.figure.number)
plt.ion()
plt.clf()
plt.plot(y_values)
except Exception as err:
print(err)
pass
def activate_buttons(self, buttons):
"""Activate the buttons in a list"""
for button in buttons:
button.setEnabled(True)
def deactivate_buttons(self, buttons):
"""Deactivate the buttons in a list"""
for button in buttons:
button.setDisabled(True)
if __name__ == "__main__":
app = QApplication(sys.argv)
font = QFont()
font.setFamily("IBM Plex Sans")
app.setFont(font)
ex = App()
sys.exit(app.exec_())
Classes
class App-
QWidget(parent: QWidget = None, flags: Union[Qt.WindowFlags, Qt.WindowType] = Qt.WindowFlags())
Initialize the application
Expand source code
class App(QWidget): def __init__(self): """Initialize the application""" super().__init__() self.cwd = os.path.dirname(os.path.dirname(__file__)) self.roi_extent = None self.image_index = 0 self.previous_index = 0 self.files_to_read = True self.live_preview_light_index = 0 self.initUI() def closeEvent(self, *args, **kwargs): """Stop all processes when closing the application""" self.files_to_read = False def initUI(self): """Initialize the user interface""" self.setWindowTitle("Brain Scout") self.setGeometry(10, 10, 640, 480) self.grid_layout = QGridLayout() self.grid_layout.setAlignment(Qt.AlignLeft) self.grid_layout.setAlignment(Qt.AlignTop) # self.grid_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(self.grid_layout) self.settings_window = QVBoxLayout() self.settings_window.setAlignment(Qt.AlignLeft) self.settings_window.setAlignment(Qt.AlignTop) self.grid_layout.addLayout(self.settings_window, 0, 0) self.settings_window2 = QVBoxLayout() self.settings_window2.setAlignment(Qt.AlignLeft) self.settings_window2.setAlignment(Qt.AlignTop) self.grid_layout.addLayout(self.settings_window2, 0, 1) # ---- self.directory_window = QHBoxLayout() self.directory_window.setAlignment(Qt.AlignLeft) self.directory_window.setAlignment(Qt.AlignTop) self.choose_directory_button = QPushButton("Select Directory") self.choose_directory_button.setIcon( QIcon(os.path.join(self.cwd, "gui", "icons", "folder-plus.png")) ) self.choose_directory_button.clicked.connect(self.choose_directory) self.directory_window.addWidget(self.choose_directory_button) self.directory_cell = QLineEdit("") self.directory_cell.setReadOnly(True) self.directory_window.addWidget(self.directory_cell) self.settings_window.addLayout(self.directory_window) # ---- self.light_channel_layout = QHBoxLayout() self.preview_light_label = QLabel("Light Channel Preview") self.light_channel_layout.addWidget(self.preview_light_label) self.preview_light_combo = QComboBox() self.preview_light_combo.setEnabled(False) self.preview_light_combo.currentIndexChanged.connect( self.change_preview_light_channel ) self.light_channel_layout.addWidget(self.preview_light_combo) self.settings_window.addLayout(self.light_channel_layout) # self.import_window = QHBoxLayout() # self.import_progress = QLabel("0% Imported") # self.import_window.addWidget(self.import_progress) # self.settings_window.addLayout(self.import_window) # -- # ------------- self.index_window = QVBoxLayout() self.current_index_window = QHBoxLayout() self.current_index_label = QLabel("Current Index:") self.current_index_window.addWidget(self.current_index_label) self.current_index = QLineEdit("0") self.current_index.textChanged.connect(self.adjust_index) self.current_index_window.addWidget(self.current_index) self.index_window.addLayout(self.current_index_window) self.start_index_window = QHBoxLayout() self.start_index_label = QLabel("Start Index:") self.start_index_window.addWidget(self.start_index_label) self.start_index = QLineEdit("0") self.start_index_window.addWidget(self.start_index) self.index_window.addLayout(self.start_index_window) self.end_index_window = QHBoxLayout() self.end_index_label = QLabel("End Index:") self.end_index_window.addWidget(self.end_index_label) self.end_index = QLineEdit("0") self.end_index_window.addWidget(self.end_index) self.index_window.addLayout(self.end_index_window) self.settings_window2.addLayout(self.index_window) # self.settings_window.addStretch() self.make_time_course_button = QPushButton("Generate Time Course") self.make_time_course_button.setIcon( QIcon(os.path.join(self.cwd, "gui", "icons", "chart-line.png")) ) self.make_time_course_button.clicked.connect(self.make_time_course) self.make_time_course_layout = QHBoxLayout() self.make_time_course_layout.setAlignment(Qt.AlignLeft) self.make_time_course_layout.setAlignment(Qt.AlignTop) self.make_time_course_layout.addWidget(self.make_time_course_button) self.make_time_course_container = QWidget() self.make_time_course_container.setLayout(self.make_time_course_layout) self.grid_layout.addWidget(self.make_time_course_container, 2, 1) # ------- self.slider_layout = QHBoxLayout() self.slider_layout.setAlignment(Qt.AlignLeft) self.slider_layout.setAlignment(Qt.AlignTop) # self.slider_layout.setContentsMargins(0, 0, 0, 0) self.slider_layout.addWidget(QLabel("Start")) self.time_slider = QSlider(Qt.Horizontal, self) self.time_slider.setRange(0, 0) self.time_slider.setValue(0) self.time_slider.valueChanged.connect(self.adjust_time) self.slider_layout.addWidget(self.time_slider) self.slider_layout.addWidget(QLabel("End")) self.settings_window.addLayout(self.slider_layout) # ------------- # self.graphics_layout =QHBoxLayout() # self.graphics_layout.addWidget(self.image_view) self.time_course = PlotWindow(subplots=False) self.time_course.plot([1, 2, 3], [1, 2, 3], root=False) self.grid_layout.addWidget(self.time_course, 1, 1) # self.grid_layout.addLayout(self.graphics_layout, 1, 0) # ------------- self.show() def initialize_roi(self): self.roi_buttons = QStackedLayout() self.roi_buttons.setAlignment(Qt.AlignLeft) self.roi_buttons.setAlignment(Qt.AlignTop) # self.roi_buttons.setContentsMargins(0, 0, 0, 0) self.roi_layout1 = QHBoxLayout() self.roi_layout1.setAlignment(Qt.AlignLeft) self.roi_layout1.setAlignment(Qt.AlignTop) # self.roi_layout1.setContentsMargins(0, 0, 0, 0) self.reset_roi_button = QPushButton("Reset ROI") self.reset_roi_button.setIcon( QIcon(os.path.join(self.cwd, "gui", "icons", "zoom-out-area.png")) ) self.reset_roi_button.setEnabled(False) self.reset_roi_button.clicked.connect(self.reset_roi) self.roi_layout1.addWidget(self.reset_roi_button) self.set_roi_button = QPushButton("Set ROI") self.set_roi_button.setIcon( QIcon(os.path.join(self.cwd, "gui", "icons", "zoom-in-area.png")) ) self.set_roi_button.clicked.connect(self.set_roi) self.roi_layout1.addWidget(self.set_roi_button) self.roi_layout1_container = QWidget() self.roi_layout1_container.setLayout(self.roi_layout1) self.roi_layout2 = QHBoxLayout() self.roi_layout2.setAlignment(Qt.AlignLeft) self.roi_layout2.setAlignment(Qt.AlignTop) # self.roi_layout2.setContentsMargins(0, 0, 0, 0) self.cancel_roi_button = QPushButton("Cancel") self.cancel_roi_button.setIcon( QIcon(os.path.join(self.cwd, "gui", "icons", "zoom-cancel.png")) ) self.cancel_roi_button.clicked.connect(self.cancel_roi) self.roi_layout2.addWidget(self.cancel_roi_button) self.save_roi_button = QPushButton("Save ROI") self.save_roi_button.setIcon( QIcon(os.path.join(self.cwd, "gui", "icons", "zoom-check.png")) ) self.save_roi_button.clicked.connect(self.save_roi) self.roi_layout2.addWidget(self.save_roi_button) self.roi_layout2_container = QWidget() self.roi_layout2_container.setLayout(self.roi_layout2) self.roi_buttons.addWidget(self.roi_layout1_container) self.roi_buttons.addWidget(self.roi_layout2_container) self.grid_layout.addLayout(self.roi_buttons, 2, 0) def change_preview_light_channel(self): """Change the light channel for the live preview""" self.live_preview_light_index = self.preview_light_combo.currentIndex() self.adjust_time() def actualize_lights(self): """Update the lights list in the combo box""" self.preview_light_combo.clear() if len(self.dictionary["Lights"]) == 0: self.preview_light_combo.setEnabled(False) else: self.preview_light_combo.setEnabled(True) for light in self.dictionary["Lights"]: self.preview_light_combo.addItem(light) self.preview_light_combo.setCurrentIndex(0) def choose_directory(self): """Choose the directory where to save the files""" self.directory = str(QFileDialog.getExistingDirectory(self, "Select Directory")) self.directory_cell.setText(self.directory) self.frames = [] potential_dic = os.listdir(self.directory) for file in potential_dic: if ".json" in file: self.dictionary = get_dictionary(os.path.join(self.directory, file)) self.dimensions = self.dictionary["Dimensions"] self.initialize_plot() self.initialize_roi() self.open_import_thread() def initialize_plot(self): try: self.image_view except Exception: self.image_view = PlotWindow() self.grid_layout.addWidget(self.image_view, 1, 0) self.plot_image = plt.imshow( np.zeros((self.dimensions[1], self.dimensions[0])), cmap="binary_r", vmin=0, vmax=4096, origin="lower", ) self.plot_image.axes.get_xaxis().set_visible(False) self.plot_image.axes.axes.get_yaxis().set_visible(False) def open_import_thread(self): """Open the thread that will import the frames""" self.import_thread = Thread(target=self.import_frames) self.import_thread.start() def import_frames(self): try: self.frames = [] self.time_slider.setEnabled(False) potential_data = os.listdir(os.path.join(self.directory, "data")) for file in potential_data: if ".npy" in file: self.concatenate_frames(file) self.frame_number = self.frames.shape[0] self.split_frames = separate_images(self.dictionary["Lights"], self.frames) self.end_index.setText(f"{self.frame_number-1}") self.time_slider.setRange(0, self.frame_number - 1) self.time_slider.setEnabled(True) self.actualize_lights() except Exception as err: print(err) pass def concatenate_frames(self, file): """Concatenate the frames in the directory""" if len(self.frames) == 0: self.frames = np.load(os.path.join(self.directory, "data", file)) else: self.frames = np.concatenate( (self.frames, np.load(os.path.join(self.directory, "data", file))) ) def set_roi(self): """Set the ROI""" self.roi_buttons.setCurrentIndex(1) self.cancel_roi_button.setEnabled(True) self.save_roi_button.setEnabled(False) def onselect_function(eclick, erelease): """Save the ROI dimensions as attributes""" self.roi_extent = self.rect_selector.extents self.save_roi_button.setEnabled(True) self.rect_selector = RectangleSelector( self.plot_image.axes, onselect_function, drawtype="box", useblit=True, button=[1, 3], minspanx=5, minspany=5, spancoords="pixels", interactive=True, ) def reset_roi(self): """Reset the ROI""" plt.figure(self.image_view.figure.number) plt.ion() plt.xlim(0, self.dimensions[0]) plt.ylim(0, self.dimensions[1]) self.roi_extent = None self.reset_roi_button.setEnabled(False) self.set_roi_button.setEnabled(True) self.reset_roi_button.setEnabled(False) def cancel_roi(self): """Cancel the ROI selection""" # self.activate_buttons(buttons=self.enabled_buttons) self.roi_buttons.setCurrentIndex(0) self.rect_selector.clear() self.rect_selector = None def save_roi(self): """Save the ROI""" # self.activate_buttons(buttons=self.enabled_buttons) self.roi_buttons.setCurrentIndex(0) plt.figure(self.image_view.figure.number) plt.ion() plt.xlim(self.roi_extent[0], self.roi_extent[1]) plt.ylim(self.roi_extent[2], self.roi_extent[3]) self.rect_selector.clear() self.rect_selector = None self.reset_roi_button.setEnabled(True) self.set_roi_button.setEnabled(True) def adjust_index(self): """Adjust the index""" try: self.time_slider.setValue(int(self.current_index.text())) except Exception: pass def adjust_time(self): plt.ion() try: self.image_index = self.time_slider.value() self.current_index.setText(str(self.image_index)) self.open_live_preview_thread() except Exception as err: print(err) pass def open_live_preview_thread(self): """Open the thread that will show the live preview""" self.live_preview_thread = Thread(target=self.live_preview) self.live_preview_thread.start() def live_preview(self): self.plot_image.set( array=self.split_frames[self.live_preview_light_index][ self.image_index // len(self.dictionary["Lights"]) ] ) def make_time_course(self): try: if self.roi_extent: print( shrink_array( self.split_frames[self.live_preview_light_index], self.roi_extent, ) ) y_values = get_timecourse( shrink_array( self.split_frames[self.live_preview_light_index], self.roi_extent, ), int(self.start_index.text()) // len(self.dictionary["Lights"]), int(self.end_index.text()) // len(self.dictionary["Lights"]), ) else: y_values = get_timecourse( self.split_frames[self.live_preview_light_index], int(self.start_index.text()) // len(self.dictionary["Lights"]), int(self.end_index.text()) // len(self.dictionary["Lights"]), ) plt.figure(self.time_course.figure.number) plt.ion() plt.clf() plt.plot(y_values) except Exception as err: print(err) pass def activate_buttons(self, buttons): """Activate the buttons in a list""" for button in buttons: button.setEnabled(True) def deactivate_buttons(self, buttons): """Deactivate the buttons in a list""" for button in buttons: button.setDisabled(True)Ancestors
- PyQt5.QtWidgets.QWidget
- PyQt5.QtCore.QObject
- sip.wrapper
- PyQt5.QtGui.QPaintDevice
- sip.simplewrapper
Methods
-
Activate the buttons in a list
Expand source code
def activate_buttons(self, buttons): """Activate the buttons in a list""" for button in buttons: button.setEnabled(True) def actualize_lights(self)-
Update the lights list in the combo box
Expand source code
def actualize_lights(self): """Update the lights list in the combo box""" self.preview_light_combo.clear() if len(self.dictionary["Lights"]) == 0: self.preview_light_combo.setEnabled(False) else: self.preview_light_combo.setEnabled(True) for light in self.dictionary["Lights"]: self.preview_light_combo.addItem(light) self.preview_light_combo.setCurrentIndex(0) def adjust_index(self)-
Adjust the index
Expand source code
def adjust_index(self): """Adjust the index""" try: self.time_slider.setValue(int(self.current_index.text())) except Exception: pass def adjust_time(self)-
Expand source code
def adjust_time(self): plt.ion() try: self.image_index = self.time_slider.value() self.current_index.setText(str(self.image_index)) self.open_live_preview_thread() except Exception as err: print(err) pass def cancel_roi(self)-
Cancel the ROI selection
Expand source code
def cancel_roi(self): """Cancel the ROI selection""" # self.activate_buttons(buttons=self.enabled_buttons) self.roi_buttons.setCurrentIndex(0) self.rect_selector.clear() self.rect_selector = None def change_preview_light_channel(self)-
Change the light channel for the live preview
Expand source code
def change_preview_light_channel(self): """Change the light channel for the live preview""" self.live_preview_light_index = self.preview_light_combo.currentIndex() self.adjust_time() def choose_directory(self)-
Choose the directory where to save the files
Expand source code
def choose_directory(self): """Choose the directory where to save the files""" self.directory = str(QFileDialog.getExistingDirectory(self, "Select Directory")) self.directory_cell.setText(self.directory) self.frames = [] potential_dic = os.listdir(self.directory) for file in potential_dic: if ".json" in file: self.dictionary = get_dictionary(os.path.join(self.directory, file)) self.dimensions = self.dictionary["Dimensions"] self.initialize_plot() self.initialize_roi() self.open_import_thread() def closeEvent(self, *args, **kwargs)-
Stop all processes when closing the application
Expand source code
def closeEvent(self, *args, **kwargs): """Stop all processes when closing the application""" self.files_to_read = False def concatenate_frames(self, file)-
Concatenate the frames in the directory
Expand source code
def concatenate_frames(self, file): """Concatenate the frames in the directory""" if len(self.frames) == 0: self.frames = np.load(os.path.join(self.directory, "data", file)) else: self.frames = np.concatenate( (self.frames, np.load(os.path.join(self.directory, "data", file))) ) -
Deactivate the buttons in a list
Expand source code
def deactivate_buttons(self, buttons): """Deactivate the buttons in a list""" for button in buttons: button.setDisabled(True) def import_frames(self)-
Expand source code
def import_frames(self): try: self.frames = [] self.time_slider.setEnabled(False) potential_data = os.listdir(os.path.join(self.directory, "data")) for file in potential_data: if ".npy" in file: self.concatenate_frames(file) self.frame_number = self.frames.shape[0] self.split_frames = separate_images(self.dictionary["Lights"], self.frames) self.end_index.setText(f"{self.frame_number-1}") self.time_slider.setRange(0, self.frame_number - 1) self.time_slider.setEnabled(True) self.actualize_lights() except Exception as err: print(err) pass def initUI(self)-
Initialize the user interface
Expand source code
def initUI(self): """Initialize the user interface""" self.setWindowTitle("Brain Scout") self.setGeometry(10, 10, 640, 480) self.grid_layout = QGridLayout() self.grid_layout.setAlignment(Qt.AlignLeft) self.grid_layout.setAlignment(Qt.AlignTop) # self.grid_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(self.grid_layout) self.settings_window = QVBoxLayout() self.settings_window.setAlignment(Qt.AlignLeft) self.settings_window.setAlignment(Qt.AlignTop) self.grid_layout.addLayout(self.settings_window, 0, 0) self.settings_window2 = QVBoxLayout() self.settings_window2.setAlignment(Qt.AlignLeft) self.settings_window2.setAlignment(Qt.AlignTop) self.grid_layout.addLayout(self.settings_window2, 0, 1) # ---- self.directory_window = QHBoxLayout() self.directory_window.setAlignment(Qt.AlignLeft) self.directory_window.setAlignment(Qt.AlignTop) self.choose_directory_button = QPushButton("Select Directory") self.choose_directory_button.setIcon( QIcon(os.path.join(self.cwd, "gui", "icons", "folder-plus.png")) ) self.choose_directory_button.clicked.connect(self.choose_directory) self.directory_window.addWidget(self.choose_directory_button) self.directory_cell = QLineEdit("") self.directory_cell.setReadOnly(True) self.directory_window.addWidget(self.directory_cell) self.settings_window.addLayout(self.directory_window) # ---- self.light_channel_layout = QHBoxLayout() self.preview_light_label = QLabel("Light Channel Preview") self.light_channel_layout.addWidget(self.preview_light_label) self.preview_light_combo = QComboBox() self.preview_light_combo.setEnabled(False) self.preview_light_combo.currentIndexChanged.connect( self.change_preview_light_channel ) self.light_channel_layout.addWidget(self.preview_light_combo) self.settings_window.addLayout(self.light_channel_layout) # self.import_window = QHBoxLayout() # self.import_progress = QLabel("0% Imported") # self.import_window.addWidget(self.import_progress) # self.settings_window.addLayout(self.import_window) # -- # ------------- self.index_window = QVBoxLayout() self.current_index_window = QHBoxLayout() self.current_index_label = QLabel("Current Index:") self.current_index_window.addWidget(self.current_index_label) self.current_index = QLineEdit("0") self.current_index.textChanged.connect(self.adjust_index) self.current_index_window.addWidget(self.current_index) self.index_window.addLayout(self.current_index_window) self.start_index_window = QHBoxLayout() self.start_index_label = QLabel("Start Index:") self.start_index_window.addWidget(self.start_index_label) self.start_index = QLineEdit("0") self.start_index_window.addWidget(self.start_index) self.index_window.addLayout(self.start_index_window) self.end_index_window = QHBoxLayout() self.end_index_label = QLabel("End Index:") self.end_index_window.addWidget(self.end_index_label) self.end_index = QLineEdit("0") self.end_index_window.addWidget(self.end_index) self.index_window.addLayout(self.end_index_window) self.settings_window2.addLayout(self.index_window) # self.settings_window.addStretch() self.make_time_course_button = QPushButton("Generate Time Course") self.make_time_course_button.setIcon( QIcon(os.path.join(self.cwd, "gui", "icons", "chart-line.png")) ) self.make_time_course_button.clicked.connect(self.make_time_course) self.make_time_course_layout = QHBoxLayout() self.make_time_course_layout.setAlignment(Qt.AlignLeft) self.make_time_course_layout.setAlignment(Qt.AlignTop) self.make_time_course_layout.addWidget(self.make_time_course_button) self.make_time_course_container = QWidget() self.make_time_course_container.setLayout(self.make_time_course_layout) self.grid_layout.addWidget(self.make_time_course_container, 2, 1) # ------- self.slider_layout = QHBoxLayout() self.slider_layout.setAlignment(Qt.AlignLeft) self.slider_layout.setAlignment(Qt.AlignTop) # self.slider_layout.setContentsMargins(0, 0, 0, 0) self.slider_layout.addWidget(QLabel("Start")) self.time_slider = QSlider(Qt.Horizontal, self) self.time_slider.setRange(0, 0) self.time_slider.setValue(0) self.time_slider.valueChanged.connect(self.adjust_time) self.slider_layout.addWidget(self.time_slider) self.slider_layout.addWidget(QLabel("End")) self.settings_window.addLayout(self.slider_layout) # ------------- # self.graphics_layout =QHBoxLayout() # self.graphics_layout.addWidget(self.image_view) self.time_course = PlotWindow(subplots=False) self.time_course.plot([1, 2, 3], [1, 2, 3], root=False) self.grid_layout.addWidget(self.time_course, 1, 1) # self.grid_layout.addLayout(self.graphics_layout, 1, 0) # ------------- self.show() def initialize_plot(self)-
Expand source code
def initialize_plot(self): try: self.image_view except Exception: self.image_view = PlotWindow() self.grid_layout.addWidget(self.image_view, 1, 0) self.plot_image = plt.imshow( np.zeros((self.dimensions[1], self.dimensions[0])), cmap="binary_r", vmin=0, vmax=4096, origin="lower", ) self.plot_image.axes.get_xaxis().set_visible(False) self.plot_image.axes.axes.get_yaxis().set_visible(False) def initialize_roi(self)-
Expand source code
def initialize_roi(self): self.roi_buttons = QStackedLayout() self.roi_buttons.setAlignment(Qt.AlignLeft) self.roi_buttons.setAlignment(Qt.AlignTop) # self.roi_buttons.setContentsMargins(0, 0, 0, 0) self.roi_layout1 = QHBoxLayout() self.roi_layout1.setAlignment(Qt.AlignLeft) self.roi_layout1.setAlignment(Qt.AlignTop) # self.roi_layout1.setContentsMargins(0, 0, 0, 0) self.reset_roi_button = QPushButton("Reset ROI") self.reset_roi_button.setIcon( QIcon(os.path.join(self.cwd, "gui", "icons", "zoom-out-area.png")) ) self.reset_roi_button.setEnabled(False) self.reset_roi_button.clicked.connect(self.reset_roi) self.roi_layout1.addWidget(self.reset_roi_button) self.set_roi_button = QPushButton("Set ROI") self.set_roi_button.setIcon( QIcon(os.path.join(self.cwd, "gui", "icons", "zoom-in-area.png")) ) self.set_roi_button.clicked.connect(self.set_roi) self.roi_layout1.addWidget(self.set_roi_button) self.roi_layout1_container = QWidget() self.roi_layout1_container.setLayout(self.roi_layout1) self.roi_layout2 = QHBoxLayout() self.roi_layout2.setAlignment(Qt.AlignLeft) self.roi_layout2.setAlignment(Qt.AlignTop) # self.roi_layout2.setContentsMargins(0, 0, 0, 0) self.cancel_roi_button = QPushButton("Cancel") self.cancel_roi_button.setIcon( QIcon(os.path.join(self.cwd, "gui", "icons", "zoom-cancel.png")) ) self.cancel_roi_button.clicked.connect(self.cancel_roi) self.roi_layout2.addWidget(self.cancel_roi_button) self.save_roi_button = QPushButton("Save ROI") self.save_roi_button.setIcon( QIcon(os.path.join(self.cwd, "gui", "icons", "zoom-check.png")) ) self.save_roi_button.clicked.connect(self.save_roi) self.roi_layout2.addWidget(self.save_roi_button) self.roi_layout2_container = QWidget() self.roi_layout2_container.setLayout(self.roi_layout2) self.roi_buttons.addWidget(self.roi_layout1_container) self.roi_buttons.addWidget(self.roi_layout2_container) self.grid_layout.addLayout(self.roi_buttons, 2, 0) def live_preview(self)-
Expand source code
def live_preview(self): self.plot_image.set( array=self.split_frames[self.live_preview_light_index][ self.image_index // len(self.dictionary["Lights"]) ] ) def make_time_course(self)-
Expand source code
def make_time_course(self): try: if self.roi_extent: print( shrink_array( self.split_frames[self.live_preview_light_index], self.roi_extent, ) ) y_values = get_timecourse( shrink_array( self.split_frames[self.live_preview_light_index], self.roi_extent, ), int(self.start_index.text()) // len(self.dictionary["Lights"]), int(self.end_index.text()) // len(self.dictionary["Lights"]), ) else: y_values = get_timecourse( self.split_frames[self.live_preview_light_index], int(self.start_index.text()) // len(self.dictionary["Lights"]), int(self.end_index.text()) // len(self.dictionary["Lights"]), ) plt.figure(self.time_course.figure.number) plt.ion() plt.clf() plt.plot(y_values) except Exception as err: print(err) pass def open_import_thread(self)-
Open the thread that will import the frames
Expand source code
def open_import_thread(self): """Open the thread that will import the frames""" self.import_thread = Thread(target=self.import_frames) self.import_thread.start() def open_live_preview_thread(self)-
Open the thread that will show the live preview
Expand source code
def open_live_preview_thread(self): """Open the thread that will show the live preview""" self.live_preview_thread = Thread(target=self.live_preview) self.live_preview_thread.start() def reset_roi(self)-
Reset the ROI
Expand source code
def reset_roi(self): """Reset the ROI""" plt.figure(self.image_view.figure.number) plt.ion() plt.xlim(0, self.dimensions[0]) plt.ylim(0, self.dimensions[1]) self.roi_extent = None self.reset_roi_button.setEnabled(False) self.set_roi_button.setEnabled(True) self.reset_roi_button.setEnabled(False) def save_roi(self)-
Save the ROI
Expand source code
def save_roi(self): """Save the ROI""" # self.activate_buttons(buttons=self.enabled_buttons) self.roi_buttons.setCurrentIndex(0) plt.figure(self.image_view.figure.number) plt.ion() plt.xlim(self.roi_extent[0], self.roi_extent[1]) plt.ylim(self.roi_extent[2], self.roi_extent[3]) self.rect_selector.clear() self.rect_selector = None self.reset_roi_button.setEnabled(True) self.set_roi_button.setEnabled(True) def set_roi(self)-
Set the ROI
Expand source code
def set_roi(self): """Set the ROI""" self.roi_buttons.setCurrentIndex(1) self.cancel_roi_button.setEnabled(True) self.save_roi_button.setEnabled(False) def onselect_function(eclick, erelease): """Save the ROI dimensions as attributes""" self.roi_extent = self.rect_selector.extents self.save_roi_button.setEnabled(True) self.rect_selector = RectangleSelector( self.plot_image.axes, onselect_function, drawtype="box", useblit=True, button=[1, 3], minspanx=5, minspany=5, spancoords="pixels", interactive=True, )