Merge commit 'e1053513ced8'

This commit is contained in:
Markus Rosenstihl 2019-06-11 17:23:37 +02:00
commit ca018cbdc8
3 changed files with 210 additions and 11 deletions

View File

@ -91,6 +91,15 @@ class Experiment:
self.rf_sources = rf_sources self.rf_sources = rf_sources
self.rf_gates = rf_gates self.rf_gates = rf_gates
#for tracking the experiment length:
#because loops are possible we need to track the length for each loop level
self.total_time=[]
self.total_time.append(0.0)
#and we need to know the number of iterations of the loops to multiply the state.
self.loop_iterations=[]
self.loop_iterations.append(1)
# Commands ------------------------------------------------------------------------------------- # Commands -------------------------------------------------------------------------------------
## Creates a state with ttl signals of duration *length*. ## Creates a state with ttl signals of duration *length*.
@ -119,6 +128,8 @@ class Experiment:
self.state_list.append(StateSimple(length, \ self.state_list.append(StateSimple(length, \
'<ttlout value="0x%06x"/>' % the_value)) '<ttlout value="0x%06x"/>' % the_value))
self.total_time[-1] += length
## Same as ttl_pulse, but no *channel* keyword ## Same as ttl_pulse, but no *channel* keyword
def ttls(self, length = None, value = None): def ttls(self, length = None, value = None):
""" """
@ -132,9 +143,11 @@ class Experiment:
s_content = '<ttlout value="0x%06x"/>' % the_value s_content = '<ttlout value="0x%06x"/>' % the_value
if length is not None: if length is not None:
self.state_list.append(StateSimple(length, s_content)) self.state_list.append(StateSimple(length, s_content))
self.total_time[-1] += length
else: else:
self.state_list.append(s_content) self.state_list.append(s_content)
def rf_pulse(self, length=None, phase=0, source=0): def rf_pulse(self, length=None, phase=0, source=0):
""" """
make an rf pulse, including gating and phase switching make an rf pulse, including gating and phase switching
@ -157,6 +170,7 @@ class Experiment:
This must be closed with state_end() This must be closed with state_end()
""" """
self.state_list.append('<state time="%s">\n' % repr(time)) self.state_list.append('<state time="%s">\n' % repr(time))
self.total_time[-1] += time
## End of *state_start* ## End of *state_start*
def state_end(self): def state_end(self):
@ -185,6 +199,8 @@ class Experiment:
else: else:
self.state_list.append(StateSimple(time)) self.state_list.append(StateSimple(time))
self.total_time[-1] += time
## Records data with given number of samples, sampling-frequency frequency and sensitivity ## Records data with given number of samples, sampling-frequency frequency and sensitivity
# @param samples Number of samples to record # @param samples Number of samples to record
# @param frequency Sampling frequency # @param frequency Sampling frequency
@ -247,6 +263,7 @@ class Experiment:
if timelength is None: if timelength is None:
timelength = samples / float(frequency)#*1.01 timelength = samples / float(frequency)#*1.01
self.state_list.append(StateSimple(timelength, s_content)) self.state_list.append(StateSimple(timelength, s_content))
self.total_time[-1] += timelength
## Create a loop on the pulse programmer. Loop contents can not change inside the loop. ## Create a loop on the pulse programmer. Loop contents can not change inside the loop.
# @params iterations Number of loop iterations # @params iterations Number of loop iterations
@ -265,6 +282,9 @@ class Experiment:
self.list_stack.append(self.state_list) self.list_stack.append(self.state_list)
self.state_list = l self.state_list = l
self.total_time.append(0.0)
self.loop_iterations.append(iterations)
## End loop state ## End loop state
def loop_end(self): def loop_end(self):
""" """
@ -273,6 +293,10 @@ class Experiment:
# (This line could probably be guarded by a mutex) # (This line could probably be guarded by a mutex)
self.state_list = self.list_stack.pop(-1) self.state_list = self.list_stack.pop(-1)
looptime=self.total_time.pop(-1)
loopiterations=self.loop_iterations.pop(-1)
self.total_time[-1] += looptime*loopiterations
## Set the frequency and phase of the frequency source. ## Set the frequency and phase of the frequency source.
## This state needs 2us. ## This state needs 2us.
# @param frequency New frequency in Hz # @param frequency New frequency in Hz
@ -292,6 +316,8 @@ class Experiment:
s_content += '<ttlout value="0x%06x"/>' % ttls s_content += '<ttlout value="0x%06x"/>' % ttls
self.state_list.append(StateSimple(2e-6, s_content)) self.state_list.append(StateSimple(2e-6, s_content))
self.total_time[-1] += 2e-6
## Creates a, possibly shaped, pulsed gradient. ## Creates a, possibly shaped, pulsed gradient.
# @param dac_value DAC value to set # @param dac_value DAC value to set
# @param length Duration of the state, minimum length is 42*90ns=3.78us (default) # @param length Duration of the state, minimum length is 42*90ns=3.78us (default)
@ -331,21 +357,27 @@ class Experiment:
if form == 'rec': # shape==None --> rectangular gradients if form == 'rec': # shape==None --> rectangular gradients
s_content = '<ttlout value="%s"/><analogout id="1" dac_value="%i"/>' % (trigger, dac_value) s_content = '<ttlout value="%s"/><analogout id="1" dac_value="%i"/>' % (trigger, dac_value)
self.state_list.append(StateSimple(length, s_content)) self.state_list.append(StateSimple(length, s_content))
self.total_time[-1] += length
if not is_seq: if not is_seq:
s_content = '<analogout id="1" dac_value="0"/>' s_content = '<analogout id="1" dac_value="0"/>'
self.state_list.append(StateSimple(42*9e-8, s_content)) self.state_list.append(StateSimple(42*9e-8, s_content))
self.total_time[-1] += 42*9e-8
elif form == 'sin2': elif form == 'sin2':
# sin**2 shape # sin**2 shape
for t in t_steps: for t in t_steps:
dac = int (dac_value*numpy.sin(numpy.pi/length*t)**2) dac = int (dac_value*numpy.sin(numpy.pi/length*t)**2)
s_content = '<ttlout value="%s"/><analogout id="1" dac_value="%i"/>' % (trigger, dac) s_content = '<ttlout value="%s"/><analogout id="1" dac_value="%i"/>' % (trigger, dac)
self.state_list.append(StateSimple(resolution, s_content)) self.state_list.append(StateSimple(resolution, s_content))
# set it back to zero # set it back to zero
s_content = '<ttlout value="%s"/><analogout id="1" dac_value="0"/>' % (trigger) s_content = '<ttlout value="%s"/><analogout id="1" dac_value="0"/>' % (trigger)
self.state_list.append(StateSimple(resolution, s_content)) self.state_list.append(StateSimple(resolution, s_content))
self.total_time[-1] += resolution*(len(t_steps)+1)
elif form == 'sin': elif form == 'sin':
# sin shape # sin shape
for t in t_steps: for t in t_steps:
@ -355,6 +387,8 @@ class Experiment:
# set it back to zero # set it back to zero
s_content = '<ttlout value="%s"/><analogout id="1" dac_value="0"/>' % (trigger) s_content = '<ttlout value="%s"/><analogout id="1" dac_value="0"/>' % (trigger)
self.state_list.append(StateSimple(resolution, s_content)) self.state_list.append(StateSimple(resolution, s_content))
self.total_time[-1] += resolution*(len(t_steps)+1)
else: # don't know what to do else: # don't know what to do
raise SyntaxError , "form is unknown: %s"%form raise SyntaxError , "form is unknown: %s"%form
@ -385,11 +419,16 @@ class Experiment:
s_content = '<analogout id="%d" dac_value="%i"/><ttlout value="0x%06x"/>' \ s_content = '<analogout id="%d" dac_value="%i"/><ttlout value="0x%06x"/>' \
% (dac_id, dac_value, ttls) % (dac_id, dac_value, ttls)
self.state_list.append(StateSimple(length, s_content)) self.state_list.append(StateSimple(length, s_content))
self.total_time[-1] += length
if not is_seq: if not is_seq:
s_content = '<analogout id="%d" dac_value="0"/><ttlout value="0x%06x"/>' \ s_content = '<analogout id="%d" dac_value="0"/><ttlout value="0x%06x"/>' \
% (dac_id, ttls) % (dac_id, ttls)
self.state_list.append(StateSimple(42*9e-8, s_content)) self.state_list.append(StateSimple(42*9e-8, s_content))
self.total_time[-1] += 42*9e-8
## sets the phase of the frequency source. ## sets the phase of the frequency source.
## This state needs 0.5us, though the phase switching time is dependent on the frequency source ## This state needs 0.5us, though the phase switching time is dependent on the frequency source
# @param phase New phase to set # @param phase New phase to set
@ -409,6 +448,8 @@ class Experiment:
s_content += '<ttlout value="%d"/>' % ttls s_content += '<ttlout value="%d"/>' % ttls
self.state_list.append(StateSimple(0.5e-6, s_content)) self.state_list.append(StateSimple(0.5e-6, s_content))
self.total_time[-1] += 0.5e-6
## sets a description which is carried via the back end result ## sets a description which is carried via the back end result
## file to the result script in the front end. In the result script ## file to the result script in the front end. In the result script
## you can extract the description with get_description(key) ## you can extract the description with get_description(key)
@ -435,6 +476,8 @@ class Experiment:
self.state_list.append(StateSimple(1e-6, '<ttlout value="0xf000"/>')) self.state_list.append(StateSimple(1e-6, '<ttlout value="0xf000"/>'))
self.state_list.append(StateSimple(1e-6, '<ttlout value="0x8000"/>')) self.state_list.append(StateSimple(1e-6, '<ttlout value="0x8000"/>'))
self.total_time[-1] += 2e-6
# / Commands ----------------------------------------------------------------------------------- # / Commands -----------------------------------------------------------------------------------
@ -509,6 +552,16 @@ class Experiment:
""" """
return '<?xml version="1.0" encoding="ISO-8859-1"?>\n<quit/>' return '<?xml version="1.0" encoding="ISO-8859-1"?>\n<quit/>'
def get_length(self):
timelength = 0.0
#calculate the correct timelength also for unclosed loops, if there is no unclosed loop
#the timelength of this experiment is self.total_time[-1].
for i in range(len(self.total_time)):
timelength += self.total_time[i]
timelength *= self.loop_iterations[i]
return timelength
class Quit(Experiment): class Quit(Experiment):
def write_xml_string(self): def write_xml_string(self):
@ -529,8 +582,7 @@ def self_test():
e.ttl_pulse(1e-6/3, None, 7) # val = 7 e.ttl_pulse(1e-6/3, None, 7) # val = 7
if True: if True:
e.loop_start(30) e.loop_start(30)
e.set_pfg(dac_value=1024, is_seq = True) e.set_pfg(dac_value=1024, length=5e-6, is_seq = True, shape=('rec', 42*9e-8))
e.set_pfg_wt(dac_value=2048)
e.loop_start(400) e.loop_start(400)
e.set_phase(270, ttls = 32) e.set_phase(270, ttls = 32)
e.loop_end() e.loop_end()
@ -551,5 +603,7 @@ def self_test():
e.set_pts_local() e.set_pts_local()
print e.write_xml_string() print e.write_xml_string()
print e.get_length()
if __name__ == '__main__': if __name__ == '__main__':
self_test() self_test()

