#!/usr/bin/python -tti from factdimserver import * # List of Wobble Positions source_list = { '1ES 1218+304' : [( 0.6, -5), (0.6, 175)] ,\ 'Crab' : [(0.6, 50), (0.6, -130)], \ 'Mrk 421' : [(0.6, 90),(0.6, -90)], \ 'Mrk 501' : [(0.6, 90),(0.6, -90)] } def TakeFullSet( source = 'Crab', verbose = True): msg = MSG( verbose ) drs_calib_done = False # Drs Calib is only done in the 1st wobble pos if not source in source_list: raise ValueError('source not in source_list') msg("Possible sources are:") for src in source_list.keys(): msg(src) return False # set is a list of wobble positions, stored as 2-tuple for set in source_list(source): # wobble is a 2-tuple: (Shift, Angle) for wobble in set: TrackSource( source, wobble[0] , wobble[1] , CalmDownTime=45) if not drs_calib_done: TakeDrsAmplitudeCalibration( roi=1024 ) TakeDrsTimeCalibration( mode='upshifted' ) AddDrsAmplitudeCalibration( roi=300 ) drs_calib_done = True VoltageOn( mode='current' ) TakeData() #Ped | ExtLP | 4x Data VoltageOff() StopTracking() return True #=========== TRACKING ========================================================= def TrackSource( Shift=0.6, Angle=50, SrcName='Crab', CalmDownTime = None, verbose=True): drive = drive_control msg = MSG( verbose ) SrcName += '\0' if not StopTracking( timeout = 5, verbose = False ): msg.fail('Cannot start Tracking, because I cannot Stop the Drive') return False drive.track_source( Shift, Angle, SrcName) if CalmDownTime != None: if not WaitToCalmDown( CalmDownTime, verbose = True): msg.fail("a problem in WaitToCalmDown(). drive state: "+drive.sts) return False msg.ok('Tracking Source '+SrcName + ' Angle:'+str(Angle)+' Shift:'+str(Shift)) return True def WaitToCalmDown( CalmDownTime = 45, time_until_moving = 10, time_until_tracking = 40, verbose = True): """ before calling this function, one should call TrackSource() this function waits until Drive is in state 'Tracking' and then sleeps *CalmDownTime* seconds in order to give the Drive time to calm down. """ drive = drive_control msg = MSG(verbose) starttime = time.time() while not drive.stn == 6: #Moving if time.time() - starttime > time_until_moving: msg.fail("DRIVE not in Moving after "+str(time_until_moving)) return False time.sleep(0.5) msg.ok("Drive is Moving, waiting for Tracking") starttime = time.time() while not drive.stn == 7: #Tracking if time.time() - starttime > time_until_tracking: msg.fail("DRIVE not in Tracking after "+str(time_until_tracking)) return False time.sleep(0.5) msg.ok("Drive is Tracking, waiting to calm down...") time.sleep(CalmDownTime) msg.ok("Drive hopefully has calmed down") return True def StopTracking( timeout = 3, verbose = True ): msg = MSG(verbose) drive = drive_control starttime = time.time() while not drive.stn == 5: if time.time() - starttime > timeout: msg.fail('Did not get DRIVE into Armed state within '+str(timeout)+' seconds') return False if drive.stn < 5: msg.fail('DRIVE in state'+drive.sts+" I don't know how to STOP") if drive.stn >= 256: msg.fail('DRIVE in state'+drive.sts+" I don't know how to STOP") if drive.stn in [6,7]: drive.stop() time.sleep(0.5) msg.ok('DRIVE Stopped: current state:'+drive.sts) return True #=========== DRS CALIBRATION ================================================== def TakeDrsAmplitudeCalibration( roi = None, verbose = True): """ Takes DRS Amplitude Calibration *roy* integer: 300, 1024 or *roy* string : 'both' in case of both, the roi=300 calibration is done last. after each complete AmpliteCalibration a 4th pedestal run of the same roi is taken, for crosschecking. """ msg = MSG( verbose ) bias = bias_control fad = fad_control if not roi in [300,1024,'both']: raise ValueError("roi must be 300,1024 or the string 'both'") bias.set_zero_voltage() if not bias.wait(7, 10): msg.warn("bias has not switched of after 10sec") return False fad.start_drs_calibration() Take( -1, 1000, 'drs-pedestal') Take( -1, 1000, 'drs-gain') if roi == 300: Take( -1, 1000, 'pedestal') fad.set_file_format(2) Take( -1, 1000, 'pedestal') elif roi == 1024: Take( -1, 1000, 'drs-pedestal') fad.set_file_format(2) Take( -1, 1000, 'drs-pedestal') elif roi == 'both': Take( -1, 1000, 'drs-pedestal') fad.set_file_format(2) Take( -1, 1000, 'drs-pedestal') fad.reset_secondary_drs_baseline() Take( -1, 1000, 'pedestal') fad.set_file_format(2) Take( -1, 1000, 'pedestal') def TakeDrsTimeCalibration( mode = 'upshifted', verbose = True): """ Takes DRS Time Calibration *mode* can be 'upshifted', 'old' or 'both' """ msg = MSG( verbose ) bias = bias_control fad = fad_control if not mode in ['upshifted', 'old', 'both']: raise ValueError("mode must be: 'upshifted','old' or 'both'") bias.set_zero_voltage() if not bias.wait(7, 10): msg.warn("bias has not switched of after 10sec") return False fad.set_file_format(2) if mode == 'old': Take(-1, 1000, 'drs-time') if mode == 'upshifted': Take(-1, 1000, 'drs-time-upshifted') if mode == 'both': Take(-1, 1000, 'drs-time') Take(-1, 1000, 'drs-time-upshifted') def AddDrsAmplitudeCalibration( roi = None, verbose = True): """ Adds a DRS Amplitude Calibration, do not call, in case you did not *Take* one before *roy* integer: 300, 1024 after each complete AmpliteCalibration a 4th pedestal run of the same roi is taken, for crosschecking. """ msg = MSG( verbose ) bias = bias_control fad = fad_control if not roi in [300,1024]: raise ValueError("roi must be 300,1024") if not bias.stn == 'VoltageOff': msg.fail('a DRS amplitude calibration should not be taken with Voltage On') return False fad.reset_secondary_drs_baseline() if roi == 300: Take( -1, 1000, 'pedestal') fad.set_file_format(2) Take( -1, 1000, 'pedestal') elif roi == 1024: Take( -1, 1000, 'drs-pedestal') fad.set_file_format(2) Take( -1, 1000, 'drs-pedestal') return True #============ BIAS VOLTAGE ==================================================== time_of_last_overcurrent = -1. * float('inf') number_of_overcurrent_occurences = 0 def VoltageOn( mode = None, Watchdog = None, timeout = 30, verbose = True): """ High Level Method for switching on the bias Voltage can be called, in whatever state the bias and the feedback might be. In case the voltage is on and the feedback is already in the mode requested, nothing happens. In all other cases, the method will perform the needed steps to switch on the bias voltage, the way the user requested raises NotImplementedError in case of 'feedback' """ msg = MSG( verbose ) bias = bias_control fb = feedback if not mode in ['temperature', 'current', 'feedback']: raise ValueError("mode must be 'temperature', 'current' or 'feedback'") if mode == 'temperature': fb_target = 10 #TempControl elif mode == 'feedback': #fb_target = 11 # FeedbackControl raise NotImplementedError('The author of this script did not know how to start this mode') elif mode == 'current': fb_target = 12 #CurrentControl bias_target = 9 # VoltageOn starttime = time.time() long_enough = (time.time() - bias.last_st_change > 2) and (time.time() - fb.last_st_change > 2) while not ((bias.stn == bias_target) and (fb.stn == fb_target) and long_enough): if time.time() - starttime > timeout: msg.fail("VoltageOn did not succeed after "+str(timeout)+' seconds') return False elif fb.stn == fb_target-3: # everything fine, but output disabled fb.enable_output(1) elif fb.stn == fb_target and bias.stn == 5: # feedback ok, but we are Ramping # lets try to wait time.sleep(0.5) elif fb.stn == 6: #Connected if mode == 'temperature': fb.start_temp_control(0.0) elif mode == 'current': fb.start_current_control(0.0) elif mode == 'feedback': raise NotImplementedError('The author of this script did not know how to start this mode') elif bias.stn == 1: #Disconnected bias.reconnect() # makes no sense to be quick in this case time.sleep(2) elif bias.stn == 6: # Overcurrent if number_of_overcurrent_occurences < 3: bias.set_zero_voltage() bias.reset_over_current_status() elif time.time() - time_of_last_overcurrent > 60: number_of_overcurrent_occurences = 0 number_of_overcurrent_occurences += 1 time_of_last_overcurrent = time.time() elif bias.stn == 7: # VoltageOff bias.set_global_dac(1) elif bias.stn == 8: # NotReferenced bias.set_zero_voltage() bias.set_global_dac(1) else: # if nothing was done. sleep a while time.sleep(0.5) long_enough = (time.time() - bias.last_st_change > 2) and (time.time() - fb.last_st_change > 2) msg.ok("Voltage is On") if mode == 'current': msg("Waiting 45sec, so we get at least 3 current readings") time.sleep(45) return True def VoltageOff( timeout = 10, verbose = True): """ High Level Method for switching off the bias Voltage """ msg = MSG( verbose ) bias = bias_control bias.set_zero_voltage() starttime = time.time() while not bias.stn == 7: # VoltageOff if time.time() - starttime > timeout: msg.fail("VoltageOff did not succeed after "+str(timeout)+' seconds') return False time.sleep(1) msg.ok("Voltage is Off") return True def std_bias_watchdog( state, verbose=True ): msg = MSG(verbose) if state == 1: #Disconnected msg.warn("BIAS just DISCONNECTED .. trying to reconnect") msg.warn("current runnumber:"+fad_control.runnumber() ) bias.reconnect() time.sleep(1) bias.set_zero_voltage() # TODO: This should work, but it is stupid. bias.reset_over_current_status() bias.reset_over_current_status() bias.set_zero_voltage() bias.reset_over_current_status() bias.set_global_dac(1) #============================================================================== def IsReadyForDataTaking( TrackingNeeded = True, verbose = True ): drive = drive_control bias = bias_control fad = fad_control msg = MSG() msg.output = verbose msg("Checking if System isready for data taking... ") ok = True if TrackingNeeded: if not drive.stn == 7: msg.warn(drive.name + ':' + drive.sts + " NOT ok") ok = False else: msg.ok(drive.name + ':' + drive.sts + " OK") if not feedback.stn == 12: msg.warn(feedback.name +':'+ feedback.sts + " NOT ok") ok = False else: msg.ok(feedback.name +':'+ feedback.sts + " OK") if not bias.stn == 9: msg.warn(bias.name +':'+ bias.sts + " NOT ok") ok = False else: msg.ok(bias.name +':'+ bias.sts + " OK") if not fad.stn == 4: msg.warn(fad.name +':'+ fad.sts + " NOT ok") ok = False else: msg.ok(fad.name +':'+ fad.sts + " ok") if ok: msg.ok( " all ok " ) return ok def TakeDataRun( verbose = True ): fad = fad_control msg = MSG(verbose) if not IsReadyForDataTaking( verbose=False ): msg.fail("System not Ready for DataTaking") IsReadyForDataTaking( verbose=True ) return False mcp.start(300,-1,'data\0') if not fad.wait(8, 10): msg.warn("FAD not in Writing Data after 10seconds") return False msg("... taking data: 300 seconds - normal data run") if not fad.wait(4, 330): msg.warn("FAD did not return to Connected, after 330 seconds") return False return True def TakePedestalOnRun( verbose = True ): msg = MSG(verbose) if not IsReadyForDataTaking( TrackingNeeded=False, verbose=False ): msg.fail("System not Ready for DataTaking") IsReadyForDataTaking( verbose=True ) return False mcp.start(-1,1000,'pedestal\0') if not fad.wait(8, 10): msg.warn("FAD not in Writing Data after 10seconds") return False msg("... taking ped: 1000evts @25Hz") if not fad.wait(4, 50): msg.warn("FAD did not return to Connected, after 50 seconds") return False return True def TakeExtLpRun( verbose = True ): msg = MSG(verbose) if not IsReadyForDataTaking( TrackingNeeded=False, verbose=False ): msg.fail("System not Ready for DataTaking") IsReadyForDataTaking( verbose=True ) return False mcp.start(-1,1000,'light-pulser-ext\0') if not fad.wait(8, 10): msg.warn("FAD not in Writing Data after 10seconds") return False msg("... taking light-pulser-ext: 1000evts @25Hz") if not fad.wait(4, 50): msg.warn("FAD did not return to Connected, after 50 seconds") return False return True def TakeData( verbose = True): msg = MSG(verbose) TakePedestalOnRun() TakeExtLpRun() for i in range(4): i +=1 msg("Taking Data Run "+str(i)+" of 4") TakeDataRun() def Take( time=0, events=0, runtype='drs-pedestal', verbose=True): msg = MSG( verbose ) fad = fad_control runtype += '\0' if not fad.wait(4, 10): msg.warn("fad not connected after 10sec") return False mcp.start( time, events, runtype) if not fad.wait(8, 30): msg.warn("fad not Writing Data after 30sec") return False timeout = float('inf') if time != -1: timeout = time*1.1 if not fad.wait(4, timeout): msg.warn("Data Writing not finished after "+str(timeout)+"sec") return False return True def BlinkenLights(verbose = True): msg = MSG(verbose) fad = fad_control for i in range(10): fad.set_file_format(2) time.sleep(1) fad.set_file_format(0) time.sleep(1) #============================================================================== def Connect(): prepare_ftm_control() prepare_fsc_control() feedback.stop() prepare_bias_control() prepare_feedback() prepare_data_logger() def prepare_fsc_control( verbose = True, timeout = 10, delay = 0.2): msg = MSG( verbose ) fsc = fsc_control start_time = time.time() if timeout == None: timeout = float('inf') if delay < 0.: delay = 0. while not fsc.stn == 2: #Connected if time.time() > start_time + timeout: return False if (fsc.stn <= 0) or (fsc.stn >= 256): msg.fail("FSC_CONTROL is in state "+fsc.sts) msg.fail(prepare_fsc_control.__name__ + "does not know how to handle this") return False elif fsc.stn == 1: # Disconnected fsc.reconnect() return True def prepare_ftm_control( verbose = True, timeout = 10, delay = 0.2): msg = MSG( verbose ) ftm = ftm_control start_time = time.time() if timeout == None: timeout = float('inf') if delay < 0.: delay = 0. while not ftm.stn == 3: if time.time() > start_time + timeout: return False if (ftm.stn <= 0) or (ftm.stn >= 256): msg.fail("FMT_CONTROL is in state "+ftm.sts) msg.fail("ftm_to_Idle() does not know how to handle this") return False elif ftm.stn == 1: # Disconnected ftm.reconnect() elif ftm.stn == 2: #Connected # just wait a second time.sleep(1) elif ftm.stn == 4: #TriggerOn ftm.enable_trigger(0) #switch trigger off elif ftm.stn in [5,6,7]: # some Configure state ftm.reset_configure() return True def prepare_data_logger( verbose = True, timeout = 10, delay = 0.2): msg = MSG(verbose) dl = data_logger if timeout == None: timeout = float('inf') if delay < 0.: delay = 0. start_time = time.time() raise NotImplementedError('prepare_data_logger() is not yet implemented') def prepare_fad_control( verbose = True, timeout = 10, delay = 0.2): msg = MSG(verbose) fad = fad_control ftm = ftm_control if timeout == None: timeout = float('inf') if delay < 0.: delay = 0. start_time = time.time() while not fad.stn == 4: # Timeout if time.time() > start_time + timeout: msg.fail("Timeout in " + prepare_fad_control.__name__) return False # Strange States if (fad.stn <= 0) or (fad.stn >= 256): msg.fail("FAD_CONTROL is in state "+fad.sts) msg.fail(prepare_fad_control.__name__ + "does not know how to handle this") return False elif fad.stn == 1: # Disengaged fad.start() elif fad.stn == 2: # Disconnected fad.start() elif fad.stn == 3: # Connecting # it might just need time if time.time() - fad.last_st_change < 5: time.sleep(2) timeout += 1 else: # there might be a problem with one of the boards conns = map( ord, fad.connections()[0] ) problems = {} for fad,conn in enumerate(conns): if conn < 255: print "FAD:", fad, "has a problem" if not fad/10 in problems: problems[fad/10] = [] else: problems[fad/10].append( fad%10 ) for fad in range(10): for crate in problems.keys(): fad.disconnect(crate*10+fad) ftm.toggle_ftu(crate*10+fad) for crate in problems.keys(): time.sleep(1) ftm.reset_crate(crate) for fad in range(10): for crate in problems.keys(): time.sleep(3.5) fad.connect(crate*10+fad) ftm.toggle_ftu(crate*10+fad) elif fad.stn == 5: # Configuring1 if time.time() - fad.last_st_change < 5: time.sleep(1) else: msg.warn("FAD is in Configuring1 since more than 5sec") elif fad.stn == 6: # Configuring2 if time.time() - fad.last_st_change < 5: time.sleep(1) else: msg.warn("FAD is in Configuring2 since more than 5sec") elif fad.stn == 7: # Configured if time.time() - fad.last_st_change < 5: time.sleep(1) else: msg.warn("FAD is in Configuring2 since more than 5sec") elif fad.stn == 8: #WritingData # I don't know how to get from WritingData to Connected # well. .. one could wait for a timeout, but I hate that. fad.close_open_files() time.sleep(delay) return True def prepare_bias_control( verbose = True, timeout = 10, delay = 0.2): msg = MSG(verbose) bias = bias_control if timeout == None: timeout = float('inf') if delay < 0.: delay = 0. start_time = time.time() while (bias.stn != 4) and (bias.stn != 7): #Connected or VoltageOff # Timeout if time.time() > start_time + timeout: msg.fail("Timeout in " + prepare_bias_control.__name__) return False # Strange States if (bias.stn <= 0) or (bias.stn >= 256): msg.fail("BIAS_CONTROL is in state "+bias.sts) msg.fail(prepare_bias_control.__name__ + "does not know how to handle this") return False elif bias.stn == 1: # Disconnected bias.reconnect() elif bias.stn == 2: # Connecting if time.time() - bias.last_st_change < 5: time.sleep(1) else: msg.warn("BIAS_CONTROL is in Connecting since more than 5sec") elif bias.stn == 3: # Initializing if time.time() - bias.last_st_change < 5: time.sleep(1) else: msg.warn("BIAS_CONTROL is in Initializing since more than 5sec") elif bias.stn == 5: #Ramping if time.time() - bias.last_st_change < 10: time.sleep(1) else: msg.warn("BIAS_CONTROL is in Ramping since more than 10sec") bias.stop() elif bias.stn == 6: #OverCurrent time.sleep(0.5) bias.set_zero_voltage() time.sleep(0.5) bias.reset_over_current_status() time.sleep(0.5) elif bias.stn == 8: #NotReferenced time.sleep(0.5) bias.set_zero_voltage() time.sleep(0.5) elif bias.stn == 9: # VoltageOn time.sleep(0.5) bias.set_zero_voltage() time.sleep(0.5) elif bias.stn == 10: # ExpoertMode msg.fail("BIAS is in ExportMode ... wtf") return False time.sleep(delay) return True def prepare_feedback( verbose = True, timeout = 10, delay = 0.2): msg = MSG(verbose) fb = feedback if timeout == None: timeout = float('inf') if delay < 0.: delay = 0. start_time = time.time() while not fb.stn == 6: #Connected # Timeout if time.time() > start_time + timeout: msg.fail("Timeout in " + prepare_feedback.__name__) return False # Strange States if (fb.stn <= 1) or (fb.stn >= 256): msg.fail("FEEDBACK is in state "+fb.sts) msg.fail(prepare_feedback.__name__ + "does not know how to handle this") return False elif fb.stn in [2,3,4,5]: if time.time() - fb.last_st_change < 10: time.sleep(1) else: msg.warn("BIAS_CONTROL is in "+fb.sts+" since more than 10sec") elif fb.stn in [7,8,9]: fb.stop() elif fb.stn in [10,11,12]: fb.enable_output(0) fb.stop() elif fb.stn == 13: # maybe waiting helps if time.time() - fb.last_st_change < 20: time.sleep(1) else: msg.warn("FEEDBACK is in "+fb.sts+" since more than 20sec \n sending STOP") fb.stop() time.sleep(delay) return True #============================================================================== # create introduction: class INTRO(object): def __init__(self): # nothing to do pass def __repr__(self): print "welcome to PyDimCtrl V0.1:" print "--------------------------" print "If all the programs are already up and running, you might want to" print " TakeDrsAmplitudeCalibration(roi=1024) or " print " TakeDrsAmplitudeCalibration(roi=300)" print " i.e. ped, gain, trigger_offset + extra ped(for X-check)" print " TakeDrsTimeCalibration( type='upshifted' ) or " print " TakeDrsTimeCalibration( type='old' ) or " print " " print "In case you would like to ramp up the Bias voltage try:" print " VoltageOn( mode='temperature' ) or" print " VoltageOn( mode='current' ) or" print " VoltageOn( mode='light_pulser' )" print "Switch off with:" print " VoltageOff()" print "In case you would like to simply take Data of a certain source try:" print " TakeFullSet(source = 'Crab')" print "" print "look at the 'source_list' to get an overview, of the " print "current sources available:" print " pprint(source_list)" print "" print "" print "" print "" return "" intro = INTRO() if __name__ == '__main__': print "welcome:" print " type: intro" print " for a short introduction" #IsReadyForDataTaking() #TrackSource( Shift=0.6, Angle=50, SrcName='Crab', verbose=True) #WaitForTracking( CalmDownTime = 30, verbose = True) #TakeDataRun() #StopTracking()