-
Notifications
You must be signed in to change notification settings - Fork 0
/
LabRAD-Sweeper.py
243 lines (181 loc) · 9.01 KB
/
LabRAD-Sweeper.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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
'''
LabRAD sweeper
main.py
All functionality is contained in the widgets (located in \components\)
Components:
__init__.py - exists to make the \components\ directory a package
widgets.py - contains some user-defined interface objects (dropdown lists, etc)
widget_sweeper.py - has most of the actual sweeper functionality. Takes measurements, performs and manages sweeps.
widget_parameter_box.py - defines user interface for selecting parameters to pass to swept and recorded settings
widget_grapher.py - has the functionality to graph the data that are being collected
widget_comment_box.py - provides user interface for writing comments to saved data set
logger.py - has the functionality for saving collected data through data vault
excluded_servers.py - has a list of LabRAD servers that will be ignored by the sweeper
colormaps.py - has the list of available premade colormaps for 2-D graphing
'''
from PyQt4 import QtCore as core, QtGui as gui
import sys,math,time,os
from os import getenv
from components.widgets import simpleDropdown,simpleList,selector
from components.widget_sweeper import sweeperWidget
from components.widget_grapher import grapherWidget
class interface(gui.QMainWindow):
def __init__(self,**args):
super(interface,self).__init__()
# connect to LabRAD
self.connect()
# create internal timer for managing timed events
self.timer = core.QTimer(self)
self.timer.setInterval(1)
self.timer.timeout.connect(self.timer_event)
self.timer.start()
self.time = time.time()
self.last_error_check = self.time
# If we found no active device servers (with active devices) then we close the program
# if self.cen.found_servers is False:
# self.close()
# self.grapher.close()
def closeEvent(self,event):
print("Stopping main LabRAD connection...")
self.connection.disconnect()
print("Main LabRAD connection stopped.")
print("Stopping grapher connections...")
for ID in self.grapher.IDs:
if self.grapher.sweepers[ID].status != 'CANCELLED':self.grapher.sweepers[ID].data_set.close_dataset()
print("Done.")
self.grapher.close()
def timer_event(self):
"""This function is called each time the internal timer times out.
It updates everything that needs to be updated on a timer.
These include: running any ongoing sweep, and checking for errors
in new sweep creation."""
# get the current time
self.time=time.time()
# If it's been more than a second since the last check, update the error readout in the new sweep creation tabs.
if (self.time - self.last_error_check) > 1.0:
self.cen.s1d.check_warnings()
self.cen.s2d.check_warnings()
self.last_error_check = self.time
# manage all running sweeps
for ID in self.grapher.IDs:
if self.grapher.sweepers[ID].status == 'running':
elapsed = self.time - self.grapher.sweepers[ID].time # time since last measurement
# 1D graphs
if self.grapher.sweepers[ID].kind=='1d':
# If time since last measurement exceeds measurement interval, perform a new measurement.
if elapsed >= (self.grapher.sweepers[ID].det['delay']/1000.0):
# reset time since last measurement
self.grapher.sweepers[ID].time = self.time
# x coordinant = the step that the sweep is currently on
xval = self.grapher.sweepers[ID].xsetting
# this will be populated by each setting that the sweep is recording
yval = {}
# take measurement
self.grapher.sweepers[ID].do_measurement(self.connection)
# set swept setting to the next value
self.grapher.sweepers[ID].advance(self.connection,elapsed)
# update the graph(s)
self.grapher.sweepers[ID].update_graphs()
# 2D graphs
elif self.grapher.sweepers[ID].kind == '2d':
# If time since last measurement exceeds measurement interval, perform a new measurement.
if elapsed >= (self.grapher.sweepers[ID].current_delay/1000.0):
# reset time since last measurement
self.grapher.sweepers[ID].time = self.time
# "xn" and "yn" are the x and y integer coordinants of the current position in the 2-D sweep
xn = self.grapher.sweepers[ID].x_num
yn = self.grapher.sweepers[ID].y_num
# again, "values" will be populated by the values of each recorded setting
values = {}
# take measurement
self.grapher.sweepers[ID].do_measurement(self.connection)
# advance
self.grapher.sweepers[ID].advance(self.connection,elapsed)
# update graphs
self.grapher.sweepers[ID].update_graphs()
def connect(self):
# otherwise, prompt user for password
import labrad
firstAttempt=True
success=connect=False
# check to see if the password has been set in the environment
try:
pwd = os.environ["LABRADPASSWORD"]
if pwd == None:
print("Warning: environment variable <LABRADPASSWORD> has not yet been set")
raise
self.connection = labrad.connect(password = pwd)
success = True
connect = True
except:
print("Error: LabRAD is not running properly.")
while not success:
if firstAttempt:pwd,ok=gui.QInputDialog.getText(self,"Password","Enter LabRAD password")
else:pwd,ok=gui.QInputDialog.getText(self,"Password","Something went wrong. Either thepassword\nwas incorrect or LabRAD isn't running.")
try:
self.connection = labrad.connect(password = str(pwd))
success=True;connect=True
except:
if pwd=='exit':success=True
firstAttempt=False
if connect:
self.password = str(pwd)
self.doUI()
else:
gui.qApp.quit()
def doUI(self):
self.resize(1024+256,512+64)
#Title
self.setWindowTitle("Sweeper settings interface")
#Menu bar
self.menu = self.menuBar()
self.menus={
'program':self.menu.addMenu("&program"),
'connect':self.menu.addMenu("&connect"),
}
action_grapher = gui.QAction(gui.QIcon("missingno.png"),"Show grapher",self)
action_grapher.setShortcut("Ctrl+G")
action_grapher.triggered.connect(self.open_grapher)
self.menus['program'].addAction(action_grapher)
self.cen = sweeperWidget(self,False)
if self.cen.found_servers is True:
self.setCentralWidget(self.cen)
self.grapher = grapherWidget(self.password)
self.grapher.setWindowTitle("Grapher")
self.show()
else:
self.connection.disconnect()
sys.exit()
def open_grapher(self):
self.grapher.show()
def sweep_start(self,kind):
details = self.cen.get_details(kind)
self.open_grapher()
# select the lowest positive ID not currently in use
# If there are not active IDs, then zero is available, so use it.
if len(self.grapher.IDs)==0:
ID=0
# otherwise, take ID = 1 greater than the highest value currently used.
else:
ID = 1+max(self.grapher.IDs)
# add required data to details, i.e. sweep settings
if kind == '1d':
details.update([
['xlabel' , details['setting_swept'][2]],
['ylabels', [st.rpartition('//')[2] for st in details['settings_read']]],
['xrng' , [details['start'],details['stop']]],
['start_timestamp',time.localtime()],
])
elif kind=='2d':
details.update([
['xlabel',details['fast_swept'][2]],
['ylabel',details['slow_swept'][2]],
['logged_labels',[st.rpartition('//')[2] for st in details['settings_read']]],
['start_timestamp',time.localtime()],
])
self.grapher.add_sweeper(ID,details,kind=kind)
self.grapher.sweepers[ID].initialize_sweep(self.connection) # moves the parameters to their start values
if __name__=='__main__':
app = gui.QApplication(sys.argv)
i = interface()
sys.exit(app.exec_())