#!/usr/bin/python -tti import time from factdimserver import * import numpy as np import types import sys import threading import Queue import logging # create logger with 'spam_application' logger = logging.getLogger('PyDimCtrl') logger.setLevel(logging.DEBUG) # create file handler which logs even debug messages fh = logging.FileHandler('PyDimCtrl.log') fh.setLevel(logging.DEBUG) # create console handler with a higher log level ch = logging.StreamHandler() ch.setLevel(logging.WARNING) # create formatter and add it to the handlers formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setFormatter(formatter) ch.setFormatter(formatter) # add the handlers to the logger logger.addHandler(fh) logger.addHandler(ch) last_drive_kwargs = {} last_drive_method = None bias_calibration = {} bias_current = {} report_length = 0 source_list = [ ['Crab', 0.6, 50, -130], ["1ES 2344+51.4", 0.6, 90, -90 ], ["Mrk 501", 0.6, -22, -22+180 ], ["Mrk 421", 0.6, 90, -90 ], ["1ES 1218+304", 0.6, -5, -5+180 ], ["1ES 1959+650", 0.6, 155, 155-180 ], ["Dark Patch 2", 0.6, 90, -90 ], ["Dark Patch 3", 0.6, 90, -90 ], ["H 1426+428", 0.6, 90, -90 ], ["IC 310", 0.6, -18, -18+180 ], ["PKS 2155-304", 0.6, 90, -90 ] ] crazyPatches = [66,191,193] sourcedict = {} def make_sourcedict(): for s in source_list: sourcedict[s[0]] = {} sourcedict[s[0]]['wobble_offset'] = s[1] sourcedict[s[0]]['wobble_angle1'] = s[2] sourcedict[s[0]]['wobble_angle2'] = s[3] def wait_nice(self, state_num, timeout=None): global report_length if not hasattr(self, 'stn'): raise TypeError(self.name+' has no CMD called STATE') if timeout == None: timeout = float('inf') else: timeout = float(timeout) start = time.time() intermed = time.time()-1. while not self.stn == state_num: time.sleep(0.1) if time.time() - intermed >= 1.: report = str(fad_control.events()[0]) + ' events @ ' + str( ftm_control.trigger_rates()[3]) + ' Hz' sys.stdout.write('\r'+' '*report_length) sys.stdout.flush() sys.stdout.write('\r'+report) sys.stdout.flush() report_length = len(report) intermed = time.time() if time.time() >= start+timeout: report_length=0 print return False report_length=0 print return True fad_control.wait_nice = types.MethodType( wait_nice, fad_control) def FadConnectCrate( crate ): cratenum = None if crate == 'all': print "connecting to all crates" for i in range( 40 ): time.sleep(3.8) fad_control.connect(i) print "... done" else: try: cratenum = int(crate) except ValueError as e: print "cannot convert crate parameter to integer. crate=", crate print e raise if cratenum != None: print "connecting to crate", cratenum for i in range(cratenum*10, (cratenum+1)*10 ): time.sleep(3.8) fad_control.connect(i) print "... done" def FadDisconnectCrate( crate ): cratenum = None if crate == 'all': print "connecting to all crates" for i in range( 40 ): fad_control.disconnect(i) print "... done" else: try: cratenum = int(crate) except ValueError as e: print "cannot convert crate parameter to integer. crate=", crate print e raise if cratenum != None: print "connecting to crate", cratenum for i in range(cratenum*10, (cratenum+1)*10 ): print 'disconnecting from ', i fad_control.disconnect(i) print "... done" def IsReadyForDataTaking( verbose=False ): """ Checking the system statuses if they are ready for data taking """ if verbose: print "--------------------------------------" print "Checking the system statuses of:" print "FEEDBACK, BIAS, FAD and DRIVE_CONTROL" print "--------------------------------------" print "...waiting for FEEDBACK" print " to be in state 12: CurrentControl" feedback.wait(12) if verbose: print "...waiting for BIAS_CONTROL" print " to be in state 9: VoltageOn" bias_control.wait(9) if verbose: print "...waiting for FAD_CONTROL" print " to be in state 4: Connected" fad_control.wait(4) if verbose: print "...waiting for drive_CONTROL" print " to be in state 8: Tracking" drive_control.wait(8) if verbose: print "...system statuses OK" print "--------------------------------------" def NotReadyForDataTaking( servers_n_targets = [ (feedback, 12), (bias_control, 9), (fad_control, 4) ] ): """ Checking the system statuses if they are ready for data taking return list of servers, which are NOT ready for Data Taking so one can use this function like this if not NotReadyForDataTaking(): # freak out else: # start data taking """ not_ready = [] print "--------------------------------------" print "Checking the system statuses of:" for server,target in servers_n_targets: print server.__name__ , ',' print print "--------------------------------------" for n, server, target in enumerate(servers_n_targets): if server.stn != target: print server.__name__, "NOT in state ", target not_ready.apppend((server,target)) return not_ready def PrepareBiasForDataTaking(): """ should have the original behaviour, no new fancy features check feedback state before switching BIAS ON and ramping up to nominal Voltage """ start = time.time() while (feedback.stn != 12): time.sleep(0.1) if time.time() > start + 10.: print "===================================================" print " feedback is not in state 'CurrentControl' " print " OPERATOR: " print " goto feedback console and check the state of " print " feedback by typing [st] to find out what the" print " current state means and maybe needs to be done" print " this script will wait for state 'CurrentControl'" print "===================================================" feedback.wait(12) bias_control.set_global_dac(1) start = time.time() while (bias_control.stn != 9): time.sleep(0.1) if time.time() > start + 10.: print '===================================================' print ' switching on bias not successfull' print ' biasctrl is not in state "VoltageOn"' print '' print ' OPERATOR:' print ' goto biasctrl console and check the state of' print ' biasctrl by typing [st] to find out what the' print ' current state means and maybe needs to be done' print '' print ' this script will wait for state "VoltageOn"' print '===================================================' bias_control.wait(9) bias_control.wait(5) bias_control.wait(9) print "bias is on, and feedback-program is working, but we wait 45sec for the current readings..." time.sleep(45) print "...done" def StopTracking(): """ should have the original behaviour, no new fancy features stop drivectrl tracking the current source """ drive_control.stop() drive_control.wait(6) #Armed print "Drive Armed" print "Tracking Stopped" def SwitchOnBias(): """ should have the original behaviour, no new fancy features bring Feedback to state CurrentControIdle and switch on Bias """ print ' switching on current controll feedback' feedback.stop() print ' ... starting current control feedback ' feedback.start_current_control(0.) feedback.enable_output(1) # 1 means True here ... this needs improvement. print ' ...waiting for FEEDBACK to be in state 9: CurrentCtrlIdle' feedback.wait(9) print '... feedback is running.' print ' switching bias on by, setting DAC to 1 globally' bias_control.set_global_dac(1) print ' ...waiting for BIAS to be in state 9: VoltageOn' bias_control.wait(9) print ' ...1 DAC globally set' print ' ...waiting for BIAS to be in state 5: Ramping' bias_control.wait(5) print ' ...ramping to nominal voltage' print ' ...waiting for BIAS to be in state 9: VoltageOn' bias_control.wait(9) print ' ...bias on' print ' waiting 45sec for the current control to stabilize...' time.sleep(45.) print ' ... done, bias on' # the feedback should be in state 'CurrentCtrlIdle'(9) now since 30.05.12 # if feedback.stn != 9: # print "feedback is in state:", feedback.sts , "(", feedback.stn, ")" # print "but is should be in state CurrentCtrlIdle (9)" # print "aborting" # return def WaitForTracking( verbose = False): """ Wait for drivectrl to reply that its tracking the given source """ if verbose: print "...waiting for DRIVE_CONTROL" print " to be in state 7: Moving" drive_control.wait(7) if verbose: print "...moving" if verbose: print "...waiting for DRIVE_CONTROL" print " to be in state 8: Tracking" drive_control.wait(8) if verbose: print "...tracking requested wobble position" if verbose: print "waiting 10 sec for drive to calm down" print "and tracking beeing stable" time.sleep(10) def Take( time, num_events, runtype, verbose=False): """ more general version of e.g. TakePedestalOnRun Note: One has to check, if Ready for *Take* by oneself """ runtype += '\0' if verbose: print ' taking', runtype,'. ', num_events, 'events in', time, 'seconds' mcp.start(time, num_events, runtype) if verbose: print '...waiting for FAD to be in state 8: Writing Data' fad_control.wait(8) # Writing Data if verbose: print '...waiting for FAD to be in state 4: Connected' fad_control.wait_nice(4) # Connected if verbose: print '... done' def TakeBetter( time, num_events, runtype, Bias = None, Drive = None, verbose=False): """ """ if Bias not in [None, 'On', 'Off']: raise ValueError('Bias needs to be one of [None, "On", "Off"]') return False # Sanity check # Drive can be: # Drive = 'sourcename' # Drive = ('sourcename', wobble_pos = 1 || 2) # Drive = None if type(Drive) not in [type(''), type((0,0)), type(None) ]: raise ValueError('Bias needs to be one of [None, "On", "Off"]') return False runtype += '\0' # FAD: # # It makes no sense to try to take data, when the FADs are not well connected. # Also I think it makes no sense to start datataking, when FAD is in WritingData # and when MCP is not in an Idle state... # # we will check if FAD is in Connected(4), if in Writing_Data(8), we will send: close_all_open_files() # if in one of the configuring states(5,6,7) we will send reset_configure # if in Connecting(3), we will try to find which board is making problems... # and disconnect and connect it --> THREE TIMES # if it doesn't help. # we abort. # # # FTM: # the ftm is not so critcal, since it makes no problems normally... # It can be in triggerON(4) or Idle(3) # Connected(2) is not good here we need a power cycle # Any of the Configured States (5,6,7) should be treated with reset_configure() # # we will anyway check if in Connected(2) before starting. # DRIVE_CONTROL: # in case *Drive* is a valid sourcename from sourcedict, # we will give the command to point to that source in ON mode # in case *Drive* is a tuple of ('sourcename', 1 || 2) # We will point to that soource in wobble mode. # # If Drive is 'Stop. The Drive will be stopped # # In anycase The Drive will be checked for not beeing in the state ERROR # in that case we will send DRIVE_CONTROL/STOP and the last tracking # command or nothing in case Drive = 'Stop' # # In case Drive is None no commands will be send to DRIVE_CONTROL at allow # Drive can be: # Drive = 'sourcename' # Drive = ('sourcename', wobble_pos = 1 || 2) # Drive = None # RATE_CTRL # # Rate_control should be in Connected(4) and not lower # 5,6,7 should not be the case ... STOP will help, I hope # # we will try to get it into Connected, by sending STOP once # if not successful we abort start_time = time.time() duration = 10. while fad_control.stn != 4: if fad_control.stn in [5,6,7]: # Configure State --> Reset_Configure fad_control.reset_configure() elif fad_control.stn == 8: #WritingData --> Close_all_open_files() fad_control.close_open_files() elif fad_control.stn == 3: #Connecting --> try to find 'bad' board and reconnect duration = 60. print 'fad_control in state Connecting ... trying to find "bad" board' print 'timeout increased to 60.sec' conn = GetFadConnections() bad = np.where( conn != 0x42 )[0] print 'possible bad boards', bad print 'disconnecting' for b in bad: fad_control.disconnect(b) time.sleep(3.) for b in bad: fad_control.connect(b) else: # really bad .. abort print 'ERROR: FAD_CTRL in state', fad_control.stn, fad_control.sts print 'I do not know how to treat that ... aborting' return False time.sleep(1.) if time.time() - start_time > duration: print 'Timeout during try to get FAD into Connected' return False # BIAS # # As well it makes no sense to try to take data, when the Bias control is in an # undefined state. # When *Bias* is 'On' we will take care that the Bias voltage is on, and stays on # When *Bias* is 'Off' we will shut bias down and do nothing more # When *Bias* is None -default- then no commands will be send to BiasCtrl start_time = time.time() duration = 20. if Bias == 'On': if ( (bias_control.voltage()[0:320].mean() > 60) and ( (bias_control.stn == 5) or (bias_control.stn == 9) ) ): pass elif Bias == 'Off': pass if verbose: print ' taking', runtype,'. ', num_events, 'events in', time, 'seconds' mcp.start(time, num_events, runtype) if verbose: print '...waiting for FAD to be in state 8: Writing Data' fad_control.wait(8) # Writing Data if verbose: print '...waiting for FAD to be in state 4: Connected' fad_control.wait_nice(4) # Connected if verbose: print '... done' def TakeData(): """ taking a Data Set (1x Pedestal On, 1x LPext, 4x5min DataRun) """ # take a Pedestal run IsReadyForDataTaking() print 'taking pedestal run with 1000 events' Take(-1, 1000, 'pedestal') # take a ExtLP run IsReadyForDataTaking() print 'taking External Light Pulser with BIAS on 1000 ...' Take(-1, 1000, 'light-pulser-ext') #Data Taking with Full Trigger Area (4x5min) for run in range(4): print 'taking data run', run+1, 'out of 4' IsReadyForDataTaking() Take( 300, -1, 'data') def TakeDrsCalibration(): """ script for DRS-Calibration before Data taking """ print 'script for DRS-Calibration before Data taking' print 'starting up...' feedback.enable_output(1) # Making sure bias is off, before the DRS calibration starts bias_control.set_zero_voltage() print '...ramping Voltage down' print ' ...waiting for BIAS to be in state 7: Voltage Off' bias_control.wait(7) #VoltageOff print '...BIAS voltage is switched off' # starting the DRS calibration fad_control.start_drs_calibration() # taking first DRS:Pedestal with 1000 Events and ROI 1024 print 'taking DRS:Pedestal 1000 ...' fad_control.wait(4) #Connected Take(-1, 1000, 'drs-pedestal') # taking DRS:Gain with 1000 Events and ROI 1024 print ' taking DRS:Gain 1000 ...' fad_control.wait(4) #Connected Take(-1, 1000, 'drs-gain') # taking DRS:Pedestal 1000 Events and ROI 1024 print 'taking DRS:Pedestal 1000 ...' fad_control.wait(4) #Connected Take(-1, 1000, 'drs-pedestal') print ' ... done' # taking again a DRS:Pedestal with 1000 Events and ROI 1024 for a crosscheck of calculated calibrations constants print ' taking crosscheck DRS:Pedestal 1000 ...' fad_control.set_file_format(2) fad_control.wait(4) #Connected Take(-1, 1000, 'drs-pedestal') # taking DRS:Time with 1000 Events and ROI 1024 print ' taking DRS:Time 1000 ...' fad_control.wait(4) #Connected Take(-1, 1000, 'drs-time') # taking DRS:Time upshifted 1000 Events and ROI 1024 print 'taking DRS:Time upshifted 1000 ...' fad_control.wait(4) #Connected Take(-1, 1000, 'drs-time-upshifted') # taking a Pedestal with 1000 Events and ROI 300 for secondary baseline... print 'taking Pedestal 1000 for secondary baseline... with ROI=300' fad_control.reset_secondary_drs_baseline() fad_control.wait(4) #Connected Take(-1, 1000, 'pedestal') # taking crosscheck Pedestal 1000 Events and ROI 300 print ' taking crosscheck Pedestal 1000 ...with ROI=300' fad_control.set_file_format(2) fad_control.wait(4) #Connected Take(-1, 1000, 'pedestal') print '----------------------------------------------------' print 'This is the end of the' print 'DRS-Calibration before Data taking' print '----------------------------------------------------' def FirstDrsCalib( SkipCurrentCalib=False ): logger = logging.getLogger('PyDimCtrl.FDC') """ performs the everything, which is done in the FirstDrsCalib Script as well . """ # As a First step we want to calibrate the current, which are read from the bias crate, # and not take a DRS calibration, as it is mentioned in the data taking page... # so for this we should get the feedback and biasctrl programs into known states # I think it is good to try a RECONNECT to the bias, and make sure the voltage is off # Since we do not know, what the feedback program is doing at the moment, we should as well, # tell it to keep its mouth shut ... just to be sure, we know whats going on logger.debug("stopping feedback") feedback.stop() time.sleep(2) # stopping should always be possible, and end in state 'Connected'(6) logger.debug(" ...waiting for FEEDBACK to be in state 6: Connected") print feedback.wait(6) print "..done" #BIAS_CONTROL/RECONNECT # If we were disconnected, and this was the first try of the night, the bias_ctrl should # be in state 'VoltageOff'(7) more or less immediately #.s BIAS_CONTROL 3 #.s BIAS_CONTROL 7 5000 # if these assumptions are all wrong, then we might have been properly connected anyway, # and just have to ramp down... lets do it, but wait forever, in case it does not work print " switching off bias" bias_control.set_zero_voltage() time.sleep(2) print " ...waiting for BIAS to be in state 7: VoltageOff" bias_control.wait(7) print " ...done" if not SkipCurrentCalib: # in case we reach this line, the voltages are all off, and the feedback does not do anything # So lets do the current calibration, therefor we tell the bias crate to ramp up just 1 single DAC count(~22mV) # the result of this action is, to get bias_ctrl into the state 'VoltageOn'(9), but since we only go one DAC count it shouldn't take long print " setting bias globally to 1 DAC" bias_control.set_global_dac(1) time.sleep(2) print " ...waiting for BIAS to be in state 9: VoltageOn" bias_control.wait(9) print " ...done" # now we may tell the feedback program to calibrate the currents ... # I do not understand, if I have to explicitely allow the feedback program to generate output, # or if it just produces output... # As far as I understand, the feedback output enable status is the same, # as it was before I send the STOP command... so it is unknown at this point. # and in addition enabling or disabling the output, when STOPed is not possible as far as I know... # I try to enable it anyway. print " enabling output for feedback" feedback.enable_output(1) time.sleep(2) print " ...done" print " calibrating bias crate current readings..." feedback.calibrate_currents() time.sleep(5) # in order to find out when the calibration ends, we have to wait for the transistion from state # 'Calibrating'(13) back to 'Connected'(6) print " ...waiting for FEEDBACK to be in state 13: Calibrating" feedback.wait(13) print " ...waiting for FEEDBACK to be in state 6: Connected" feedback.wait(6) # Thomas Bretz told me, that the feedback, after this is step has disabled its output # and is in the mode, we might call 'temperature control' even there is no temerature beeing controlled. # I don't know where the voltage is ... in order to perform the calibration, the feedback had to # ramp up to 2V below the operational voltage, i.e. about 1V below the breakdown voltage # We want to take a DRS amplitude calibration so we have to ramp down the bias voltage. # this 10sec wait is needed in order for the bias not to disconect all the time... print " ... current calibration done" #time.sleep(10) print " switching off bias" bias_control.set_zero_voltage() #time.sleep(5) print " ...waiting for BIAS to be in state 7: VoltageOff" bias_control.wait(7) print " ...done" # So now we can take the 3 runs, which are called DRS amplitude calibration: # A pedestal run with ROI=1024 # A gain calibration run with ROI=1024 # and a second pedestal run, with the same ROI as our next data will be, i.e. ROI=300 in this case print "taking DRS:Pedestal 1000 ..." #print "===================================================" #print "OPERATOR: " #print "observe Events tab and make sure there are no patches " #print "with strange behaviour, which can be caused " #print "by DRS-CHIP Problems" #print "===================================================" fad_control.start_drs_calibration() #time.sleep(0.5) Take( -1, 1000, 'drs-pedestal') print "taking DRS:Gain 1000 ..." Take( -1, 1000, 'drs-gain') time.sleep(2) if GetDrsCalibGainRms(): print print 'First DRS Calib Script will be aborted' print 'operator, please power cycle FACT' return False print "taking Pedestal 1000 ..." Take( -1, 1000, 'pedestal') # okay this is the DRS calibration for the next few runs. # we are now asked to take again a pedestal run, which can be used, to # calculate the electronics noise for instance ... since the shutter is closed and the # voltage is off .. there should not be alot of signal in it :-) print "taking crosscheck Pedestal 1000 ..." fad_control.set_file_format(2) Take(-1, 1000, 'pedestal') # now we want to take a run, with dark counts events # so we need to ramp up the voltage # we want to use the 'current control' more so we give the commands for this... print "switching on current controll feedback ..." feedback.stop() feedback.start_current_control(0.0) feedback.enable_output(1) # the feedback should be in state 'CurrentControl'(12) now # the feedback should be in state 'CurrentCtrlIdle'(9) now since 30.05.12 print "...waiting for FEEDBACK to be in state 12: CurrentControl" feedback.wait(12) print "... done" print "switching on bias" # now we give the feedback a hint, that it may ramp ... bias_control.set_global_dac(1) # after this command the bias_ctrl should be in state 'VoltageOn'(9) after a second or so print "...waiting for BIAS to be in state 9: VoltageOn" bias_control.wait(9) print "...1 DAC globally set" # then usually it takes some time until the feedback has enough information to really start controlling the voltage # when the feedback actually kicks in, the bias is first in state 'Ramping'(5) for some seconds and finally in 'VoltageOn'(9) # again print "...waiting for BIAS to be in state 5: Ramping" bias_control.wait(5) print "...ramping to nominal voltage" print "...waiting for BIAS to be in state 9: VoltageOn" bias_control.wait(9) print "...bias on" # here we should wait 45 sec in order for the current control to get enough current readings and temp readings to stabilize.. print "waiting 45sec for the current control to stabilize..." time.sleep(45) print "... done" # so now we can take the dark count run ... # this might be changed in the future ... either the number of events or the the ROI might be changed # then the DRS calibration above, and the pedestal run in between have to be changed as well. print "taking Pedestal with BIAS on 3000 ..." Take(-1, 3000, 'pedestal') # at the end the bias voltage should be ramped down, since in a few seconds a shifter wit ha flashlight # will come out to open the shutter... print "switching OFF bias ..." bias_control.set_zero_voltage() print "...waiting for BIAS to be in state 7: VoltageOff" bias_control.wait(7) print "...done" print "This is the end of First DRS Calibration" print "----------------------------------------------------" print ">" def Ratescan( ra=None, dec=None, sourcename=None): """ # call it by: .x ScriptsForDimCtrl/Ratescan.dim mode= ra= dec= source= # mode=0: Manual tracking Mode: set tracking in drivectrl manually # mode=1: Coordinate Mode: scripts sends tracking command to drivectrl with the given RaDec coordinates # mode=2: source Mode: scripts sends tracking command to drivectrl with the given source_name """ print '======================================' print 'RATESCAN' print '======================================' print 'Preparing Drive' if None == ra and None == dec and None == sourcename: print 'Manual tracking Mode' print '---------------------' print 'OPERATOR' print 'change tracking in drivectrl manually' print 'script will wait for drive' print 'to be in state tracking' elif None != ra or None != dec: try: ra = float(ra) dec = float(dec) except TypeError: raise print '...stop tracking' StopTracking() print '...change tracking of telescope to:' print '...Ra = ', ra print '...Dec = ', dec drive_control.track( ra, dec) elif None != sourcename: print '...stop tracking' StopTracking() print '...change tracking of telescope to:', sourcename sourcename += '\0' drive_control.track_source( 0, 0, sourcename) else: print 'type(ra)', type(ra), '\tra', ra print 'type(dec)', type(dec), '\tdec', dec print 'type(sourcename)', type(sourcename), '\tsourcename', sourcename raise ValueError('RateScan does not know what to do with its parameters. Bug!') return False IsReadyForDataTaking() print 'Starting Ratescan' print '...waiting for Ratescan' print ' to be in state 4: Connected' if not rate_scan.wait(4, timeout=5.): #Connected # we went into timeout! print 'Rate_Scan not in correct state' print 'OPERATOR:' print '+ check connection to ftm control' print 'we went into to 5sec. timeout while waiting for RATE_SCAN to be in state Connected' print 'aborting' return False rate_scan.start_threshold_scan( 50, 1000, -10) if not rate_scan.wait( 6, timeout=10.): # Statename??? # we went into timeout print 'ratescan not started' print 'we went into 10sec. timeout while waiting for RATE_SCAN to start the Scan' print 'aborting' return False print '...processing ratescan' if not rate_scan.wait( 4, timeout=2700.): # Connected # we went into timeout print 'we went into 2700sec. timeout while waiting for RATE_SCAN to finish' print 'aborting' return False print 'Ratescan finished successfully' return True def ResetCrate( crate_num ): """ Reset Crate crate_num = 0,1,2 or 3 the number of the crate to reset. crate_num = 'all' is NOT YET SUPPORTED """ c = int(crate_num) print '======================================' print 'Crate-Reset for crate ', c print '======================================' print '...resetting MCP' mcp.reset() time.sleep(5.) print '...diconnecting FAD boards of crate ', c FadDisconnectCrate( c ) time.sleep(2.) print '...disconnecting All FTUs' ftm_control.enable_ftu( -1, 0) # -1 for all, and 0 for False time.sleep(2.) print '...checking state of FTM_Control' print '...waiting for state 3: Idle' if not ftm_control.wait(3, 2.): # Idle print '...stopping trigger' ftm_control.stop_trigger() ftm_control.wait(3) # wait for Idle endlessly print '...resetting crate' ftm_control.reset_crate( c ) time.sleep(2.) print '...connecting All FTUs' ftm_control.enable_ftu( -1, 1) # -1 for all, and 1 for yes, or True time.sleep(4.) print '...pinging FTUs' ftm_control.ping() print '...connecting FAD boards of crate', c FadConnectCrate(c) print '======================================' print 'Crate-Reset for crate', c, 'finished' print '======================================' def GetDrsCalibGainRms(): #drs_calibration(self) method of factdimserver.FAD_CONTROL instance #DESC in SERVICE_DESC is empty ?! #I:1;I:3;F:1474560;F:1474560;F:1474560;F:1474560;F:1474560;F:1474560;F:163840;F:163840 data = fad_control.drs_calibration() N1 = data[0] N3 = data[1:4] OffsetMean = np.array(data[4:4+1024*1440]).reshape(1440,1024) OffsetRms = np.array(data[4+1024*1440:4+1024*1440*2]).reshape(1440,1024) GainMean = np.array(data[4+1024*1440*2:4+1024*1440*3]).reshape(1440,1024) GainRms = np.array(data[4+1024*1440*3:4+1024*1440*4]).reshape(1440,1024) gr = GainRms.mean(axis=1) lala = np.zeros(len(gr)/9) for i,v in enumerate(lala): lala[i] = gr[i*9:(i+1)*9].mean() # outliers mean = lala.mean() std = lala.std() print 'Mean DRS GainRms value:', mean print 'std:', std outs = np.where( lala > mean+7*std)[0] if len(outs) > 0: print 'WARNING possible DRS underflow detected!!!' for out in outs: out = int(out) crate= out/40 board = (out-40*crate)/4 chip = out-40*crate-4*board print 'possible DRS underflow in DRS:', crate, board, chip, '--> Mean-GainRms:', lala[out] return outs else: return False def GetBiasCalibration(): cali = feedback.calibration() bias_calibration['Time'] = time.time() bias_calibration['Calibration'] = cali def _GetBiasCurrent_Raw(verbose = False): """ return median, std, max and min current """ if 'Time' in bias_calibration: cali = bias_calibration['Calibration'] else: GetBiasCalibration() cali = bias_calibration['Calibration'] r = np.array(cali[2*416:2*416+320]) bias = bias_control I = np.array(bias.current()[0:320], dtype=float) II = I/4096. * 5000 V = np.array(bias.voltage()[0:320]) if len(sys.argv) > 1: i = int(sys.argv[1]) else: i=0 # print 'I:', I[i], 'dac\t', II[i], 'uA' # print 'V:', V[i] # print '' # print 'GUI offset:', V[i]/r[i]*1e6 # print 'GUI feedback:', II[0] - V[0]/r[0]*1e6 # GUII means current(I) as it is written in the GUI :-) # read: GUI-I :-) GUII = II-V/r*1e6 if verbose: print 'median', np.median(GUII) print 'mean', GUII.mean() # print 'rms', ((GUII- GUII.mean())**2).sum() print 'std', GUII.std() print 'max', GUII.max() print 'min', GUII.min() bias_current['Time'] = time.time() bias_current['raw_patch_current'] = GUII return GUII def GetPatchCurrents(crazyPatches=crazyPatches ,verbose = False, max_age_sec=1. ): if 'Time' in bias_current: if time.time() - bias_current['Time'] > max_age_sec: raw_cur = _GetBiasCurrent_Raw() else: raw_cur = bias_current['raw_patch_current'] else: raw_cur = _GetBiasCurrent_Raw() if crazyPatches is None: return raw_cur else: try: crazyPatches = list(crazyPatches) except: raise goodPatches = [x for x in range(320) if x not in crazyPatches] return raw_cur[goodPatches] def GetPixelCurrents(crazyPatches=crazyPatches ,verbose = False, max_age_sec=1. ): if 'Time' in bias_current: if time.time() - bias_current['Time'] > max_age_sec: raw_cur = _GetBiasCurrent_Raw() else: raw_cur = bias_current['raw_patch_current'] else: raw_cur = _GetBiasCurrent_Raw() pixel_cur = np.zeros(len(raw_cur)) for i in range(len(raw_cur)): if i/2: pixel_cur[i] = raw_cur[i]/5. else: pixel_cur[i] = raw_cur[i]/4. if crazyPatches is None: return pixel_cur else: try: crazyPatches = list(crazyPatches) except: raise goodPatches = [x for x in range(320) if x not in crazyPatches] return pixel_cur[goodPatches] def PrintPixelCurrents( delay = 4.0): while True: time.sleep( delay ) current = GetPixelCurrents() interesting = current.min(), np.median(current), current.mean(), current.max() print time.strftime('%d %b %Y %H:%M:%S UTC', time.gmtime()), interesting def TrackSourceWobbleX( sourcename, wobble_pos ): """ general Tracking function """ wp = int(wobble_pos) if wp != 1 and wp != 2: raise ValueError('wobble_pos *must* be 1 or 2') if sourcename not in sourcedict: print sourcedict.keys() raise ValueError('sourcename: '+ sourcename +' must be in sourcedict.') logger.debug('TrackSourceWobbleX: sending drive_control.stop()') drive_control.stop() logger.debug('TrackSourceWobbleX: waiting for DRIVE_CONTROL to be "Armed"') drive_control.wait(6) #Armed logger.info('moving telescope to wobble position %s of %s' % str(wp), sourcename) wobble_offset = sourcedict[sourcename]['wobble_offset'] wobble_angle = sourcedict[sourcename]['wobble_angle'+str(wp)] sourcename += '\0' # this is just book keeping. I store the method, which is used # in this case drive_control.track_source() # and the arguments, in some global vars .. in order to be able to # resend the command if necessary. last_drive_method = drive_control.track_source last_drive_kwargs = { 'wobble_offset' : wobble_offset, 'wobble_angle' : wobble_angle, 'source_name' : sourcename } kwa = last_drive_kwargs # Here I really send the command last_drive_method(kwa['wobble_offset'], kwa['wobble_angle'], kwa['source_name']) logger.debug('TrackSourceWobbleX: waiting for DRIVE_CONTROL to be "Tracking"') drive_control.wait(8) #Tracking return True def TakeSource( name ): if name not in sourcedict: print name, 'not in dict of sources, possible sources are:' print sorted(sourcedict.keys()) raise ValueError('wrong source name') TrackSourceWobbleX( name, 1) # Track Wobble pos 1 of source WaitForTracking() # Take a DRS-Calibration before beginning to take physics Data TakeDrsCalibration() # check feedback state before switching BIAS ON and ramping up to nominal Voltage PrepareBiasForDataTaking() # taking a Data Set (1x Pedestal 1000 Bias On, 1x LPext 1000, 4x5min DataRun) TakeData() StopTracking() TrackSourceWobbleX( name, 2) # Track Wobble pos 2 of source WaitForTracking() # taking a Data Set (1x Pedestal 1000 Bias On, 1x LPext 1000, 4x5min DataRun) TakeData() StopTracking() def set_file_format_to_FITS(): fad_control.set_file_format(2) # (Time , Drive, Bias, DAQ, call-before-run) class RunType(object): drs_pedestal = (-1, 1000, 'drs-pedestal') drs_gain = (-1, 1000, 'drs-gain') drs_time = (-1, 1000, 'drs-time') drs_time_upshifted = (-1, 1000, 'drs-gain-upshifted') pedestal = (-1, 1000, 'pedestal') lightpulser = (-1, 1000, 'light-pulser-ext') data = (300, -1, 'data') class Schedule(object): drs_calib_crab = [ ( None , ('Crab',1) , 'Off', RunType.drs_pedestal , fad_control.start_drs_calibration ), ( None , ('Crab',1) , 'Off', RunType.drs_gain , None ), ( None , ('Crab',1) , 'Off', RunType.drs_pedestal , None ), ( None , ('Crab',1) , 'Off', RunType.drs_pedestal , set_file_format_to_FITS ), ( None , ('Crab',1) , 'Off', RunType.drs_time , None ), ( None , ('Crab',1) , 'Off', RunType.drs_time_upshifted , None ), ( None , ('Crab',1) , 'Off', RunType.pedestal , fad_control.reset_secondary_drs_baseline ), ( None , ('Crab',1) , 'Off', RunType.pedestal , None ) ] drs_calib_not_moving = [ ( None , None , 'Off', RunType.drs_pedestal , fad_control.start_drs_calibration ), ( None , None , 'Off', RunType.drs_gain , None ), ( None , None , 'Off', RunType.drs_pedestal , None ), ( None , None , 'Off', RunType.drs_pedestal , set_file_format_to_FITS ), ( None , None , 'Off', RunType.drs_time , None ), ( None , None , 'Off', RunType.drs_time_upshifted , None ), ( None , None , 'Off', RunType.pedestal , fad_control.reset_secondary_drs_baseline ), ( None , None , 'Off', RunType.pedestal , None ) ] data_crab_Wobble_1 = [ ( None , ('Crab',1) , 'On', RunType.pedestal , None ), ( None , ('Crab',1) , 'On', RunType.lightpulser , None ), ( None , ('Crab',1) , 'On', RunType.data , None ), ( None , ('Crab',1) , 'On', RunType.data , None ), ( None , ('Crab',1) , 'On', RunType.data , None ), ( None , ('Crab',1) , 'On', RunType.data , None ), ] data_crab_Wobble_2 = [ ( None , ('Crab',2) , 'On', RunType.pedestal , None ), ( None , ('Crab',2) , 'On', RunType.lightpulser , None ), ( None , ('Crab',2) , 'On', RunType.data , None ), ( None , ('Crab',2) , 'On', RunType.data , None ), ( None , ('Crab',2) , 'On', RunType.data , None ), ( None , ('Crab',2) , 'On', RunType.data , None ), ] class ScheduledDataTakingThread( threading.Thread ): """ """ def __init__( self , delay = 5): threading.Thread.__init__(self) self.stoprequest = threading.Event() self.warning_state = 'Unknown' self.state_change = time.time() self.logger = logging.getLogger('PyDimCtrl.ScheduledDataTakingThread') self.delay = delay self.queue = Queue.Queue() def run(self): while not self.stoprequest.isSet(): task = self.queue.get() start_time = task[0] drive_task = task[1] bias_task = task[2] daq_task = task[3] pre_action = task[4] if drive_task is not None: TrackSourceWobbleX( *drive_task ) # if start_time is None or start_time > time.gmtime(): # # do it # if drive_task is not None: # TrackSourceWobbleX( *drive_task ) # this blocks until 'Tracking' # # TODO: # # spawn a new DriveMonitorThread here and start it. if bias_task is not None: if bias_task == 'On': Make_Bias_On() else: Make_Bias_On() # TODO: # spawn a new BiasMonitorThread here and start it. if daq_task is not None: if pre_action is not None: pre_action() MakeReadyForDataTaking() Take( *daq_task ) # TODO: # spawn a new DaqMonitorThread here and start it. self.queue.task_done() time.sleep( self.delay ) def join( self, timeout=None): self.stoprequest.set() self.logger.info('was requested to die with timeout=%s' % str(timeout) ) #super(CheckBiasThread, self).join() threading.Thread.join(self) def MakeReadyForDataTaking( delay=1 ): while fad_control.stn != 4 or ftm_control.stn != 3: # Connected & Idle logger.info('MakeReadyForDataTaking FTM trigger is still on') if ftm_control.stn == 4: # Trigger is on ftm_control.stop_trigger() logger.warning('MakeReadyForDataTaking FAD: still in WritingData') if fad_control.stn == 8: # Writing Data fad_control.close_all_open_files() logger.warning('MakeReadyForDataTaking FAD: still in one of the Configure(ing) states') if fad_control.stn in [5,6,7]: # one of the Configure(ing) states fad_control.reset_configure() logger.warning('MakeReadyForDataTaking FTM: still in one of the Configure(ing) states') if ftm_control.stn in [5,6,7]: # one of the Configure(ing) states ftm_control.reset_configure() time.sleep(delay) return True def PrintCurrents( x = 1.0): while True: time.sleep( x ) GUII = GetBiasCurrent() interesting = GUII.mean(), GUII.std(), GUII.max(), GUII.min() print time.strftime('%d %b %Y %H:%M:%S UTC', time.gmtime()), interesting def GetFadConnections( verbose = False ): """ return np.array(40) with bitmaps, showing the FADs connection status: apperently this is the meaning: 0x43 -- well connected and well configured -- green with white tick mark 0x42 -- well connected -- green 0x09 -- something is wrong with the connection -- orange or red? 0x00 -- not connected, and not attempting to connect -- grey """ conn = np.array(map( ord, fad_control.connections()[0] )) if verbose: for crate in range(4): print map( hex, conn[crate*10: (crate+1) *10 ] ) return conn def GetFadBadConnections( good = 0x42 ): """ returns list of bad FAD IDs """ conn = GetFadConnections() bads = np.where( conn != good) [0] return bads def StartUp(): fad_control.start() bias_control.reconnect() bias_control.set_zero_voltage() while bias_control.stn == 6 : # OverCurrent bias_control.set_zero_voltage() bias_control.reset_over_current_status() ftm_control.reconnect() number_of_loops = 3 while True: bad = GetFadBadConnections() if len(bad) == 0: break for b in set( bad/10 ): # set(b/10) contains the crate ids, which have bad FADs ResetCrate( b ) number_of_loops -= 1 if not number_of_loops: print 'StartUp aborted while trying to get the FADs into Connected state ... ' return False if not MakeDriveCtrlReady(): return False return True def Shutdown(): fad_control.stop() ftm_control.disconnect() feedback.stop() bias_control.set_zero_voltage() def MakeDriveCtrlReady(): """ Tries to get Drive ctrl from Disconnected, locked or Error to Armed after a few tries it gives up and returns False """ outer_counter = 3 while drive_control.stn != 6: #Armed # print 'MakeDriveCtrlReady outer_counter', outer_counter counter = 3 while drive_control.stn == 1: #Disconnected # print 'MakeDriveCtrlReady in while 1, counter:', counter drive_control.reconnect() time.sleep(0.5) counter -= 1 if not counter: print 'count not connect drive control to cosy ... please check if cosy is running' return False counter = 3 while drive_control.stn == 3: # Locked # print 'MakeDriveCtrlReady in while 2, counter:', counter drive_control.unlock() time.sleep(0.5) counter -= 1 if not counter: print 'could not unlock drive control WTF?' return False counter = 3 while drive_control.stn == 256: # ERROR # print 'MakeDriveCtrlReady in while 3, counter:', counter drive_control.stop() time.sleep(0.5) counter -= 1 if not counter: print 'could not unlock drive control WTF?' return False outer_counter -= 1 if not outer_counter: print 'ERROR while trying to get Drive control ready' return False return True feedback_calibration_done = None # Bool... def Make_Bias_Off(): bias_control.set_zero_voltage() bias_control.wait(7) def Make_Bias_On(): """ Tries to get the Bias, and Feedback into a defined safe Off state While beeing as ready as possible to go into On state """ global feedback_calibration_done # Feedback states: #List of available states: #-[-1]: NotReady (State machine not ready, events are ignored.) #-[0]: Ready (State machine ready to receive events.) #-[1]: DimNetworkNotAvailable (The Dim DNS is not reachable.) #-[2]: Disconnected (The Dim DNS is reachable, but the required subsystems are not available.) #-[3]: Connecting (Only biasctrl is available and connected with its hardware.) #-[4]: ConnectedFSC (biasctrl and fscctrl are available and connected with their hardware.) #-[5]: ConnectedFAD (biasctrl and fadctrl are available and connected with their hardware.) #-[6]: Connected (biasctrl, fadctrl and fscctrl are available and connected with their hardware.) #-[7]: TempCtrlIdle (Temperature control activated, but voltage output disabled.) #-[8]: FeedbackIdle (Feedback control activated, but voltage output disabled.) #-[9]: CurrentCtrlIdle (Current control activated, but voltage output disabled.) #-[10]: TempControl (Temperature control activated and voltage output enabled.) #-[11]: FeedbackControl (Feedback control activated and voltage output enabled.) #-[12]: CurrentControl (Current/Temp control activated and voltage output enabled.) #-[13]: Calibrating (Calibrating current offsets.) #-[256]: ERROR (Common error state.) #-[65535]: FATAL (A fatal error occured, the eventloop is stopped.) while not ( (feedback.stn == 12) and (bias_control.stn == 9) and (np.array(bias_control.voltage()[0:320]).mean() > 65.) ): # for security feedback.enable_output(0) # try to get bias_control into state: VoltageOn while not bias_control.stn == 9: if bias_control.stn == 1: #Disconnected bias_control.reconnect() if bias_control.stn == 2: #Connecting time.sleep(1) if bias_control.stn == 3: #Initializing time.sleep(1) if bias_control.stn == 4: #Connected # this seems never to happen ... time.sleep(1) #bias_control.set_global_dac(1) if bias_control.stn == 5: #Ramping time.sleep(1) if bias_control.stn == 6: #OverCurrent bias_control.set_zero_voltage() time.sleep(1) bias_control.reset_over_current_status() if bias_control.stn == 7: #VoltageOff bias_control.set_global_dac(1) if bias_control.stn == 8: #NotReferenced bias_control.set_zero_voltage() if bias_control.stn == 9: #VoltageOn pass if bias_control.stn > 9: print "BIAS control is in strange status... don't know what to do" time.sleep(1) time.sleep(1) # Try to get Feedback into CurrentControl while not (feedback.stn == 12): if feedback.stn < 6: # not properly connected. # State 6 is 'Connected' but this normaly hardly shows up # Its either voltageOff or any other meaningful state... print "FEEDBACK not properly connected..." time.sleep(1) if feedback.stn == 13: #Calibrating time.sleep(1) continue if not feedback_calibration_done: if feedback.calibration() is None: print "FEEDBACK has not CURRENT CALIBRATION" print "TRYING TO CALIBRATE" feedback.calibrate_currents() time.sleep(0.5) continue else: feedback_calibration_done = True if feedback.stn == 6: #Connected feedback.start_current_control(0.0) if feedback.stn in [7,8]: #TempCtrlIdle , FeedbackIdle feedback.stop() time.sleep(0.5) feedback.start_current_control(0.0) if feedback.stn == 9: #CurrentCtrlIdle feedback.enable_output(1) if feedback.stn in [10,11]: #TempControl, FeedbackControl feedback.stop() time.sleep(0.5) feedback.start_current_control(0.0) if feedback.stn == 12: # This is where we want ot be pass time.sleep(1) # Bias States #List of available states: #-[-1]: NotReady (State machine not ready, events are ignored.) #-[0]: Ready (State machine ready to receive events.) #-[1]: Disconnected (Bias-power supply not connected via USB.) #-[2]: Connecting (Trying to establish USB connection to bias-power supply.) #-[3]: Initializing (USB connection to bias-power supply established, synchronizing USB stream.) #-[4]: Connected (USB connection to bias-power supply established.) #-[5]: Ramping (Voltage ramping in progress.) #-[6]: OverCurrent (At least one channel is in over current state.) #-[7]: VoltageOff (All voltages are supposed to be switched off.) #-[8]: NotReferenced (Internal reference voltage does not match last sent voltage.) #-[9]: VoltageOn (At least one voltage is switched on and all are at reference.) #-[10]: ExpertMode (Special (risky!) mode to directly send command to the bias-power supply.) #-[256]: ERROR (Common error state.) #-[65535]: FATAL (A fatal error occured, the eventloop is stopped.) class CheckBiasThread( threading.Thread ): """ Thread, which continously monitors the Bias_Control status every *delay* seconds. in case of too high currents it will ... .... do nothing :-) yet. So far it will just change its internal state from 'Normal' to 'PreWarning' or 'Serious'. If the currents remain "high" for more than *serious_action_after* seconds. some action would be taken. I our case, just a WARNING will be logged. The caller thread should check the *warning_state* from outside this thread and take apropriate actions, when 'PreWarning' is reached... """ def __init__( self , delay=5, serious_action_after = 60 ): #super(CheckBiasThread, self).__init__() threading.Thread.__init__(self) self.stoprequest = threading.Event() self.warning_state = 'Unknown' self.state_change = time.time() self.delay = delay self.serious_action_after = serious_action_after self.logger = logging.getLogger('PyDimCtrl.CheckBiasThread') def run(self): while not self.stoprequest.isSet(): if (self.warning_state == 'Serious' and time.time()-self.state_change > self.serious_action_after): # Remergency Ramp Down self.logger.info('At this moment, I would ramp down the voltage') self.logger.warning('G-APD currents are too high, since %d seconds' % self.serious_action_after) self.logger.warning('Emergency voltage shutdown [not yet implemented]') currents = GetPixelCurrents() if ( (np.median(currents) > 70) or (currents.max() > 90) ): if self.warning_state != 'Serious': self.logger.info('trasit into Serious Warning') self.warning_state = 'Serious' self.state_change = time.time() elif ( (np.median(currents) > 60) or (currents.max() > 80) ): if self.warning_state != 'PreWarning': self.logger.info('transit into Pre Warning') self.warning_state = 'PreWarning' self.state_change = time.time() elif ( (np.median(currents) < 60) or (currents.max() < 80) ): if self.warning_state != 'Normal': self.logger.info('transit into Normal Situation') self.warning_state = 'Normal' self.state_change = time.time() if bias_control.stn == 6: #Overcurrent if self.warning_state != 'OverCurrent': self.logger.warning('trasit into Overcurrent State during data Taking') self.warning_state = 'OverCurrent' self.state_change = time.time() if bias_control.stn == 1: #Disconnected if self.warning_state != 'Disconnected': self.logger.warning('trasit into Disconnected state during data Taking') self.warning_state = 'Disconnected' self.state_change = time.time() time.sleep( self.delay ) def join( self, timeout=None): self.stoprequest.set() self.logger.info('was requested to die with timeout=%s' % str(timeout) ) #super(CheckBiasThread, self).join() threading.Thread.join(self) class CheckDriveThread( threading.Thread ): """ Thread, which continously monitors the Drive_Control status every *delay* seconds. in case Drive_Control goes into Error State it will send: * STOP * and then resend the last tracking command In case sending STOP is not bringing the Drive_Control back to state 'Armed' it will try again. Until the *try_counter* is zero. Then it will totally Freak out. .... does nothing really! :-) yet. """ def __init__( self , try_counter = 5, timeout = 30, delay=5 ): threading.Thread.__init__(self) self.stoprequest = threading.Event() self.error_counter = 0 self.try_counter = try_counter self.timeout = timeout self.delay = delay self.warning_state = 'Unknown' self.state_change = time.time() self.logger = logging.getLogger('PyDimCtrl.CheckDriveThread') def run(self): while not self.stoprequest.isSet(): if drive_control.stn == 256: #Error self.error_counter += 1 self.state_change = time.time() self.warning_state = 'ErrorFound' self.logger.info('found Error State ... starting to react on it.') self.logger.warning(' Error State ') start_of_Error_reaction = time.time() while not drive.stn == 8: #Tracking if drive_control.stn == 256: #Error if try_counter: self.logger.info('sending STOP') drive_control.stop() try_counter -= 1 time.sleep(1) elif drive_control.stn == 6: #Armed kwa = last_drive_kwargs self.logger.info('resending last tracking command') last_drive_method(kwa['wobble_offset'], kwa['wobble_angle'], kwa['source_name']) time.sleep(2) else: self.logger.error('found Error, but now neither Error state nor Armed state?!') self.logger.error('what should I do?') self.logger.error('thread aborting') self.warning_state = 'Critical' self.stoprequest.set() threading.Thread.join(self) if time.time() - start_of_Error_reaction > self.timeout: self.logger.error('timed out while trying to react on Drive Control Error') self.logger.error('what should I do?') self.logger.error('thread aborting') self.warning_state = 'Critical' #self.stoprequest.set() #threading.Thread.join(self) self.join() else: if self.warning_state != 'Normal': self.logger.info('transit into Normal Situation') self.warning_state = 'Normal' self.state_change = time.time() time.sleep( self.delay ) def join( self, timeout=None): self.stoprequest.set() self.logger.info('was requested to die with timeout=%s' % str(timeout)) threading.Thread.join(self) class BiasThread(threading.Thread): """ A worker thread that takes directory names from a queue, finds all files in them recursively and reports the result. Input is done by setting the *requested_state*: ['On', 'Off'] Output is done by setting the *readyness*: ['Ready', 'NotYet', 'CantDoIt'] Ask the thread to stop by calling its join() method. """ requests = ['On', 'Off'] readynesses = ['Ready', 'NotYet', 'CantDoIt'] requested_state = None readyness = 'NotYet' def __init__(self, start_state = 'Off'): super(BiasThread, self).__init__() BiasThread.requested_state = start_state self.stoprequest = threading.Event() def run(self): # As long as we weren't asked to stop, try to find out, if we are in # the requested state, if not, try to reach the state... while not self.stoprequest.isSet(): if not self.InRequestedState(): print 'not in Requested State', BiasThread.requested_state BiasThread.readyness = 'NotYet' try: dirname = self.dir_q.get(True, 0.05) filenames = list(self._files_in_dir(dirname)) self.result_q.put((self.name, dirname, filenames)) except Queue.Empty: continue def join(self, timeout=None): self.stoprequest.set() super(BiasThread, self).join(timeout) def InRequestedState(): """ """ if BiasThread.requested_state == 'On': pass elif BiasThread.requested_state == 'Off': pass else: # Houston we have a problem! pass class CheckDaqThread( threading.Thread ): """ Thread, which continously monitors the Rate in case the rate is < 1Hz --> Bing bing """ def __init__( self , delay=5 ): threading.Thread.__init__(self) self.stoprequest = threading.Event() self.delay = delay self.warning_state = 'Unknown' self.state_change = time.time() self.logger = logging.getLogger('PyDimCtrl.CheckDaqThread') def run(self): while not self.stoprequest.isSet(): rate = ftm_control.trigger_rates()[3] if rate < 1: if self.warning_state != 'SmallRate': self.logger.warning('SmallRate detected!') self.warning_state = 'SmallRate' self.state_change = time.time() else: if self.warning_state != 'Normal': self.logger.info('transit to Normal') self.warning_state = 'Normal' self.state_change = time.time() time.sleep( self.delay ) def join( self, timeout=None): self.stoprequest.set() self.logger.info('was requested to die with timeout=%s' % str(timeout)) threading.Thread.join(self) def off(): for m in monis: m.join() monis = [] if __name__ == '__main__': print 'Welcome to PyDimCtrl' make_sourcedict() print print 'possible sources:' print sorted( sourcedict.keys() ) print 'available Dim Servers' for dim in dims: print dim.name, print #bm = CheckBiasThread() #dm = CheckDriveThread() #rm = CheckDaqThread() #monis = [bm, dm, rm] # bm.start() # dm.start() # rm.start() #print #print 'monis created'