# -*- coding: utf-8 -*-
"""
This module implements NeuroChaT_Ui, the main class for NeuroChaT GUI.
It contains other graphical and data objects and connects to
the NeuroChaT class for setting configuration and analysis in NeuroChaT.
@author: Md Nurul Islam; islammn at tcd dot ie
"""
# Form implementation generated from reading ui file 'NeuroChaT.ui'
#
# Created: Thu Jan 12 13:04:12 2017
# by: PyQt5 UI code generator 4.11.3
#
# WARNING! All changes made in this file will be lost!
import os
import sys
import logging
import webbrowser
from datetime import datetime
from PyQt5 import QtCore, QtWidgets, QtGui
from neurochat.nc_uiutils import NOut, PandasModel, ScrollableWidget, add_radio_button, \
add_push_button, add_check_box, add_combo_box, add_log_box, add_label, \
add_line_edit, add_group_box, add_spin_box, add_double_spin_box, xlt_from_utf8
from neurochat.nc_uimerge import UiMerge
from neurochat.nc_control import NeuroChaT
from neurochat.nc_utils import make_dir_if_not_exists, log_exception
from neurochat.nc_utils import remove_extension
import pandas as pd
try:
_encoding = QtWidgets.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtWidgets.QApplication.translate(
context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtWidgets.QApplication.translate(context, text, disambig)
[docs]class NeuroChaT_Ui(QtWidgets.QMainWindow):
"""This class creates the main neurochat UI menu."""
def __init__(self):
"""See class description."""
super().__init__()
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.nout = NOut()
sys.stdout.write = self.nout.write
self._control = NeuroChaT(parent=self)
self._results_ui = UiResults(self)
self._mode_dict = self._control.get_all_modes()
self._default_loc = os.path.join(
os.path.expanduser("~"), ".nc_saved", "last_dir_location.txt")
self._last_excel_loc = ""
make_dir_if_not_exists(self._default_loc)
if os.path.isfile(self._default_loc):
with open(self._default_loc, "r") as f:
default_dir = f.readline()
if os.path.isdir(default_dir):
os.chdir(default_dir)
else:
self._curr_dir = "/home/"
else:
self._curr_dir = "/home/"
self.setup_ui()
self._should_clear_backend = True
[docs] def setup_ui(self):
"""Set up the elements of NeuroChaT_ui class."""
self.setObjectName(xlt_from_utf8("MainWindow"))
self.setEnabled(True)
# For windows
if os.name == 'nt':
self.setFixedSize(900, 560)
else:
self.setFixedSize(1000, 600)
self.centralwidget = QtWidgets.QWidget(self)
self.centralwidget.setObjectName(xlt_from_utf8("centralwidget"))
layer_6_1 = QtWidgets.QVBoxLayout()
self.mode_label = add_label(text="Analysis Mode", obj_name="modeLabel")
self.mode_box = add_combo_box(obj_name="modeBox")
layer_6_1.addWidget(self.mode_label)
layer_6_1.addWidget(self.mode_box)
layer_6_2 = QtWidgets.QVBoxLayout()
self.unit_label = add_label(text="Unit No", obj_name="unitLabel")
self.unit_no_box = add_combo_box(obj_name="unitNoBox")
self.unit_no_box.addItems([str(i) for i in list(range(256))])
layer_6_2.addWidget(self.unit_label)
layer_6_2.addWidget(self.unit_no_box)
layer_6_3 = QtWidgets.QVBoxLayout()
self.chan_label = add_label(text="LFP Ch No", obj_name="chanLabel")
self.lfp_chan_box = add_combo_box(obj_name="lfpChanBox")
self.lfp_chan_box.setSizeAdjustPolicy(
self.lfp_chan_box.AdjustToContents)
layer_6_3.addWidget(self.chan_label)
layer_6_3.addWidget(self.lfp_chan_box)
layer_5_1 = QtWidgets.QHBoxLayout()
layer_5_1.addLayout(layer_6_1)
layer_5_1.addLayout(layer_6_2)
layer_5_1.addLayout(layer_6_3)
# Spike browser
layer_5_2_1 = QtWidgets.QHBoxLayout()
self.browse_button_spike = add_push_button(
text="Browse Spike ", obj_name="browseButtonSpike")
self.filename_line_spike = add_line_edit(
obj_name="filenameLineSpike", text="")
layer_5_2_1.addWidget(self.browse_button_spike)
layer_5_2_1.addWidget(self.filename_line_spike)
# LFP Browser
layer_5_2_2 = QtWidgets.QHBoxLayout()
self.browse_button_lfp = add_push_button(
text="Browse LFP ", obj_name="browseButtonLFP")
self.filename_line_lfp = add_line_edit(
obj_name="filenameLineLFP", text="")
layer_5_2_2.addWidget(self.browse_button_lfp)
layer_5_2_2.addWidget(self.filename_line_lfp)
# Spatial Browser
layer_5_2_3 = QtWidgets.QHBoxLayout()
self.browse_button_spatial = add_push_button(
text="Browse Spatial", obj_name="browseButtonSpatial")
self.filename_line_spatial = add_line_edit(
obj_name="filenameLineSpatial", text="")
layer_5_2_3.addWidget(self.browse_button_spatial)
layer_5_2_3.addWidget(self.filename_line_spatial)
layer_5_2 = QtWidgets.QVBoxLayout()
layer_5_2.addLayout(layer_5_2_1)
layer_5_2.addLayout(layer_5_2_2)
layer_5_2.addLayout(layer_5_2_3)
layer_4_1 = QtWidgets.QVBoxLayout()
layer_4_1.addLayout(layer_5_1)
layer_4_1.addLayout(layer_5_2)
self.cell_type_box = self.select_cell_type_ui()
layer_3_2 = QtWidgets.QVBoxLayout()
layer_3_2.addLayout(layer_4_1)
layer_3_2.addWidget(self.cell_type_box)
self.inp_format_label = add_label(
text="Input Data Format", obj_name="inpFormatLabel")
self.file_format_box = add_combo_box(obj_name="fileFormatBox")
self.graphic_format_box = self.selectGraphicFormatUi()
self.start_button = add_push_button(
text="Start", obj_name="startButton")
self.save_log_button = add_push_button(
text="Save log", obj_name="saveLogButton")
self.clear_log_button = add_push_button(
text="Clear log", obj_name="clearLogButton")
layer_3_1 = QtWidgets.QVBoxLayout()
layer_3_1.addWidget(self.inp_format_label)
layer_3_1.addWidget(self.file_format_box)
layer_3_1.addWidget(self.graphic_format_box)
layer_3_1.addStretch(1)
self.start_button.setSizePolicy(
QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
layer_3_1.addWidget(self.start_button)
layer_3_1.addStretch(1)
layer_2_1 = QtWidgets.QHBoxLayout()
layer_2_1.addLayout(layer_3_1)
layer_2_1.addLayout(layer_3_2, 2)
layer_2_2 = QtWidgets.QHBoxLayout()
self.save_log_button.setSizePolicy(
QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
self.clear_log_button.setSizePolicy(
QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
layer_2_2.addWidget(self.save_log_button, 0, QtCore.Qt.AlignLeft)
layer_2_2.addWidget(self.clear_log_button, 0, QtCore.Qt.AlignRight)
self.log_text = add_log_box(obj_name="logText")
layer_1_1 = QtWidgets.QVBoxLayout()
layer_1_1.addLayout(layer_2_1)
layer_1_1.addLayout(layer_2_2)
layer_1_1.addWidget(self.log_text)
layer_1_2 = self.select_analysis_ui()
final_layer = QtWidgets.QHBoxLayout()
final_layer.addLayout(layer_1_1, 4)
final_layer.addLayout(layer_1_2, 2)
self.mode_box.addItems(
["Single Unit", "Single Session", "Listed Units"])
self.file_format_box.addItems(["Axona", "Neuralynx", "NWB"])
self.lfp_chan_getitems()
self.centralwidget.setLayout(final_layer)
self.menu_ui()
self.retranslate_ui()
# Set up child windows
self._results_ui.setup_ui()
self._merge_ui = UiMerge(self)
self._param_ui = UiParameters(self)
self.setCentralWidget(self.centralwidget)
QtCore.QMetaObject.connectSlotsByName(self)
# Set the callbacks
self.behaviour_ui()
# Set the initial text
self._set_dictation()
[docs] def behaviour_ui(self):
"""Set up the behaviour of NeuroChaT_ui widgets."""
# self.connect(self.nout, QtCore.SIGNAL('update_log(QString)'), self.update_log)
self.nout.emitted[str].connect(self.update_log)
self.file_format_box.currentIndexChanged[int].connect(
self.data_format_select)
self.mode_box.currentIndexChanged[int].connect(self.mode_select)
self.pdf_button.setChecked(True)
self.graphic_format_group.buttonClicked.connect(
self.graphic_format_select)
self.unit_no_box.currentIndexChanged[int].connect(self.set_unit_no)
self.lfp_chan_box.currentIndexChanged[int].connect(self.set_lfp_chan)
self.select_all_box.stateChanged.connect(self.select_all)
self.browse_button_spike.clicked.connect(self.browse_spike)
self.browse_button_lfp.clicked.connect(self.browse_lfp)
self.browse_button_spatial.clicked.connect(self.browse_spatial)
self.clear_log_button.clicked.connect(self.clear_log)
self.save_log_button.clicked.connect(self.save_log)
self.open_file_act.triggered.connect(self.browse_all)
self.clear_files_act.triggered.connect(self.clear_files)
self.append_excel_act.triggered.connect(self.append_excel)
self.save_session_act.triggered.connect(self.save_session)
self.load_session_act.triggered.connect(self.load_session)
self.start_button.clicked.connect(self.start)
self.exit_act.triggered.connect(self.exit_nc)
self.export_results_act.triggered.connect(self.export_results)
self.export_graphic_info_act.triggered.connect(
self.export_graphic_info)
self.view_results_act.triggered.connect(self.restore_start_button)
self.merge_act.triggered.connect(self.merge_output)
self.accumulate_act.triggered.connect(self.accumulate_output)
# self.angle_act.triggered.connect(self.angle_calculation)
self.multi_place_cell_act.triggered.connect(self.place_cell_plots)
self.view_help_act.triggered.connect(self.view_help)
# self.tutorial_act.triggered.connect(self.tutorial)
self.about_nc_act.triggered.connect(self.about_nc)
self.view_api_act.triggered.connect(self.view_api)
self.verify_units_act.triggered.connect(self.verify_units)
self.evaluate_act.triggered.connect(self.cluster_evaluate)
self.compare_units_act.triggered.connect(self.compare_units)
self.convert_files_act.triggered.connect(self.convert_to_nwb)
self.param_set_act.triggered.connect(self.set_parameters)
self._results_ui.export_button.clicked.connect(self.export_results)
self.cell_type_group.buttonClicked.connect(self.cell_type_select)
[docs] def select_cell_type_ui(self):
"""Set up the cell type selection panel in NeuroChaT GUI."""
positions = [(i, j) for j in range(3) for i in range(4)]
self.place_cell_button = add_radio_button(
text="Place", obj_name="place_cell_button")
self.hd_cell_button = add_radio_button(
text="Head-directional", obj_name="hd_cell_button")
self.grid_cell_button = add_radio_button(
text="Grid", obj_name="grid_cell_button")
self.boundary_cell_button = add_radio_button(
text="Boundary", obj_name="boundary_cell_button")
self.gradient_cell_button = add_radio_button(
text="Gradient", obj_name="gradientCell_button")
self.hd_by_place_cell_button = add_radio_button(
text="HDxPlace", obj_name="hdXPlaceCell_button")
self.theta_cell_button = add_radio_button(
text="Theta-rhythmic", obj_name="theta_cell_button")
self.theta_skip_cell_button = add_radio_button(
text="Theta-skipping", obj_name="theta_skip_cell_button")
layout = QtWidgets.QGridLayout()
layout.addWidget(self.place_cell_button, *positions[0])
layout.addWidget(self.hd_cell_button, *positions[1])
layout.addWidget(self.grid_cell_button, *positions[2])
layout.addWidget(self.boundary_cell_button, *positions[3])
layout.addWidget(self.gradient_cell_button, *positions[4])
layout.addWidget(self.hd_by_place_cell_button, *positions[5])
layout.addWidget(self.theta_cell_button, *positions[6])
layout.addWidget(self.theta_skip_cell_button, *positions[7])
cell_type_box = add_group_box(
title="Select Cell Type", obj_name="cellTypeBox")
cell_type_box.setLayout(layout)
self.cell_type_group = QtWidgets.QButtonGroup(cell_type_box)
self.cell_type_group.setObjectName(xlt_from_utf8("graphicFormatGoup"))
self.cell_type_group.addButton(self.place_cell_button)
self.cell_type_group.addButton(self.hd_cell_button)
self.cell_type_group.addButton(self.grid_cell_button)
self.cell_type_group.addButton(self.boundary_cell_button)
self.cell_type_group.addButton(self.gradient_cell_button)
self.cell_type_group.addButton(self.hd_by_place_cell_button)
self.cell_type_group.addButton(self.theta_cell_button)
self.cell_type_group.addButton(self.theta_skip_cell_button)
return cell_type_box
[docs] def select_analysis_ui(self):
"""Set up the analysis type selection panel in NeuroChaT GUI."""
self.isi = add_check_box(text="Interspike Interval", obj_name="isi")
self.isi_corr = add_check_box(
text="ISI Autocorrelation", obj_name="isi_corr")
self.theta_cell = add_check_box(
text="Theta-modulated Cell Index", obj_name="theta_cell")
self.theta_skip_cell = add_check_box(
text="Theta-skipping Cell Index", obj_name="theta_skip_cell")
self.burst = add_check_box(text="Burst Property", obj_name="burst")
self.speed = add_check_box(
text="Spike Rate vs Running Speed", obj_name="speed")
self.ang_vel = add_check_box(
text="Spike Rate vs Angular Velocity", obj_name="ang_vel")
self.hd_rate = add_check_box(
text="Spike Rate vs Head Direction", obj_name="hd_rate")
self.hd_shuffle = add_check_box(
text="Head Directional Shuffling Analysis", obj_name="hd_shuffle")
self.hd_time_lapse = add_check_box(
text="Head Directional Time Lapse Analysis", obj_name="hd_time_lapse")
self.hd_time_shift = add_check_box(
text="Head Directional Time Shift Analysis", obj_name="hd_time_shift")
self.loc_rate = add_check_box(
text="Spike Rate vs Location", obj_name="loc_rate")
self.loc_shuffle = add_check_box(
text="Locational Shuffling Analysis", obj_name="loc_shuffle")
self.loc_time_lapse = add_check_box(
text="Locational Time Lapse Analysis", obj_name="loc_time_lapse")
self.loc_time_shift = add_check_box(
text="Locational Time Shift Analysis", obj_name="loc_time_shift")
self.spatial_corr = add_check_box(
text="Spatial Autocorrelation", obj_name="spatial_corr")
self.grid = add_check_box(text="Grid Cell Analysis", obj_name="grid")
self.border = add_check_box(
text="Border Cell Analysis", obj_name="border")
self.gradient = add_check_box(
text="Gradient Cell Analysis", obj_name="gradient")
self.multiple_regression = add_check_box(
text="Multiple Regression", obj_name="multiple_regression")
self.inter_depend = add_check_box(
text="Interdependence Analysis", obj_name="inter_depend")
self.lfp_spectrum = add_check_box(
text="LFP Frequency Spectrum", obj_name="lfp_spectrum")
self.spike_phase = add_check_box(
text="Unit LFP-phase Distribution", obj_name="spike_phase")
self.phase_lock = add_check_box(
text="Unit LFP-phase Locking", obj_name="phase_lock")
self.lfp_spike_causality = add_check_box(
text="Unit-LFP Causality", obj_name="lfp_spike_causality")
self.wave_property = add_check_box(
text="Waveform Properties", obj_name="wave_property")
self.scroll_layout = QtWidgets.QVBoxLayout()
self.scroll_layout.addWidget(self.isi)
self.scroll_layout.addWidget(self.isi_corr)
self.scroll_layout.addWidget(self.wave_property)
self.scroll_layout.addWidget(self.theta_cell)
self.scroll_layout.addWidget(self.theta_skip_cell)
self.scroll_layout.addWidget(self.burst)
self.scroll_layout.addWidget(self.speed)
self.scroll_layout.addWidget(self.ang_vel)
self.scroll_layout.addWidget(self.hd_rate)
self.scroll_layout.addWidget(self.hd_shuffle)
self.scroll_layout.addWidget(self.hd_time_lapse)
self.scroll_layout.addWidget(self.hd_time_shift)
self.scroll_layout.addWidget(self.loc_rate)
self.scroll_layout.addWidget(self.loc_shuffle)
self.scroll_layout.addWidget(self.loc_time_lapse)
self.scroll_layout.addWidget(self.loc_time_shift)
self.scroll_layout.addWidget(self.spatial_corr)
self.scroll_layout.addWidget(self.grid)
self.scroll_layout.addWidget(self.border)
self.scroll_layout.addWidget(self.gradient)
self.scroll_layout.addWidget(self.multiple_regression)
self.scroll_layout.addWidget(self.inter_depend)
self.scroll_layout.addWidget(self.lfp_spectrum)
self.scroll_layout.addWidget(self.spike_phase)
self.scroll_layout.addWidget(self.phase_lock)
self.scroll_layout.addWidget(self.lfp_spike_causality)
self.function_widget = ScrollableWidget()
self.function_widget.setContents(self.scroll_layout)
self.function_select_label = add_label(
text="Analysis Selection", obj_name="funcSelectLabel")
self.select_all_box = add_check_box(
text="Select All", obj_name="selectAll")
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.function_select_label, 0, QtCore.Qt.AlignCenter)
layout.addWidget(self.select_all_box, 0, QtCore.Qt.AlignCenter)
layout.addWidget(self.function_widget, 5)
return layout
[docs] def retranslate_ui(self):
"""Set up the title and icon in NeuroChaT GUI."""
import neurochat
version = neurochat.__version__
self.setWindowTitle(_translate(
"MainWindow",
"NeuroChaT - The Neuron Characterisation Toolbox (Version {})".format(
version),
None)
)
# <-- absolute dir the script is in
script_dir = os.path.dirname(__file__)
rel_path = "../NeuroChat.png"
abs_file_path = os.path.join(script_dir, rel_path)
self.setWindowIcon(QtGui.QIcon(abs_file_path))
[docs] def start(self):
"""
Called when start button is clicked.
Starts the entire backend operation in NeuroChaT
"""
self._get_config()
self._control.finished.connect(self.restore_start_button)
self._control.start()
# self.nthread = QtCore.QThread()
# self.worker = Worker(self.startAnalysis)
# self.worker.moveToThread(self.nthread)
# self.nthread.started.connect(self.worker.run)
# [self.worker.finished.connect(x) for x in [self.restoreStartButton, self.nthread.quit]]
# self.nthread.start()
[docs] def export_results(self):
"""
Called when 'Export Results' button is clicked.
Opens a file dialogue for the selection of an Excel file, and
exports the results in the table to the file
"""
try:
if self.mode_box.currentIndex() == 0:
default_filename = (
os.path.splitext(self._control._pdf_file)[0] + ".xlsx")
elif self.mode_box.currentIndex() == 1:
default_filename = (
os.path.splitext(self._control.hdf._filename)[0] + ".xlsx")
else:
default_filename = (
os.path.splitext(self._control.get_excel_file())[0] +
"_results.xlsx")
except BaseException as ex:
now = datetime.now()
whole_time = now.strftime("%Y-%m-%d--%H-%M-%S")
log_exception(
ex, "Automatically generating results name")
default_filename = 'nc_results--' + whole_time + '.xlsx'
excel_file = QtCore.QDir.toNativeSeparators(
QtWidgets.QFileDialog.getSaveFileName(
self, 'Export analysis results to...',
os.getcwd() + os.sep + default_filename,
"Excel Files (*.xlsx .*xls)")[0]
)
if not excel_file:
logging.warning(
"No excel file selected! Results cannot be exported!")
else:
try:
results = self._control.get_results()
results.to_excel(excel_file)
logging.info("Analysis results exported to: " +
excel_file.rstrip("\n\r").split(os.sep)[-1])
except BaseException:
logging.error('Failed to export results!')
[docs] def export_graphic_info(self):
"""
Called when 'Export graphic file info' menu is clicked.
Opens a file dialogue for the selection of an Excel file, and
exports the graphic file info in the table to the file
"""
excel_file = QtCore.QDir.toNativeSeparators(
QtWidgets.QFileDialog.getSaveFileName(
self, 'Export information to...',
os.getcwd() + os.sep + 'nc_graphicInfo.xlsx',
"Excel Files (*.xlsx .*xls)")[0]
)
if not excel_file:
logging.warning(
"No excel file selected! Information cannot be exported!")
else:
try:
info = self._control.get_output_files()
info.to_excel(excel_file)
logging.info("Graphics information exported to: " +
excel_file.rstrip("\n\r").split(os.sep)[-1])
except BaseException:
logging.error('Failed to export graphics information!')
[docs] def closeEvent(self, event):
"""
Called when NeuroChaT window is about to close.
Opens a dialogue for saving the session information in NeuroChaT
configuration file (.ncfg).
"""
def save_last(event):
try:
with open(self._default_loc, "w") as f:
f.write(os.getcwd())
event.accept()
except Exception as e:
log_exception(e, "Failed to save last location {} in {}".format(
os.getcwd(), self._default_loc))
event.ignore()
reply = QtWidgets.QMessageBox.question(
self, "Message",
"Save current session before you quit?",
QtWidgets.QMessageBox.Save | QtWidgets.QMessageBox.Close | QtWidgets.QMessageBox.Cancel,
QtWidgets.QMessageBox.Save)
if reply == QtWidgets.QMessageBox.Save:
config_file = QtCore.QDir.toNativeSeparators(
QtWidgets.QFileDialog.getSaveFileName(
self, 'Save session as...', os.getcwd(), "*.ncfg")[0])
if config_file:
try:
self._get_config()
self._control.save_config(config_file)
logging.info("Session saved in: " + config_file)
os.chdir(os.path.dirname(config_file))
save_last(event)
except BaseException:
logging.error('Failed to save configuration!')
event.ignore()
elif reply == QtWidgets.QMessageBox.Close:
save_last(event)
else:
event.ignore()
[docs] def exit_nc(self):
"""
Called when 'Exit' menu item is clicked.
Closes the NeuroChaT window.
"""
self.close()
[docs] def mode_select(self, ind):
"""
Called when there is a change in the analysis mode selection combo box.
Sets the data analysis mode to the selected item.
"""
self._control.set_analysis_mode(ind)
logging.info("Analysis mode set to: " + self.mode_box.itemText(ind))
self._set_dictation()
self.clear_backend_files()
[docs] def cell_type_select(self):
"""
Called when there is a change in the cell type selection button groups.
Sets the cell type to the selected item.
"""
button = self.cell_type_group.checkedButton()
text = button.text()
self._control.set_cell_type(text)
logging.info("Cell type set to: " + text)
self.cell_type_analysis(text)
[docs] def select_all(self):
"""
Called when 'Select All' box is checked or unchecked.
It checks or unchecks all other analyses.
"""
if self.select_all_box.isChecked():
logging.info("Selected ALL analyses")
for checkbox in self.function_widget.findChildren(
QtWidgets.QCheckBox):
checkbox.setChecked(True)
else:
logging.info("Deselected ALL analyses")
for checkbox in self.function_widget.findChildren(
QtWidgets.QCheckBox):
checkbox.setChecked(False)
[docs] def lfp_chan_getitems(self):
"""
Return the list of LFP items.
This depends on the system, and returns files (Neuralynx)
or their file extension (Axona)
once the spike data is set using the 'Browse' button.
"""
file_format = self.file_format_box.itemText(
self.file_format_box.currentIndex())
items = [""]
if file_format == "Neuralynx":
files = os.listdir(os.getcwd())
items = [f for f in files if f.endswith('ncs')]
elif file_format == "Axona":
def get_int_eeg(x):
if len(x) == 3:
return 1
else:
return int(x[3:])
files = os.listdir(os.getcwd())
eeg_items = []
egf_items = []
for f in files:
if '.eeg' in f:
eeg_items.append(f.split('.')[-1])
if '.egf' in f:
egf_items.append(f.split('.')[-1])
try:
eeg_items = sorted(eeg_items, key=get_int_eeg)
except BaseException:
eeg_items = eeg_items
try:
egf_items = sorted(egf_items, key=get_int_eeg)
except BaseException:
egf_items = egf_items
items = eeg_items + egf_items
elif file_format == "NWB":
try:
path = '/processing/Neural Continuous/LFP'
self._control.open_hdf_file()
items = self._control.get_hdf_groups(path=path)
self._control.close_hdf_file()
except BaseException:
logging.error('Cannot read the hdf file')
else:
items = [str(i) for i in list(range(256))]
self._first_chan_call = True
self.lfp_chan_box.clear()
self.lfp_chan_box.addItems(items)
self._first_chan_call = False
if len(items) == 0:
self.filename_line_lfp.setText(
"No LFP information found")
self._control.set_lfp_file("")
[docs] def unit_getitems(self):
"""Return the list of units once spike data is set."""
try:
file_format = self.file_format_box.itemText(
self.file_format_box.currentIndex())
if file_format == "NWB":
self._control.open_hdf_file()
if "+" in self._control.get_spike_file():
_, path = self._control.get_spike_file().split("+")
path = path + '/Clustering/cluster_nums'
items = self._control.hdf.f[path]
else:
logging.warning("No spike information found in hdf5 file")
items = [str(i) for i in range(256)]
if self._control.get_unit_no() != 0:
self.unit_no_box.clear()
self.unit_no_box.addItems(items)
else:
from neurochat.nc_spike import NSpike
spike_file = self._control.get_spike_file()
system = self._control.format
if os.path.isfile(spike_file):
spike_obj = NSpike(filename=spike_file, system=system)
spike_obj.load()
items = spike_obj.get_unit_list()
else:
logging.warning(
"No spike information found in {} file".format(
file_format))
items = [str(i) for i in range(256)]
if self._control.get_unit_no() != 0:
self.unit_no_box.clear()
self.unit_no_box.addItems(items)
if len(items) == 0:
logging.error("No units in this file.")
items = [i for i in range(256)]
str_items = [str(x) for x in items]
self.unit_no_box.clear()
self.unit_no_box.addItems(str_items)
if file_format == "NWB":
self._control.close_hdf_file()
except Exception as e:
log_exception(
e, "Populating unit list failed - you can still manually select a unit.")
items = [str(i) for i in range(256)]
self.unit_no_box.clear()
self.unit_no_box.addItems(items)
[docs] def browse_spike(self):
"""
Open a file dialog for selecting a spike file.
Depending on the mode, also browses Excel or HDF5 files.
Also populates a set of units and lfps available on selection.
"""
mode_id = self.mode_box.currentIndex()
file_format = self._control.get_data_format()
if mode_id == 0 or mode_id == 1:
if file_format == "Axona" or file_format == "Neuralynx":
if file_format == "Axona":
spike_filter = "".join(
["*." + str(x) + ";;" for x in list(range(1, 129))])
elif file_format == "Neuralynx":
spike_filter = "*.ntt;; *.nst;; *.nse"
spike_file = QtCore.QDir.toNativeSeparators(
QtWidgets.QFileDialog.getOpenFileName(
self, 'Select {} spike file...'.format(file_format),
os.getcwd(), spike_filter)[0])
if not spike_file:
logging.warning("No spike file selected")
else:
words = spike_file.rstrip("\n\r").split(os.sep)
directory = os.sep.join(words[0:-1])
os.chdir(directory)
self._control.set_spike_file(spike_file)
self._control.ndata.set_spike_file(spike_file)
logging.info("New spike file added: " + words[-1])
self.filename_line_spike.setText(
"Selected {}".format(spike_file))
self.unit_getitems()
self.lfp_chan_getitems()
elif file_format == "NWB":
nwb_file = QtCore.QDir.toNativeSeparators(
QtWidgets.QFileDialog.getOpenFileName(
self, 'Select NWB file...', os.getcwd(), "*.hdf5")[0])
if not nwb_file:
logging.warning("No NWB file selected")
else:
self.clear_backend_files()
words = nwb_file.rstrip("\n\r").split(os.sep)
directory = os.sep.join(words[0:-1])
os.chdir(directory)
self._control.set_nwb_file(nwb_file)
logging.info("New NWB file added: " + words[-1])
self.filename_line_spike.setText(
"Selected {}".format(nwb_file))
try:
path = '/processing/Shank'
self._control.open_hdf_file()
items = self._control.get_hdf_groups(path=path)
if items:
item, ok = QtWidgets.QInputDialog.getItem(
self, "Select electrode group",
"Electrode groups: ", items, 0, False)
if ok:
self._control.set_spike_file(
nwb_file + '+' + path + '/' + item)
logging.info(
'Spike data set to electrode group: '
+ path + '/' + item)
self.filename_line_spike.setText(
"Selected {} with electrodes {}".format(
os.path.basename(nwb_file), path + '/' + item))
path = '/processing/Behavioural/Position'
if self._control.exist_hdf_path(path=path):
self._control.set_spatial_file(
nwb_file + '+' + path)
logging.info(
'Position data set to group: ' + path)
self.filename_line_spatial.setText(
"Selected HDF5 Path {}".format(path))
else:
logging.warning(
path +
' not found. Spatial data not set.')
self.filename_line_spatial.setText(
"No spatial data found")
self._control.close_hdf_file()
except Exception as e:
log_exception(
e, "Cannot read hdf file in nc_ui browse")
self.unit_getitems()
self.lfp_chan_getitems()
elif mode_id == 2:
excel_file = QtCore.QDir.toNativeSeparators(
QtWidgets.QFileDialog.getOpenFileName(
self, 'Select Excel file...', os.getcwd(), "*.xlsx;; .*xls")[0])
if not excel_file:
logging.warning("No excel file selected")
else:
words = excel_file.rstrip("\n\r").split(os.sep)
directory = os.sep.join(words[0:-1])
os.chdir(directory)
self._control.set_excel_file(excel_file)
logging.info("New excel file added: " + words[-1])
self.filename_line_spike.setText(
"Selected {}".format(excel_file))
# elif mode_id == 3:
# data_directory = QtCore.QDir.toNativeSeparators(
# QtWidgets.QFileDialog.getExistingDirectory(self,
# 'Select data directory...', os.getcwd()))
# if not data_directory:
# logging.warning("No data directory selected")
# else:
# self._control.set_dataDir(data_directory)
# logging.info("New directory added: "+ data_directory)
[docs] def browse_lfp(self):
"""
Open a file dialog for selecting an lfp file.
This is disabled, depending on the mode and file format.
"""
mode_id = self.mode_box.currentIndex()
file_format = self._control.get_data_format()
if mode_id == 0 or mode_id == 1:
if file_format == "Axona" or file_format == "Neuralynx":
if file_format == "Axona":
lfp_filter = "*.eeg*;; *.egf*"
elif file_format == "Neuralynx":
lfp_filter = "*.ncs"
lfp_file = QtCore.QDir.toNativeSeparators(
QtWidgets.QFileDialog.getOpenFileName(
self, 'Select {} lfp file...'.format(file_format),
os.getcwd(), lfp_filter)[0])
if not lfp_file:
logging.warning("No lfp file selected")
else:
words = lfp_file.rstrip("\n\r").split(os.sep)
directory = os.sep.join(words[0:-1])
os.chdir(directory)
logging.info("New lfp file added: " + words[-1])
self._control.set_lfp_file(lfp_file)
self.filename_line_lfp.setText(
"Selected {}".format(lfp_file))
self.lfp_chan_getitems()
[docs] def browse_spatial(self):
"""
Open a file dialog for selecting a spatial file.
This is disabled, depending on the mode and file format.
"""
mode_id = self.mode_box.currentIndex()
file_format = self._control.get_data_format()
if mode_id == 0 or mode_id == 1:
if file_format == "Axona" or file_format == "Neuralynx":
if file_format == "Axona":
spatial_filter = "*.txt"
elif file_format == "Neuralynx":
spatial_filter = "*.nvt"
spatial_file = QtCore.QDir.toNativeSeparators(
QtWidgets.QFileDialog.getOpenFileName(
self, 'Select {} spatial file...'.format(file_format),
os.getcwd(), spatial_filter)[0])
if not spatial_file:
logging.warning("No spatial file selected")
else:
words = spatial_file.rstrip("\n\r").split(os.sep)
directory = os.sep.join(words[0:-1])
os.chdir(directory)
self._control.set_spatial_file(spatial_file)
logging.info("New spatial file added: " + words[-1])
self.filename_line_spatial.setText(
"Selected {}".format(spatial_file))
[docs] def browse_all(self):
"""
In turn, browse spike, lfp and spatial.
See also
--------
neurochat.nc_ui.browse_spike
neurochat.nc_ui.browse_spatial
neurochat.nc_ui.browse_lfp
"""
if self.browse_button_spike.isEnabled():
self.browse_spike()
if self.browse_button_lfp.isEnabled():
self.browse_lfp()
if self.browse_button_spatial.isEnabled():
self.browse_spatial()
[docs] def append_excel(self):
if os.path.isfile(self._last_excel_loc):
_default = os.path.dirname(self._last_excel_loc)
else:
_default = os.getcwd()
excel_file = QtCore.QDir.toNativeSeparators(
QtWidgets.QFileDialog.getSaveFileName(
self, 'Select Excel file...',
_default, "*.xlsx;; .*xls")[0])
if excel_file != "":
if not os.path.splitext(excel_file)[1] in [".xlsx", ".xls"]:
excel_file = excel_file + ".xlsx"
self._control.append_selection_to_excel(excel_file)
[docs] def update_log(self, msg):
"""
Update the log-box with new message.
Parameters
----------
msg
New log message or record
Returns
-------
None
"""
self.log_text.insert_log(msg)
[docs] def clear_log(self):
"""Clear the texts in the log box."""
self.log_text.clear()
logging.info("Log cleared!")
[docs] def save_log(self):
"""
Open a file dialog for the user to select an output file.
The current contents of the log-box are exported to this text file.
"""
text = self.log_text.get_text()
name = QtCore.QDir.toNativeSeparators(QtWidgets.QFileDialog.getSaveFileName(
self, 'Save log as...', os.getcwd(), "Text files(*.txt)")[0])
if not name:
logging.warning("File not specified. Log is not saved")
else:
try:
file = open(name, 'w')
file.write(text)
logging.info("Log saved in: " + name)
except BaseException:
logging.error(
'Log is not saved! See if the file is open in another application!')
[docs] def set_unit_no(self, value):
"""
Called when the selection in the 'Unit No' is changed.
Sets the unit number accordingly.
"""
if value < 0:
return
unit_no = int(self.unit_no_box.itemText(value))
self._control.set_unit_no(unit_no)
logging.info("Selected Unit: " + str(unit_no))
[docs] def set_lfp_chan(self, value):
"""
Called when the selection in the 'LFP Ch No' is changed.
Sets the lfp channel accordingly.
"""
lfpID = self.lfp_chan_box.itemText(value)
should_set = True
if self._first_chan_call:
data_format = self._control.get_data_format()
lfp_file = self._control.get_lfp_file()
if data_format == 'Axona':
if os.path.isfile(lfp_file):
_, lfpID = remove_extension(lfp_file, return_ext=True)
should_set = False
elif data_format == 'Neuralynx':
if os.path.isfile(lfp_file):
lfpID = os.path.basename(lfp_file)
should_set = False
elif data_format == 'NWB':
should_set = True
else:
logging.error('Input data format not supported for file')
index = self.lfp_chan_box.findText(lfpID)
if index >= 0:
self.lfp_chan_box.setCurrentIndex(index)
if lfpID and should_set:
logging.info("Selected LFP channel: " + lfpID)
data_format = self._control.get_data_format()
if data_format == 'Axona':
spike_file = self._control.get_spike_file()
lfp_file = self._control.get_lfp_file()
if spike_file != "":
lfp_file = remove_extension(spike_file) + lfpID
elif lfp_file != "":
lfp_file = remove_extension(lfp_file) + lfpID
if not os.path.isfile(lfp_file):
raise ValueError("LFP file {} not found".format(lfp_file))
elif data_format == 'Neuralynx':
spike_file = self._control.get_spike_file()
lfp_file = self._control.get_lfp_file()
if spike_file != "":
lfp_file = (os.sep.join(
spike_file.split(os.sep)[:-1]) + os.sep + lfpID)
elif lfp_file != "":
lfp_file = os.path.join(os.path.dirname(lfp_file), lfpID)
if not os.path.isfile(lfp_file):
raise ValueError("LFP file {} not found".format(lfp_file))
elif data_format == 'NWB':
nwb_file = self._control.get_nwb_file()
lfp_file = (
nwb_file + '+' + '/processing/Neural Continuous/LFP' + '/' + lfpID)
else:
logging.error('Input data format not supported!')
self._control.set_lfp_file(lfp_file)
if data_format == "NWB":
self.filename_line_lfp.setText("Selected HDF5 Path {}".format(
lfp_file.split("+")[1]))
else:
self.filename_line_lfp.setText("Selected {}".format(lfp_file))
[docs] def view_help(self):
"""Display user guide pdf on GitHub."""
url = r"https://github.com/shanemomara/NeuroChaT/blob/master/docs/NeuroChaT%20User%20Guide.pdf"
webbrowser.open_new(url)
[docs] def view_api(self):
"""Display API documentation for neurochat."""
script_dir = os.path.dirname(__file__)
rel_path = "../docs/index.html"
url = os.path.join(script_dir, rel_path)
if not os.path.isfile(url):
url = "https://neurochat.readthedocs.io/en/latest/reference/neurochat.html"
webbrowser.open_new(url)
[docs] def tutorial(self):
"""Display a tutorial for the program."""
pass
[docs] def about_nc(self):
"""Display a wiki page about the program."""
url = "https://neurochat.readthedocs.io/en/latest/index.html"
webbrowser.open_new(url)
def _set_dictation(self):
"""
Set the dictation in the text-box.
This is used for the browse button as the input data format changes.
"""
file_format = self._control.get_data_format()
analysis_mode, mode_id = self._control.get_analysis_mode()
# Set dictation for spike browse button
_dictation_spike = [
"Select spike(.n) file",
"Select spike(.n) file",
"Select excel(.xls/.xlsx) file with unit list",
"Select folder"]
_dictation_lfp = [
"Select lfp(.eeg/.egf) file",
"Select lfp(.eeg/.egf) file",
"Unused in this mode",
"Unused in this mode"]
_dictation_spatial = [
"Select position(.txt) file produced by TINT",
"Select position(.txt) file produced by TINT",
"Unused in this mode",
"Unused in this mode"]
if file_format == "Axona":
self.browse_button_lfp.setEnabled(True)
self.browse_button_spatial.setEnabled(True)
elif file_format == "Neuralynx":
_dictation_spike[:2] = ["Select spike(.ntt/.nst/.nse) file"] * 2
_dictation_lfp[:2] = ["Select lfp(.ncs) file"] * 2
_dictation_spatial[:2] = ["Select postion(.nvt) file"] * 2
self.browse_button_lfp.setEnabled(True)
self.browse_button_spatial.setEnabled(True)
elif file_format == "NWB":
_dictation_spike[:2] = ["Select .hdf5 file"] * 2
_dictation_lfp[:2] = ["Unused in this mode"] * 2
_dictation_spatial[:2] = ["Unused in this mode"] * 2
self.browse_button_lfp.setEnabled(False)
self.browse_button_spatial.setEnabled(False)
if mode_id >= 2:
self.browse_button_lfp.setEnabled(False)
self.browse_button_spatial.setEnabled(False)
if mode_id == 2:
self.browse_button_spike.setText("Browse Excel ")
else:
if file_format == "NWB":
self.browse_button_spike.setText("Browse HDF5 ")
else:
self.browse_button_spike.setText("Browse Spike ")
# Set the text boxes
self.filename_line_spike.setText(_dictation_spike[mode_id])
self.filename_line_lfp.setText(_dictation_lfp[mode_id])
self.filename_line_spatial.setText(_dictation_spatial[mode_id])
def _get_config(self):
"""
Retrive all the configurations from the GUI elements.
After retrieval, it sets them to the Configuration() object
through the NeuroChaT() object.
"""
# Get selected function from functioWidget
for checkbox in self.function_widget.findChildren(QtWidgets.QCheckBox):
self._control.set_analysis(
checkbox.objectName(), checkbox.isChecked())
for checkbox in self._param_ui.findChildren(QtWidgets.QCheckBox):
self._control.set_param(
checkbox.objectName(), checkbox.isChecked())
for spinbox in self._param_ui.findChildren(QtWidgets.QSpinBox):
self._control.set_param(spinbox.objectName(), spinbox.value())
for spinbox in self._param_ui.findChildren(QtWidgets.QDoubleSpinBox):
self._control.set_param(spinbox.objectName(), spinbox.value())
for combobox in self._param_ui.findChildren(QtWidgets.QComboBox):
text = combobox.currentText()
try:
value = int(text)
self._control.set_param(combobox.objectName(), value)
except BaseException:
self._control.set_param(combobox.objectName(), text)
[docs] def save_session(self):
"""
Prompt the user to select a .ncfg file and saves config.
The current settings and parameters
from the GUI elements are saved to the file.
"""
ncfg_file = QtCore.QDir.toNativeSeparators(
QtWidgets.QFileDialog.getSaveFileName(
self, 'Save session as...', os.getcwd(), "*.ncfg")[0])
if not ncfg_file:
logging.warning("File not specified. Session is not saved")
else:
self._get_config()
self._control.save_config(ncfg_file)
logging.info("Session saved in: " + ncfg_file)
os.chdir(os.path.dirname(ncfg_file))
[docs] def load_session(self):
"""
Prompt the user to select a .ncfg file and loads the config.
The settings and parameters from the file are passed to the GUI elements.
"""
ncfg_file = QtCore.QDir.toNativeSeparators(
QtWidgets.QFileDialog.getOpenFileName(
self, 'Select NCFG file...', os.getcwd(), "(*.ncfg)")[0])
if not ncfg_file:
logging.warning("No saved session selected.")
return
else:
self._should_clear_backend = True
self.clear_backend_files()
self._should_clear_backend = False
self._control.load_config(ncfg_file)
os.chdir(os.path.dirname(ncfg_file))
index = self.file_format_box.findText(self._control.get_data_format())
if index >= 0:
self.file_format_box.setCurrentIndex(index)
mode, mode_id = self._control.get_analysis_mode()
self.mode_box.setCurrentIndex(mode_id)
getattr(self, self._control.get_graphic_format() +
'_button').setChecked(True)
self.graphic_format_select()
# populate unit list
old_unit_no = self._control.get_unit_no()
self.unit_getitems()
index = self.unit_no_box.findText(str(old_unit_no))
if index >= 0:
self._control.set_unit_no(old_unit_no)
self.unit_no_box.setCurrentIndex(index)
file = self._control.get_lfp_file()
if self._control.get_data_format() == 'Axona':
file_tag = file.split('.')[-1]
elif self._control.get_data_format() == 'Neuralynx':
file_tag = file.split(os.sep)[-1].split('.')[0]
elif self._control.get_data_format() == 'NWB':
file_tag = file.split('/')[-1]
if os.path.isfile(self._control.get_spike_file()):
os.chdir(os.path.dirname(self._control.get_spike_file()))
elif os.path.isfile(self._control.get_lfp_file()):
os.chdir(os.path.dirname(self._control.get_lfp_file()))
self.lfp_chan_getitems()
index = self.lfp_chan_box.findText(file_tag)
if index >= 0:
self.lfp_chan_box.setCurrentIndex(index)
cell_type = self._control.get_cell_type()
select_by_type = False
for button in self.cell_type_group.buttons():
if button.text == cell_type:
select_by_type = True
button.click()
if not select_by_type:
for key in self._control.get_analysis_list():
getattr(self, key).setChecked(self._control.get_analysis(key))
param_list = self._control.get_param_list()
for name in param_list:
param_widget = self._param_ui.findChild(
QtWidgets.QWidget, name)
if isinstance(param_widget, QtWidgets.QComboBox):
index = param_widget.findText(
str(self._control.get_params(name)))
if index >= 0:
param_widget.setCurrentIndex(index)
elif isinstance(param_widget, QtWidgets.QCheckBox):
param_widget.setChecked(self._control.get_params(name))
else:
param_widget.setValue(self._control.get_params(name))
lfp_file = self._control.get_lfp_file()
if os.path.isfile(lfp_file):
self.filename_line_lfp.setText("Selected {}".format(lfp_file))
spike_file = self._control.get_spike_file()
if os.path.isfile(spike_file):
self.filename_line_spike.setText("Selected {}".format(spike_file))
position_file = self._control.get_spatial_file()
if os.path.isfile(position_file):
self.filename_line_spatial.setText(
"Selected {}".format(position_file))
self._should_clear_backend = True
[docs] def merge_output(self):
"""Open the UiMerge() object to merge PDF or PS files."""
self._merge_ui.merge_enable = True
self._merge_ui.setWindowTitle(QtWidgets.QApplication.translate(
"mergeWindow", "Merge PDF/PS", None))
self._merge_ui.set_default()
self._merge_ui.show()
logging.info(
"Tool to MERGE graphic files activated! Only PDF files can be merged!")
[docs] def accumulate_output(self):
"""Open the UiMerge() object to accumulate PDF or PS files."""
self._merge_ui.merge_enable = False
self._merge_ui.setWindowTitle(QtWidgets.QApplication.translate(
"mergeWindow", "Accumulate PDF/PS", None))
self._merge_ui.set_default()
self._merge_ui.show()
logging.info("Tool to ACCUMULATE graphic files activated")
[docs] def compare_units(self):
"""
Open a file dialog for selecting the Excel list.
This excel list contains specifications for comparing units
and compares the units through NeuroChaT().cluster_similarity() method.
See also
--------
NeuroChaT().cluster_similarity()
"""
excel_file = QtCore.QDir.toNativeSeparators(
QtWidgets.QFileDialog.getOpenFileName(
self, 'Select unit-pair list...', os.getcwd(), "*.xlsx;; .*xls")[0])
if not excel_file:
logging.warning(
"No excel file selected! Comparing units is unsuccessful!")
else:
self._merge_ui.filename_line.setText(excel_file)
logging.info("New excel file added: " +
excel_file.rstrip("\n\r").split(os.sep)[-1])
excel_data = pd.read_excel(excel_file)
print('Create an excel read warpper from PANDAS')
print(excel_data)
[docs] def clear_backend_files(self):
"""Reset all file selections to default."""
if self._should_clear_backend:
# Clear names on the config object
self._control.set_lfp_file("")
self._control.set_spike_file("")
self._control.set_spatial_file("")
self._control.set_nwb_file("")
self.unit_no_box.clear()
items = [str(i) for i in range(256)]
self.unit_no_box.addItems(items)
self._control.set_unit_no(0)
# Clear names on the data object
self._control.ndata.set_lfp_file("")
self._control.ndata.set_spike_file("")
self._control.ndata.set_spatial_file("")
self._set_dictation()
[docs] def clear_files(self):
"""Call to clear_backend_files."""
temp = self._should_clear_backend
self._should_clear_backend = True
logging.info("Clearing selected files and units")
self.clear_backend_files()
self._should_clear_backend = temp
[docs] def angle_calculation(self):
"""
Open an excel file and calculate angles between centroids.
The centroids are computed from the highest firing place
field identified from the firing map.
See also
--------
NeuroChaT.angle_calculation
"""
excel_file = QtCore.QDir.toNativeSeparators(
QtWidgets.QFileDialog.getOpenFileName(
self,
'Select data description list...', os.getcwd(), "*.xlsx;; .*xls")[0])
if not excel_file:
logging.warning("No excel file selected!")
else:
self._get_config()
logging.info("New excel file added: " +
excel_file.rstrip("\n\r").split(os.sep)[-1])
pdf_name = excel_file[:excel_file.find(".")] + "_output.pdf"
dict_info = {
"key": self.angle_calculation.__name__,
"excel_file": excel_file,
"pdf_name": pdf_name}
self._control.set_special_analysis(dict_info)
self.start()
[docs] def place_cell_plots(self):
"""Plot place cell figures for each set file in a directory."""
directory = (
QtCore.QDir.toNativeSeparators(
QtWidgets.QFileDialog.getExistingDirectory(
self, 'Select data folder', os.getcwd(),
QtWidgets.QFileDialog.ShowDirsOnly
| QtWidgets.QFileDialog.DontResolveSymlinks)))
if directory:
dict_info = {
"key": self.place_cell_plots.__name__,
"directory": directory,
"dpi": 400}
self._control.set_special_analysis(dict_info)
self.start()
[docs] def verify_units(self):
"""
Open a file dialog for selecting the Excel list.
This excel list contains specifications for verifying the units
and verifies the unit using the NeuroChaT().verify_units() method.
See also
--------
NeuroChaT().verify_units()
"""
excel_file = QtCore.QDir.toNativeSeparators(
QtWidgets.QFileDialog.getOpenFileName(
self,
'Select data description list...', os.getcwd(), "*.xlsx;; .*xls")[0])
if not excel_file:
logging.warning(
"No excel file selected! Verification of units is unsuccessful!")
else:
logging.info("New excel file added: " +
excel_file.rstrip("\n\r").split(os.sep)[-1])
self._control.verify_units(excel_file)
[docs] def cluster_evaluate(self):
"""
Open a file dialog for selecting the Excel list.
This excel list contains specifications for cluster evaluation
and evaluates the clusters using NeuroChaT().cluster_evaluate() method.
See also
--------
NeuroChaT().cluster_evaluate()
"""
excel_file = QtCore.QDir.toNativeSeparators(
QtWidgets.QFileDialog.getOpenFileName(
self,
'Select data description list...', os.getcwd(), "*.xlsx;; .*xls")[0])
if not excel_file:
logging.warning(
"No excel file selected! Verification of units is unsuccessful!")
else:
logging.info("New excel file added: " +
excel_file.rstrip("\n\r").split(os.sep)[-1])
self._control.cluster_evaluate(excel_file)
[docs] def convert_to_nwb(self):
"""
Open a file dialog for selecting the Excel list.
This excel list contains specifications for NWB file for conversion.
It then converts the files using the NeuroChaT().convert_to_nwb() method.
See also
--------
NeuroChaT().convert_to_nwb()
"""
excel_file = QtCore.QDir.toNativeSeparators(
QtWidgets.QFileDialog.getOpenFileName(
self,
'Select data description list...', os.getcwd(), "*.xlsx;; .*xls")[0])
if not excel_file:
logging.warning(
"No excel file selected! Conversion to NWB is unsuccessful!")
else:
logging.info("New excel file added: " +
excel_file.rstrip("\n\r").split(os.sep)[-1])
self._control.convert_to_nwb(excel_file)
[docs] def set_parameters(self):
"""Show the UiParameters() widget."""
self._param_ui.show()
[docs] def cell_type_analysis(self, cell_type):
"""Set the analysis checkboxes based on the type of cell selected."""
if cell_type == "Place":
self.wave_property.setChecked(True)
self.isi.setChecked(True)
self.isi_corr.setChecked(True)
self.burst.setChecked(False)
self.speed.setChecked(True)
self.ang_vel.setChecked(True)
self.hd_rate.setChecked(False)
self.hd_shuffle.setChecked(False)
self.hd_time_lapse.setChecked(False)
self.hd_time_shift.setChecked(False)
self.loc_rate.setChecked(True)
self.loc_shuffle.setChecked(True)
self.loc_time_lapse.setChecked(True)
self.loc_time_shift.setChecked(True)
self.spatial_corr.setChecked(True)
self.grid.setChecked(False)
self.border.setChecked(False)
self.gradient.setChecked(False)
self.multiple_regression.setChecked(True)
self.inter_depend.setChecked(True)
self.theta_cell.setChecked(False)
self.theta_skip_cell.setChecked(False)
self.lfp_spectrum.setChecked(False)
self.spike_phase.setChecked(False)
self.phase_lock.setChecked(False)
self.lfp_spike_causality.setChecked(False)
elif cell_type == "Head-directional":
self.wave_property.setChecked(True)
self.isi.setChecked(True)
self.isi_corr.setChecked(True)
self.burst.setChecked(False)
self.speed.setChecked(True)
self.ang_vel.setChecked(True)
self.hd_rate.setChecked(True)
self.hd_shuffle.setChecked(True)
self.hd_time_lapse.setChecked(True)
self.hd_time_shift.setChecked(True)
self.loc_rate.setChecked(False)
self.loc_shuffle.setChecked(False)
self.loc_time_lapse.setChecked(False)
self.loc_time_shift.setChecked(False)
self.spatial_corr.setChecked(False)
self.grid.setChecked(False)
self.border.setChecked(False)
self.gradient.setChecked(False)
self.multiple_regression.setChecked(True)
self.inter_depend.setChecked(True)
self.theta_cell.setChecked(False)
self.theta_skip_cell.setChecked(False)
self.lfp_spectrum.setChecked(False)
self.spike_phase.setChecked(False)
self.phase_lock.setChecked(False)
self.lfp_spike_causality.setChecked(False)
elif cell_type == "Grid":
self.wave_property.setChecked(True)
self.isi.setChecked(True)
self.isi_corr.setChecked(True)
self.burst.setChecked(False)
self.speed.setChecked(True)
self.ang_vel.setChecked(True)
self.hd_rate.setChecked(False)
self.hd_shuffle.setChecked(False)
self.hd_time_lapse.setChecked(False)
self.hd_time_shift.setChecked(False)
self.loc_rate.setChecked(True)
self.loc_shuffle.setChecked(False)
self.loc_time_lapse.setChecked(True)
self.loc_time_shift.setChecked(False)
self.spatial_corr.setChecked(False)
self.grid.setChecked(True)
self.border.setChecked(False)
self.gradient.setChecked(False)
self.multiple_regression.setChecked(True)
self.inter_depend.setChecked(True)
self.theta_cell.setChecked(False)
self.theta_skip_cell.setChecked(False)
self.lfp_spectrum.setChecked(False)
self.spike_phase.setChecked(False)
self.phase_lock.setChecked(False)
self.lfp_spike_causality.setChecked(False)
elif cell_type == "Boundary":
self.wave_property.setChecked(True)
self.isi.setChecked(True)
self.isi_corr.setChecked(True)
self.burst.setChecked(False)
self.speed.setChecked(True)
self.ang_vel.setChecked(True)
self.hd_rate.setChecked(False)
self.hd_shuffle.setChecked(False)
self.hd_time_lapse.setChecked(False)
self.hd_time_shift.setChecked(False)
self.loc_rate.setChecked(True)
self.loc_shuffle.setChecked(False)
self.loc_time_lapse.setChecked(True)
self.loc_time_shift.setChecked(False)
self.spatial_corr.setChecked(False)
self.grid.setChecked(False)
self.border.setChecked(True)
self.gradient.setChecked(False)
self.multiple_regression.setChecked(True)
self.inter_depend.setChecked(True)
self.theta_cell.setChecked(False)
self.theta_skip_cell.setChecked(False)
self.lfp_spectrum.setChecked(False)
self.spike_phase.setChecked(False)
self.phase_lock.setChecked(False)
self.lfp_spike_causality.setChecked(False)
elif cell_type == "Gradient":
self.wave_property.setChecked(True)
self.isi.setChecked(True)
self.isi_corr.setChecked(True)
self.burst.setChecked(False)
self.speed.setChecked(True)
self.ang_vel.setChecked(True)
self.hd_rate.setChecked(False)
self.hd_shuffle.setChecked(False)
self.hd_time_lapse.setChecked(False)
self.hd_time_shift.setChecked(False)
self.loc_rate.setChecked(True)
self.loc_shuffle.setChecked(False)
self.loc_time_lapse.setChecked(True)
self.loc_time_shift.setChecked(False)
self.spatial_corr.setChecked(False)
self.grid.setChecked(False)
self.border.setChecked(False)
self.gradient.setChecked(True)
self.multiple_regression.setChecked(True)
self.inter_depend.setChecked(True)
self.theta_cell.setChecked(False)
self.theta_skip_cell.setChecked(False)
self.lfp_spectrum.setChecked(False)
self.spike_phase.setChecked(False)
self.phase_lock.setChecked(False)
self.lfp_spike_causality.setChecked(False)
elif cell_type == "HDxPlace":
self.wave_property.setChecked(True)
self.isi.setChecked(True)
self.isi_corr.setChecked(True)
self.burst.setChecked(False)
self.speed.setChecked(True)
self.ang_vel.setChecked(True)
self.hd_rate.setChecked(True)
self.hd_shuffle.setChecked(True)
self.hd_time_lapse.setChecked(True)
self.hd_time_shift.setChecked(True)
self.loc_rate.setChecked(True)
self.loc_shuffle.setChecked(True)
self.loc_time_lapse.setChecked(True)
self.loc_time_shift.setChecked(True)
self.spatial_corr.setChecked(True)
self.grid.setChecked(False)
self.border.setChecked(False)
self.gradient.setChecked(False)
self.multiple_regression.setChecked(True)
self.inter_depend.setChecked(True)
self.theta_cell.setChecked(False)
self.theta_skip_cell.setChecked(False)
self.lfp_spectrum.setChecked(False)
self.spike_phase.setChecked(False)
self.phase_lock.setChecked(False)
self.lfp_spike_causality.setChecked(False)
elif cell_type == "Theta-rhythmic":
self.wave_property.setChecked(True)
self.isi.setChecked(True)
self.isi_corr.setChecked(True)
self.burst.setChecked(True)
self.speed.setChecked(True)
self.ang_vel.setChecked(True)
self.hd_rate.setChecked(False)
self.hd_shuffle.setChecked(False)
self.hd_time_lapse.setChecked(False)
self.hd_time_shift.setChecked(False)
self.loc_rate.setChecked(False)
self.loc_shuffle.setChecked(False)
self.loc_time_lapse.setChecked(False)
self.loc_time_shift.setChecked(False)
self.spatial_corr.setChecked(False)
self.grid.setChecked(False)
self.border.setChecked(False)
self.gradient.setChecked(False)
self.multiple_regression.setChecked(False)
self.inter_depend.setChecked(False)
self.theta_cell.setChecked(True)
self.theta_skip_cell.setChecked(False)
self.lfp_spectrum.setChecked(True)
self.spike_phase.setChecked(True)
self.phase_lock.setChecked(True)
self.lfp_spike_causality.setChecked(True)
elif cell_type == "Theta-skipping":
self.wave_property.setChecked(True)
self.isi.setChecked(True)
self.isi_corr.setChecked(True)
self.burst.setChecked(True)
self.speed.setChecked(True)
self.ang_vel.setChecked(True)
self.hd_rate.setChecked(False)
self.hd_shuffle.setChecked(False)
self.hd_time_lapse.setChecked(False)
self.hd_time_shift.setChecked(False)
self.loc_rate.setChecked(False)
self.loc_shuffle.setChecked(False)
self.loc_time_lapse.setChecked(False)
self.loc_time_shift.setChecked(False)
self.spatial_corr.setChecked(False)
self.grid.setChecked(False)
self.border.setChecked(False)
self.gradient.setChecked(False)
self.multiple_regression.setChecked(False)
self.inter_depend.setChecked(False)
self.theta_cell.setChecked(False)
self.theta_skip_cell.setChecked(True)
self.lfp_spectrum.setChecked(True)
self.spike_phase.setChecked(True)
self.phase_lock.setChecked(True)
self.lfp_spike_causality.setChecked(True)
[docs]class UiResults(QtWidgets.QDialog):
"""
NeuroChaT user interface for displaying the analysis results.
Also facilitates the exporting of results.
"""
def __init__(self, parent=None):
"""See class description."""
super().__init__(parent)
[docs] def setup_ui(self):
"""
Set up the GUI elements of the widget and their behaviour.
Clicking on the 'Export Results' button
calls the NeuroChaT_Ui.export_results() method.
See also
--------
PandasModel
"""
self.setObjectName(xlt_from_utf8("resultsWindow"))
self.setEnabled(True)
self.setFixedSize(900, 480)
self.setWindowTitle(QtWidgets.QApplication.translate(
"resultsWindow", "Analysis results", None))
# layout
self.layout = QtWidgets.QVBoxLayout()
self.table = QtWidgets.QTableView()
self.table.resizeColumnsToContents()
self.table.showGrid()
self.table.setSelectionMode(
QtWidgets.QAbstractItemView.ExtendedSelection)
self.export_button = add_push_button(
text="Export results", obj_name="Export")
self.layout.addWidget(self.export_button)
self.layout.addWidget(self.table)
self.setLayout(self.layout)
self.set_default()
[docs] def set_data(self, pd_model):
"""
Set the PandasModel as the data model for the table-view.
Parameters
----------
pd_model : PandasModel
PandasModel as the table-data
"""
self.table.setModel(pd_model)
[docs] def set_default(self):
"""
Not implemented.
Can be used for clearing the table and the data model
underneath.
"""
pass
# class UiConvert(QtWidgets.QDialog):
# def __init__(self, parent=None):
# super().__init__(parent)
# def setup_ui(self):
# self.setObjectName(xlt_from_utf8("convertWindow"))
# self.setEnabled(True)
# self.setFixedSize(324, 220)
# self.setWindowTitle("Convert Files")
# self.inp_format_label = add_label(self, (20, 10, 111, 17), "inpFormatLabel", "Convert From")
# self.file_format_box = add_combo_box(self, (20, 30, 111, 22), "fileFormatBox")
# self.file_format_box.addItems(["Axona", "Neuralynx"])
# self.browse_excel_button = add_push_button(self, (30, 60, 60, 23), "browseExcel", "Browse")
# self.filename_line = add_line_edit(self, (95, 60, 215, 23), "filename", "")
# self.filename_line.setText("Select Excel (.xls/.xlsx) file")
[docs]class UiParameters(QtWidgets.QDialog):
"""NeuroChaT user interface for setting analysis specific parameters."""
def __init__(self, parent=None):
"""See class description."""
super().__init__(parent)
self.parent = parent
self.setup_ui()
self.behaviour_ui()
[docs] def setup_ui(self):
"""Set the GUI elements for the widget."""
self.setObjectName(xlt_from_utf8("paramSetWindow"))
self.setEnabled(True)
self.setFixedSize(900, 480)
self.setWindowTitle(QtWidgets.QApplication.translate(
"paramSetWindow", "Parameter settings", None))
self.selectLabel = add_label(
self, (10, 10, 260, 17), "inpFormatLabel",
"Double click an analysis to set parameters")
self.param_list = QtWidgets.QListWidget(self)
self.param_list.setGeometry(QtCore.QRect(10, 30, 260, 420))
self.param_list.setObjectName(xlt_from_utf8("paramList"))
items = []
widget_names = []
for checkbox in self.parent.function_widget.findChildren(
QtWidgets.QCheckBox):
items.append(checkbox.text())
widget_names.append(checkbox.objectName())
self.param_list.addItems(items)
self.param_stack = QtWidgets.QStackedWidget(self)
self.param_stack.setGeometry(QtCore.QRect(290, 30, 560, 420))
self.param_stack.setObjectName(xlt_from_utf8("paramStack"))
self.param_stack.addWidget(self.isi_page())
self.param_stack.addWidget(self.isi_corr_page())
self.param_stack.addWidget(self.waveform_page())
self.param_stack.addWidget(self.theta_cell_page())
self.param_stack.addWidget(self.theta_skip_cell_page())
self.param_stack.addWidget(self.burst_page())
self.param_stack.addWidget(self.speed_page())
self.param_stack.addWidget(self.ang_vel_page())
self.param_stack.addWidget(self.hd_rate_page())
self.param_stack.addWidget(self.hd_shuffle_page())
self.param_stack.addWidget(self.hd_time_lapse_page())
self.param_stack.addWidget(self.hd_time_shift_page())
self.param_stack.addWidget(self.loc_rate_page())
self.param_stack.addWidget(self.loc_shuffle_page())
self.param_stack.addWidget(self.loc_time_lapse_page())
self.param_stack.addWidget(self.loc_time_shift_page())
self.param_stack.addWidget(self.spatial_corr_page())
self.param_stack.addWidget(self.grid_page())
self.param_stack.addWidget(self.border_page())
self.param_stack.addWidget(self.gradient_page())
self.param_stack.addWidget(self.multiple_regression_page())
self.param_stack.addWidget(self.inter_depend_page())
self.param_stack.addWidget(self.lfp_spectrum_page())
self.param_stack.addWidget(self.spike_phase_page())
self.param_stack.addWidget(self.phase_lock_page())
self.param_stack.addWidget(self.lfp_spike_causality_page())
[docs] def behaviour_ui(self):
"""Set the behaviour of the GUI elements."""
self.param_list.itemActivated.connect(self.change_stack_page)
self.loc_rate_filter.activated[str].connect(self.set_loc_rate_filter)
self.spatial_corr_filter.activated[str].connect(
self.set_spat_corr_filter)
self.param_list.itemActivated.connect(self.change_stack_page)
[docs] def change_stack_page(self):
"""
Change the stacked widgets of parameter settings.
This is updated according to the
analysis selected from the list on left of the window.
"""
self.param_stack.setCurrentWidget(
self.param_stack.widget(self.param_list.currentRow()))
[docs] def set_loc_rate_filter(self, filt_type):
"""Set the ui elements for the filters for firing rate map."""
if filt_type == "Gaussian":
self.loc_rate_kern_len.setSingleStep(1)
self.loc_rate_kern_len.setValue(3)
elif filt_type == "Box":
self.loc_rate_kern_len.setSingleStep(2)
self.loc_rate_kern_len.setValue(5)
[docs] def set_spat_corr_filter(self, filt_type):
"""Set the ui elements for the filters for autocorrelation of fmap."""
if filt_type == "Gaussian":
self.spatial_corr_kern_len.setSingleStep(1)
self.spatial_corr_kern_len.setValue(3)
elif filt_type == "Box":
self.spatial_corr_kern_len.setSingleStep(2)
self.spatial_corr_kern_len.setValue(5)
[docs] def waveform_page(self):
"""Set the ui elements for the 'Waveform Analysis' parameters."""
widget = ScrollableWidget()
self.waveform_gb1 = add_group_box(title="", obj_name="waveform_gb1")
box_layout = QtWidgets.QVBoxLayout()
box_layout.addWidget(QtWidgets.QLabel("No parameter to set"))
self.waveform_gb1.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.waveform_gb1)
widget.setContents(layout)
return widget
[docs] def isi_page(self):
"""Set the ui elements for the 'isi' analysis parameters."""
widget = ScrollableWidget()
# Box- 1
self.isi_gb1 = add_group_box(title="Histogram", obj_name="isi_gb1")
self.isi_bin = add_spin_box(min_val=1, max_val=50, obj_name="isi_bin")
self.isi_bin.setValue(1)
self.isi_length = add_spin_box(
min_val=10, max_val=1000, obj_name="isi_length")
self.isi_length.setValue(200)
box_layout = ParamBoxLayout()
box_layout.addRow("Histogram Binsize",
self.isi_bin, "ms [range: 1-50]")
box_layout.addRow("Histogram Length", self.isi_length,
"ms [range: 10-1000]")
self.isi_gb1.setLayout(box_layout)
# Box- 2
self.isi_gb2 = add_group_box(title="log-log plot", obj_name="isi_gb2")
self.isi_log_no_bins = add_spin_box(
min_val=10, max_val=100, obj_name="isiLogNoBins")
self.isi_log_no_bins.setValue(70)
self.isi_log_length = add_spin_box(
min_val=10, max_val=1000, obj_name="isiLogLength")
self.isi_log_length.setValue(350)
box_layout = ParamBoxLayout()
box_layout.addRow("No. of Histogram Bins",
self.isi_log_no_bins, "[range: 10-100]")
box_layout.addRow("Histogram Length",
self.isi_log_length, "ms [range: 10-1000]")
self.isi_gb2.setLayout(box_layout)
# Box- 3
self.isi_gb3 = add_group_box(title="Refractory", obj_name="isi_gb3")
self.isi_refractory = add_double_spin_box(
min_val=0, max_val=10, obj_name="isi_refractory")
self.isi_refractory.setSingleStep(0.1)
self.isi_refractory.setValue(2)
box_layout = ParamBoxLayout()
box_layout.addRow(
"Refractory Threshold", self.isi_refractory, "ms [range 0 - 10]")
self.isi_gb3.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.isi_gb1)
layout.addWidget(self.isi_gb2)
layout.addWidget(self.isi_gb3)
widget.setContents(layout)
return widget
[docs] def isi_corr_page(self):
"""Set the ui elements for the 'isi_corr' analysis parameters."""
widget = ScrollableWidget()
# Box- 1
self.isi_corr_gb1 = add_group_box(
title="Zoomed In", obj_name="isi_corr_gb1")
self.isi_corr_bin_short = add_spin_box(
min_val=1, max_val=10, obj_name="isi_corr_bin_short")
self.isi_corr_bin_short.setValue(1)
self.isi_corr_len_short = add_spin_box(
min_val=5, max_val=50, obj_name="isi_corr_len_short")
self.isi_corr_len_short.setValue(10)
box_layout = ParamBoxLayout()
box_layout.addRow("Autcorrelation Histogram Binsize",
self.isi_corr_bin_short, "ms [range: 1-10]")
box_layout.addRow("Autocorrelation Length",
self.isi_corr_len_short, "ms [range: 5-50]")
self.isi_corr_gb1.setLayout(box_layout)
# Box- 2
self.isi_corr_gb2 = add_group_box(
title="Zoomed Out", obj_name="isi_corr_gb2")
self.isi_corr_bin_long = add_spin_box(
min_val=1, max_val=50, obj_name="isi_corr_bin_long")
self.isi_corr_bin_long.setValue(1)
self.isi_corr_len_long = add_spin_box(
min_val=10, max_val=1000, obj_name="isi_corr_len_long")
self.isi_corr_len_long.setValue(350)
box_layout = ParamBoxLayout()
box_layout.addRow("Autcorrelation Histogram Binsize",
self.isi_corr_bin_long, "ms [range: 1-50]")
box_layout.addRow("Autocorrelation Length",
self.isi_corr_len_long, "ms [range: 10-1000]")
self.isi_corr_gb2.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.isi_corr_gb1)
layout.addWidget(self.isi_corr_gb2)
widget.setContents(layout)
return widget
[docs] def theta_cell_page(self):
"""Set the ui elements for the 'theta_cell' analysis parameters."""
widget = ScrollableWidget()
self.theta_cell_gb1 = add_group_box(
title="Curve Fitting Parameters", obj_name="theta_cell_gb1")
self.theta_cell_freq_min = add_double_spin_box(
min_val=1, max_val=10, obj_name="theta_cell_freq_min")
self.theta_cell_freq_min.setValue(6)
self.theta_cell_freq_min.setSingleStep(0.5)
self.theta_cell_freq_max = add_double_spin_box(
min_val=8, max_val=16, obj_name="theta_cell_freq_max")
self.theta_cell_freq_max.setValue(12)
self.theta_cell_freq_max.setSingleStep(0.5)
self.theta_cell_freq_start = add_double_spin_box(
min_val=5, max_val=10, obj_name="theta_cell_freq_start")
self.theta_cell_freq_start.setValue(6)
self.theta_cell_freq_start.setSingleStep(0.5)
self.theta_cell_tau1_max = add_double_spin_box(
min_val=0.5, max_val=15, obj_name="theta_cell_tau1_max")
self.theta_cell_tau1_max.setValue(5)
self.theta_cell_tau1_max.setSingleStep(0.5)
self.theta_cell_tau1_start = add_double_spin_box(
min_val=0, max_val=15, obj_name="theta_cell_tau1_start")
self.theta_cell_tau1_start.setValue(0.1)
self.theta_cell_tau1_start.setSingleStep(0.05)
self.theta_cell_tau2_max = add_double_spin_box(
min_val=0, max_val=0.1, obj_name="theta_cell_tau2_max")
self.theta_cell_tau2_max.setValue(0.05)
self.theta_cell_tau2_max.setSingleStep(0.005)
self.theta_cell_tau2_start = add_double_spin_box(
min_val=0, max_val=0.1, obj_name="theta_cell_tau2_start")
self.theta_cell_tau2_start.setValue(0.05)
self.theta_cell_tau2_start.setSingleStep(0.005)
box_layout = ParamBoxLayout()
box_layout.addRow(
"Minimum Frequency", self.theta_cell_freq_min,
"Hz [range: 1-10, step: 0.5]")
box_layout.addRow(
"Maximum Frequency", self.theta_cell_freq_max,
"Hz [range: 8-16, step: 0.5]")
box_layout.addRow(
"Starting Frequency", self.theta_cell_freq_start,
"Hz [range: 5-10, step: 0.5]")
box_layout.addRow(
"Max Time Constant (Tau-1)",
self.theta_cell_tau1_max,
"sec [range: 0.5-10, step: 0.5]")
box_layout.addRow(
"Starting Tau-1", self.theta_cell_tau1_start,
"sec [range: 0-15, step: 0.05]")
box_layout.addRow(
"Gaussian Time Constant (Tau-2)",
self.theta_cell_tau2_max,
"sec [range: 0-0.1, step: 0.005]")
box_layout.addRow(
"Start of Tau-2", self.theta_cell_tau2_start,
"sec [range: 0-0.1, step: 0.005]")
self.theta_cell_gb1.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.theta_cell_gb1)
widget.setContents(layout)
return widget
[docs] def theta_skip_cell_page(self):
"""Set the ui elements for the 'theta_skip_cell' analysis parameters."""
widget = ScrollableWidget()
self.theta_skip_cell_gb1 = add_group_box(
title="Curve Fitting Parameters", obj_name="theta_skip_cell_gb1")
box_layout = QtWidgets.QVBoxLayout()
box_layout.addWidget(QtWidgets.QLabel(
"Uses the parameters from 'Theta-modulated Cell Index' analysis.\n" +
"The fitting parameters for 2nd frequency component are derived " +
"from the 1st component"))
self.theta_skip_cell_gb1.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.theta_skip_cell_gb1)
widget.setContents(layout)
return widget
[docs] def burst_page(self):
"""Set the ui elements for the 'burst' analysis parameters."""
widget = ScrollableWidget()
# Box- 1
self.burst_gb1 = add_group_box(
title="Bursting Conditions", obj_name="burst_gb1")
self.burst_thresh = add_spin_box(
min_val=1, max_val=15, obj_name="burst_thresh")
self.burst_thresh.setValue(5)
self.spikes_to_burst = add_spin_box(
min_val=2, max_val=10, obj_name="spikesToBurst")
self.spikes_to_burst.setValue(2)
self.ibi_thresh = add_spin_box(
min_val=5, max_val=1000, obj_name="ibi_thresh")
self.ibi_thresh.setValue(50)
box_layout = ParamBoxLayout()
box_layout.addRow("Burst Threshold",
self.burst_thresh, "ms [range: 1-15]")
box_layout.addRow("Spikes to Burst",
self.spikes_to_burst, "[range: 2-10]")
box_layout.addRow("Interburst Interval Lower Cutoff",
self.ibi_thresh, "ms [range: 5-1000]")
self.burst_gb1.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.burst_gb1)
widget.setContents(layout)
return widget
[docs] def speed_page(self):
"""Set the ui elements for the 'speed' analysis parameters."""
widget = ScrollableWidget()
self.speed_gb1 = add_group_box(
title="Analyses Parameters", obj_name="speed_gb1")
self.speed_bin = add_spin_box(
min_val=1, max_val=10, obj_name="speed_bin")
self.speed_bin.setValue(1)
self.speed_min = add_spin_box(
min_val=0, max_val=10, obj_name="speed_min")
self.speed_min.setValue(0)
self.speed_max = add_spin_box(
min_val=10, max_val=200, obj_name="speed_max")
self.speed_max.setValue(40)
box_layout = ParamBoxLayout()
box_layout.addRow("Speed Binsize", self.speed_bin,
"cm/sec [range: 1-10]")
box_layout.addRow("Minimum Speed", self.speed_min,
"cm/sec [range: 0-10]")
box_layout.addRow("Maximum Speed", self.speed_max,
"cm/sec [range: 10-200]")
self.speed_gb1.setLayout(box_layout)
self.speed_gb2 = add_group_box(
title="Smoothing Box Kernel Length", obj_name="speed_gb2")
self.speed_kern_len = add_spin_box(
min_val=1, max_val=25, obj_name="speedKernLen")
self.speed_kern_len.setValue(3)
self.speed_kern_len.setSingleStep(2)
# set validator in controller to accept only the odd numbers
self.speed_rate_kern_len = add_spin_box(
min_val=1, max_val=7, obj_name="speed_rate_kern_len")
self.speed_rate_kern_len.setValue(3)
self.speed_rate_kern_len.setSingleStep(2)
box_layout = ParamBoxLayout()
box_layout.addRow("Speed", self.speed_kern_len,
"samples [range: 1-25, odds]")
box_layout.addRow("Spike Rate", self.speed_rate_kern_len,
"bins [range: 1-7, odds]")
self.speed_gb2.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.speed_gb1)
layout.addWidget(self.speed_gb2)
widget.setContents(layout)
return widget
[docs] def ang_vel_page(self):
"""Set the ui elements for the 'ang_vel' analysis parameters."""
widget = ScrollableWidget()
self.ang_vel_gb1 = add_group_box(
title="Analyses Parameters", obj_name="ang_vel_gb1")
self.ang_vel_bin = add_spin_box(
min_val=5, max_val=50, obj_name="ang_vel_bin")
self.ang_vel_bin.setValue(10)
self.ang_vel_bin.setSingleStep(5)
self.ang_vel_min = add_spin_box(
min_val=-500, max_val=0, obj_name="ang_vel_min")
self.ang_vel_min.setValue(-200)
self.ang_vel_max = add_spin_box(
min_val=0, max_val=500, obj_name="ang_vel_max")
self.ang_vel_max.setValue(200)
self.ang_vel_cutoff = add_spin_box(
min_val=0, max_val=100, obj_name="ang_vel_cutoff")
self.ang_vel_cutoff.setValue(10)
box_layout = ParamBoxLayout()
box_layout.addRow("Angular Velocity Binsize",
self.ang_vel_bin, "deg/sec [range: 1-50]")
box_layout.addRow("Minimum Velocity", self.ang_vel_min,
"deg/sec [range: -500 to 0]")
box_layout.addRow("Maximum Velocity", self.ang_vel_max,
"deg/sec [range: 0 to 500]")
box_layout.addRow("Cutoff Velocity", self.ang_vel_cutoff,
"deg/sec [range: 0 to 100]")
self.ang_vel_gb1.setLayout(box_layout)
self.ang_vel_gb2 = add_group_box(
title="Smoothing Box Kernel Length", obj_name="ang_vel_gb2")
self.ang_vel_kern_len = add_spin_box(
min_val=1, max_val=25, obj_name="ang_vel_kern_len")
self.ang_vel_kern_len.setValue(3)
self.ang_vel_kern_len.setSingleStep(2)
# Set controller to recieve odd values
self.ang_vel_rate_kern_len = add_spin_box(
min_val=1, max_val=5, obj_name="ang_vel_rate_kern_len")
self.ang_vel_rate_kern_len.setValue(3)
self.ang_vel_rate_kern_len.setSingleStep(2)
box_layout = ParamBoxLayout()
box_layout.addRow("Head Direction", self.ang_vel_kern_len,
"samples [range: 1-25, odds]")
box_layout.addRow(
"Spike Rate", self.ang_vel_rate_kern_len, "bins [range: 1-5, odds]")
self.ang_vel_gb2.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.ang_vel_gb1)
layout.addWidget(self.ang_vel_gb2)
widget.setContents(layout)
return widget
[docs] def hd_rate_page(self):
"""Set the ui elements for the 'hd_rate' analysis parameters."""
widget = ScrollableWidget()
self.hd_rate_gb1 = add_group_box(
title="Analyses Parameters", obj_name="hd_rate_gb1")
self.hd_bin = add_combo_box(obj_name="hd_bin")
hd_bin_items = [str(d) for d in range(1, 360) if 360 %
d == 0 and d >= 5 and d <= 45]
self.hd_bin.addItems(hd_bin_items)
self.hd_ang_vel_cutoff = add_spin_box(
min_val=0, max_val=100, obj_name="hd_ang_vel_cutoff")
self.hd_ang_vel_cutoff.setValue(10)
self.hd_ang_vel_cutoff.setSingleStep(5)
self.hd_show_predicted = add_check_box(obj_name='hd_show_predicted')
self.hd_show_predicted.setChecked(True)
box_layout = ParamBoxLayout()
box_layout.addRow("Head Directional Binsize", self.hd_bin, "degree")
box_layout.addRow("Angular Velocity Cutoff",
self.hd_ang_vel_cutoff, "deg/sec [range: 0-100, step: 5]")
box_layout.addRow(
"Show predicted head directional rate",
self.hd_show_predicted, "Boolean value")
self.hd_rate_gb1.setLayout(box_layout)
self.hd_rate_gb2 = add_group_box(
title="Smoothing Box Kernel Length", obj_name="hd_rate_gb2")
self.hd_rate_kern_len = add_spin_box(
min_val=1, max_val=11, obj_name="hd_rate_kern_len")
self.hd_rate_kern_len.setValue(5)
self.hd_rate_kern_len.setSingleStep(2)
box_layout = ParamBoxLayout()
box_layout.addRow("Spike Rate", self.hd_rate_kern_len,
"bins [range: 1-11, odds]")
self.hd_rate_gb2.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.hd_rate_gb1)
layout.addWidget(self.hd_rate_gb2)
widget.setContents(layout)
return widget
[docs] def hd_shuffle_page(self):
"""Set the ui elements for the 'hd_shuffle' analysis parameters."""
widget = ScrollableWidget()
self.hd_shuffle_gb1 = add_group_box(
title="Analyses Parameters", obj_name="hd_shuffle_gb1")
self.hd_shuffle_total = add_spin_box(
min_val=100, max_val=10000, obj_name="hd_shuffle_total")
self.hd_shuffle_total.setValue(500)
self.hd_shuffle_total.setSingleStep(50)
self.hd_shuffle_limit = add_spin_box(
min_val=0, max_val=500, obj_name="hd_shuffle_limit")
self.hd_shuffle_limit.setValue(0)
self.hd_shuffle_limit.setSingleStep(2)
self.hd_shuffle_bins = add_spin_box(
min_val=10, max_val=200, obj_name="hd_shuffle_bins")
self.hd_shuffle_bins.setValue(100)
self.hd_shuffle_bins.setSingleStep(10)
box_layout = ParamBoxLayout()
box_layout.addRow("No of Shuffles", self.hd_shuffle_total,
"[range: 100-10000, step: 50]")
box_layout.addRow("Shuffling Limit", self.hd_shuffle_limit,
"sec [range: 0-500, 0 for Random, step: 2]")
box_layout.addRow("No of Histogram Bins",
self.hd_shuffle_bins, "[range: 10-200, step: 10]")
self.hd_shuffle_gb1.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.hd_shuffle_gb1)
widget.setContents(layout)
return widget
[docs] def hd_time_lapse_page(self):
"""Set the ui elements for the 'hd_time_lapse' analysis parameters."""
widget = ScrollableWidget()
self.hd_time_lapse_gb1 = add_group_box(
title="", obj_name="hd_time_lapse_gb1")
box_layout = QtWidgets.QVBoxLayout()
box_layout.addWidget(QtWidgets.QLabel("No parameter to set"))
self.hd_time_lapse_gb1.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.hd_time_lapse_gb1)
widget.setContents(layout)
return widget
[docs] def hd_time_shift_page(self):
"""Set the ui elements for the 'hd_time_shift' analysis parameters."""
widget = ScrollableWidget()
self.hd_time_shift_gb1 = add_group_box(
title="Shift Specifications", obj_name="hdTimeShift_gb1")
self.hd_shift_max = add_spin_box(
min_val=1, max_val=100, obj_name="hd_shift_max")
self.hd_shift_max.setValue(10)
self.hd_shift_min = add_spin_box(
min_val=-100, max_val=-1, obj_name="hd_shift_min")
self.hd_shift_min.setValue(-10)
self.hd_shift_step = add_spin_box(
min_val=1, max_val=3, obj_name="hd_shift_step")
self.hd_shift_step.setValue(1)
box_layout = ParamBoxLayout()
box_layout.addRow("Maximum Shift", self.hd_shift_max,
"indices [range: 1 to 100]")
box_layout.addRow("Minimum Shift", self.hd_shift_min,
"indices [range: -1 to -100]")
box_layout.addRow("Index Steps", self.hd_shift_step, "[1, 2, 3]")
self.hd_time_shift_gb1.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.hd_time_shift_gb1)
widget.setContents(layout)
return widget
[docs] def loc_rate_page(self):
"""Set the ui elements for the 'loc_rate' analysis parameters."""
widget = ScrollableWidget()
# Box- 1
self.loc_rate_gb1 = add_group_box(
title="Firing Map", obj_name="loc_rate_gb1")
self.loc_pixel_size = add_spin_box(
min_val=1, max_val=100, obj_name="loc_pixel_size")
self.loc_pixel_size.setValue(3)
self.loc_chop_bound = add_spin_box(
min_val=3, max_val=20, obj_name="loc_chop_bound")
self.loc_chop_bound.setValue(5)
box_layout = ParamBoxLayout()
box_layout.addRow(
"Pixel Size", self.loc_pixel_size, "cm [range: 1-100]")
box_layout.addRow(
"Bound for Chopping Edges",
self.loc_chop_bound, "pixels [range: 3-20]")
self.loc_rate_gb1.setLayout(box_layout)
# Box 2
self.loc_rate_gb2 = add_group_box(
title="Place Field", obj_name="loc_rate_gb2")
self.loc_field_thresh = add_double_spin_box(
min_val=0.01, max_val=1.0, obj_name="loc_field_thresh")
self.loc_field_thresh.setValue(0.20)
self.loc_field_thresh.setSingleStep(0.01)
self.loc_field_smooth = add_check_box(obj_name='loc_field_smooth')
self.loc_field_smooth.setChecked(False)
self.loc_field_bins = add_spin_box(
min_val=3, max_val=50, obj_name="loc_field_bins")
self.loc_field_bins.setValue(9)
box_layout = ParamBoxLayout()
box_layout.addRow(
"Place Field Threshold",
self.loc_field_thresh, "[range: 0.01-1, step: 0.01]")
box_layout.addRow(
"Compute Place Field from Smoothed Map",
self.loc_field_smooth, "True or False")
box_layout.addRow(
"Required Adjacent Bins for Place Field",
self.loc_field_bins, "[range: 5-50]")
self.loc_rate_gb2.setLayout(box_layout)
# Box- 3
self.loc_rate_gb3 = add_group_box(
title="Smoothing Box Kernel", obj_name="loc_rate_gb3")
self.loc_rate_filter = add_combo_box(obj_name="loc_rate_filter")
self.loc_rate_filter.addItems(["Box", "Gaussian"])
self.loc_rate_kern_len = add_spin_box(
min_val=1, max_val=11, obj_name="loc_rate_kern_len")
self.loc_rate_kern_len.setValue(5)
self.loc_rate_kern_len.setSingleStep(2)
# Change step size to 0.5 if Gaussian is selected
box_layout = ParamBoxLayout()
box_layout.addRow(
"Smoothing Filter", self.loc_rate_filter, "")
box_layout.addRow(
"Spike Rate Pixels/Sigma",
self.loc_rate_kern_len, "[range: 1-11]\n\r Box: odds")
self.loc_rate_gb3.setLayout(box_layout)
# Box 4
self.loc_style = add_combo_box(obj_name="loc_style")
self.loc_style.addItems(
["contour", "digitized", "interpolated"])
self.loc_colormap = add_combo_box(obj_name="loc_colormap")
self.loc_colormap.addItems(
["viridis", "default", "gray", "plasma",
"inferno", "magma", "cividis"])
self.loc_contour_levels = add_spin_box(
min_val=4, max_val=12, obj_name="loc_contour_levels")
self.loc_contour_levels.setValue(5)
self.loc_rate_gb4 = add_group_box(
title="Plotting Style", obj_name="loc_rate_gb4")
box_layout = ParamBoxLayout()
box_layout.addRow(
"Firing Rate Map Style", self.loc_style, "")
box_layout.addRow(
"Firing Rate Map Colormap", self.loc_colormap, "")
box_layout.addRow(
"Firing Rate Map Contour Levels",
self.loc_contour_levels, "range [4-12]")
self.loc_rate_gb4.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.loc_rate_gb1)
layout.addWidget(self.loc_rate_gb2)
layout.addWidget(self.loc_rate_gb3)
layout.addWidget(self.loc_rate_gb4)
widget.setContents(layout)
return widget
[docs] def loc_shuffle_page(self):
"""Set the ui elements for the 'loc_shuffle' analysis parameters."""
widget = ScrollableWidget()
self.loc_shuffle_gb1 = add_group_box(
title="Analyses Parameters", obj_name="loc_shuffle_gb1")
self.loc_shuffle_total = add_spin_box(
min_val=100, max_val=10000, obj_name="loc_shuffle_total")
self.loc_shuffle_total.setValue(500)
self.loc_shuffle_total.setSingleStep(50)
self.loc_shuffle_limit = add_spin_box(
min_val=0, max_val=500, obj_name="loc_shuffle_limit")
self.loc_shuffle_limit.setValue(0)
self.loc_shuffle_limit.setSingleStep(2)
self.loc_shuffle_nbins = add_spin_box(
min_val=10, max_val=200, obj_name="loc_shuffle_nbins")
self.loc_shuffle_nbins.setValue(100)
self.loc_shuffle_nbins.setSingleStep(10)
box_layout = ParamBoxLayout()
box_layout.addRow("No of Shuffles", self.loc_shuffle_total,
"[range: 100-10000, step: 50]")
box_layout.addRow("Shuffling Limit", self.loc_shuffle_limit,
"sec [range: 0-500, 0 for Random, step: 2]")
box_layout.addRow("No of Histogram Bins",
self.loc_shuffle_nbins, "[range: 10-200, step: 10]")
self.loc_shuffle_gb1.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.loc_shuffle_gb1)
widget.setContents(layout)
return widget
[docs] def loc_time_lapse_page(self):
"""Set the ui elements for the 'loc_time_lapse' analysis parameters."""
widget = ScrollableWidget()
self.loc_time_lapse_gb1 = add_group_box(
title="", obj_name="loc_time_lapse_gb1")
box_layout = QtWidgets.QVBoxLayout()
box_layout.addWidget(QtWidgets.QLabel(
"No parameters to set, plotting style is in Spike Rate vs Location"))
self.loc_time_lapse_gb1.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.loc_time_lapse_gb1)
widget.setContents(layout)
return widget
[docs] def loc_time_shift_page(self):
"""Set the ui elements for the 'loc_time_shift' analysis parameters."""
widget = ScrollableWidget()
self.loc_time_shift_gb1 = add_group_box(
title="Shift Specifications", obj_name="loc_time_shift_gb1")
self.loc_shift_max = add_spin_box(
min_val=1, max_val=100, obj_name="loc_shift_max")
self.loc_shift_max.setValue(10)
self.loc_shift_min = add_spin_box(
min_val=-100, max_val=-1, obj_name="loc_shift_min")
self.loc_shift_min.setValue(-10)
self.loc_shift_step = add_spin_box(
min_val=1, max_val=3, obj_name="loc_shift_step")
self.loc_shift_step.setValue(1)
box_layout = ParamBoxLayout()
box_layout.addRow("Maximum Shift", self.loc_shift_max,
"indices [range: 1 to 100]")
box_layout.addRow("Minimum Shift", self.loc_shift_min,
"indices [range: -1 to -100]")
box_layout.addRow("Index Steps", self.loc_shift_step, "[1, 2, 3]")
self.loc_time_shift_gb1.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.loc_time_shift_gb1)
widget.setContents(layout)
return widget
[docs] def spatial_corr_page(self):
"""Set the ui elements for the 'spatial_corr' analysis parameters."""
widget = ScrollableWidget()
# Box- 1
self.spatial_corr_gb1 = add_group_box(
title="2D Correlation", obj_name="spatial_corr_gb1")
self.spatial_corr_min_obs = add_spin_box(
min_val=0, max_val=100, obj_name="spatial_corr_min_obs")
self.spatial_corr_min_obs.setValue(20)
box_layout = ParamBoxLayout()
box_layout.addRow("Minimum No. of Valid Pixels",
self.spatial_corr_min_obs, "[range: 1-100]")
self.spatial_corr_gb1.setLayout(box_layout)
# Box- 2
self.spatial_corr_gb2 = add_group_box(
title="Rotational Correlation", obj_name="spatial_corr_gb2")
self.rot_corr_bin = add_combo_box(obj_name="rot_corr_bin")
rot_corr_bin_items = [str(d) for d in range(
1, 360) if 360 % d == 0 and d >= 3 and d <= 45]
self.rot_corr_bin.addItems(rot_corr_bin_items)
box_layout = ParamBoxLayout()
box_layout.addRow("Rotational Correlation Binsize",
self.rot_corr_bin, "degree")
self.spatial_corr_gb2.setLayout(box_layout)
# Box- 3
self.spatial_corr_gb3 = add_group_box(
title="Smoothing Box Kernel", obj_name="spatial_corr_gb3")
self.spatial_corr_filter = add_combo_box(
obj_name="spatial_corr_filter")
self.spatial_corr_filter.addItems(["Box", "Gaussian"])
self.spatial_corr_kern_len = add_spin_box(
min_val=1, max_val=11, obj_name="spatial_corr_kern_len")
self.spatial_corr_kern_len.setValue(5)
self.spatial_corr_kern_len.setSingleStep(2)
# Change step size to 0.5 if Gaussian is selected
box_layout = ParamBoxLayout()
box_layout.addRow("Smoothing Filter", self.spatial_corr_filter, "")
box_layout.addRow("Correlation Pixels Num/Sigma", self.spatial_corr_kern_len,
"[range: 1-11]\n\r Box: odds")
self.spatial_corr_gb3.setLayout(box_layout)
# Box- 4
self.spatial_corr_style = add_combo_box(
obj_name="spatial_corr_style")
self.spatial_corr_style.addItems(
["contour", "digitized"])
self.spatial_corr_colormap = add_combo_box(
obj_name="spatial_corr_colormap")
self.spatial_corr_colormap.addItems(
["coolwarm", "default", "seismic", "bwr", "RdBu",
"viridis", "gray", "plasma", "magma", "cividis"])
self.spatial_corr_contour_levels = add_spin_box(
min_val=4, max_val=12, obj_name="spatial_corr_contour_levels")
self.spatial_corr_contour_levels.setValue(10)
self.spatial_corr_gb4 = add_group_box(
title="Plotting Style", obj_name="spatial_corr_gb4")
box_layout = ParamBoxLayout()
box_layout.addRow(
"Correlation Map Style", self.spatial_corr_style, "")
box_layout.addRow(
"Correlation Map Colormap", self.spatial_corr_colormap, "")
box_layout.addRow(
"Correlation Map Contour Levels", self.spatial_corr_contour_levels,
"range [4-12]")
self.spatial_corr_gb4.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.spatial_corr_gb1)
layout.addWidget(self.spatial_corr_gb2)
layout.addWidget(self.spatial_corr_gb3)
layout.addWidget(self.spatial_corr_gb4)
widget.setContents(layout)
return widget
[docs] def grid_page(self):
"""Set the ui elements for the 'grid' analysis parameters."""
widget = ScrollableWidget()
self.grid_gb1 = add_group_box(
title="Analyses Parameters", obj_name="grid_gb1")
self.grid_ang_tol = add_spin_box(
min_val=1, max_val=5, obj_name="grid_ang_tol")
self.grid_ang_tol.setValue(2)
self.grid_ang_bin = add_combo_box(obj_name="grid_ang_bin")
grid_ang_bin_items = [str(d) for d in range(
1, 360) if 360 % d == 0 and d >= 3 and d <= 45]
self.grid_ang_bin.addItems(grid_ang_bin_items)
box_layout = ParamBoxLayout()
box_layout.addRow("Angular Tolerance",
self.grid_ang_tol, "degree [range: 1 to 5]")
box_layout.addRow("Angular Binsize", self.grid_ang_bin, "degree")
self.grid_gb1.setLayout(box_layout)
self.grid_gb2 = add_group_box(
title="Plotting Style", obj_name="grid_gb2")
box_layout = ParamBoxLayout()
box_layout.addWidget(QtWidgets.QLabel(
"Plotting Style is managed in Spatial Autocorrelation"))
self.grid_gb2.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.grid_gb1)
layout.addWidget(self.grid_gb2)
widget.setContents(layout)
return widget
[docs] def border_page(self):
"""Set the ui elements for the 'border' analysis parameters."""
widget = ScrollableWidget()
self.border_gb1 = add_group_box(
title="Analyses Parameters", obj_name="border_gb1")
self.border_firing_thresh = add_double_spin_box(
min_val=0, max_val=1, obj_name="border_firing_thresh")
self.border_firing_thresh.setValue(0.1)
self.border_firing_thresh.setSingleStep(0.05)
self.border_ang_bin = add_combo_box(obj_name="border_ang_bin")
border_ang_bin_items = [str(d) for d in range(
1, 360) if 360 % d == 0 and d >= 3 and d <= 45]
self.border_ang_bin.addItems(border_ang_bin_items)
self.border_stair_steps = add_spin_box(
min_val=4, max_val=10, obj_name="border_stair_steps")
self.border_stair_steps.setValue(5)
box_layout = ParamBoxLayout()
box_layout.addRow("Firing Threshold", self.border_firing_thresh,
"degree [range: 0 to 1, step: 0.05]")
box_layout.addRow("Angular Binsize", self.border_ang_bin, "degree")
box_layout.addRow("Stair Plot Steps",
self.border_stair_steps, "4 to 10")
self.border_gb1.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.border_gb1)
widget.setContents(layout)
return widget
[docs] def gradient_page(self):
"""Set the ui elements for the 'gradient' analysis parameters."""
widget = ScrollableWidget()
self.gradient_gb1 = add_group_box(
title="Gompertz Function Parameters", obj_name="gradient_gb1")
self.grad_asymp_lim = add_double_spin_box(
min_val=0.1, max_val=1, obj_name="grad_asymp_lim")
self.grad_asymp_lim.setValue(0.25)
self.grad_asymp_lim.setSingleStep(0.05)
self.grad_displace_lim = add_double_spin_box(
min_val=0.1, max_val=1, obj_name="grad_displace_lim")
self.grad_displace_lim.setValue(0.25)
self.grad_displace_lim.setSingleStep(0.05)
self.grad_growth_rate_lim = add_double_spin_box(
min_val=0.1, max_val=1, obj_name="grad_growth_rate_lim")
self.grad_growth_rate_lim.setValue(0.5)
self.grad_growth_rate_lim.setSingleStep(0.05)
box_layout = ParamBoxLayout()
box_layout.addRow("Asymptote a \xb1 ", self.grad_asymp_lim,
"*a [range 0.1 to 1, step: 0.05]")
box_layout.addRow("Displacement b \xb1 ",
self.grad_displace_lim, "*b [range 0.1 to 1, step: 0.05]")
box_layout.addRow(
"Growth Rate c \xb1 ", self.grad_growth_rate_lim,
"*c [range 0.1 to 1, step: 0.05]")
self.gradient_gb1.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.gradient_gb1)
widget.setContents(layout)
return widget
[docs] def multiple_regression_page(self):
"""Set the ui elements for the 'multiple_regression' parameters."""
widget = ScrollableWidget()
self.mra_gb1 = add_group_box(
title="Analyses Parameters", obj_name="mra_gb1")
self.mra_interval = add_double_spin_box(
min_val=0.1, max_val=2, obj_name="mra_interval")
self.mra_interval.setValue(0.1)
self.mra_interval.setSingleStep(0.1)
self.mra_episode = add_spin_box(
min_val=60, max_val=300, obj_name="mra_episode")
self.mra_episode.setValue(120)
self.mra_episode.setSingleStep(30)
self.mra_nrep = add_spin_box(
min_val=100, max_val=2000, obj_name="mra_nrep")
self.mra_nrep.setValue(1000)
self.mra_nrep.setSingleStep(100)
box_layout = ParamBoxLayout()
box_layout.addRow("Subsampling Interval",
self.mra_interval, "sec [range: 0.1-1, step: 0.1]")
box_layout.addRow("Chunk Length for Regression",
self.mra_episode, "sec [range: 60-300, step: 30]")
box_layout.addRow("No of Replication", self.mra_nrep,
"[range: 100-2000, step: 100]")
self.mra_gb1.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.mra_gb1)
widget.setContents(layout)
return widget
[docs] def inter_depend_page(self):
"""Set the ui elements for the 'inter_depend' analysis parameters."""
widget = ScrollableWidget()
self.inter_depend_gb1 = add_group_box(
title="", obj_name="interDepend_gb1")
box_layout = QtWidgets.QVBoxLayout()
box_layout.addWidget(QtWidgets.QLabel(
"Uses the parameters from other analyses"))
self.inter_depend_gb1.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.inter_depend_gb1)
widget.setContents(layout)
return widget
[docs] def lfp_spectrum_page(self):
"""Set the ui elements for the 'lfp_spectrum' analysis parameters."""
widget = ScrollableWidget()
# Box- 1
self.lfp_spectrum_gb1 = add_group_box(
title="Pre-filter (Butterworth) Properties", obj_name="lfp_spectrum_gb1")
self.lfp_prefilt_lowcut = add_double_spin_box(
min_val=1.0, max_val=4, obj_name="lfp_prefilt_lowcut")
self.lfp_prefilt_lowcut.setValue(1.5)
self.lfp_prefilt_lowcut.setSingleStep(0.1)
self.lfp_prefilt_highcut = add_spin_box(
min_val=10, max_val=500, obj_name="lfp_prefilt_highcut")
self.lfp_prefilt_highcut.setValue(40)
self.lfp_prefilt_highcut.setSingleStep(5)
self.lfp_prefilt_order = add_spin_box(
min_val=1, max_val=20, obj_name="lfp_prefilt_order")
self.lfp_prefilt_order.setValue(5)
box_layout = ParamBoxLayout()
box_layout.addRow("Lower Cutoff Frequency",
self.lfp_prefilt_lowcut, "Hz [range: 1.0-4, step: 0.1]")
box_layout.addRow("Higher Cutoff Frequency",
self.lfp_prefilt_highcut, "Hz [range: 10-500, step: 5]")
box_layout.addRow(
"Filter Order", self.lfp_prefilt_order, "[range: 1-20]")
self.lfp_spectrum_gb1.setLayout(box_layout)
# Box- 2
self.lfp_spectrum_gb2 = add_group_box(
title="Spectrum Analysis (PWELCH) Settings", obj_name="lfp_spectrum_gb2")
self.lfp_pwelch_seg_size = add_double_spin_box(
min_val=0.5, max_val=100, obj_name="lfp_pwelch_seg_size")
self.lfp_pwelch_seg_size.setValue(2)
self.lfp_pwelch_seg_size.setSingleStep(0.5)
self.lfp_pwelch_overlap = add_double_spin_box(
min_val=0.5, max_val=50, obj_name="lfp_pwelch_overlap")
self.lfp_pwelch_overlap.setValue(1)
self.lfp_pwelch_overlap.setSingleStep(0.5)
self.lfp_pwelch_nfft = add_combo_box(obj_name="lfp_pwelch_nfft")
nfft_items = [str(2**d) for d in range(7, 14)]
self.lfp_pwelch_nfft.addItems(nfft_items)
self.lfp_pwelch_nfft.setCurrentIndex(3)
self.lfp_pwelch_freq_max = add_spin_box(
min_val=10, max_val=500, obj_name="lfp_pwelch_freq_max")
self.lfp_pwelch_freq_max.setValue(40)
self.lfp_pwelch_freq_max.setSingleStep(5)
box_layout = ParamBoxLayout()
box_layout.addRow("Segment Size", self.lfp_pwelch_seg_size,
"sec [range: 0.5-100, step: 0.5]")
box_layout.addRow("Overlap", self.lfp_pwelch_overlap,
"sec [range: 0.5-50, step: 0.5]")
box_layout.addRow("NFFT", self.lfp_pwelch_nfft,
"[range: 128-8192, step: 128]")
box_layout.addRow(
"Maximum Frequency", self.lfp_pwelch_freq_max,
"Hz [range: 10-500, step: 5]")
self.lfp_spectrum_gb2.setLayout(box_layout)
# Box- 3
self.lfp_spectrum_gb3 = add_group_box(
title="STFT Settings", obj_name="lfp_spectrum_gb3")
self.lfp_stft_seg_size = add_double_spin_box(
min_val=0.5, max_val=100, obj_name="lfp_stft_seg_size")
self.lfp_stft_seg_size.setValue(2)
self.lfp_stft_seg_size.setSingleStep(0.5)
self.lfp_stft_overlap = add_double_spin_box(
min_val=0.5, max_val=50, obj_name="lfp_stft_overlap")
self.lfp_stft_overlap.setValue(1)
self.lfp_stft_overlap.setSingleStep(0.5)
self.lfp_stft_nfft = add_combo_box(obj_name="lfp_stft_nfft")
nfft_items = [str(2**d) for d in range(7, 14)]
self.lfp_stft_nfft.addItems(nfft_items)
self.lfp_stft_nfft.setCurrentIndex(3)
self.lfp_stft_freq_max = add_spin_box(
min_val=10, max_val=500, obj_name="lfp_stft_freq_max")
self.lfp_stft_freq_max.setValue(40)
self.lfp_stft_freq_max.setSingleStep(5)
box_layout = ParamBoxLayout()
box_layout.addRow("Segment Size", self.lfp_stft_seg_size,
"sec [range: 0.5-100, step: 0.5]")
box_layout.addRow("Overlap", self.lfp_stft_overlap,
"sec [range: 0.5-50, step: 0.5]")
box_layout.addRow("NFFT", self.lfp_stft_nfft,
"[range: 128-8192, step: 128]")
box_layout.addRow("Maximum Frequency",
self.lfp_stft_freq_max, "Hz [range: 10-500, step: 5]")
self.lfp_spectrum_gb3.setLayout(box_layout)
# Box 4
self.lfp_lowband_lowcut = add_double_spin_box(
min_val=0.5, max_val=100, obj_name="lfp_lowband_lowcut")
self.lfp_lowband_lowcut.setValue(1.5)
self.lfp_lowband_lowcut.setSingleStep(0.5)
self.lfp_lowband_highcut = add_double_spin_box(
min_val=3, max_val=500, obj_name="lfp_lowband_highcut")
self.lfp_lowband_highcut.setValue(4)
self.lfp_lowband_highcut.setSingleStep(0.5)
self.lfp_highband_lowcut = add_double_spin_box(
min_val=0.5, max_val=100, obj_name="lfp_highband_lowcut")
self.lfp_highband_lowcut.setValue(5)
self.lfp_highband_lowcut.setSingleStep(0.5)
self.lfp_highband_highcut = add_double_spin_box(
min_val=3, max_val=500, obj_name="lfp_highband_highcut")
self.lfp_highband_highcut.setValue(11)
self.lfp_highband_highcut.setSingleStep(0.5)
self.lfp_band_win_len = add_double_spin_box(
min_val=0.5, max_val=5, obj_name="lfp_band_win_len")
self.lfp_band_win_len.setValue(1.6)
self.lfp_band_win_len.setSingleStep(0.1)
box_layout = ParamBoxLayout()
box_layout.addRow("Lower Band Low Cutoff",
self.lfp_lowband_lowcut, "Hz [range: 0.5-100, step: 0.5]")
box_layout.addRow("Lower Band High Cutoff",
self.lfp_lowband_highcut, "Hz [range: 3-500, step: 0.5]")
box_layout.addRow("Upper Band Low Cutoff",
self.lfp_highband_lowcut, "Hz [range: 0.5-100, step: 0.5]")
box_layout.addRow("Upper Band High Cutoff",
self.lfp_highband_highcut, "Hz [range: 3-500, step: 0.5]")
box_layout.addRow("Band Power Window Length",
self.lfp_band_win_len, "sec [range 0.5 - 5, step: 0.1]")
self.lfp_spectrum_gb4 = add_group_box(
title="Band Power Settings", obj_name="lfp_spectrum_gb4")
self.lfp_spectrum_gb4.setLayout(box_layout)
# Box 5
self.lfp_spectrum_colormap = add_combo_box(
obj_name="lfp_spectrum_colormap")
self.lfp_spectrum_colormap.addItems(
["magma", "default", "gray", "plasma",
"inferno", "viridis", "cividis"])
self.lfp_spectrum_gb5 = add_group_box(
title="Plotting Style", obj_name="lfp_spectrum_gb5")
box_layout = ParamBoxLayout()
box_layout.addRow(
"Spectogram Colormap", self.lfp_spectrum_colormap, "")
self.lfp_spectrum_gb5.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.lfp_spectrum_gb1)
layout.addWidget(self.lfp_spectrum_gb2)
layout.addWidget(self.lfp_spectrum_gb3)
layout.addWidget(self.lfp_spectrum_gb4)
layout.addWidget(self.lfp_spectrum_gb5)
widget.setContents(layout)
return widget
[docs] def spike_phase_page(self):
"""Set the ui elements for the 'spike_phase' analysis parameters."""
widget = ScrollableWidget()
self.spike_phase_gb1 = add_group_box(
title="Analysis Parameters", obj_name="spike_phase_gb1")
self.phase_freq_min = add_double_spin_box(
min_val=1, max_val=10, obj_name="phase_freq_min")
self.phase_freq_min.setValue(6)
self.phase_freq_min.setSingleStep(0.5)
self.phase_freq_max = add_double_spin_box(
min_val=8, max_val=16, obj_name="phase_freq_max")
self.phase_freq_max.setValue(12)
self.phase_freq_max.setSingleStep(0.5)
self.phase_power_thresh = add_double_spin_box(
min_val=0, max_val=1, obj_name="phase_power_thresh")
self.phase_power_thresh.setValue(0.1)
self.phase_power_thresh.setSingleStep(0.05)
self.phase_amp_thresh = add_double_spin_box(
min_val=0, max_val=1, obj_name="phase_amp_thresh")
self.phase_amp_thresh.setValue(0.15)
self.phase_amp_thresh.setSingleStep(0.05)
self.phase_bin = add_combo_box(obj_name="phase_bin")
phase_bin_items = [str(d) for d in range(
1, 360) if 360 % d == 0 and d >= 5 and d <= 45]
self.phase_bin.addItems(phase_bin_items)
self.phase_raster_bin = add_spin_box(
min_val=1, max_val=15, obj_name="phase_raster_bin")
self.phase_raster_bin.setValue(2)
box_layout = ParamBoxLayout()
box_layout.addRow("Frequency of Interest (Min)",
self.phase_freq_min, "Hz [range: 1-10, step: 0.5]")
box_layout.addRow("Frequency of Interest (Max)",
self.phase_freq_max, "Hz [range: 1-10, step: 0.5]")
box_layout.addRow("Band to Total Power Ratio (Min)",
self.phase_power_thresh, "[range: 0-1, step: 0.05]")
box_layout.addRow("Segment to Overall Amplitude Ratio (Min)",
self.phase_amp_thresh, "[range: 0-1, step: 0.05]")
box_layout.addRow("Phase Plot Binsize", self.phase_bin, "degree")
box_layout.addRow("Phase Raster Plot Binsize",
self.phase_raster_bin, "degree[range: 1-15]")
self.spike_phase_gb1.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.spike_phase_gb1)
widget.setContents(layout)
return widget
[docs] def phase_lock_page(self):
"""Set the ui elements for the 'phase_lock' analysis parameters."""
widget = ScrollableWidget()
self.phase_lock_gb1 = add_group_box(
title="Analysis Parameters", obj_name="phase_lock_gb1")
self.phase_lock_win_low = add_double_spin_box(
min_val=-1, max_val=-0.1, obj_name="phase_loc_win_low")
self.phase_lock_win_low.setValue(-0.4)
self.phase_lock_win_low.setSingleStep(0.05)
self.phase_lock_win_up = add_double_spin_box(
min_val=0.1, max_val=1, obj_name="phase_loc_win_up")
self.phase_lock_win_up.setValue(0.4)
self.phase_lock_win_up.setSingleStep(0.05)
self.phase_lock_nfft = add_combo_box(obj_name="phase_loc_nfft")
nfft_items = [str(2**d) for d in range(7, 14)]
self.phase_lock_nfft.addItems(nfft_items)
self.phase_lock_nfft.setCurrentIndex(3)
self.phase_lock_freq_max = add_spin_box(
min_val=10, max_val=500, obj_name="phase_loc_freq_max")
self.phase_lock_freq_max.setValue(40)
self.phase_lock_freq_max.setSingleStep(5)
box_layout = ParamBoxLayout()
box_layout.addRow("Analysis Window (Lower)",
self.phase_lock_win_low, "sec [range: -1 to -0.1, step: 0.05]")
box_layout.addRow("Analysis Window (Upper)",
self.phase_lock_win_up, "sec [range: 0.1 to 1, step: 0.05]")
box_layout.addRow("NFFT", self.phase_lock_nfft,
"[range: 128-8192, step: 128]")
box_layout.addRow("Frequency of Interest (Max)",
self.phase_lock_freq_max, "Hz [range: 1-10, step: 0.5]")
self.phase_lock_gb1.setLayout(box_layout)
self.phase_lock_gb2 = add_group_box(
title="Plotting Style", obj_name="phase_lock_gb2")
self.phase_loc_colormap = add_combo_box(
obj_name="phase_loc_colormap")
self.phase_loc_colormap.addItems(
["magma", "default", "gray", "plasma",
"inferno", "viridis", "cividis"])
box_layout = ParamBoxLayout()
box_layout.addRow(
"Phase Locking Colormap", self.phase_loc_colormap, "")
self.phase_lock_gb2.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.phase_lock_gb1)
layout.addWidget(self.phase_lock_gb2)
widget.setContents(layout)
return widget
[docs] def lfp_spike_causality_page(self):
"""Set the ui elements for the 'lfp_spike_causality' parameters."""
widget = ScrollableWidget()
self.causality_gb1 = add_group_box(title="", obj_name="causality_gb1")
box_layout = QtWidgets.QVBoxLayout()
box_layout.addWidget(QtWidgets.QLabel("Analysis not implemented yet!"))
self.causality_gb1.setLayout(box_layout)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.causality_gb1)
widget.setContents(layout)
return widget
[docs]class ParamBoxLayout(QtWidgets.QVBoxLayout):
"""
Facilitates adding new widget items to the analysis parameter window.
Subclass of QtWidgets.QVBoxLayout.
"""
def __int__(self):
super().__init__()
[docs] def addRow(self, label_1, widg, label_2):
"""
Add a new row of widget using the QtWidgets.QHBoxLayout().
Parameters
----------
label_1 : str
Name of the parameter
widg
PyQt5 widget to add
label_2 : str
Additional description of the parameter, i.e., unit, range etc.
"""
widg.resize(widg.sizeHint())
hLayout = QtWidgets.QHBoxLayout()
hLayout.addWidget(QtWidgets.QLabel(label_1), 0, QtCore.Qt.AlignLeft)
hLayout.addWidget(widg, 0, QtCore.Qt.AlignLeft)
hLayout.addWidget(QtWidgets.QLabel(label_2), 0, QtCore.Qt.AlignLeft)
self.addLayout(hLayout)