View File

@ -53,9 +53,11 @@ matplotlib.rcParams[ "axes.formatter.limits" ] = "-3,3"
if matplotlib.rcParams[ "backend" ] == "GTK": if matplotlib.rcParams[ "backend" ] == "GTK":
from matplotlib.backends.backend_gtk import FigureCanvasGTK as FigureCanvas from matplotlib.backends.backend_gtk import FigureCanvasGTK as FigureCanvas
max_points_to_display = 0 # no limit max_points_to_display = 0 # no limit
elif matplotlib.rcParams[ "backend" ] == "GTKCairo": elif matplotlib.rcParams[ "backend" ] == "GTKCairo":
from matplotlib.backends.backend_gtkcairo import FigureCanvasGTKCairo as FigureCanvas from matplotlib.backends.backend_gtkcairo import FigureCanvasGTKCairo as FigureCanvas
max_points_to_display = 1 << 14 # cairo cannot render longer paths than 18??? max_points_to_display = 1 << 14 # cairo cannot render longer paths than 18???
else: else:
# default # default
@ -181,7 +183,7 @@ class DamarisGUI:
# my notebook # my notebook
self.main_notebook = self.xml_gui.get_widget( "main_notebook" ) self.main_notebook = self.xml_gui.get_widget( "main_notebook" )
self.log = LogWindow( self.xml_gui ) self.log = LogWindow( self.xml_gui , self)
self.sw = ScriptWidgets( self.xml_gui ) self.sw = ScriptWidgets( self.xml_gui )
@ -196,6 +198,9 @@ class DamarisGUI:
self.lockfile = LockFile() # = os.path.expanduser("~/.damaris.lock") self.lockfile = LockFile() # = os.path.expanduser("~/.damaris.lock")
self.id = None self.id = None
#to stop queued experiments
self.stop_experiment_flag = threading.Event()
exp_script = u"" exp_script = u""
if exp_script_filename is not None and exp_script_filename != "": if exp_script_filename is not None and exp_script_filename != "":
self.sw.exp_script_filename = exp_script_filename[ : ] self.sw.exp_script_filename = exp_script_filename[ : ]
@ -277,11 +282,14 @@ class DamarisGUI:
self.toolbar_run_button.emit("clicked") self.toolbar_run_button.emit("clicked")
gtk.main( ) gtk.main( )
gtk.gdk.threads_leave( ) gtk.gdk.threads_leave( )
self.si = None self.si = None
self.sw = None self.sw = None
self.config = None self.config = None
self.xml_gui = None self.xml_gui = None
# event handling: the real acitons in gui programming
# first global events # first global events
def quit_event( self, widget, data=None ): def quit_event( self, widget, data=None ):
@ -449,10 +457,13 @@ class DamarisGUI:
self.log.textbuffer.create_mark( "lastdumped", self.log.textbuffer.get_end_iter( ), left_gravity=True ) self.log.textbuffer.create_mark( "lastdumped", self.log.textbuffer.get_end_iter( ), left_gravity=True )
loop_run=0 loop_run=0
#user shorter interval because this blocks user events from the GUI
interval = 0.1 interval = 0.1
self.stop_experiment_flag.clear()
self.id = self.lockfile.add_experiment() self.id = self.lockfile.add_experiment()
while not self.lockfile.am_i_next(): while not self.lockfile.am_i_next():
time.sleep(interval) self.stop_experiment_flag.wait(interval)
while gtk.events_pending(): while gtk.events_pending():
gtk.main_iteration(False) gtk.main_iteration(False)
if loop_run > 1: if loop_run > 1:
@ -460,6 +471,19 @@ class DamarisGUI:
loop_run = 0 loop_run = 0
loop_run += interval loop_run += interval
if self.stop_experiment_flag.isSet():
#Experiment has been stopped, clean up and leave
self.experiment_script_statusbar_label.set_text("Experiment stopped")
self.state = DamarisGUI.Edit_State
self.sw.enable_editing( )
self.toolbar_run_button.set_sensitive( True )
self.toolbar_stop_button.set_sensitive( False )
self.toolbar_pause_button.set_sensitive( False )
self.toolbar_pause_button.set_active( False )
#delete experiment from queue so that next experiment may start
self.lockfile.del_experiment(self.id)
return
# start experiment # start experiment
try: try:
self.spool_dir = os.path.abspath( actual_config[ "spool_dir" ] ) self.spool_dir = os.path.abspath( actual_config[ "spool_dir" ] )
@ -504,6 +528,8 @@ class DamarisGUI:
self.toolbar_stop_button.set_sensitive( False ) self.toolbar_stop_button.set_sensitive( False )
self.toolbar_pause_button.set_sensitive( False ) self.toolbar_pause_button.set_sensitive( False )
self.toolbar_pause_button.set_active( False ) self.toolbar_pause_button.set_active( False )
#delete Experiment from queue
self.lockfile.del_experiment(self.id)
return return
# switch to grapics # switch to grapics
@ -541,6 +567,33 @@ class DamarisGUI:
r = self.si.data.get( "__recentresult", -1 ) + 1 r = self.si.data.get( "__recentresult", -1 ) + 1
b = self.si.data.get( "__resultsinadvance", -1 ) + 1 b = self.si.data.get( "__resultsinadvance", -1 ) + 1
e = self.si.data.get( "__recentexperiment", -1 ) + 1 e = self.si.data.get( "__recentexperiment", -1 ) + 1
experimentstarttime = self.si.data.get( "__experimentstarted", 0 )
expectedexperimentruntime = self.si.data.get( "__totalexperimentlength", 0 )
experimentsfinishedtime = 0.0
for i in range(0, b):
experimentsfinishedtime += self.si.data.get("__experimentlengths", {}).get(i, 0.0)
experimentruntime = time.time() - experimentstarttime
experimenttimetext = ""
if experimentstarttime > 0 and expectedexperimentruntime > 0:
runtimemin, runtimesec = divmod(math.floor(experimentruntime), 60)
runtimehours, runtimemin = divmod(runtimemin, 60)
experimenttimetext += " ({:02d}:{:02d}:{:02d} / ".format(int(runtimehours), int(runtimemin), int(runtimesec))
expectedmin, expectedsec = divmod(math.ceil(expectedexperimentruntime), 60)
expectedhours, expectedmin = divmod(expectedmin, 60)
experimenttimetext += "{:02d}:{:02d}:{:02d})".format(int(expectedhours), int(expectedmin), int(expectedsec))
backendtimetext = ""
if experimentsfinishedtime > 0:
finexperimmin, finexperimsec = divmod(round(experimentsfinishedtime), 60)
finexperimhours, finexperimmin = divmod(finexperimmin, 60)
backendtimetext = " ({:02d}:{:02d}:{:02d})".format(int(finexperimhours), int(finexperimmin), int(finexperimsec))
e_text = None e_text = None
r_text = None r_text = None
b_text = None b_text = None
@ -560,6 +613,7 @@ class DamarisGUI:
else: else:
#print self.si.back_driver.get_messages() #print self.si.back_driver.get_messages()
e_text = "Experiment Script Running (%d)" % e e_text = "Experiment Script Running (%d)" % e
e_text += experimenttimetext
if self.si.res_handling is not None: if self.si.res_handling is not None:
if not self.si.res_handling.isAlive( ): if not self.si.res_handling.isAlive( ):
@ -588,6 +642,7 @@ class DamarisGUI:
b_text = "Backend Running" b_text = "Backend Running"
if b != 0: if b != 0:
b_text += " (%d)" % b b_text += " (%d)" % b
b_text += backendtimetext
if self.dump_thread is not None: if self.dump_thread is not None:
if self.dump_thread.isAlive( ): if self.dump_thread.isAlive( ):
@ -656,7 +711,7 @@ class DamarisGUI:
# keep data to display but throw away everything else # keep data to display but throw away everything else
self.si = None self.si = None
# delete locak file so that other experiment can start # delete lock file so that other experiment can start
self.lockfile.del_experiment(self.id) self.lockfile.del_experiment(self.id)
return False return False
@ -904,6 +959,7 @@ class DamarisGUI:
def stop_experiment( self, widget, data=None ): def stop_experiment( self, widget, data=None ):
if self.state in [ DamarisGUI.Run_State, DamarisGUI.Pause_State ]: if self.state in [ DamarisGUI.Run_State, DamarisGUI.Pause_State ]:
self.stop_experiment_flag.set()
if self.si is None: if self.si is None:
return return
still_running = filter( None, [ self.si.exp_handling, self.si.res_handling, self.si.back_driver ] ) still_running = filter( None, [ self.si.exp_handling, self.si.res_handling, self.si.back_driver ] )
@ -990,7 +1046,8 @@ class DamarisGUI:
# check generic debian location # check generic debian location
self.doc_urls[ "Python DAMARIS" ] = "file:///usr/share/doc/python-damaris/html/index.html" self.doc_urls[ "Python DAMARIS" ] = "file:///usr/share/doc/python-damaris/html/index.html"
else: else:
self.doc_urls[ "Python DAMARIS" ] = "https://element.fkp.physik.tu-darmstadt.de/damaris_cms/index.php?id=a-not-so-short-tutorial-on-damaris"
self.doc_urls[ "Python DAMARIS" ] = "https://element.fkp.physik.tu-darmstadt.de/damaris_cms/index.php?id=documentation"
self.doc_browser = None self.doc_browser = None
@ -1060,10 +1117,12 @@ class LogWindow:
writes messages to the log window writes messages to the log window
""" """
def __init__( self, xml_gui ): def __init__( self, xml_gui, damaris_gui ):
self.xml_gui = xml_gui self.xml_gui = xml_gui
self.damaris_gui = damaris_gui
self.textview = self.xml_gui.get_widget( "messages_textview" ) self.textview = self.xml_gui.get_widget( "messages_textview" )
self.textview.connect( "key-press-event", self.textview_keypress)
self.textbuffer = self.textview.get_buffer( ) self.textbuffer = self.textview.get_buffer( )
self.logstream = log self.logstream = log
self.logstream.gui_log = self self.logstream.gui_log = self
@ -1087,6 +1146,14 @@ class LogWindow:
self.textview.scroll_to_mark( self.textbuffer.get_insert( ), 0.1 ) self.textview.scroll_to_mark( self.textbuffer.get_insert( ), 0.1 )
gtk.gdk.threads_leave( ) gtk.gdk.threads_leave( )
def textview_keypress( self, widget, event, data=None ):
if event.state & gtk.gdk.CONTROL_MASK != 0:
if event.keyval == gtk.gdk.keyval_from_name("f"):
self.damaris_gui.sw.search(None, None)
return True
return False
def __del__( self ): def __del__( self ):
self.logstream.gui_log = None self.logstream.gui_log = None
self.logstream = None self.logstream = None
@ -1125,13 +1192,22 @@ class ScriptWidgets:
self.data_handling_textbuffer.set_language(langpython) self.data_handling_textbuffer.set_language(langpython)
self.data_handling_textbuffer.set_highlight_syntax(True) self.data_handling_textbuffer.set_highlight_syntax(True)
fontdesc = pango.FontDescription("monospace")
self.experiment_script_textview.set_buffer( self.experiment_script_textbuffer ) self.experiment_script_textview.set_buffer( self.experiment_script_textbuffer )
self.experiment_script_textview.set_show_line_numbers(True) self.experiment_script_textview.set_show_line_numbers(True)
self.experiment_script_textview.set_auto_indent(True) self.experiment_script_textview.set_auto_indent(True)
self.experiment_script_textview.set_insert_spaces_instead_of_tabs(True)
self.experiment_script_textview.set_tab_width(4)
self.experiment_script_textview.set_smart_home_end(True)
self.experiment_script_textview.modify_font(fontdesc)
self.data_handling_textview.set_buffer( self.data_handling_textbuffer ) self.data_handling_textview.set_buffer( self.data_handling_textbuffer )
self.data_handling_textview.set_show_line_numbers(True) self.data_handling_textview.set_show_line_numbers(True)
self.data_handling_textview.set_auto_indent(True) self.data_handling_textview.set_auto_indent(True)
self.data_handling_textview.set_insert_spaces_instead_of_tabs(True)
self.data_handling_textview.set_tab_width(4)
self.data_handling_textview.set_smart_home_end(True)
self.data_handling_textview.modify_font(fontdesc)
keywords = """for if else elif in print try finally except global lambda not or pass def keywords = """for if else elif in print try finally except global lambda not or pass def
class import from as return yield while continue break assert None True False AccumulatedValue class import from as return yield while continue break assert None True False AccumulatedValue
@ -1455,10 +1531,62 @@ get_job_id get_description set_description get_xdata get_ydata set_xdate set_yda
elif event.keyval == gtk.gdk.keyval_from_name("f"): elif event.keyval == gtk.gdk.keyval_from_name("f"):
self.search(None, None) self.search(None, None)
return True return True
return 0 return False
#Handle Backspace (delete more than one space on line beginning)
if event.keyval == 0xFF08:
textbuffer = widget.get_buffer( )
if textbuffer.get_has_selection():
return False
cursor_mark = textbuffer.get_insert( )
cursor_iter = textbuffer.get_iter_at_mark( cursor_mark )
linestart_iter = cursor_iter.copy( )
linestart_iter.set_line_offset( 0 )
linebegin = textbuffer.get_text( linestart_iter, cursor_iter ).expandtabs(4)
if linebegin.isspace() and len(linebegin) > 0:
linebegin = u' ' * int((len( linebegin ) - 1) / 4) * 4
textbuffer.delete( linestart_iter, cursor_iter )
textbuffer.insert( linestart_iter, linebegin )
return True
elif event.keyval == 0xFF0D:
textbuffer = widget.get_buffer( )
if textbuffer.get_has_selection():
return False
cursor_mark = textbuffer.get_insert( )
cursor_iter = textbuffer.get_iter_at_mark( cursor_mark )
lastchar_iter = cursor_iter.copy()
lastchar = lastchar_iter.backward_char( )
if not lastchar_iter.get_char( ) == u":":
return False
linestart_iter = cursor_iter.copy( )
linestart_iter.set_line_offset( 0 )
spaceend_iter = linestart_iter.copy( )
while (not spaceend_iter.ends_line( ) and not spaceend_iter.is_end( ) and spaceend_iter.get_char( ).isspace( )):
spaceend_iter.forward_char( )
linebegin = textbuffer.get_text( linestart_iter, spaceend_iter ).expandtabs(4)
indent_length = int((int(len(linebegin)/4)+1)*4)
intext = u"\n" + (u" " * indent_length)
textbuffer.insert(cursor_iter, intext)
widget.scroll_to_mark( cursor_mark, 0.0, 0 )
return True
#self.textviews_moved(widget) #self.textviews_moved(widget)
return 0 return False
def load_file_as_unicode( self, script_filename ): def load_file_as_unicode( self, script_filename ):
script_file = file( script_filename, "rU" ) script_file = file( script_filename, "rU" )
@ -3229,6 +3357,7 @@ class ScriptInterface:
self.data = DataPool( ) self.data = DataPool( )
def runScripts( self ): def runScripts( self ):
try: try:
# get script engines # get script engines
self.exp_handling = self.res_handling = None self.exp_handling = self.res_handling = None

