Changeset 14659 for fact/tools/PyDimCtrl


Ignore:
Timestamp:
11/19/12 12:10:01 (12 years ago)
Author:
neise
Message:
long time since last checkin
File:
1 edited

Legend:

Unmodified
Added
Removed
  • fact/tools/PyDimCtrl/ScriptsForPyDimCtrl.py

    r14466 r14659  
    66import types
    77import sys
     8import threading
     9import Queue
     10
     11import logging
     12# create logger with 'spam_application'
     13logger = logging.getLogger('PyDimCtrl')
     14logger.setLevel(logging.DEBUG)
     15# create file handler which logs even debug messages
     16fh = logging.FileHandler('PyDimCtrl.log')
     17fh.setLevel(logging.DEBUG)
     18# create console handler with a higher log level
     19ch = logging.StreamHandler()
     20ch.setLevel(logging.WARNING)
     21# create formatter and add it to the handlers
     22formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
     23fh.setFormatter(formatter)
     24ch.setFormatter(formatter)
     25# add the handlers to the logger
     26logger.addHandler(fh)
     27logger.addHandler(ch)
    828
    929last_drive_kwargs = {}
     
    1131
    1232bias_calibration = {}
     33
     34bias_current = {}
    1335
    1436report_length = 0
     
    2648  ["IC 310",        0.6, -18, -18+180 ],
    2749  ["PKS 2155-304",  0.6,  90, -90 ] ]
     50 
     51crazyPatches = [66,191,193]
    2852 
    2953sourcedict = {}
     
    117141    print "connecting to crate", cratenum
    118142    for i in range(cratenum*10, (cratenum+1)*10 ):
    119       print 'disconnecting from i', time.time()
     143      print 'disconnecting from ', i
    120144      fad_control.disconnect(i)
    121145    print "... done"
     
    310334
    311335
     336
    312337def Take( time, num_events, runtype, verbose=False):
    313338  """ more general version of e.g. TakePedestalOnRun
     
    337362  """
    338363  if Bias not in [None, 'On', 'Off']:
    339     raise ValueError('Bias needs to be one of [None, 'On', 'Off']')
     364    raise ValueError('Bias needs to be one of [None, "On", "Off"]')
     365    return False
     366
     367  # Sanity check
     368  # Drive can be:
     369  # Drive = 'sourcename'
     370  # Drive = ('sourcename', wobble_pos = 1 || 2)
     371  # Drive = None
     372  if type(Drive) not in [type(''), type((0,0)), type(None) ]:
     373    raise ValueError('Bias needs to be one of [None, "On", "Off"]')
    340374    return False
    341375
     
    380414  #
    381415  # In case Drive is None no commands will be send to DRIVE_CONTROL at allow
     416 
     417  # Drive can be:
     418  # Drive = 'sourcename'
     419  # Drive = ('sourcename', wobble_pos = 1 || 2)
     420  # Drive = None
    382421 
    383422  # RATE_CTRL
     
    430469  duration = 20.
    431470  if Bias == 'On':
    432     if (bias_control.voltage()[0:320].mean() > 60) and
    433       ( (bias_control.stn == 5) or (bias_control.stn == 9) )
     471    if ( (bias_control.voltage()[0:320].mean() > 60) and
     472            ( (bias_control.stn == 5) or
     473              (bias_control.stn == 9) ) ):
     474      pass
    434475     
    435476  elif Bias == 'Off':
    436    
     477    pass
    437478
    438479  if verbose:
     
    456497  # take a Pedestal run
    457498  IsReadyForDataTaking()
    458   print 'taking External Light Pulser with BIAS on 1000 ...'
     499  print 'taking pedestal run with 1000 events'
    459500  Take(-1, 1000, 'pedestal')
    460501 
     
    541582
    542583def FirstDrsCalib( SkipCurrentCalib=False ):
     584  logger = logging.getLogger('PyDimCtrl.FDC')
    543585  """ performs the everything, which is done in the FirstDrsCalib Script as well .
    544586  """
     
    549591  # Since we do not know, what the feedback program is doing at the moment, we should as well,
    550592  # tell it to keep its mouth shut ... just to be sure, we know whats going on
    551   print "stopping feedback"
     593  logger.debug("stopping feedback")
    552594  feedback.stop()
    553595
    554596  time.sleep(2)
    555597  # stopping should always be possible, and end in state 'Connected'(6)
    556   print " ...waiting for FEEDBACK to be in state 6: Connected"
     598 
     599  logger.debug(" ...waiting for FEEDBACK to be in state 6: Connected")
     600  print
    557601  feedback.wait(6)
    558602  print "..done"
     
    628672  # and a second pedestal run, with the same ROI as our next data will be, i.e. ROI=300 in this case
    629673  print "taking DRS:Pedestal 1000 ..."
    630   print "==================================================="
    631   print "OPERATOR: "
    632   print "observe Events tab and make sure there are no patches "
    633   print "with strange behaviour, which can be caused "
    634   print "by DRS-CHIP Problems"
    635   print "==================================================="
     674  #print "==================================================="
     675  #print "OPERATOR: "
     676  #print "observe Events tab and make sure there are no patches "
     677  #print "with strange behaviour, which can be caused "
     678  #print "by DRS-CHIP Problems"
     679  #print "==================================================="
    636680
    637681  fad_control.start_drs_calibration()
     
    669713  # the feedback should be in state 'CurrentControl'(12) now
    670714  # the feedback should be in state 'CurrentCtrlIdle'(9) now since 30.05.12
    671   print "...waiting for FEEDBACK to be in state 9: CurrentCtrlIdle"
    672   feedback.wait(9)
     715  print "...waiting for FEEDBACK to be in state 12: CurrentControl"
     716  feedback.wait(12)
    673717  print "... done"
    674718  print "switching on bias"
     
    874918    return False
    875919
    876 
    877 
    878 
    879920def GetBiasCalibration():
    880921  cali = feedback.calibration()
     
    882923  bias_calibration['Calibration'] = cali
    883924
    884 def GetBiasCurrent(verbose = False):
     925def _GetBiasCurrent_Raw(verbose = False):
    885926  """ return median, std, max and min current
    886927  """
     
    907948#  print 'GUI feedback:', II[0] - V[0]/r[0]*1e6
    908949
     950  # GUII means current(I) as it is written in the GUI :-)
     951  # read: GUI-I :-)
    909952  GUII = II-V/r*1e6
    910953  if verbose:
     
    916959    print 'min', GUII.min()
    917960
    918   return GUII.mean(), GUII.std(), GUII.max(), GUII.min()
    919 
    920  
     961  bias_current['Time'] = time.time()
     962  bias_current['raw_patch_current'] = GUII
     963  return GUII
     964
     965def GetPatchCurrents(crazyPatches=crazyPatches ,verbose = False, max_age_sec=1. ):
     966 
     967  if 'Time' in bias_current:
     968    if time.time() - bias_current['Time'] > max_age_sec:
     969      raw_cur = _GetBiasCurrent_Raw()
     970    else:
     971      raw_cur = bias_current['raw_patch_current']
     972  else:
     973    raw_cur = _GetBiasCurrent_Raw()
     974   
     975  if crazyPatches is None:
     976    return raw_cur
     977  else:
     978    try:
     979      crazyPatches = list(crazyPatches)
     980    except:
     981        raise
     982    goodPatches = [x for x in range(320) if x not in crazyPatches]
     983    return raw_cur[goodPatches]
     984
     985def GetPixelCurrents(crazyPatches=crazyPatches ,verbose = False, max_age_sec=1. ):
     986 
     987  if 'Time' in bias_current:
     988    if time.time() - bias_current['Time'] > max_age_sec:
     989      raw_cur = _GetBiasCurrent_Raw()
     990    else:
     991      raw_cur = bias_current['raw_patch_current']
     992  else:
     993    raw_cur = _GetBiasCurrent_Raw()
     994
     995  pixel_cur = np.zeros(len(raw_cur))
     996  for i in range(len(raw_cur)):
     997    if i/2:
     998      pixel_cur[i] = raw_cur[i]/5.
     999    else:
     1000      pixel_cur[i] = raw_cur[i]/4.
     1001
     1002  if crazyPatches is None:
     1003    return pixel_cur
     1004  else:
     1005    try:
     1006      crazyPatches = list(crazyPatches)
     1007    except:
     1008        raise
     1009    goodPatches = [x for x in range(320) if x not in crazyPatches]
     1010    return pixel_cur[goodPatches]
     1011
     1012def PrintPixelCurrents( delay = 4.0):
     1013  while True:
     1014    time.sleep( delay )
     1015    current = GetPixelCurrents()
     1016    interesting =  current.min(), np.median(current), current.mean(), current.max()
     1017    print time.strftime('%d %b %Y %H:%M:%S UTC', time.gmtime()), interesting
    9211018
    9221019
    9231020def TrackSourceWobbleX( sourcename, wobble_pos ):
    924   """ general Tracking function
    925   """
    926   wp = int(wobble_pos)
    927   if wp != 1 and wp != 2:
    928     raise ValueError('wobble_pos *must* be 1 or 2')
    929  
    930   if sourcename not in sourcedict:
    931     print sourcedict.keys()
    932     raise ValueError('sourcename: '+ sourcename +' must be in sourcedict.')
    933 
    934   print 'moving telescope to wobble position ', wp, 'of ', sourcename
    935   print '...waiting for DRIVE_CONTROL'
    936   print '   to be in state 6: Armed'
    937   drive_control.stop()
    938   drive_control.wait(6) #Armed
    939   print 'DRIVE: ARMED'
    940   time.sleep(5.)
    941 
    942   wobble_offset = sourcedict[sourcename]['wobble_offset']
    943   wobble_angle = sourcedict[sourcename]['wobble_angle'+str(wp)]
    944   sourcename += '\0'
    945  
    946   last_drive_method = drive_control.track_source
    947   last_drive_kwargs = { 'wobble_offset' : wobble_offset,
     1021    """ general Tracking function
     1022    """
     1023    wp = int(wobble_pos)
     1024    if wp != 1 and wp != 2:
     1025        raise ValueError('wobble_pos *must* be 1 or 2')
     1026 
     1027    if sourcename not in sourcedict:
     1028        print sourcedict.keys()
     1029        raise ValueError('sourcename: '+ sourcename +' must be in sourcedict.')
     1030   
     1031    logger.debug('TrackSourceWobbleX: sending drive_control.stop()')
     1032    drive_control.stop()
     1033    logger.debug('TrackSourceWobbleX: waiting for DRIVE_CONTROL to be "Armed"')
     1034    drive_control.wait(6) #Armed
     1035   
     1036    logger.info('moving telescope to wobble position %s of %s' % str(wp), sourcename)
     1037
     1038   
     1039    wobble_offset = sourcedict[sourcename]['wobble_offset']
     1040    wobble_angle = sourcedict[sourcename]['wobble_angle'+str(wp)]
     1041    sourcename += '\0'
     1042 
     1043    # this is just book keeping. I store the method, which is used
     1044    # in this case drive_control.track_source()
     1045    # and the arguments, in some global vars .. in order to be able to
     1046    # resend the command if necessary.
     1047    last_drive_method = drive_control.track_source
     1048    last_drive_kwargs = { 'wobble_offset' : wobble_offset,
    9481049                          'wobble_angle' : wobble_angle,
    9491050                          'source_name' : sourcename }
    950   kwa = last_drive_kwargs
    951   last_drive_method(kwa['wobble_offset'], kwa['wobble_angle'], kwa['source_name'])
    952  
    953   print '... done'
     1051    kwa = last_drive_kwargs
     1052    # Here I really send the command
     1053    last_drive_method(kwa['wobble_offset'], kwa['wobble_angle'], kwa['source_name'])
     1054
     1055    logger.debug('TrackSourceWobbleX: waiting for DRIVE_CONTROL to be "Tracking"')
     1056    drive_control.wait(8) #Tracking
     1057   
     1058    return True
    9541059
    9551060def TakeSource( name ):
     
    9761081  StopTracking()
    9771082
    978 
    979 
    980 
    981 
     1083def set_file_format_to_FITS():
     1084    fad_control.set_file_format(2)
     1085
     1086# (Time , Drive, Bias, DAQ, call-before-run)
     1087class RunType(object):
     1088    drs_pedestal = (-1, 1000, 'drs-pedestal')
     1089    drs_gain = (-1, 1000, 'drs-gain')
     1090    drs_time = (-1, 1000, 'drs-time')
     1091    drs_time_upshifted = (-1, 1000, 'drs-gain-upshifted')
     1092    pedestal = (-1, 1000, 'pedestal')
     1093    lightpulser = (-1, 1000, 'light-pulser-ext')
     1094    data = (300, -1, 'data')
     1095
     1096class Schedule(object):
     1097    drs_calib_crab = [
     1098      ( None , ('Crab',1) , 'Off', RunType.drs_pedestal , fad_control.start_drs_calibration ),
     1099      ( None , ('Crab',1) , 'Off', RunType.drs_gain     , None ),
     1100      ( None , ('Crab',1) , 'Off', RunType.drs_pedestal , None ),
     1101      ( None , ('Crab',1) , 'Off', RunType.drs_pedestal , set_file_format_to_FITS ),
     1102      ( None , ('Crab',1) , 'Off', RunType.drs_time     , None ),
     1103      ( None , ('Crab',1) , 'Off', RunType.drs_time_upshifted , None ),
     1104      ( None , ('Crab',1) , 'Off', RunType.pedestal     , fad_control.reset_secondary_drs_baseline ),
     1105      ( None , ('Crab',1) , 'Off', RunType.pedestal     , None )
     1106    ]
     1107
     1108    drs_calib_not_moving = [
     1109      ( None , None , 'Off', RunType.drs_pedestal , fad_control.start_drs_calibration ),
     1110      ( None , None , 'Off', RunType.drs_gain     , None ),
     1111      ( None , None , 'Off', RunType.drs_pedestal , None ),
     1112      ( None , None , 'Off', RunType.drs_pedestal , set_file_format_to_FITS ),
     1113      ( None , None , 'Off', RunType.drs_time     , None ),
     1114      ( None , None , 'Off', RunType.drs_time_upshifted , None ),
     1115      ( None , None , 'Off', RunType.pedestal     , fad_control.reset_secondary_drs_baseline ),
     1116      ( None , None , 'Off', RunType.pedestal     , None )
     1117    ]
     1118
     1119    data_crab_Wobble_1 = [
     1120      ( None , ('Crab',1) , 'On', RunType.pedestal    , None ),
     1121      ( None , ('Crab',1) , 'On', RunType.lightpulser , None ),
     1122      ( None , ('Crab',1) , 'On', RunType.data        , None ),
     1123      ( None , ('Crab',1) , 'On', RunType.data        , None ),
     1124      ( None , ('Crab',1) , 'On', RunType.data        , None ),
     1125      ( None , ('Crab',1) , 'On', RunType.data        , None ),
     1126    ]
     1127    data_crab_Wobble_2 = [
     1128      ( None , ('Crab',2) , 'On', RunType.pedestal    , None ),
     1129      ( None , ('Crab',2) , 'On', RunType.lightpulser , None ),
     1130      ( None , ('Crab',2) , 'On', RunType.data        , None ),
     1131      ( None , ('Crab',2) , 'On', RunType.data        , None ),
     1132      ( None , ('Crab',2) , 'On', RunType.data        , None ),
     1133      ( None , ('Crab',2) , 'On', RunType.data        , None ),
     1134    ]
     1135
     1136
     1137
     1138class ScheduledDataTakingThread( threading.Thread ):
     1139    """
     1140       
     1141    """
     1142    def __init__( self , delay = 5):
     1143        threading.Thread.__init__(self)
     1144        self.stoprequest = threading.Event()
     1145        self.warning_state = 'Unknown'
     1146        self.state_change = time.time()
     1147        self.logger = logging.getLogger('PyDimCtrl.ScheduledDataTakingThread')
     1148       
     1149        self.delay = delay
     1150        self.queue = Queue.Queue()
     1151
     1152    def run(self):
     1153        while not self.stoprequest.isSet():
     1154
     1155            task = self.queue.get()
     1156           
     1157            start_time = task[0]
     1158            drive_task = task[1]
     1159            bias_task = task[2]
     1160            daq_task = task[3]
     1161            pre_action = task[4]
     1162               
     1163            if drive_task is not None:
     1164                TrackSourceWobbleX( *drive_task )
     1165
     1166            #    if start_time is None or start_time > time.gmtime():
     1167            #        # do it
     1168            #        if drive_task is not None:
     1169            #            TrackSourceWobbleX( *drive_task ) # this blocks until 'Tracking'
     1170            #            # TODO:
     1171            #            # spawn a new DriveMonitorThread here and start it.
     1172                   
     1173            if bias_task is not None:
     1174                if bias_task == 'On':
     1175                    Make_Bias_On()
     1176                else:
     1177                    Make_Bias_On()
     1178                    # TODO:
     1179                    # spawn a new BiasMonitorThread here and start it.
     1180                   
     1181            if daq_task is not None:
     1182                if pre_action is not None:
     1183                    pre_action()
     1184                MakeReadyForDataTaking()
     1185                Take( *daq_task )
     1186                # TODO:
     1187                # spawn a new DaqMonitorThread here and start it.
     1188                       
     1189                       
     1190            self.queue.task_done()
     1191            time.sleep( self.delay )
     1192           
     1193    def join( self, timeout=None):
     1194        self.stoprequest.set()       
     1195        self.logger.info('was requested to die with timeout=%s' % str(timeout) )
     1196        #super(CheckBiasThread, self).join()
     1197        threading.Thread.join(self)
     1198
     1199
     1200
     1201
     1202def MakeReadyForDataTaking( delay=1 ):
     1203    while fad_control.stn != 4 or ftm_control.stn != 3: # Connected & Idle
     1204        logger.info('MakeReadyForDataTaking FTM trigger is still on')
     1205        if ftm_control.stn == 4: # Trigger is on
     1206            ftm_control.stop_trigger()
     1207   
     1208        logger.warning('MakeReadyForDataTaking FAD: still in WritingData')
     1209        if fad_control.stn == 8: # Writing Data
     1210            fad_control.close_all_open_files()
     1211       
     1212        logger.warning('MakeReadyForDataTaking FAD: still in one of the Configure(ing) states')
     1213        if fad_control.stn in [5,6,7]: # one of the Configure(ing) states
     1214            fad_control.reset_configure()
     1215           
     1216        logger.warning('MakeReadyForDataTaking FTM: still in one of the Configure(ing) states')
     1217        if ftm_control.stn in [5,6,7]: # one of the Configure(ing) states
     1218            ftm_control.reset_configure()
     1219
     1220        time.sleep(delay)
     1221
     1222    return True
    9821223
    9831224def PrintCurrents( x = 1.0):
    9841225  while True:
    9851226    time.sleep( x )
    986     print time.strftime('%d %b %Y %H:%M:%S UTC', time.gmtime()), GetBiasCurrent()
    987 
     1227    GUII = GetBiasCurrent()
     1228    interesting =  GUII.mean(), GUII.std(), GUII.max(), GUII.min()
     1229    print time.strftime('%d %b %Y %H:%M:%S UTC', time.gmtime()), interesting
    9881230
    9891231
     
    10031245  return conn
    10041246 
    1005  
    1006  
     1247def GetFadBadConnections( good = 0x42 ):
     1248  """ returns list of bad FAD IDs
     1249  """
     1250  conn = GetFadConnections()
     1251  bads = np.where( conn != good) [0]
     1252  return bads
     1253
     1254
     1255def StartUp():
     1256  fad_control.start()
     1257  bias_control.reconnect()
     1258  bias_control.set_zero_voltage()
     1259  while bias_control.stn == 6 : # OverCurrent
     1260    bias_control.set_zero_voltage()
     1261    bias_control.reset_over_current_status()
     1262 
     1263  ftm_control.reconnect()
     1264 
     1265  number_of_loops = 3
     1266  while True:
     1267    bad = GetFadBadConnections()
     1268    if len(bad) == 0:
     1269      break
     1270     
     1271    for b in set( bad/10 ): # set(b/10) contains the crate ids, which have bad FADs
     1272      ResetCrate( b )
     1273     
     1274    number_of_loops -= 1
     1275    if not number_of_loops:
     1276      print 'StartUp aborted while trying to get the FADs into Connected state ... '
     1277      return False
     1278 
     1279 
     1280  if not MakeDriveCtrlReady():
     1281    return False
     1282 
     1283  return True
     1284 
     1285def Shutdown():
     1286    fad_control.stop()
     1287    ftm_control.disconnect()
     1288    feedback.stop()
     1289    bias_control.set_zero_voltage()
     1290   
     1291
     1292
     1293def MakeDriveCtrlReady():
     1294  """ Tries to get Drive ctrl from
     1295      Disconnected, locked or Error to Armed
     1296      after a few tries it gives up and returns False
     1297  """
     1298  outer_counter = 3
     1299  while drive_control.stn != 6: #Armed
     1300#    print 'MakeDriveCtrlReady outer_counter', outer_counter
     1301 
     1302    counter = 3
     1303    while drive_control.stn == 1: #Disconnected
     1304#      print 'MakeDriveCtrlReady in while 1, counter:', counter
     1305      drive_control.reconnect()
     1306      time.sleep(0.5)
     1307      counter -= 1
     1308      if not counter:
     1309        print 'count not connect drive control to cosy ... please check if cosy is running'
     1310        return False
     1311   
     1312    counter = 3
     1313    while drive_control.stn == 3: # Locked
     1314#      print 'MakeDriveCtrlReady in while 2, counter:', counter
     1315      drive_control.unlock()
     1316      time.sleep(0.5)
     1317      counter -= 1
     1318      if not counter:
     1319        print 'could not unlock drive control WTF?'
     1320        return False
     1321
     1322    counter = 3
     1323    while drive_control.stn == 256: # ERROR
     1324#      print 'MakeDriveCtrlReady in while 3, counter:', counter
     1325      drive_control.stop()
     1326      time.sleep(0.5)
     1327      counter -= 1
     1328      if not counter:
     1329        print 'could not unlock drive control WTF?'
     1330        return False
     1331
     1332    outer_counter -= 1
     1333    if not outer_counter:
     1334      print 'ERROR while trying to get Drive control ready'
     1335      return False
     1336
     1337  return True
     1338 
     1339feedback_calibration_done = None # Bool...
     1340
     1341def Make_Bias_Off():
     1342
     1343    bias_control.set_zero_voltage()
     1344    bias_control.wait(7)
     1345
     1346
     1347def Make_Bias_On():
     1348    """ Tries to get the Bias, and Feedback into a defined safe Off state
     1349        While beeing as ready as possible to go into On state
     1350    """
     1351    global feedback_calibration_done
     1352    # Feedback states:
     1353    #List of available states:
     1354    #-[-1]:    NotReady (State machine not ready, events are ignored.)
     1355    #-[0]:     Ready (State machine ready to receive events.)
     1356    #-[1]:     DimNetworkNotAvailable (The Dim DNS is not reachable.)
     1357    #-[2]:     Disconnected (The Dim DNS is reachable, but the required subsystems are not available.)
     1358    #-[3]:     Connecting (Only biasctrl is available and connected with its hardware.)
     1359    #-[4]:     ConnectedFSC (biasctrl and fscctrl are available and connected with their hardware.)
     1360    #-[5]:     ConnectedFAD (biasctrl and fadctrl are available and connected with their hardware.)
     1361    #-[6]:     Connected (biasctrl, fadctrl and fscctrl are available and connected with their hardware.)
     1362    #-[7]:     TempCtrlIdle (Temperature control activated, but voltage output disabled.)
     1363    #-[8]:     FeedbackIdle (Feedback control activated, but voltage output disabled.)
     1364    #-[9]:     CurrentCtrlIdle (Current control activated, but voltage output disabled.)
     1365    #-[10]:    TempControl (Temperature control activated and voltage output enabled.)
     1366    #-[11]:    FeedbackControl (Feedback control activated and voltage output enabled.)
     1367    #-[12]:    CurrentControl (Current/Temp control activated and voltage output enabled.)
     1368    #-[13]:    Calibrating (Calibrating current offsets.)
     1369    #-[256]:   ERROR (Common error state.)
     1370    #-[65535]: FATAL (A fatal error occured, the eventloop is stopped.)
     1371
     1372
     1373    while not  ( (feedback.stn == 12) and
     1374                 (bias_control.stn == 9) and
     1375                 (np.array(bias_control.voltage()[0:320]).mean() > 65.) ):
     1376
     1377        # for security
     1378        feedback.enable_output(0)
     1379
     1380        # try to get bias_control into state: VoltageOn
     1381        while not bias_control.stn == 9:
     1382           
     1383            if bias_control.stn == 1: #Disconnected
     1384                bias_control.reconnect()
     1385            if bias_control.stn == 2: #Connecting
     1386                time.sleep(1)
     1387            if bias_control.stn == 3: #Initializing
     1388                time.sleep(1)
     1389            if bias_control.stn == 4: #Connected
     1390                # this seems never to happen ...
     1391                time.sleep(1)
     1392                #bias_control.set_global_dac(1)
     1393            if bias_control.stn == 5: #Ramping
     1394                time.sleep(1)
     1395            if bias_control.stn == 6: #OverCurrent
     1396                bias_control.set_zero_voltage()
     1397                time.sleep(1)
     1398                bias_control.reset_over_current_status()
     1399            if bias_control.stn == 7: #VoltageOff
     1400                bias_control.set_global_dac(1)
     1401            if bias_control.stn == 8: #NotReferenced
     1402                bias_control.set_zero_voltage()
     1403            if bias_control.stn == 9: #VoltageOn
     1404                pass
     1405            if bias_control.stn > 9:
     1406                print "BIAS control is in strange status... don't know what to do"
     1407                time.sleep(1)
     1408            time.sleep(1)
     1409
     1410
     1411        # Try to get Feedback into CurrentControl
     1412        while not (feedback.stn == 12):
     1413           
     1414            if feedback.stn < 6:    # not properly connected.
     1415                # State 6 is 'Connected' but this normaly hardly shows up
     1416                # Its either voltageOff or any other meaningful state...
     1417                print "FEEDBACK not properly connected..."
     1418                time.sleep(1)
     1419
     1420            if feedback.stn == 13: #Calibrating
     1421                time.sleep(1)
     1422                continue
     1423               
     1424            if not feedback_calibration_done:
     1425                if feedback.calibration() is None:
     1426                    print "FEEDBACK has not CURRENT CALIBRATION"
     1427                    print "TRYING TO CALIBRATE"
     1428                    feedback.calibrate_currents()
     1429                    time.sleep(0.5)
     1430                    continue
     1431                else:
     1432                    feedback_calibration_done = True
     1433           
     1434            if feedback.stn == 6: #Connected
     1435                feedback.start_current_control(0.0)
     1436           
     1437            if feedback.stn in [7,8]: #TempCtrlIdle , FeedbackIdle
     1438                feedback.stop()
     1439                time.sleep(0.5)
     1440                feedback.start_current_control(0.0)
     1441               
     1442            if feedback.stn == 9: #CurrentCtrlIdle
     1443                feedback.enable_output(1)
     1444           
     1445            if feedback.stn in [10,11]: #TempControl, FeedbackControl
     1446                feedback.stop()
     1447                time.sleep(0.5)
     1448                feedback.start_current_control(0.0)
     1449               
     1450            if feedback.stn == 12: # This is where we want ot be
     1451                pass
     1452               
     1453           
     1454            time.sleep(1)
     1455        # Bias States
     1456        #List of available states:
     1457        #-[-1]:    NotReady (State machine not ready, events are ignored.)
     1458        #-[0]:     Ready (State machine ready to receive events.)
     1459        #-[1]:     Disconnected (Bias-power supply not connected via USB.)
     1460        #-[2]:     Connecting (Trying to establish USB connection to bias-power supply.)
     1461        #-[3]:     Initializing (USB connection to bias-power supply established, synchronizing USB stream.)
     1462        #-[4]:     Connected (USB connection to bias-power supply established.)
     1463        #-[5]:     Ramping (Voltage ramping in progress.)
     1464        #-[6]:     OverCurrent (At least one channel is in over current state.)
     1465        #-[7]:     VoltageOff (All voltages are supposed to be switched off.)
     1466        #-[8]:     NotReferenced (Internal reference voltage does not match last sent voltage.)
     1467        #-[9]:     VoltageOn (At least one voltage is switched on and all are at reference.)
     1468        #-[10]:    ExpertMode (Special (risky!) mode to directly send command to the bias-power supply.)
     1469        #-[256]:   ERROR (Common error state.)
     1470        #-[65535]: FATAL (A fatal error occured, the eventloop is stopped.)
     1471               
     1472
     1473class CheckBiasThread( threading.Thread ):
     1474    """ Thread, which continously monitors the Bias_Control status every
     1475        *delay* seconds.
     1476        in case of too high currents it will ...
     1477        .... do nothing :-) yet.
     1478        So far it will just change its internal state from 'Normal'
     1479        to 'PreWarning' or 'Serious'.
     1480        If the currents remain "high" for more than
     1481        *serious_action_after* seconds. some action would be taken.
     1482        I our case, just a WARNING will be logged.
     1483       
     1484        The caller thread should check the *warning_state* from outside this
     1485        thread and take apropriate actions, when 'PreWarning' is reached...
     1486       
     1487       
     1488    """
     1489    def __init__( self , delay=5, serious_action_after = 60 ):
     1490        #super(CheckBiasThread, self).__init__()
     1491        threading.Thread.__init__(self)
     1492        self.stoprequest = threading.Event()
     1493        self.warning_state = 'Unknown'
     1494        self.state_change = time.time()
     1495        self.delay = delay
     1496        self.serious_action_after = serious_action_after
     1497        self.logger = logging.getLogger('PyDimCtrl.CheckBiasThread')
     1498
     1499    def run(self):
     1500        while not self.stoprequest.isSet():
     1501           
     1502            if  (self.warning_state == 'Serious' and
     1503                    time.time()-self.state_change > self.serious_action_after):
     1504                # Remergency Ramp Down
     1505                self.logger.info('At this moment, I would ramp down the voltage')
     1506                self.logger.warning('G-APD currents are too high, since %d seconds' % self.serious_action_after)
     1507                self.logger.warning('Emergency voltage shutdown [not yet implemented]')
     1508
     1509            currents = GetPixelCurrents()
     1510            if ( (np.median(currents) > 70) or (currents.max() > 90) ):
     1511                if self.warning_state != 'Serious':
     1512                    self.logger.info('trasit into Serious Warning')
     1513                    self.warning_state = 'Serious'
     1514                    self.state_change = time.time()
     1515               
     1516            elif ( (np.median(currents) > 60) or (currents.max() > 80) ):
     1517                if self.warning_state != 'PreWarning':
     1518                    self.logger.info('transit into Pre Warning')
     1519                    self.warning_state = 'PreWarning'
     1520                    self.state_change = time.time()
     1521               
     1522            elif ( (np.median(currents) < 60) or (currents.max() < 80) ):
     1523                if self.warning_state != 'Normal':
     1524                    self.logger.info('transit into Normal Situation')
     1525                    self.warning_state = 'Normal'
     1526                    self.state_change = time.time()
     1527               
     1528            if bias_control.stn == 6: #Overcurrent
     1529                if self.warning_state != 'OverCurrent':
     1530                    self.logger.warning('trasit into Overcurrent State during data Taking')
     1531                    self.warning_state = 'OverCurrent'
     1532                    self.state_change = time.time()
     1533                   
     1534            if bias_control.stn == 1: #Disconnected
     1535                if self.warning_state != 'Disconnected':
     1536                    self.logger.warning('trasit into Disconnected state during data Taking')
     1537                    self.warning_state = 'Disconnected'
     1538                    self.state_change = time.time()
     1539               
     1540               
     1541           
     1542            time.sleep( self.delay )
     1543           
     1544    def join( self, timeout=None):
     1545        self.stoprequest.set()
     1546       
     1547        self.logger.info('was requested to die with timeout=%s' % str(timeout) )
     1548        #super(CheckBiasThread, self).join()
     1549        threading.Thread.join(self)
     1550
     1551
     1552class CheckDriveThread( threading.Thread ):
     1553    """ Thread, which continously monitors the Drive_Control status every
     1554        *delay* seconds.
     1555        in case Drive_Control goes into Error State it will
     1556        send:
     1557              * STOP
     1558              * and then resend the last tracking command
     1559             
     1560        In case sending STOP is not bringing the Drive_Control back to
     1561        state 'Armed' it will try again. Until the *try_counter* is zero.
     1562        Then it will totally Freak out.
     1563       
     1564        .... does nothing really! :-) yet.
     1565       
     1566    """
     1567    def __init__( self , try_counter = 5, timeout = 30, delay=5 ):
     1568        threading.Thread.__init__(self)
     1569        self.stoprequest = threading.Event()
     1570       
     1571        self.error_counter = 0
     1572        self.try_counter = try_counter
     1573        self.timeout = timeout
     1574        self.delay = delay
     1575       
     1576        self.warning_state = 'Unknown'
     1577        self.state_change = time.time()
     1578
     1579        self.logger = logging.getLogger('PyDimCtrl.CheckDriveThread')
     1580
     1581    def run(self):
     1582        while not self.stoprequest.isSet():
     1583           
     1584            if drive_control.stn == 256: #Error
     1585                self.error_counter += 1
     1586                self.state_change = time.time()
     1587                self.warning_state = 'ErrorFound'
     1588                self.logger.info('found Error State ... starting to react on it.')
     1589                self.logger.warning(' Error State ')
     1590               
     1591                start_of_Error_reaction = time.time()
     1592                while not drive.stn == 8: #Tracking
     1593                    if drive_control.stn == 256: #Error
     1594                        if try_counter:
     1595                            self.logger.info('sending STOP')
     1596                            drive_control.stop()
     1597                            try_counter -= 1
     1598                            time.sleep(1)
     1599
     1600                    elif drive_control.stn == 6: #Armed
     1601                        kwa = last_drive_kwargs
     1602                        self.logger.info('resending last tracking command')
     1603                        last_drive_method(kwa['wobble_offset'],
     1604                                        kwa['wobble_angle'],
     1605                                        kwa['source_name'])
     1606                        time.sleep(2)
     1607                    else:
     1608                        self.logger.error('found Error, but now neither Error state nor Armed state?!')
     1609                        self.logger.error('what should I do?')
     1610                        self.logger.error('thread aborting')
     1611                        self.warning_state = 'Critical'
     1612                        self.stoprequest.set()
     1613                        threading.Thread.join(self)
     1614                       
     1615                    if time.time() - start_of_Error_reaction > self.timeout:
     1616                        self.logger.error('timed out while trying to react on Drive Control Error')
     1617                        self.logger.error('what should I do?')
     1618                        self.logger.error('thread aborting')
     1619                        self.warning_state = 'Critical'
     1620                        #self.stoprequest.set()
     1621                        #threading.Thread.join(self)
     1622                        self.join()
     1623                       
     1624            else:
     1625                if self.warning_state != 'Normal':
     1626                    self.logger.info('transit into Normal Situation')
     1627                    self.warning_state = 'Normal'
     1628                    self.state_change = time.time()
     1629                                   
     1630            time.sleep( self.delay )
     1631           
     1632    def join( self, timeout=None):
     1633        self.stoprequest.set()
     1634        self.logger.info('was requested to die with timeout=%s' % str(timeout))
     1635        threading.Thread.join(self)
     1636
     1637
     1638class BiasThread(threading.Thread):
     1639  """ A worker thread that takes directory names from a queue, finds all
     1640      files in them recursively and reports the result.
     1641
     1642      Input is done by setting the *requested_state*:
     1643      ['On', 'Off']
     1644      Output is done by setting the *readyness*:
     1645      ['Ready', 'NotYet', 'CantDoIt']
     1646     
     1647      Ask the thread to stop by calling its join() method.
     1648  """
     1649  requests = ['On', 'Off']
     1650  readynesses = ['Ready', 'NotYet', 'CantDoIt']
     1651  requested_state = None
     1652  readyness = 'NotYet'
     1653 
     1654  def __init__(self, start_state = 'Off'):
     1655    super(BiasThread, self).__init__()
     1656    BiasThread.requested_state = start_state
     1657    self.stoprequest = threading.Event()
     1658
     1659  def run(self):
     1660    # As long as we weren't asked to stop, try to find out, if we are in
     1661    # the requested state, if not, try to reach the state...
     1662    while not self.stoprequest.isSet():
     1663       
     1664        if not self.InRequestedState():
     1665          print 'not in Requested State', BiasThread.requested_state
     1666          BiasThread.readyness = 'NotYet'
     1667     
     1668        try:
     1669            dirname = self.dir_q.get(True, 0.05)
     1670            filenames = list(self._files_in_dir(dirname))
     1671            self.result_q.put((self.name, dirname, filenames))
     1672        except Queue.Empty:
     1673            continue
     1674
     1675  def join(self, timeout=None):
     1676    self.stoprequest.set()
     1677    super(BiasThread, self).join(timeout)
     1678 
     1679  def InRequestedState():
     1680    """
     1681    """
     1682    if BiasThread.requested_state == 'On':
     1683      pass
     1684    elif BiasThread.requested_state == 'Off':
     1685      pass
     1686    else: # Houston we have a problem!
     1687      pass
     1688
     1689
     1690
     1691
     1692class CheckDaqThread( threading.Thread ):
     1693    """ Thread, which continously monitors the Rate
     1694       
     1695        in case the rate is < 1Hz --> Bing bing
     1696       
     1697    """
     1698    def __init__( self , delay=5 ):
     1699        threading.Thread.__init__(self)
     1700        self.stoprequest = threading.Event()
     1701       
     1702        self.delay = delay
     1703       
     1704        self.warning_state = 'Unknown'
     1705        self.state_change = time.time()
     1706
     1707        self.logger = logging.getLogger('PyDimCtrl.CheckDaqThread')
     1708
     1709    def run(self):
     1710        while not self.stoprequest.isSet():
     1711           
     1712            rate = ftm_control.trigger_rates()[3]
     1713            if rate < 1:
     1714                if self.warning_state != 'SmallRate':
     1715                    self.logger.warning('SmallRate detected!')
     1716                    self.warning_state = 'SmallRate'
     1717                    self.state_change = time.time()
     1718            else:
     1719                if self.warning_state != 'Normal':
     1720                    self.logger.info('transit to Normal')
     1721                    self.warning_state = 'Normal'
     1722                    self.state_change = time.time()
     1723               
     1724            time.sleep( self.delay )
     1725           
     1726    def join( self, timeout=None):
     1727        self.stoprequest.set()
     1728        self.logger.info('was requested to die with timeout=%s' % str(timeout))
     1729        threading.Thread.join(self)
     1730
     1731 
     1732
     1733def off():
     1734    for m in monis:
     1735        m.join()
     1736   
     1737monis = []
    10071738if __name__ == '__main__':
    10081739  print 'Welcome to PyDimCtrl'
     
    10171748  print
    10181749
    1019 
     1750  #bm = CheckBiasThread()
     1751  #dm = CheckDriveThread()
     1752  #rm = CheckDaqThread()
     1753  #monis = [bm, dm, rm]
     1754#  bm.start()
     1755#  dm.start()
     1756#  rm.start()
     1757  #print
     1758  #print 'monis created'
Note: See TracChangeset for help on using the changeset viewer.