def __init__(self, inst, props, *args, **kwargs): """Class initialization.""" CounterTimerController.__init__(self, inst, props, *args, **kwargs) self._log.debug("__init__(%s, %s): Entering...", repr(inst), repr(props)) try: self.pandabox = PandA(self.PandaboxHost) self.pandabox.connect_to_panda() except (NameError, socket.gaierror): raise Exception('Unable to connect to PandABox.') # make sure PCAP block is reset self.pandabox.query('PCAP.ENABLE=ZERO') self.pandabox.query('*PCAP.DISARM=') try: self.data_socket = TCP(self.PandaboxHost, 8889, timeout=3) self.data_socket.open() except: raise Exception('Unable to open PandABox data stream.') # check if data stream starts correctly ack = self.data_socket.write_readline('\n') if "OK" not in ack: raise Exception('Acknowledge to data stream failed!') print "PandaboxCoTiCtrl: data stream listener starts...", ack self.data_buffer = "" self.header_okay_flag = False self.data_end_flag = False self.attributes = {} self.hw_trigger_cfg = {} self.hw_trigger_cfg['enable'] = self.PcapEnable self.hw_trigger_cfg['gate'] = self.PcapGate self.hw_trigger_cfg['trig'] = self.PcapTrig self.channels_order = [] # channels and modes available self._modes = ['Value', 'Diff', 'Min', 'Max', 'Sum', 'Mean'] self._channels = [ 'INENC1.VAL', 'INENC2.VAL', 'INENC3.VAL', 'INENC4.VAL', 'CALC1.OUT', 'CALC2.OUT', 'COUNTER1.OUT', 'COUNTER2.OUT', 'COUNTER3.OUT', 'COUNTER4.OUT', 'COUNTER5.OUT', 'COUNTER6.OUT', 'COUNTER7.OUT', 'COUNTER8.OUT', 'FILTER1.OUT', 'FILTER2.OUT', 'PGEN1.OUT', 'PGEN2.OUT', 'QDEC.OUT', 'FMC_IN.VAL1', 'FMC_IN.VAL2', 'FMC_IN.VAL3', 'FMC_IN.VAL4', 'FMC_IN.VAL5', 'FMC_IN.VAL6', 'FMC_IN.VAL7', 'FMC_IN.VAL8', 'PCAP.SAMPLES' ] self.index = 0 self._repetitions = 0
data = s.recv(1024) raw_data = "" while True: # print 'data:', repr(data) data = s.recv(1024) raw_data += data if "END" in repr(data): break s.close() # print 'Received data:', repr(raw_data) return raw_data host = 'pandabox' panda = PandA(host) panda.connect_to_panda() # trigger source (how fast to acquire) panda.query('CLOCKS.B_PERIOD=0.001') panda.query('CLOCKS.B_PERIOD.UNITS=s') # gate signal to PCAP, how long acquiring acq_time = 0.005 acq_time_units = "s" panda.query('PULSE1.WIDTH=%f' % (acq_time)) panda.query('PULSE1.WIDTH.UNITS=%s' % (acq_time_units)) # linking blocks # PCAP panda.query('PCAP.TRIG=CLOCKS.OUTB')
from pandaboxlib import PandA import numpy as np #host = 'pandabox' host = 'b308a-cab04-pandabox-temp-0' panda = PandA(host) panda.connect_to_panda() # max_length = 4096 rows positions = np.arange(1, 20, 1) #positions = np.array((1000,1100,1500,1600,1700,1800)) print positions # user options for SEQ table repeats = 1 trigger = 'posb>=position' time1 = 1 phase1 = { 'a': True, 'b': False, 'c': False, 'd': False, 'e': False, 'f': False } time2 = 1 phase2 = { 'a': False, 'b': False,
from pandaboxlib import PandA import numpy as np host = 'pandabox' panda = PandA(host) panda.connect_to_panda() panda.query('CLOCKS.A_PERIOD=.05') panda.query('CLOCKS.A_PERIOD.UNITS=s') panda.query('PGEN1.TRIG=CLOCKS.OUTA') panda.query('PGEN1.CYCLES=1') num_pts = 1001 pos_i = 0 pos_f = 1000 pos = np.linspace(pos_i, pos_f, num=num_pts) pos_cmd = ['%d\n' % p for p in pos] print(pos_cmd) panda.query('PGEN1.TABLE<\n' + ''.join(pos_cmd)) panda.query('PCOMP1.INP=PGEN1.OUT') panda.query('PCOMP1.START=10') step_size = 10 pnum = (pos_f - pos_i) / step_size print('pnum: ', pnum) panda.query('PCOMP1.PRE_START=-1')
def __init__(self, inst, props, *args, **kwargs): TriggerGateController.__init__(self, inst, props, *args, **kwargs) self.pandabox = PandA(self.pandaboxhostname) self.pandabox.connect_to_panda()
class PandaBoxTriggerGateCtrl(TriggerGateController): """ TriggerGateController to control Panda Box. """ organization = "MAX IV" gender = "TriggerGate" model = "Panda Box" ctrl_properties = { "pandaboxhostname": { Type: str, Description: "Pandabox hostname" }, "acq_delay": { Type: float, Description: "Delay before to start acquisition.", DefaultValue: 0.0 }, "trigger_block": { Type: str, Description: "Trigger block on Pandabox", DefaultValue: "PULSE1" }, } @handle_error(msg="Init: Connection fail to panda box") def __init__(self, inst, props, *args, **kwargs): TriggerGateController.__init__(self, inst, props, *args, **kwargs) self.pandabox = PandA(self.pandaboxhostname) self.pandabox.connect_to_panda() @debug_it def StateOne(self, axis): try: status_bit = self.pandabox.numquery("{}.QUEUED?".format( self.trigger_block)) if float(status_bit) != 0: state = tango.DevState.MOVING status = "Triggering" else: state = tango.DevState.ON status = "Standby" return state, status except Exception as e: return tango.DevState.FAULT, "Panda Box is not responding." @debug_it def PreStartOne(self, axis): return True @debug_it @handle_error(msg="StartOne: Could not Trigger the device:") def StartOne(self, axis): self.enableBlocks("ONE") @debug_it @handle_error(msg="AbortOne: Unable to abort PandaBox") def AbortOne(self, axis): self.enableBlocks("ZERO") @debug_it def SynchOne(self, axis, configuration): self.enableBlocks("ZERO") # Configuration group = configuration[0] trigger_count = group[SynchParam.Repeats] # total time for one repeat total = group[SynchParam.Total][SynchDomain.Time] # integration time (as passed from the scan macros) int_time = group[SynchParam.Active][SynchDomain.Time] # Configure Panda self.configure_panda(trigger_count, total, int_time) @debug_it @handle_error(msg="Unable to configure_panda") def configure_panda(self, trigger_count, total, int_time): # set integration time to PULSE block self.pandabox.query("{}.DELAY.UNITS=".format(self.trigger_block) + "s") self.pandabox.query("{}.WIDTH.UNITS=".format(self.trigger_block) + "s") self.pandabox.query("{}.STEP.UNITS=".format(self.trigger_block) + "s") self.pandabox.query("{}.ENABLE.DELAY=".format(self.trigger_block) + "0") self.pandabox.query("{}.TRIG.DELAY=".format(self.trigger_block) + "0") self.pandabox.query("{}.DELAY=".format(self.trigger_block) + str(self.acq_delay)) self.pandabox.query("{}.PULSES=".format(self.trigger_block) + str(trigger_count)) self.pandabox.query("{}.WIDTH=".format(self.trigger_block) + str(int_time)) # step = total = int_time + latency_time # in pandabox = time between successive rising edges self.pandabox.query("{}.STEP=".format(self.trigger_block) + str(total)) @debug_it @handle_error(msg="Error on enableBlocks") def enableBlocks(self, value): self.pandabox.query("{}.ENABLE=".format(self.trigger_block) + value) self.pandabox.query("{}.TRIG=".format(self.trigger_block) + value)
class PandaboxCoTiCtrl(CounterTimerController): MaxDevice = 28 # TODO remove this or check pandabox maximum number of channels ctrl_properties = { 'PandaboxHost': { 'Description': 'Pandabox Host name', 'Type': 'PyTango.DevString' }, 'PcapEnable': { 'Description': 'Hardware trigger config: PCAP.ENABLE', 'Type': 'PyTango.DevString' }, 'PcapGate': { 'Description': 'Hardware trigger config: PCAP.GATE', 'Type': 'PyTango.DevString' }, 'PcapTrig': { 'Description': 'Hardware trigger config: PCAP.TRIG', 'Type': 'PyTango.DevString' }, } ctrl_attributes = {} axis_attributes = { "ChannelName": { Type: str, Description: 'Channel name from pandabox', Memorize: Memorized, Access: DataAccess.ReadWrite, }, "AcquisitionMode": { Type: str, Description: 'Acquisition mode: value, mean, min, max,...', Memorize: Memorized, DefaultValue: 'Value', Access: DataAccess.ReadWrite, }, } def __init__(self, inst, props, *args, **kwargs): """Class initialization.""" CounterTimerController.__init__(self, inst, props, *args, **kwargs) self._log.debug("__init__(%s, %s): Entering...", repr(inst), repr(props)) try: self.pandabox = PandA(self.PandaboxHost) self.pandabox.connect_to_panda() except (NameError, socket.gaierror): raise Exception('Unable to connect to PandABox.') # make sure PCAP block is reset self.pandabox.query('PCAP.ENABLE=ZERO') self.pandabox.query('*PCAP.DISARM=') try: self.data_socket = TCP(self.PandaboxHost, 8889, timeout=3) self.data_socket.open() except: raise Exception('Unable to open PandABox data stream.') # check if data stream starts correctly ack = self.data_socket.write_readline('\n') if "OK" not in ack: raise Exception('Acknowledge to data stream failed!') print "PandaboxCoTiCtrl: data stream listener starts...", ack self.data_buffer = "" self.header_okay_flag = False self.data_end_flag = False self.attributes = {} self.hw_trigger_cfg = {} self.hw_trigger_cfg['enable'] = self.PcapEnable self.hw_trigger_cfg['gate'] = self.PcapGate self.hw_trigger_cfg['trig'] = self.PcapTrig self.channels_order = [] # channels and modes available self._modes = ['Value', 'Diff', 'Min', 'Max', 'Sum', 'Mean'] self._channels = [ 'INENC1.VAL', 'INENC2.VAL', 'INENC3.VAL', 'INENC4.VAL', 'CALC1.OUT', 'CALC2.OUT', 'COUNTER1.OUT', 'COUNTER2.OUT', 'COUNTER3.OUT', 'COUNTER4.OUT', 'COUNTER5.OUT', 'COUNTER6.OUT', 'COUNTER7.OUT', 'COUNTER8.OUT', 'FILTER1.OUT', 'FILTER2.OUT', 'PGEN1.OUT', 'PGEN2.OUT', 'QDEC.OUT', 'FMC_IN.VAL1', 'FMC_IN.VAL2', 'FMC_IN.VAL3', 'FMC_IN.VAL4', 'FMC_IN.VAL5', 'FMC_IN.VAL6', 'FMC_IN.VAL7', 'FMC_IN.VAL8', 'PCAP.SAMPLES' ] self.index = 0 self._repetitions = 0 def AddDevice(self, axis): """Add device to controller.""" self._log.debug("AddDevice(%d): Entering...", axis) self.attributes[axis - 1] = { 'ChannelName': None, 'AcquisitionMode': 'Value' } # count buffer for the continuous scan if axis != 1: self.index = 0 def DeleteDevice(self, axis): """Delete device from the controller.""" self._log.debug("DeleteDevice(%d): Entering...", axis) self.data_socket.close() self.pandabox.disconnect_from_panda() def StateAll(self): """Read state of all axis.""" # self._log.debug("StateAll(): Entering...") state = self.pandabox.query('*PCAP.STATUS?') if "Busy" in state: self.state = State.Moving elif "Idle" in state: self.state = State.On elif "OK" not in state: self.state = State.Fault else: self.state = State.Fault self._log.debug( "StateAll(): %r %r UNKNWON STATE: %s" % (self.state, self.status), state) self.status = state # self._log.debug("StateAll(): %r %r" %(self.state, self.status)) def StateOne(self, axis): """Read state of one axis.""" # self._log.debug("StateOne(%d): Entering...", axis) return self.state, self.status def LoadOne(self, axis, value, repetitions): # self._log.debug("LoadOne(%d, %f, %d): Entering...", axis, value, # repetitions) if axis != 1: raise Exception('The master channel should be the axis 1') self.itime = value self.index = 0 # Set Integration time in s per point self.pandabox.query('PULSE1.WIDTH.UNITS=s') if value < 8e-08: # minimum reliable integration time is # 10 FPGA clock ticks 125 MHz -> 80 ns self._log.debug("The minimum integration time is 80 ns") value = 8e-08 self.pandabox.query('PULSE1.WIDTH=%.9f' % (value)) # Set falling edge capture to have # "gate signal that marks the capture boundaries" # in order to respect the integration time # see PCAP block documentation self.pandabox.query('PCAP.TRIG_EDGE=Falling') if self._synchronization in [ AcqSynch.SoftwareTrigger, AcqSynch.SoftwareGate ]: # self._log.debug("SetCtrlPar(): setting synchronization " # "to SoftwareTrigger") self._repetitions = 1 self.pandabox.query('PULSE1.PULSES=1') # link blocks for software acquisition trig = 'PULSE1.OUT' else: # self._log.debug("SetCtrlPar(): setting synchronization " # "to HardwareTrigger") self._repetitions = repetitions # link blocks for hardware acquisition trig = self.hw_trigger_cfg['trig'] # create links to PCAP block # TODO: separate gated mode? #self.pandabox.query('PCAP.GATE=ONE') self.pandabox.query('PCAP.GATE=' + trig) self.pandabox.query('PCAP.TRIG=' + trig) # reset data buffer and header flag self.header_okay_flag = False self.data_end_flag = False self.data_buffer = '' def PreStartOneCT(self, axis): # self._log.debug("PreStartOneCT(%d): Entering...", axis) if axis != 1: self.index = 0 return True def StartAllCT(self): """ Starting the acquisition is done only if before was called PreStartOneCT for master channel. """ # self._log.debug("StartAllCT(): Entering...") ret = self.pandabox.query('*PCAP.ARM=') if "OK" not in ret: print "Pandabox arm PCAP failed. Disarm and arm again..." ret = self.pandabox.query('*PCAP.DISARM=') ret = self.pandabox.query('*PCAP.ARM=') # start acquisition by enabling PCAP self.pandabox.query('PCAP.ENABLE=ONE') # trig acquisition if self._synchronization in [ AcqSynch.SoftwareTrigger, AcqSynch.SoftwareGate ]: self.pandabox.query( 'PULSE1.ENABLE=ONE') # make sure block is enabled self.pandabox.query('PULSE1.TRIG=ZERO') self.pandabox.query('PULSE1.TRIG=ONE') # else wait for triggers (hardware mode) # THIS PROTECTION HAS TO BE REVIEWED # FAST INTEGRATION TIMES MAY RAISE WRONG EXCEPTIONS # e.g. 10ms ACQTIME -> self.state MAY BE NOT MOVING BECAUSE # FINISHED, NOT FAILED self.StateAll() t0 = time.time() while (self.state != State.Moving): if time.time() - t0 > 3: raise Exception('The HW did not start the acquisition') self.StateAll() return True def ReadAll(self): # self._log.debug("ReadAll(): Entering...") self.data_ready = int(self.pandabox.numquery('*PCAP.CAPTURED?')) #print "Points acquired: %d"%self.data_ready self.new_data = [] #self.index = 0 if self.data_ready == 0: print "Pandabox: No data available yet." self._ParseHeader() return elif self.data_ready <= self._repetitions: if self.data_ready == self._repetitions: print "Pandabox data acquisition has finished, disabling PCAP..." self.pandabox.query('PCAP.ENABLE=ZERO') # it disarms PCAP too try: if not self.data_end_flag: data = self.data_socket.readline() if 'END' not in data: self.data_buffer += data else: print "Pandabox data acquisition ENDs okay!" self.data_end_flag = True except socket.error, e: print "Pandabox: data socket error: ", e self.data_socket.close() data_only = np.genfromtxt(StringIO(self.data_buffer), dtype='float64') # TODO: hw scan mode fails with int time < 100 ms # we have only one line per execution of this method, fix it if data_only.ndim > 1: # crop to get only new data data_only = data_only[self.index:self.data_ready + 1] if self.index <= self.data_ready: # mandatory to avoid extra lines self.new_data = np.ndarray.tolist(data_only.transpose()) if type(self.new_data[0]) != list: one_line_data = [] for value in self.new_data: one_line_data.append([value]) self.new_data = one_line_data time_data = [self.itime] * len(self.new_data[0]) self.new_data.insert(0, time_data) if self._repetitions != 1: self.index += len(time_data)
from pandaboxlib import PandA import numpy as np import time import socket from multiprocessing.pool import ThreadPool host = 'w-kitslab-pandabox-0' panda = PandA(host) panda.connect_to_panda() panda.save_config("test.dat") panda.load_config("test.dat")