View File

@ -66,6 +66,7 @@ class ExperimentHandling(threading.Thread):
self.traceback=traceback_file.getvalue() self.traceback=traceback_file.getvalue()
traceback_file=None traceback_file=None
return return
while exp_iterator is not None and not self.quit_flag.isSet(): while exp_iterator is not None and not self.quit_flag.isSet():
# get next experiment from script # get next experiment from script
try: try:
@ -86,6 +87,21 @@ class ExperimentHandling(threading.Thread):
if isinstance(job, Experiment): if isinstance(job, Experiment):
if self.data is not None: if self.data is not None:
self.data["__recentexperiment"]=job.job_id+0 self.data["__recentexperiment"]=job.job_id+0
# track time when experiment is started. This is placed after executing the script
# and getting the iterator so that time for initializing devices etc. is not included
if "__experimentstarted" not in self.data:
self.data["__experimentstarted"] = time.time()
# track time of experiments in queue, the total time and for each experiment:
if "__totalexperimentlength" not in self.data:
self.data["__totalexperimentlength"] = 0.0
if "__experimentlengths" not in self.data:
self.data["__experimentlengths"] = {}
experimentlength = job.get_length()
self.data["__experimentlengths"][job.job_id+0] = experimentlength
self.data["__totalexperimentlength"] += experimentlength
# relax for a short time # relax for a short time
if "__resultsinadvance" in self.data and self.data["__resultsinadvance"]+100<job.job_id: if "__resultsinadvance" in self.data and self.data["__resultsinadvance"]+100<job.job_id:
self.quit_flag.wait(0.05) self.quit_flag.wait(0.05)