#!/usr/bin/env python # Classes to handle BCAL modules. # To get the information of the data base tables 'Detector_Hierarchy' and 'Voltages' the class uses sqlalchemy based objects. # # Classes Hierarchy: # SubDetector : Class representing Upstream or Downstream sub detectors. Constructor - Subdetector(side<'U' or 'D'>), auto fill Quadrant and LVMPPC objects. # Quadrant : Class representing the quadrants of the sub detectors. Constructor - Quadrant(side<'U' or 'D'>,quadrant<[1,4]>), auto fill 12 MPPCModule and 4 LED objects. # LVMPPC : Class representing the mppc LV modules for the sub detectors. Constructor - LVMPPC(side<'U' or 'D'>), auto fill 12 Detector_Hierarchy objects. # MPPCModule : Class representing the modules of the sub detectors. Constructor - MPPCModule(side<'U' or 'D'>,quadrant<[1,48]>), auto fill 4 Voltages and 4 Detector_Hierarchy objects. # LED : Class representing the LED modules of the sub detectors. Constructor - LED(side<'U' or 'D'>,quadrant<[1,4]>,column<[1,4]>), includes voltage and pulsing control. # Detector_Hierarchy : Class representing the rows of the Detector_Hierarchy table in the data base. Inherit from sqlalchemy Base class and includes functions for epics manipulation. # Voltages : Class representing the rows of the Voltages table in the data base. Inherit from sqlalchemy Base class and includes functions for epics manipulation. # # Orlando Soto, April 2014. import sys import math import time from sqlalchemy import types, event, create_engine, Column, Integer, String, TEXT, TIMESTAMP, DateTime, MetaData, Table from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker, class_mapper, relationship, backref from epics import caget, caput ############# Some code to handle SQLite DateTime type in sqlalchemy ############ def sqlite_bugfix(): import datetime class MyEpochType(types.TypeDecorator): impl = types.Integer epoch = datetime.datetime(1970, 1, 1, 0, 0, 0) def process_bind_param(self, value, dialect): return (value / 1000 - self.epoch).total_seconds() def process_result_value(self, value, dialect): return self.epoch + datetime.timedelta(seconds=value / 1000) @event.listens_for(Table, "column_reflect") def setup_epoch(inspector, table, column_info): if isinstance(column_info['type'], types.DateTime): column_info['type'] = MyEpochType() ################################################################################# #sqlite_bugfix() #engine = create_engine('sqlite:///tt_mod.db', echo=False) # Create a connector for the data base SQLite engine = create_engine('mysql://bcal:$bcal@gluondb1/BCAL_DEVEL', echo=False) # Create a connector for the data base MySQL Base = declarative_base() Base.metadata.reflect(engine,only = ('Detector_Hierarchy', 'Voltages')) class Detector_Hierarchy(Base): ''' Class used to handle rows of the Detector_Hierarchy table in the data base. This class needs the sqlalchemy module. Parameters: node_name: name of the node including all acendence. quiet: Flag to trun on/off printouts. sim: Flag to trun on/off epics caput. level: Number that represent position in class hierarchy (0: Don't belong to any class) className: The name of the class labelArray : List of possible status strings Methods: get_parent, get_node_name, show, turn_on, turn_off ''' __table__ = Base.metadata.tables['Detector_Hierarchy'] quiet = False sim = True level = 0 className = __table__.name node_name = '' labelArray = [ 'outputOn' , 'outputInhibit' , 'outputFailureMinSenseVoltage' , 'outputFailureMaxSenseVoltage' , 'outputFailureMaxTerminalVoltage' , 'outputFailureMaxCurrent' , 'outputFailureMaxTemperature' , 'outputFailureMaxPower' , 'outputFailureTimeout' , 'outputCurrentLimited' , 'outputRampUp' , 'outputRampDown' , 'outputEnableKill' , 'outputEmergencyOff' ]; def get_parent(self,session): ''' Get parent object from Detector_Hierarchy tree. ''' parent = session.query(Detector_Hierarchy).filter(Detector_Hierarchy.id == self.parent_id).one() return parent def get_node_name(self,session): ''' Get node name including all its ascendancy. ''' node_name = self.name # Node name used by epics records. parent = self while parent.parent_id: parent = parent.get_parent(session) node_name = parent.name + ":" + node_name return node_name def show(self): ''' Show some of the class content. ''' print '\t'*self.level + "Type: " + self.className + ", name: " + self.name + ", node_name: " + self.node_name def turn_on(self): ''' Turn on this node name. ''' if not self.quiet: print "caput(" + self.node_name + ":switch, 1)" if not self.sim: print caput(self.node_name + ":switch", 1) if not self.quiet: print caget(self.node_name + ":switch") def turn_off(self): ''' Turn off this node name. ''' if not self.quiet: print "caput(" + self.node_name + ":switch, 0)" if not self.sim: caput(self.node_name + ":switch", 0) if not self.quiet: print caget(self.node_name + ":switch") def reset(self): ''' Turn on this node name. ''' if not self.quiet: print "caput(" + self.node_name + ":switch, 10)" if not self.sim: print caput(self.node_name + ":switch", 10) if not self.quiet: print caget(self.node_name + ":switch") time.sleep(0.1) # wait 100ms before send another value for the same register. if not self.quiet: print "caput(" + self.node_name + ":switch, 0)" if not self.sim: print caput(self.node_name + ":switch", 0) if not self.quiet: print caget(self.node_name + ":switch") def set_value(self,v): ''' Set the value for this node name. ''' if not self.quiet: print "caput(" + self.node_name + ":v_set, %f)"%v if not self.sim: caput(self.node_name + ":v_set", v) if not self.quiet: print caget(self.node_name + ":v_set") def get_value(self): ''' Get the value for this node name. ''' if not self.quiet: print "caget(" + self.node_name + ":v_term)" ret = caget(self.node_name + ":v_term") if not self.quiet: print ret return ret def get_status(self): ''' Set the status for this node name. ''' if not self.quiet: print "caget(" + self.node_name + ":stat_string)" stat_str = caget(self.node_name + ":stat_string") ret = filter(lambda x:stat_str.lower().find(x.lower())>0,self.labelArray) return ret def is_on(self): ''' Ask if this node name is on. ''' stat = self.get_status() if (len(stat) == 1) and (self.labelArray[0] in stat): return True else: return False def is_off(self): ''' Ask if this node name is off. ''' stat = self.get_status() if not len(stat): return True else: return False class Voltages(Base): ''' Class used to handle rows of the Voltages table in the data base. This class needs the sqlalchemy module. Parameters: quiet: Flag to trun on/off printouts. sim: Flag to trun on/off epics caput. level: Number that represent position in class hierarchy (0: Don't belong to any class) className: The name of the class T: Default temperature (C) offset: Default voltage above breakdown (V) Methods: get_volt, show ''' __table__ = Base.metadata.tables['Voltages'] quiet = False sim = True level = 0 className = __table__.name T = 18 # Default temperature in C offset = 1.2 # Default offset in V def get_volt(self,T=0,offset=0): ''' Get voltage including the small corrections due to non ideal mppc supply circuit. ''' if not T : T=self.T if not offset: offset = self.offset if not self.quiet : print "Temperature:\t%f" % T if not self.quiet: print "offset:\t\t%f" % offset alpha = self.alpha_p3*(T**3) + self.alpha_p2*(T**2) + self.alpha_p1*T + self.alpha_p0 Rth = self.R0th*math.exp( self.B0th*( 1/(T + 273.15) - 1/(self.T0th + 273.15) ) ) RU = self.RLin*Rth/(self.RLin+Rth) supply_voltage = ( self.Vop_avg + self.TCV0*(T - self.TJLab) + (offset - self.Vover0) + (self.TCVNew - self.TCV0)*(T - self.THam) )/alpha + (self.ILeakNew - self.ILeak0)*(self.avg_Rstotal + RU) return supply_voltage def show(self): ''' Show some of the class content. ''' print '\t'*self.level + "Type: " + self.className + ", Channel: " + str(self.Channel) + ", Jlab Vop_avg: " + str(self.Vop_avg) + "V @ " + str(self.TJLab) + "C" class LED(object): ''' Class to handle voltages table in data base. Parameters: quiet: Flag to trun on/off printouts. sim: Flag to trun on/off epics caput commands. level: Number that represent position in class hierarchy (0: Don't belong to any class). className: The name of the class. labelArray : List of possible status strings. pref : IOC BCAL pulser prefix (upstream and downstream pulsers joined). prefpulser1 : IOC BCAL upstream pulser prefix. prefpulser2 : IOC BCAL downstream pulser prefix. prefvolt : IOC BCAL LED voltages prefix. pulser_pref : IOC pulser channel prefix (channel 1,...,32). bias_pref : IOC bias channel prefix. lv_pref : IOC lv channel prefix. bias_v : Default LED BIAS voltage. lv_v : Default LED LV voltage. side : Sub detector side 'U': Upstream, 'D': Downstream. column : Module column (1-4) quadrant : Detector quadrant (1-4) width : Default LED pulser width (ns) frequency : Default LED pulser frequency (Hz) npulses: Default LED pulser npulses (#) Methods: configure, get_pulser_name, get_volt_name, show, turn_bias_on, turn_bias_off, set_bias_value, get_bias_value, get_bias_status, is_bias_on, is_bias_off, turn_lv_on, turn_lv_off, set_lv_value, get_lv_value, get_lv_status, is_lv_on, is_lv_off, set_stop_mask, turn_pulser_on, turn_pulser_off, set_pulser_values, get_pulser_values, get_pulser_status, is_pulser_on, is_pulser_off. ''' quiet = False sim = True pref = 'BCAL:pulser' # IOC prefix prefpulser1 = 'BCAL:pulser1'# IOC prefix prefpulser2 = 'BCAL:pulser2'# IOC prefix prefvolt = 'BCALED' # IOC prefix level = 0 className = 'LED' bias_v = 6.0 lv_v = 5.0 side = 'U' # Side 'U', 'D' column = 1 # Column 1-4 quadrant = 1 # Quadrant 1-4 width = 100 # (ns) frequency = 100 # (Hz) npulses = 1 # (#) led_pulser_delay = 0.0 width_set = 100 # (ns) frequency_set = 100 # (Hz) npulses_set = 1 # (#) labelArray = [ 'outputOn' , 'outputInhibit' , 'outputFailureMinSenseVoltage' , 'outputFailureMaxSenseVoltage' , 'outputFailureMaxTerminalVoltage' , 'outputFailureMaxCurrent' , 'outputFailureMaxTemperature' , 'outputFailureMaxPower' , 'outputFailureTimeout' , 'outputCurrentLimited' , 'outputRampUp' , 'outputRampDown' , 'outputEnableKill' , 'outputEmergencyOff' ]; def __init__(self,s='U',q=1,c=1,quiet=False,sim=True): ''' Initialization of an LED object identified by side, quadrant and column. ''' self.quiet = quiet self.sim = sim self.side = s self.column = c self.quadrant = q self.get_pulser_name() self.get_volt_name() def configure(self,bias_v=0, lv_v = 0, width = 0, frequency = 0, npulses = 0): ''' Set values for bias, lv, and pulser. Set stop mask for all and start mask for trigger. ''' self.set_bias_value(bias_v) self.set_lv_value(lv_v) self.set_pulser_values(width, frequency, npulses) # Set default values self.set_stop_mask() self.set_trig_mask() def get_pulser_name(self): ''' Get pulser channel prefix. Upstream channel = 1,...,16. Downstream channel = 17,...,32. ''' base = 0 if self.side == 'U' else 16 ch = (self.quadrant-1)*4 + self.column + base self.pulser_pref = self.pref + ':' + str(ch) # Epics name self.number = ch # LED number def get_volt_name(self): ''' Get bias and lv channel prefix. ''' self.lv_pref = self.prefvolt + ':lv:' + self.side + ":" + str(self.quadrant -1) # Epics name self.bias_pref = self.prefvolt + ':bias:' + self.side + ":" + str(self.quadrant -1) # Epics name def show(self): ''' Show some of the class content. ''' print '\t'*self.level + "Type: " + self.className + ", number: " + str(self.number) + ", column: " + str(self.column) + ' ' +self.lv_pref + ' ' + self.bias_pref ########### Actions over the channels ########## #### LED bias #### def turn_bias_on(self): if not self.quiet: print "caput(" + self.bias_pref + ":switch, 1)" if not self.sim: caput(self.bias_pref + ":switch", 1) if not self.quiet: print caget(self.bias_pref + ":switch") def turn_bias_off(self): if not self.quiet: print "caput(" + self.bias_pref + ":switch, 0)" if not self.sim: caput(self.bias_pref + ":switch", 0) if not self.quiet: print caget(self.bias_pref + ":switch") def set_bias_value(self,v=0): if not v: v=self.bias_v if not self.quiet: print "caput(" + self.bias_pref + ":v_set, %f)"%v if not self.sim:caput(self.bias_pref + ":v_set", v) if not self.quiet: print caget(self.bias_pref + ":v_set") def get_bias_value(self): if not v: v=self.lv_v if not self.quiet: print "caget(" + self.bias_pref + ":v_sens)" ret = caget(self.bias_pref + ":v_sens") if not self.quiet: print ret return ret def get_bias_status(self): if not self.quiet: print "caget(" + self.bias_pref + ":stat_string)" stat_str = caget(self.bias_pref + ":stat_string") ret = filter(lambda x:stat_str.lower().find(x.lower())>0,self.labelArray) return ret def is_bias_on(self): stat = self.get_bias_status() if (len(stat) == 1) and (self.labelArray[0] in stat): return True else: return False def is_bias_off(self): stat = self.get_bias_status() if not len(stat): return True else: return False #### LED lv #### def turn_lv_on(self): if not self.quiet: print "caput(" + self.lv_pref + ":switch, 1)" if not self.sim: caput(self.lv_pref + ":switch", 1) if not self.quiet: print caget(self.lv_pref + ":switch") def turn_lv_off(self): if not self.quiet: print "caput(" + self.lv_pref + ":switch, 0)" if not self.sim: caput(self.lv_pref + ":switch", 0) if not self.quiet: print caget(self.lv_pref + ":switch") def set_lv_value(self,v=0): if not v: v=self.lv_v if not self.quiet: print "caput(" + self.lv_pref + ":v_set, %f)"%v if not self.sim: caput(self.lv_pref + ":v_set", v) if not self.quiet: print caget(self.lv_pref + ":v_set") def get_lv_value(self): if not self.quiet: print "caget(" + self.lv_pref + ":v_sens)" ret = caget(self.lv_pref + ":v_sens") if not self.quiet: print caget(self.lv_pref + ":v_sens") return ret def get_lv_status(self): if not self.quiet: print "caget(" + self.lv_pref + ":stat_string)" stat_str = caget(self.lv_pref + ":stat_string") ret = filter(lambda x:stat_str.lower().find(x.lower())>0,self.labelArray) return ret def is_lv_on(self): stat = self.get_lv_status() if (len(stat) == 1) and (self.labelArray[0] in stat): return True else: return False def is_lv_off(self): stat = self.get_lv_status() if not len(stat): return True else: return False #### LED pulser #### def set_stop_mask(self,s=''): if not s: s = self.side pp = self.prefpulser1 if s=='U' else self.prefpulser2 if not self.quiet: print "caput(" + pp + ":stop_mask_h_w, 0x0007FFFF)" if not self.quiet: print "caput(" + pp + ":stop_mask_l_w, -1)" if not self.sim: caput(pp + ":stop_mask_h_w", 0x0007FFFF) if not self.sim: caput(pp + ":stop_mask_l_w", -1) if not self.quiet: print caget(pp + ":stop_mask_h_w") if not self.quiet: print caget(pp + ":stop_mask_l_w") def set_trig_mask(self,s=''): if not s: s = self.side pp = self.prefpulser1 if s=='U' else self.prefpulser2 current_mask = caget(pp + ":start_mask_h_w") add_trig = current_mask | 0x00078000 if not self.quiet: print "caput(" + pp + ":start_mask_h_w, %x)"%add_trig if not self.sim: caput(pp + ":start_mask_h_w", add_trig) def turn_pulser_on(self): if not self.quiet: print "caput(" + self.pulser_pref + "_start_mask_w, 1)" if not self.sim: caput(self.pulser_pref + "_start_mask_w", 1) while caget(self.pulser_pref + "_start_mask_w") <> 1: pass pp = self.prefpulser1 if self.number<=16 else self.prefpulser2 while not ((caget(pp + ":start_mask_h_w")&0x00078000) == 0x00078000): self.set_trig_mask() if not self.quiet: print "caput(" + pp + ":start_stop_w, 1)" if not self.sim: caput(pp + ":start_stop_w", 1) if not self.quiet: print caget(pp + ":start_stop_w") def turn_pulser_off(self): if not self.quiet: print "caput(" + self.pulser_pref + "_start_mask_w, 0)" if not self.sim: caput(self.pulser_pref + "_start_mask_w", 0) while caget(self.pulser_pref + "_start_mask_w") <> 0: pass pp = self.prefpulser1 if self.number<=16 else self.prefpulser2 while not ((caget(pp + ":start_mask_h_w")&0x00078000) == 0x00078000): self.set_trig_mask() if not self.quiet: print "caput(" + pp + ":start_stop_w, 0)" if not self.sim: caput(pp + ":start_stop_w", 0) if not self.quiet: print caget(pp + ":start_stop_w") while self.is_pulser_on(): pass def set_pulser_values(self, width = 0, frequency = 0, npulses = 0): if not width: width = self.width if not frequency: frequency = self.frequency if not npulses : npulses = self.npulses self.width_set = width self.frequency_set = frequency self.npulses_set = npulses if width: if not self.quiet: print "caput(" + self.pref + ":all:rawwidth_w, %f)" % width if not self.sim: caput(self.pref + ":all:rawwidth_w", width) if not self.quiet: print caget(self.pref + ":all:rawwidth_w") if frequency: if not self.quiet: print "caput(" + self.pref + ":all:rawfreq_w, %f)" % frequency if not self.sim: caput(self.pref + ":all:rawfreq_w", frequency) if not self.quiet: print caget(self.pref + ":all:rawfreq_w") # trigger frequency pp = self.prefpulser1 if self.number<=16 else self.prefpulser2 for i in range(47,51): if not self.quiet: print "caput(" + pp + ":%d_period_w, %f)" % (i,100e6/frequency) if not self.sim: caput(pp + ":%d_period_w"%i, 100e6/frequency) if not self.quiet: print caget(pp + ":%d_period_w"%i) if npulses: if not self.quiet: print "caput(" + self.pref + ":all:rawnpulses_w, %f)" % (npulses) if not self.sim: caput(self.pref + ":all:rawnpulses_w", npulses) if not self.quiet: print caget(self.pref + ":all:rawnpulses_w") # trigger npulses for i in range(47,51): if not self.quiet: print "caput(" + pp + ":%d_npulses_w, %f)" % (i,npulses) if not self.sim: caput(pp + ":%d_npulses_w"%i, npulses) if not self.quiet: print caget(pp + ":%d_npulses_w"%i) def get_pulser_values(self): if not self.quiet: print "caget(" + self.pulser_pref + "_width_r) (x10 ns)" retw = caget(self.pulser_pref + "_width_r")*10 if not self.quiet: print retw if not self.quiet: print "caget(" + self.pulser_pref + "_period_r) (^-1*100e6 Hz)" retf = 100e6/caget(self.pulser_pref + "_period_r") if not self.quiet: print retf if not self.quiet: print "caget(" + self.pulser_pref + "_npulses_r)" retn = caget(self.pulser_pref + "_npulses_r") if not self.quiet: print retn return (retw, retf, retn) def get_pulser_status(self): if not self.quiet: print "caget(" + self.pref + ":status_r)" ret = caget(self.pref + ":status_r") return ret def is_pulser_on(self): stat = self.get_pulser_status() if (stat & 1<<(self.number-1)): return True else: return False def is_pulser_off(self): return not self.is_pulser_on() ################################################ class MPPCModule(object): ''' Class to handle mppc bias modules. This class needs the sqlalchemy module. Parameters: quiet: Flag to trun on/off printouts. sim: Flag to trun on/off epics caput commands. level: Number that represent position in class hierarchy (0: Don't belong to any class). className: The name of the class. bias_channel: Dictionary to hold Detector_Hierarchy objects corresponding to the 4 channels of the module. key:value --> channel_number:object voltages_channel: Dictionary to hold Voltages objects, each object includes the small correction needed on the MPPC bias. key:value --> channel_number:object Methods: configure, show, turn_on, turn_off, reset, set_bias_value, is_bias_on, is_bias_off ''' quiet = False sim = True level = 0 className = 'MPPCModule' def __init__(self,side,mod,quiet=False, sim = True): ''' Initialization of the module identified by side and module number. ''' self.quiet = quiet self.sim = sim self.number = mod Voltages.level = self.level + 1 Voltages.quiet = self.quiet Voltages.sim = self.sim Detector_Hierarchy.level = self.level + 1 Detector_Hierarchy.quiet = self.quiet Detector_Hierarchy.sim = self.sim Session = sessionmaker(bind=engine) # Bind to the data base. session = Session() # Connect to the data base (will connect on the first rollback, commit). BCAL = session.query(Detector_Hierarchy).filter(Detector_Hierarchy.name == 'BCAL').one() # Get the begining of the tree. bias = session.query(Detector_Hierarchy).filter(Detector_Hierarchy.name == 'bias',Detector_Hierarchy.parent_id == BCAL.id).one() # Getting bias node. side = session.query(Detector_Hierarchy).filter(Detector_Hierarchy.name == side, Detector_Hierarchy.parent_id == bias.id).one() # Getting side node. mod = session.query(Detector_Hierarchy).filter(Detector_Hierarchy.name == '%d'%mod,Detector_Hierarchy.parent_id == side.id).one() # Getting module node. self.bias_channel = dict((int(x.name),x) for x in session.query(Detector_Hierarchy).filter(Detector_Hierarchy.parent_id == mod.id).all()) # bias channel dictionary. self.voltages_channel = dict((int(y.Channel),y) for y in session.query(Voltages).filter(Voltages.volt_id.in_(list(x.volt_id for x in self.bias_channel.values()))).all()) # Bias channel dictionary. for v in self.bias_channel.values(): v.node_name = v.get_node_name(session) # Storing node_name in Detector_Hierarchy objects. session.close() def show(self): ''' Show some of the class content. ''' print '\t'*self.level + "Type: " + self.className + ", " + str(self.number) + ". Contains:" for i in sorted(self.bias_channel.keys()): self.bias_channel[i].show() self.voltages_channel[i].show() ########### Actions over the channels ########## def turn_on(self,ch=0): if not ch: for v in list( v for k,v in sorted(self.bias_channel.items()) ): v.turn_on() else: v = self.bias_channel[ch] v.turn_on() def turn_off(self,ch=0): if not ch: for v in list( v for k,v in sorted(self.bias_channel.items()) ): v.turn_off() else: v = self.bias_channel[ch] v.turn_off() def reset(self,ch=0): if not ch: for v in list( v for k,v in sorted(self.bias_channel.items()) ): v.reset() else: v = self.bias_channel[ch] v.reset() def set_bias_value(self,ch = 0, temp = 0, offset = 0): if not ch: for k,v in sorted(self.bias_channel.items()): v.set_value(self.voltages_channel[k].get_volt(temp,offset)) else: v = self.bias_channel[ch]; k = ch; v.set_value(self.voltages_channel[k].get_volt(temp,offset)) def is_bias_on(self,ch = 0): if not ch: ret = True for k,v in sorted(self.bias_channel.items()): ret = v.is_on() and ret return ret else: v = self.bias_channel[ch] return v.is_on() def is_bias_off(self, ch=0): if not ch: ret = True for k,v in sorted(self.bias_channel.items()): ret = v.is_off() and ret return ret else: v = self.bias_channel[ch] return v.is_off() def configure(self, temp=0, offset=0): ''' Set voltage values on the 4 channels of the module. ''' for k,v in sorted(self.bias_channel.items()): v.set_value(self.voltages_channel[k].get_volt(temp,offset)) ################################################ class LVMPPC(object): ''' Class to handle mppc LV modules This class needs the sqlalchemy module. Parameters: quiet: Flag to trun on/off printouts. sim: Flag to trun on/off epics caput commands. level: Number that represent position in class hierarchy (0: Don't belong to any class). className: The name of the class. pv: +V. nv: -V, absolute value. lv_channel: Dictionary to hold Detector_Hierarchy objects corresponding to the 12 voltages on the detector side. key:value --> channel_name:object Methods: configure, show, turn_on, turn_off, is_lv_on, is_lv_off ''' quiet = False sim = True level = 0 className = 'LVMPPC' pv = 5.0 nv = 5.0 def __init__(self,side,quiet=False, sim = True): self.quiet = quiet self.sim = sim Detector_Hierarchy.level = self.level + 1 Detector_Hierarchy.quiet = self.quiet Detector_Hierarchy.sim = self.sim Session = sessionmaker(bind=engine) # Bind to the data base. session = Session() # Connect to the data base (will connect on the first rollback, commit). BCAL = session.query(Detector_Hierarchy).filter(Detector_Hierarchy.name == 'BCAL').one() # Get the begining of the tree. lv = session.query(Detector_Hierarchy).filter(Detector_Hierarchy.name == 'lv',Detector_Hierarchy.parent_id == BCAL.id).one() # Getting lv node. side = session.query(Detector_Hierarchy).filter(Detector_Hierarchy.name == side, Detector_Hierarchy.parent_id == lv.id).one() # Getting side node. self.lv_channel = dict((x.name,x) for x in session.query(Detector_Hierarchy).filter(Detector_Hierarchy.parent_id == side.id).all()) # LV dictionary. for v in self.lv_channel.values(): v.node_name = v.get_node_name(session) # Storing node_name in Detector_Hierarchy objects. session.close() def show(self): print '\t'*self.level + "Type: " + self.className + ". Contains:" for v in self.lv_channel.values(): v.show() ########### Actions over the channels ########## def turn_on(self,ch=0): if not ch: for v in list( v for k,v in sorted(self.lv_channel.items()) ): v.turn_on() else: v = self.lv_channel[ch] v.turn_on() def turn_off(self,ch=0): if not ch: for v in list( v for k,v in sorted(self.lv_channel.items()) ): v.turn_off() else: v = self.lv_channel[ch] v.turn_off() def is_lv_on(self,ch = 0): ret = True for k,v in sorted(self.lv_channel.items()): ret = v.is_on() and ret return ret def is_lv_off(self, ch=0): ret = True for k,v in sorted(self.lv_channel.items()): ret = v.is_off() and ret return ret def configure(self): for v in list( v for k,v in sorted(self.lv_channel.items()) ): if 'n' in v.name: v.set_value(self.nv) if 'p' in v.name: v.set_value(self.pv) ############################################## class Quadrant(object): ''' Class to handle Quadrants in the detector side Parameters: quiet: Flag to trun on/off printouts. sim: Flag to trun on/off epics caput commands. level: Number that represent position in class hierarchy (0: Don't belong to any class). className: The name of the class. number: Quadrant number {1,...4}. side: Quadrant side 'U': upstream or 'D': downstream. module: Dictionary to hold MPPCModule objects corresponding to the 12 modules in the quadrant. key:value --> module_number:object. led: Dictionary to hold LED objects corresponding to the 4 led columns in the quadrant. key:value --> led_number:object. Methods: configure, configure_led_only, show, fill, turn_mppc_bias_on, turn_mppc_bias_off, reset_mppc_bias, set_bias_value, is_mppc_bias_on, is_mppc_bias_off, turn_led_bias_on, turn_led_bias_off, turn_led_lv_on, turn_led_lv_off, turn_led_pulser_on, turn_led_pulser_off, set_led_bias_value, set_led_lv_value, is_led_bias_on, is_led_bias_off, is_led_lv_on, is_led_lv_off, is_led_pulser_on, is_led_pulser_off. ''' quiet = False sim = True level = 0 className = 'Quadrant' def __init__(self,s,q,quiet = False, sim = True): self.quiet = quiet self.sim = sim if s not in ['U','D']: print ("Wrong side, 'U': Upstream or 'D': Downstream"); sys.exit(1); if q not in range(1,5): print ("Wrong quadrant, int in [1,4]"); sys.exit(1); self.side = s self.number = q self.fill() def fill(self): ''' Fill this quadrant with the modules and led objects, fill the dictionaries. ''' self.module = {} self.led = {} m_start = (self.number-1)*12 + 1 m_end = (self.number-1)*12 + 12 +1 MPPCModule.level = self.level + 1 LED.level = self.level + 1 for m in range(m_start, m_end): self.module[m] = MPPCModule(self.side,m,self.quiet,self.sim) for c in range(1,5): self.led[c] = LED(self.side,self.number,c,self.quiet,self.sim) def show(self): print '\t'*self.level + "Type: " + self.className + ", number: " + str(self.number)+ ", side: " + (" Upstream" if self.side == 'U' else " Downstream. Contains:" ) for m in sorted(self.module.keys()): self.module[m].show() for l in sorted(self.led.keys()): self.led[l].show() ################ MPPC voltages ######################### def turn_mppc_bias_on(self,m=0, ch = 0): if not m and not ch: for v in list( v for k,v in sorted(self.module.items()) ): v.turn_on() elif not m and ch : for v in list( v for k,v in sorted(self.module.items()) ): v.turn_on(ch) else: v = self.module[m] v.turn_on() def turn_mppc_bias_off(self,m=0, ch = 0): if not m and not ch: for v in list( v for k,v in sorted(self.module.items()) ): v.turn_off() elif not m and ch: for v in list( v for k,v in sorted(self.module.items()) ): v.turn_off(ch) else: v = self.module[m] v.turn_off() def reset_mppc_bias(self,m=0, ch = 0): if not m and not ch: for v in list( v for k,v in sorted(self.module.items()) ): v.reset() elif not m and ch : for v in list( v for k,v in sorted(self.module.items()) ): v.reset(ch) else: v = self.module[m] v.reset() def set_bias_value(self,m = 0, ch = 0, temp=0,offset = 0): if not m: for v in list( v for k,v in sorted(self.module.items()) ): v.set_bias_value(ch,temp,offset) else: v = self.module[m] v.set_bias_value(ch,temp,offset) def is_mppc_bias_on(self,m = 0, ch = 0): if not m: ret = True for k,v in sorted(self.module.items()): ret = v.is_bias_on() and ret return ret else: v = self.module[m] return v.is_bias_on() def is_mppc_bias_off(self,m = 0, ch=0): if not m: ret = True for k,v in sorted(self.module.items()): ret = v.is_bias_off() and ret return ret else: v = self.module[m] return v.is_bias_off() ################ LED voltages ########################## def turn_led_bias_on(self): self.led[1].turn_bias_on() def turn_led_bias_off(self): self.led[1].turn_bias_off() def turn_led_lv_on(self): self.led[1].turn_lv_on() def turn_led_lv_off(self): self.led[1].turn_lv_off() def turn_led_pulser_on(self,c=0): if not c: for l in self.led.values(): l.turn_pulser_on() else: self.led[c].turn_pulser_on() def turn_led_pulser_off(self): for l in self.led.values(): l.turn_pulser_off() def set_led_bias_value(self,v=0): self.led[1].set_bias_value(v) def set_led_lv_value(self,v=0): self.led[1].set_lv_value(v) def is_led_bias_on(self): return self.led[1].is_bias_on() def is_led_bias_off(self): return self.led[1].is_bias_off() def is_led_lv_on(self): return self.led[1].is_lv_on() def is_led_lv_off(self): return self.led[1].is_lv_off() def is_led_pulser_on(self,c=0): if not c: ret = True for c in self.led.values(): ret = ret and c.is_pulser_on() return ret else: return self.led[c].is_pulser_on() def is_led_pulser_off(self,c=0): if not c: ret = True for c in self.led.values(): ret = ret and c.is_pulser_off() return ret else: return self.led[c].is_pulser_off() ######################################################## def configure_led_only(self,led_bias=0, led_lv = 0, led_width = 0, led_frequency = 0, led_npulses = 0): for k,v in sorted(self.led.items()): v.configure(led_bias, led_lv, led_width, led_frequency, led_npulses) def configure(self,led_bias=0, led_lv = 0, led_width = 0, led_frequency = 0, led_npulses = 0, temp=0, offset=0): for k,v in sorted(self.led.items()): v.configure(led_bias, led_lv, led_width, led_frequency, led_npulses) for v in list( v for k,v in sorted(self.module.items()) ): v.configure(temp, offset) class SubDetector(object): ''' Class used to handle sub detectors (Upstream or Downstream). Parameters: quiet: Flag to trun on/off printouts. sim: Flag to trun on/off epics caput commands. level: Number that represent position in class hierarchy (0: Don't belong to any class). className: The name of the class. side: 'U': upstream or 'D': downstream. quadrant: Dictionary to hold Quadrant objects corresponding to the 4 quadrants in the side. key:value --> quadrant_number:object. lv: Dictionary to hold LVMPPC objects corresponding to the 12 low voltage in the side. key:value --> lv_number:object. Methods: configure, configure_led_only, show, fill, turn_mppc_bias_on, turn_mppc_bias_off, turn_mppc_lv_on, turn_mppc_lv_off, reset_mppc_bias, set_bias_value, is_mppc_bias_on, is_mppc_bias_off, turn_led_bias_on, turn_led_bias_off, turn_led_lv_on, turn_led_lv_off, turn_led_pulser_on, turn_led_pulser_off, set_led_bias_value, is_led_bias_on, is_led_bias_off, is_led_lv_on, is_led_lv_off, is_led_pulser_on, is_led_pulser_off. ''' quiet = False sim = True # led = {} # Dictionary to hold the 4 LED objects # module = {} # Dictionary to hold the 12 BiasModule objects level = 0 className = 'SubDetector' def __init__(self,s,quiet=False, sim = True): self.quiet = quiet self.sim = sim if s not in ['U','D']: print ("Wrong side ('U' or 'D')"); sys.exit(1); self.side = s self.name = ("Upstream" if self.side == 'U' else "Downstream" ) self.fill() def fill(self): self.quadrant = {} Quadrant.level = self.level + 1 LVMPPC.level = self.level + 1 for q in range(1, 5): self.quadrant[q] = Quadrant(self.side,q,self.quiet,self.sim) self.lv = LVMPPC(self.side,self.quiet,self.sim) def show(self): print '\t'*self.level + "Type: " + self.className + ", name: " + str(self.name) for q in sorted(self.quadrant.keys()): self.quadrant[q].show() self.lv.show() ########### MPPC voltages ############ def turn_mppc_lv_on(self,ch=0): self.lv.turn_on(ch) def turn_mppc_lv_off(self,ch=0): self.lv.turn_off(ch) def turn_mppc_bias_on(self,q=0,m=0): if not q and not m: for q in self.quadrant.values(): q.turn_mppc_bias_on() elif q and not m: q = self.quadrant[q] q.turn_mppc_bias_on() elif m : q = self.quadrant[int((m-1)/12) + 1] q.turn_mppc_bias_on(m) def turn_mppc_bias_off(self,q=0,m=0): if not q and not m: for q in self.quadrant.values(): q.turn_mppc_bias_off() elif q and not m: q = self.quadrant[q] q.turn_mppc_bias_off() elif m : q = self.quadrant[int((m-1)/12) + 1] q.turn_mppc_bias_off(m) def reset_mppc_bias(self,q=0,m=0): if not q and not m: for q in self.quadrant.values(): q.reset_mppc_bias() elif q and not m: q = self.quadrant[q] q.reset_mppc_bias() elif m : q = self.quadrant[int((m-1)/12) + 1] q.reset_mppc_bias(m) def set_mppc_bias_value(self,m = 0, ch = 0, temp=0, offset = 0): if not m: for q in self.quadrant.values(): q.set_bias_value(m,ch,temp,offset) else : q = self.quadrant[int((m-1)/12) + 1] q.set_bias_value(m,ch,temp,offset) def is_mppc_lv_on(self): return self.lv.is_lv_on() def is_mppc_lv_off(self): return self.lv.is_lv_off() def is_mppc_bias_on(self,q=0): if not q: ret = True for q in self.quadrant.values(): ret = ret and q.is_mppc_bias_on() return ret else: return self.quadrant[q].is_mppc_bias_on() def is_mppc_bias_off(self,q=0): if not q: ret = True for q in self.quadrant.values(): ret = ret and q.is_mppc_bias_off() return ret else: return self.quadrant[q].is_mppc_bias_off() ######## LED voltages ############# def turn_led_bias_on(self): for q in self.quadrant.values(): q.turn_led_bias_on() def turn_led_bias_off(self): for q in self.quadrant.values(): q.turn_led_bias_off() def turn_led_lv_on(self): for q in self.quadrant.values(): q.turn_led_lv_on() def turn_led_lv_off(self): for q in self.quadrant.values(): q.turn_led_lv_off() def set_led_bias_value(self,bias): for q in self.quadrant.values(): q.set_led_bias_value(bias) def turn_led_pulser_on(self,c=0): if not c: for q in self.quadrant.values(): q.turn_led_pulser_on() else: for q in self.quadrant.values(): q.turn_led_pulser_on(c) def turn_led_pulser_off(self): for q in self.quadrant.values(): q.turn_led_pulser_off() def is_led_bias_on(self,q=0): if not q: ret = True for q in self.quadrant.values(): ret = q.is_led_bias_on() and ret return ret else: return self.quadrant[q].is_led_bias_on() def is_led_bias_off(self,q=0): if not q: ret = True for q in self.quadrant.values(): ret = ret and q.is_led_bias_off() return ret else: return self.quadrant[q].is_led_bias_off() def is_led_lv_on(self,q=0): if not q: ret = True for q in self.quadrant.values(): ret = q.is_led_lv_on() and ret return ret else: return self.quadrant[q].is_led_lv_on() def is_led_lv_off(self,q=0): if not q: ret = True for q in self.quadrant.values(): ret = ret and q.is_led_lv_off() return ret else: return self.quadrant[q].is_led_lv_off() def is_led_pulser_on(self,q=0): if not q: ret = True for q in self.quadrant.values(): ret = q.is_led_pulser_on() and ret return ret else: return self.quadrant[q].is_led_pulser_on() def is_led_pulser_off(self,q=0): if not q: ret = True for q in self.quadrant.values(): ret = ret and q.is_led_pulser_off() return ret else: return self.quadrant[q].is_led_pulser_off() #################### def configure_led_only(self, led_bias=0, led_lv = 0, led_width = 0, led_frequency = 0, led_npulses = 0): for v in list( v for k,v in sorted(self.quadrant.items()) ): v.configure_led_only(led_bias, led_lv, led_width, led_frequency, led_npulses) def configure(self, led_bias=0, led_lv = 0, led_width = 0, led_frequency = 0, led_npulses = 0, temp=0, offset=0): for v in list( v for k,v in sorted(self.quadrant.items()) ): v.configure(led_bias, led_lv, led_width, led_frequency, led_npulses, temp, offset) self.lv.configure() def testClasses(): ''' ''' # Function for class testing. import random random.seed() print "\nTesting random Quadrant in random side ... " q,side,offset,T = (random.randint(1,4),random.choice(['U','D']),random.uniform(0,2),random.uniform(5,30)) quadrant = Quadrant(side,q) quadrant.show() mod = random.choice(quadrant.module.keys()) print "\n Testing random module in quadrant at random temperature at random offset..." print "module: %s-%02d @ %f C, offset = %f\n" % (side,mod,T,offset) module = quadrant.module[mod] for ch in range (1,5): print "Bias Channel: " + str(module.voltages_channel[ch].Channel) print module.bias_channel[ch].node_name + ":v_set set to " + str(module.voltages_channel[ch].get_volt(T,offset)) print "\nI'm not setting anything, just printing..." if __name__ == "__main__": # Do something if it gets excecuted alone. testClasses()