-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.py
162 lines (122 loc) · 5.64 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import sys
import os
import pickle
import datetime
import numpy as np
from PyQt5 import QtWidgets
from Designs import mainWindow
from Windows import AppWindows
from Models import Experiment, GuiModels
from Controllers import ExperimentControl
from PyPulse import PulseInterface
class MainApp(QtWidgets.QMainWindow, mainWindow.Ui_MainWindow):
def __init__(self):
super(self.__class__, self).__init__()
self.setupUi(self)
self.hardware_prefs = self.load_config_data()
self.setup_experiment_bindings(Experiment.Experiment())
# function bindings
self.actionAnimal_List.triggered.connect(self.open_animal_window)
self.actionHardware_Preferences.triggered.connect(self.open_hardware_window)
self.actionAnalyse_Experiment.triggered.connect(self.open_analysis_window)
self.actionSave_Experiment.triggered.connect(self.save_experiment)
self.actionLoad_Experiment.triggered.connect(self.load_experiment)
def setup_experiment_bindings(self, experiment):
self.experiment = experiment
self.experiment_control = ExperimentControl.ExperimentController(self)
self.model = GuiModels.TableModel(['Animal ID', 'Time Stamp', 'Schedule Idx', 'Trial Idx', 'Rewarded',
'Response', 'Correct', 'Timeout'],
self.experiment.trials, parent=self)
self.trialView.setModel(self.model)
try:
self.startButton.disconnect()
self.stopButton.disconnect()
except:
pass
self.startButton.clicked.connect(self.experiment_control.start)
self.stopButton.clicked.connect(self.experiment_control.stop)
self.experiment_control.trial_job.trial_end.connect(self.update_trial_view)
self.experiment_control.trial_job.trial_end.connect(self.update_data_view)
self.trialView.selectionModel().selectionChanged.connect(self.on_trial_selected)
@staticmethod
def load_config_data():
if os.path.exists('hardware.config'):
with open('hardware.config', 'rb') as fn:
return pickle.load(fn)
else:
return None
def open_animal_window(self):
animal_window = AppWindows.AnimalWindow(self)
animal_window.show()
def open_hardware_window(self):
hardware_window = AppWindows.HardwareWindow(self)
hardware_window.show()
def open_analysis_window(self):
analysis_window = AppWindows.AnalysisWindow(self.experiment, parent=self)
analysis_window.show()
def update_trial_view(self):
self.model.layoutChanged.emit()
def update_data_view(self):
self.dataView.plotItem.clear()
self.dataView.plotItem.plot(np.arange(len(self.experiment.last_data)) / self.hardware_prefs['samp_rate'],
np.array(self.experiment.last_data))
self.dataView.setYRange(0, 6)
def update_graphics_view(self, trial):
animal = self.experiment.trials[trial][0]
sched_idx = self.experiment.trials[trial][2]
trial_idx = self.experiment.trials[trial][3]
try:
trial_data = self.experiment.animal_list[animal].schedule_list[sched_idx].trial_params[trial_idx]
pulses, t = PulseInterface.make_pulse(self.hardware_prefs['samp_rate'], 0.0, 0.0, trial_data)
self.graphicsView.plotItem.clear()
for p, pulse in enumerate(pulses):
self.graphicsView.plotItem.plot(t, np.array(pulse) - (p * 1.1))
except:
pass
def on_trial_selected(self):
try:
selected_trial = self.trialView.selectionModel().selectedRows()[0].row()
except:
selected_trial = 0
self.update_graphics_view(selected_trial)
def update_experiment_info(self):
self.experimentNameLabel.setText(self.experiment.name)
self.experimentDateLabel.setText(self.experiment.date)
self.savePathLabel.setText(self.experiment.save_path)
def save_experiment(self):
# TODO - bit messy, what if the experiment class changes, should rather be saving the data in the class
fname, suff = QtWidgets.QFileDialog.getSaveFileName(self, "Save Experiment", '', "AutonoMouse Experiment (*.autmaus)")
self.experiment.name = os.path.basename(fname)
self.experiment.save_path = os.path.dirname(fname)
# We don't change the original date of creation
if self.experiment.date is None:
self.experiment.date = str(datetime.datetime.now())
self.update_experiment_info()
with open(fname, 'wb') as fn:
pickle.dump(self.experiment, fn)
def load_experiment(self):
fname, suff = QtWidgets.QFileDialog.getOpenFileName(self, "Open Experiment", '',
"AutonoMouse Experiment (*.autmaus)")
if fname != '':
with open(fname, 'rb') as fn:
experiment = pickle.load(fn)
self.setup_experiment_bindings(experiment)
self.update_experiment_info()
self.update_trial_view()
# Back up the reference to the exceptionhook
sys._excepthook = sys.excepthook
def my_exception_hook(exctype, value, traceback):
# Print the error and traceback
print(exctype, value, traceback)
# Call the normal Exception hook after
sys._excepthook(exctype, value, traceback)
sys.exit(1)
# Set the exception hook to our wrapping function
sys.excepthook = my_exception_hook
def main():
app = QtWidgets.QApplication(sys.argv)
form = MainApp()
form.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()