def handler(signum, frame): print '\n\nGot CTRL+C, stopping all motors' for pv in (epics.Motor("XF:06BMA-OP{Mono:DCM1-Ax:Bragg}Mtr"), epics.Motor("XF:06BMA-OP{Mono:DCM1-Ax:Per2}Mtr"), epics.Motor("XF:06BMA-OP{Mono:DCM1-Ax:Par2}Mtr")): pv.put('STOP', 1) for pv in (epics.PV("XF:06BMA-OP{Mono:DCM1-Ax:P2}Mtr_KILL_CMD.PROC"), epics.PV("XF:06BMA-OP{Mono:DCM1-Ax:R2}Mtr_KILL_CMD.PROC"), epics.PV("XF:06BMA-OP{Mono:DCM1-Ax:Per2}Mtr_KILL_CMD.PROC"), epics.PV("XF:06BMA-OP{Mono:DCM1-Ax:Par2}Mtr_KILL_CMD.PROC")): pv.put(1) print "" call(['python', '/home/bravel/commissioning/en.py']) exit(0)
def connect(self, pvname=None): '''connect this panel with an EPICS motor PV''' if pvname is None: raise RuntimeError, "lbl_name must not be 'None'" if len(pvname) == 0: raise RuntimeError, "lbl_name must not be ''" if self.pv is not None: self.disconnect() self.motor_pv = pvname.split('.')[0] # keep everything to left of first dot self.controls['NAME'].setText(self.motor_pv) self.pv = epics.Motor(self.motor_pv) # verifies that self.motor_pv has RTYP='motor' callback_dict = { #field: callback function 'HLS': self.onChangeHLS, 'LLS': self.onChangeLLS, } for field, func in callback_dict.iteritems(): self.pv.set_callback(attr=field, callback=func) for field in ['DESC', 'NAME', 'EGU', 'VAL', 'RBV', 'TWV', 'STOP', 'TWF', 'TWR', ]: self.controls[field].ca_connect(pvname + '.' + field)
def __init__(self, busy_pv_name, motor_pv_name, calc_pv_name, t_pv_name, x_pv_name, y_pv_name): self.busy = epics.PV(busy_pv_name) # motor: the independent variable self.motor = epics.Motor(motor_pv_name) # calc: the detector signal self.calc = epics.PV(calc_pv_name) self.calc_proc = epics.PV(calc_pv_name + ".PROC") epics.caput(calc_pv_name + ".CALC", "RNDM") # report random numbers self.calc_proc.put(1) # get a new value # waveforms: the results self.t = epics.PV(t_pv_name) self.x = epics.PV(x_pv_name) self.y = epics.PV(y_pv_name) self.cb_index = None self.processing = False # arbitrary choices for a demo program self.num_steps = min(5, MAX_WAVEFORM_LENGTH) self.step_size = 2.1 self.origin = -1.23456
def SelectMotor(self, motor): " set motor to a named motor PV" if motor is None: return dt = debugtime() epics.poll() try: if self.motor is not None: for i in self.__motor_fields: self.motor.clear_callback(attr=i) except PyDeadObjectError: return dt.add('clear callbacks') if isinstance(motor, six.string_types): self.motor = epics.Motor(motor) dt.add('create motor (name)') elif isinstance(motor, epics.Motor): self.motor = motor dt.add('create motor (motor)') self.motor.get_info() dt.add('get motor info') if self.format is None: self.format = "%%.%if" % self.motor.PREC self.FillPanel() dt.add('fill panel') for attr in self.__motor_fields: self.motor.get_pv(attr).add_callback(self.OnMotorEvent, wid=self.GetId(), field=attr) dt.add('add callbacks %i attrs ' % (len(self.__motor_fields))) if self._size == 'full': self.SetTweak(self.format % self.motor.TWV)
def fnorm_slits(existing_center=True,blades=[61,62]): '''Calibrates the vertical slit opening for JJ slits. Sets both blades to the same value. Maintains dial value, so use of dial coordinates for an absolute reference isn't messed up. Inputs: existing_center: if True, set .VAL to average of existing values. If False, set to 0. blades: numbers of slit blade motors. ''' #Make list of epics.Motor objects of the two blades blade_motors = [epics.Motor('7bmb1:m'+str(x)) for x in blades] #Get current positions and figure out final positions. current_positions = [x.get_position() for x in blade_motors] final_position = 0.0 if existing_center: final_position = sum(current_positions) / float(len(blade_motors)) #For each motor, change the user drive field without changing dial for mot in blade_motors: #Make the offset between user and dial variable if mot.FOFF: mot.FOFF = 0 mot.SET = 1 mot.drive = final_position mot.SET = 0 logging.info("Slit blades normalized.")
def finit_slits(top=57, bottom=58, inside=59, outside=60, prefix='7bmb1:m', size=14): '''Initializes a set of slits that have been powered off. Sets all slit blades to their - limit, zeros the dial, and opens the slits fully. Inputs: top,bottom,inside,outside: numbers of appropriate motors prefix: PV prefix for the motors. size: fully open size on each side of zero. ''' for motor_number in [top, bottom, inside, outside]: #Move the motor to a very negative position motor_obj = epics.Motor(prefix + str(motor_number)) motor_obj.move(-size * 3, wait=True) #Move + 1 mm, then back in small steps to more accurately hit limit motor_obj.move(1.0, relative=True, wait=True) hit_limit = 0 while not hit_limit: hit_limit = motor_obj.move(-0.1, relative=True, wait=True) #Init motor finit_motor(motor_number, prefix=prefix) time.sleep(0.5) #Move the top and inside blades to open the slits if motor_number == top or motor_number == outside: motor_obj.move(0, wait=True) motor_obj.move(size, wait=True)
def SelectMotor(self, motor): " set motor to a named motor PV" if motor is None: return # if self.motor already exists if self.motor is not None: for i in self.__motor_fields: self.motor.clear_callback(attr=i) if isinstance(motor, (str, unicode)): self.motor = epics.Motor(motor) elif isinstance(motor, epics.Motor): self.motor = motor self.motor.get_info() if self.format is None: self.format = "%%.%if" % self.motor.PREC self.FillPanel() for attr in self.__motor_fields: self.motor.get_pv(attr).add_callback(self.OnMotorEvent, wid=self.GetId(), field=attr) if self.is_full: self.SetTweak(self.format % self.motor.TWV)
def SelectMotor(self, motor): " set motor to a named motor PV" if motor is None: return epics.poll() try: if self.motor is not None: for i in self.__motor_fields: self.motor.clear_callback(attr=i) except PyDeadObjectError: return if isinstance(motor, (str, unicode)): self.motor = epics.Motor(motor) elif isinstance(motor, epics.Motor): self.motor = motor self.motor.get_info() if self.format is None: self.format = "%%.%if" % self.motor.PREC self.FillPanel() for attr in self.__motor_fields: self.motor.get_pv(attr).add_callback(self.OnMotorEvent, wid=self.GetId(), field=attr) if self._size == 'full': self.SetTweak(self.format % self.motor.TWV)
class Test(unittest.TestCase): MSTA_BIT_HOMED = 1 << (15 - 1) MSTA_BIT_MINUS_LS = 1 << (14 - 1) MSTA_BIT_PLUS_LS = 1 << (3 - 1) m1 = epics.Motor(os.getenv("TESTEDMOTORAXIS")) middle_dialPosition = round((m1.DLLM + m1.DHLM) / 2) range_postion = m1.DHLM - m1.DLLM homing_velocity = m1.HVEL jogging_velocity = m1.JVEL moving_velocity = m1.VELO acceleration = m1.ACCL saved_high_limit = m1.get('DHLM') saved_low_limit = m1.get('DLLM') print "m1.DLLM=%d m1.DHLM=%d middle_dialPosition=%d" % ( m1.DLLM, m1.DHLM, middle_dialPosition) def setUp(self): print 'set up' mymiddle_dialPosition = int((self.m1.DLLM + self.m1.DHLM) / 2) print 'self.m1.DLLM=%f self.m1.DHLM=%f self.middle_dialPosition=%f' % ( self.m1.DLLM, self.m1.DHLM, self.middle_dialPosition) print 'self.m1.DLLM=%f self.m1.DHLM=%f mymiddle_dialPosition=%f' % ( self.m1.get('DLLM'), self.m1.get('DHLM'), mymiddle_dialPosition) def tearDown(self): print 'clean up' self.m1.put('STOP', 1) if self.saved_high_limit > self.saved_low_limit: self.m1.put('DHLM', self.saved_high_limit) self.m1.put('DLLM', self.saved_low_limit) # Home the motor def test_TC_100(self): tc_no = "TC-100" print '%s Home the motor' % tc_no msta = int(self.m1.get('MSTA')) if (msta & self.MSTA_BIT_PLUS_LS): self.m1.put('HOMR', 1) else: self.m1.put('HOMF', 1) time_to_wait = 30 if self.range_postion > 0 and self.homing_velocity > 0: time_to_wait = 1 + self.range_postion / self.homing_velocity + 2 * self.acceleration # Homing velocity not implemented, wait longer time_to_wait = 180 done = waitForStartAndDone(self.m1, tc_no, time_to_wait) msta = int(self.m1.get('MSTA')) self.assertEqual(True, done, 'done = True') self.assertNotEqual(0, msta & self.MSTA_BIT_HOMED, 'MSTA.homed (Axis has been homed)')
def __init__(self, motor='7bmb1:aero:m1', asynRec='7bmb1:PSOFly1:cmdWriteRead', axis='Z', PSOInput=3, encoder_multiply=1e5): self.motor = epics.Motor(motor) self.asynRec = epics.PV(asynRec + '.BOUT') self.axis = axis self.PSOInput = PSOInput self.encoder_multiply = encoder_multiply
def test1(motorname, start, step, npts): "simple test: stepping with wait" m1 = epics.Motor(motorname) m1.drive = start m1.tweak_val = step m1.move(start, wait=True) for i in range(npts): m1.tweak(dir='forward', wait=True) print 'Motor: ', m1.description, m1.drive, ' Currently at ', m1.readback time.sleep(0.01)
def testDial(motorname, start, step, npts, offset=1.0): "test using dial coordinates" m1 = epics.Motor(motorname) m1.offset = offset m1.tweak_val = step m1.move(start, wait=True, dial=True) print('Motor position ', motorname, m1.description) user = m1.get_position() dial = m1.get_position(dial=True) raw = m1.get_position(raw=True) print(' User/Dial/Raw = %f / %f / %f' % (user, dial, raw))
def motor(self, alias): self.pvname = MOTORDATA[alias]['PV'] self.pv = epics.Motor(MOTORDATA[alias]['PV']) self.description = MOTORDATA[alias]['desc'] self.alias = alias if alias not in MOTORDATA.keys(): return False if 'xafs' in alias: thing = MOTORDATA[alias]['PV'].replace('Mtr', 'Cmd:Kill-Cmd') self.kill_pv = epics.PV(thing) self.enable_pv = None self.home_pv = None else: self.kill_pv = epics.PV(MOTORDATA[alias]['PV'] + '_KILL_CMD.PROC') self.enable_pv = epics.PV(MOTORDATA[alias]['PV'] + "_ENA_CMD.PROC") self.home_pv = None # epics.PV(MOTORDATA[alias]['PV']+"_HOME_CMD_PROC") if 'lateral' in alias: self.invacuum = 1
def __init__(self, prefix, cam_number, linear_pot_format='LP{}ADCM'): info = self.axis_info[cam_number] self.prefix = prefix self.cam_number = cam_number self.info = info try: self.motor = epics.Motor(self.prefix + info.motor) except TimeoutError: raise TimeoutError('Failed to connect to: {}' ''.format(self.prefix + info.motor)) self.stop_go_pv = self.motor.PV('SPMG') self.stop_pv = self.motor.PV('STOP') self.calibration_set_pv = self.motor.PV('SET') self.setpoint_pv = self.motor.PV('VAL') self.llm_pv = self.motor.PV('LLM') self.hlm_pv = self.motor.PV('HLM') self.readback_pv = self.motor.PV('RBV') self.velocity_pv = self.motor.PV('VELO') self.max_velocity_pv = self.motor.PV('VMAX') self.torque_enable_pv = self.motor.PV('CNEN') self.rotary_pot_pv = PV(self.prefix + info.rotary_pot_adc) self.calibrated_readback_pv = PV(self.prefix + info.rotary_pot_calibrated) self.rotary_pot_gain_pv = PV(self.prefix + info.rotary_pot_gain) self.rotary_pot_offset_pv = PV(self.prefix + info.rotary_pot_offset) self.linear_pot_pvs = [ PV(self.prefix + linear_pot_format.format(pot_id)) for pot_id in info.linear_pots ] self.all_pvs = [self.stop_go_pv, self.stop_pv, self.setpoint_pv, self.llm_pv, self.hlm_pv, self.readback_pv, self.velocity_pv, self.max_velocity_pv, self.rotary_pot_pv, self.torque_enable_pv, self.calibration_set_pv, self.calibrated_readback_pv, ] + self.linear_pot_pvs for pv in self.all_pvs: pv.wait_for_connection()
def __init__(self, busy_pv_name, motor_pv_name, calc_pv_name): self.busy = epics.PV(busy_pv_name) # motor: the independent variable self.motor = epics.Motor(motor_pv_name) # calc: the detector signal self.calc = epics.PV(calc_pv_name) self.calc_proc = epics.PV(calc_pv_name + ".PROC") epics.caput(calc_pv_name + ".CALC", "RNDM") # report random numbers self.calc_proc.put(1) # get a new value self.cb_index = None self.processing = False # arbitrary choices for a demo program self.num_steps = 5 self.step_size = 2.1 self.origin = 0
def finit_motor(motor_num, prefix='7bmb1:m', new_value=0, use_dial=True): '''Use to set the dial coordinate of a motor to zero. Specifically, do this without changing the user/dial offset, so this is suitable for using a limit switch as a home. Suitable for stepper motor stages. Inputs: motor_num: the number of the motor prefix: everything before the motor number to make a valid PV (default: 7bmb1:m) new_value: new value of the dial coordinate (default: 0) use_dial: do this in dial (default, True) or user coordinates ''' motor_obj = epics.Motor(prefix + str(motor_num)) #Freeze the offset motor_obj.freeze_offset = 1 time.sleep(0.2) #Go into set mode motor_obj.set_position(new_value, dial=use_dial) time.sleep(0.2) #Unfreeze the offset motor_obj.freeze_offset = 0 time.sleep(0.2)
def connect(self, iocPrefix=None, axisName=None): '''connect this panel with an EPICS motor PV''' if iocPrefix is None: raise RuntimeError("iocPrefix must not be 'None'") if axisName is None: raise RuntimeError("axisName must not be 'None'") self.setPvNames(iocPrefix, axisName) if len(iocPrefix) == 0 or len(axisName) == 0: raise RuntimeError("iocPrefix or axisName must not be ''") if self.motorPv is not None: self.disconnect() self.controls['NAME'].setText(self.motorPvName) self.motorPv = epics.Motor( self.motorPvName) # verifies that self.motor_pv has RTYP='motor' callback_dict = { #field: callback function 'DESC': self.onChangeDESC, 'EGU': self.onChangeEGU, 'RBV': self.onChangeRBV, 'VAL': self.onChangeVAL, 'VELO': self.onChangeVELO, 'TWV': self.onChangeTWV, 'DMOV': self.onChangeDMOV, 'HLS': self.onChangeHLS, 'LLS': self.onChangeLLS, 'CNEN': self.onChangeCNEN, 'JOGR': self.onChangeJOGR, 'JOGF': self.onChangeJOGF, 'JVEL': self.onChangeJVEL, 'HOMR': self.onChangeHOMR, 'HOMF': self.onChangeHOMF, 'MSTA': self.onChangeMSTA, } for field, func in callback_dict.items(): self.motorPv.set_callback(attr=field, callback=func) self.controls['DESC'].setText(self.motorPv.description) self.controls['EGU'].setText(self.motorPv.units) # display initial values self.onChangeRBV(value=self.motorPv.get('RBV')) self.onChangeVAL(value=self.motorPv.get('VAL')) self.onChangeTWV(value=self.motorPv.get('TWV')) self.onChangeDMOV(value=self.motorPv.get('DMOV')) self.onChangeCNEN(value=self.motorPv.get('CNEN')) self.onChangeJOGR(value=self.motorPv.get('JOGR')) self.onChangeJOGF(value=self.motorPv.get('JOGF')) self.onChangeHOMR(value=self.motorPv.get('HOMR')) self.onChangeHOMF(value=self.motorPv.get('HOMF')) self.onChangeMSTA(value=self.motorPv.get('MSTA')) self.onChangeVELO(value=self.motorPv.get('VELO')) self.onChangeJVEL(value=self.motorPv.get('JVEL')) # additional records self.axisErrorResetPv = epics.PV(self.axisErrorResetPvName) self.cntrlErrorIdPv = epics.PV(self.cntrlErrorIdPvName) self.cntrlErrorIdPv.add_callback(self.onChangeCntrlErrorIdPv) self.cntrlErrorResetPv = epics.PV(self.cntrlErrorResetPvName) self.cntrlErrorMsgPv = epics.PV(self.cntrlErrorMsgPvName) self.cntrlCmdPv = epics.PV(self.cntrlCmdPvName) self.cntrlCmdPv.add_callback(self.onChangeCntrlCmdPv) if self.controls['ArrayStat'] is not None: self.controls['ArrayStat'].connect(self.axisDiagPvName)
def fmove_to_PIN(): detector_x = epics.Motor('7bmb1:m5') detector_y = epics.Motor('7bmb1:m6') detector_x.move(-49,relative=True) detector_y.move(2.7,relative=True)
def fmove_to_imaging(): detector_x = epics.Motor('7bmb1:m5') detector_y = epics.Motor('7bmb1:m6') detector_x.move(49,relative=True) detector_y.move(-2.7,relative=True)
def tracking(params, algorithm='pin', repeat=1): #### ENABLE TAB COMPLETION readline.parse_and_bind('tab: complete') ################################################# pixel_size = 1.172 ## um / pixel slit_center_x = 1000 slit_center_y = 600 ################################################# ### MOTOR SETTINGS ################################################# mtr_samXE = PyEpics.Motor('1ide1:m34') mtr_samYE = PyEpics.Motor('1ide1:m35') mtr_samZE = PyEpics.Motor('1ide1:m36') mtr_samTh = PyEpics.Motor('1ide1:m86') mtr_samChi = PyEpics.Motor('1ide1:m87') mtr_samOme = PyEpics.Motor('1ide:m9') mtr_aeroXE = PyEpics.Motor('1ide1:m101') mtr_aeroZE = PyEpics.Motor('1ide1:m102') ################################################# pname = '/home/beams/S1IDUSER/mnt/s1c/mli_nov19/tomo' for i in range(repeat): ################################################# ### ALIGN ROTATION AXIS TO THE HS ################################################# ### MOVE STAGE TO 0 mtr_samOme.move(0, wait=True) ### TAKE AN IMAGE AT OME 0 PyEpics.caput('1idPG1:cam1:Acquire', 1) time.sleep(3) fname = PyEpics.caget('1idPG1:TIFF1:FileName_RBV', 'str') + "_%06d" % ( PyEpics.caget('1idPG1:TIFF1:FileNumber_RBV') - 1) + '.tif' pfname = os.path.join(pname, fname) print(pfname) align0 = Alignment(pfname) x0, y0 = align0.compute_center(algorithm, params) print(f"pin x,y position when omega is 0 : (x = {x0}, y = {y0}") if (x0 == -1) or (y0 == -1): print("Alignment failed at zero degress") break ### MOVE STAGE TO 180 mtr_samOme.move(180, wait=True) ### TAKE AN IMAGE AT OME 180 PyEpics.caput('1idPG1:cam1:Acquire', 1) time.sleep(3) fname = PyEpics.caget('1idPG1:TIFF1:FileName_RBV', 'str') + "_%06d" % ( PyEpics.caget('1idPG1:TIFF1:FileNumber_RBV') - 1) + '.tif' pfname = os.path.join(pname, fname) align180 = Alignment(pfname) x180, y180 = align180.compute_center(algorithm, params) if (x180 == -1) or (y180 == -1): print("Alignment failed at 180 degrees") break print(f"pin x,y position when omega is 180 : (X = {x180}, y = {180})") ### COMPUTE MOTIONS TO MAKE mid_x = (x180 + x0) / 2 half_delta_x = (x180 - x0) / 2 print(mid_x) print(half_delta_x) ### NEED TO CHECK / FIGURE OUT THE SIGNS ON THESE aeroXE_motion = ((mid_x - slit_center_x) * pixel_size) / 1000 samXE_motion = -(half_delta_x * pixel_size) / 1000 print('motions to execute') print(aeroXE_motion) print(samXE_motion) mtr_aeroXE.move(aeroXE_motion, relative=True, wait=True) mtr_samXE.move(samXE_motion, relative=True, wait=True)
class Test(unittest.TestCase): MSTA_BIT_HOMED = 1 << (15 - 1) MSTA_BIT_MINUS_LS = 1 << (14 - 1) MSTA_BIT_MOVING = 1 << (11 - 1) MSTA_BIT_PROBLEM = 1 << (10 - 1) MSTA_BIT_FOLLOW_ERR = 1 << (7 - 1) MSTA_BIT_PLUS_LS = 1 << (3 - 1) motm1 = epics.Motor(os.getenv("TESTEDMOTORAXIS")) pvm1 = epics.PV(os.getenv("TESTEDMOTORAXIS")) pv_Err = epics.PV(os.getenv("TESTEDMOTORAXIS") + "-Err") pv_nErrorId = epics.PV(os.getenv("TESTEDMOTORAXIS") + "-ErrId") pv_nErrRst = epics.PV(os.getenv("TESTEDMOTORAXIS") + "-ErrRst") pv_MSTA = epics.PV(os.getenv("TESTEDMOTORAXIS") + ".MSTA") saved_DHLM = motm1.get('DHLM') saved_DLLM = motm1.get('DLLM') saved_CNEN = motm1.get('CNEN') def setUp(self): print 'set up' def tearDown(self): print 'clean up' self.motm1.put('CNEN', self.saved_CNEN) # 10% dialPosition def test_TC_201(self): tc_no = "TC-201-10-percent-dialPosition" print '%s' % tc_no dval = (self.saved_DHLM + 9 * self.saved_DLLM) / 10 self.motm1.put('CNEN', 1) ret = self.motm1.move(dval, dial=True, wait=True) assert (ret == 0) drbv = self.motm1.get_position(readback=True, dial=True) print '%s dval=%f drbv=%f' % (tc_no, dval, drbv) assert calcAlmostEqual(self.motm1, tc_no, dval, drbv, 2) # Jog, wait for start, power off, check error, reset error def test_TC_202(self): tc_no = "TC-202-JOG-_CNEN" self.motm1.put('CNEN', 0) self.motm1.put('JOGF', 1) ret = waitForStart(self.motm1, tc_no, 2.0) # dummy wait ret = waitForStop(self.motm1, tc_no, 2.0) self.assertEqual(True, ret, 'waitForStop return True') msta = int(self.motm1.get('MSTA')) print '%s Error msta=%x' % (tc_no, msta) self.assertNotEqual(0, msta & self.MSTA_BIT_PROBLEM, 'Error MSTA.Problem should be set)') self.assertEqual(0, msta & self.MSTA_BIT_FOLLOW_ERR, 'Error MSTA.Following Error should not be set)') self.assertEqual(0, msta & self.MSTA_BIT_MOVING, 'Error MSTA.Moving)') bError = self.pv_Err.get(use_monitor=False) nErrorId = self.pv_nErrorId.get(use_monitor=False) print '%s Error bError=%d nErrorId=%d' % (tc_no, bError, nErrorId) self.assertNotEqual(0, bError, 'bError') self.assertNotEqual(0, nErrorId, 'nErrorId') self.pv_nErrRst.put(1) msta = int(self.pv_MSTA.get(use_monitor=False)) bError = self.pv_Err.get(use_monitor=False) nErrorId = self.pv_nErrorId.get(use_monitor=False) print '%s Clean MSTA_BIT_PROBLEM=%x msta=%x bError=%d nErrorId=%d' % ( tc_no, self.MSTA_BIT_PROBLEM, msta, bError, nErrorId) counter = 7 while (msta & self.MSTA_BIT_MOVING or bError != 0 or nErrorId != 0): time.sleep(polltime) print '%s sleep counter = %d' % (tc_no, counter) msta = int(self.pv_MSTA.get(use_monitor=False)) bError = self.pv_Err.get(use_monitor=False) nErrorId = self.pv_nErrorId.get(use_monitor=False) counter = counter - 1 if counter == 0: break self.assertEqual(0, msta & self.MSTA_BIT_MOVING, 'Clean MSTA.Moving)') self.assertEqual(0, bError, 'bError') self.assertEqual(0, nErrorId, 'nErrorId')
def ftomo_fly_scan_wb(trigger_busy='7bmb1:busy5', trigger_PVs={'7bm_pg1:cam1:Acquire': 1}, cam_root='7bm_pg1:'): '''Script to perform actions for WB tomography fly scan at 7-BM. Script waits for trigger_busy to be triggered. The scan then programs the stage for PSO output, checks that motors are within limits, takes bright and dark fields, then performs the actual tomography scan. This script places the data into a properly formatted DataExchange file with the proper meta data. The script also monitors the trigger_busy during the scan and aborts if it is manually set to zero. The script monitors the scan and aborts if the motion stops before acquisition is complete, indicating that the scan has hung. This script does one scan. This requires a daemon process if one does not want to explicitly call it for every tomography scan. ''' #Input EPICS PVs for scan parameters speed_PV = epics.PV('7bmb1:ExpInfo:SampleRotationSpeed') num_proj_PV = epics.PV('7bmb1:ExpInfo:NumProjections') start_PV = epics.PV('7bmb1:ExpInfo:SampleRotationStart') end_PV = epics.PV('7bmb1:ExpInfo:SampleRotationEnd') retrace_PV = epics.PV('7bmb1:ExpInfo:RetraceSpeed') #Input EPICS PVs for bright/dark image parameters bright_x_pos = epics.PV('7bmb1:ExpInfo:SampleOutPositionX') bright_y_pos = epics.PV('7bmb1:ExpInfo:SampleOutPositionY') bd_imgnum = epics.PV('7bmb1:ExpInfo:NumWhiteImages') bright_exp = epics.PV('7bmb1:ExpInfo:BrightExposureTime') #Important variables trigger_busy_PV = epics.PV(trigger_busy) HDF_capture_PV = epics.PV(cam_root + 'HDF1:Capture') num_images_PV = epics.PV(cam_root + 'cam1:NumImages') exposure_time_PV = epics.PV(cam_root + 'cam1:AcquireTime') sample_x_motor = epics.Motor('7bmb1:aero:m2') sample_y_motor = epics.Motor('7bmb1:aero:m1') #Make PV objects from the trigger PVs trig_pv_dict = {} for key in trigger_PVs.keys(): trig_pv_dict[key] = epics.PV(key) counter = 0 #Have a flag variable to show if scan completed successfully. successful_scan = False try: #Loop to check for starting a scan. while True: #If we are starting a scan ... if trigger_busy_PV.value == 1: print("Triggered to take a tomo scan now.") #Set the retrace speed on the Aerotech driver Aerotech_Theta.default_speed = float(retrace_PV.get()) #Clean up the PSO programming in case things are messed up. Aerotech_Theta.fcleanup_PSO() #Set up the object with fly scan positions fly_scan_pos = FlyScanPositions(driver=Aerotech_Theta, speed=speed_PV.value, start=start_PV.value, end=end_PV.value, num_points=num_proj_PV.value) fly_scan_pos.fcompute_positions_tomo() #Move to the requested start position now Aerotech_Theta.motor.move(fly_scan_pos.req_start) #Check that all positions will be within the motor limits. If not, throw an exception if not (sample_x_motor.within_limits(bright_x_pos.value) and sample_y_motor.within_limits(bright_y_pos.value)): print( 'Bright position not within motor limits. Check motor limits.' ) raise ValueError if not Aerotech_Theta.motor.within_limits( fly_scan_pos.motor_start): print( 'Rotation start position not within motor limits. Check motor limits.' ) raise ValueError if not Aerotech_Theta.motor.within_limits( fly_scan_pos.motor_end): print( 'Rotation end position not within motor limits. Check motor limits.' ) raise ValueError #close the shutters peu.fclose_A_shutter() print("Grabbing bright and dark fields") #Stop the HDF5 capture if it is active. Otherwise, IOC will crash if HDF_capture_PV.get() == 1: HDF_capture_PV.put(0, wait=True) #Check if we have any array data. If not, get it. if int(epics.caget(cam_root + 'HDF1:ArraySize0_RBV')) == 0: #Set outselves to internal trigger, single trigger. epics.caput(cam_root + 'cam1:TriggerMode', 0, wait=True) epics.caput(cam_root + 'cam1:ImageMode', 0, wait=True) epics.caput(cam_root + 'cam1:Acquire', 1, wait=True) #Set up the HDF plugin to stream images to HDF5. bgkd_ims = int(bd_imgnum.value) total_imgs = int(bgkd_ims * 2 + fly_scan_pos.PSO_positions.shape[0]) epics.caput(cam_root + 'HDF1:NumCapture', total_imgs, wait=True) epics.caput(cam_root + 'HDF1:ExtraDimSizeN', total_imgs, wait=True) epics.caput(cam_root + 'HDF1:FileWriteMode', 2, wait=True) epics.caput(cam_root + 'HDF1:AutoSave', 1, wait=True) #set saving of dark field images num_images_PV.put(bgkd_ims, wait=True) #Compute the proper frame rate for this exposure time data_dark_exp_time = exposure_time_PV.get() max_framerate = math.floor(1.0 / data_dark_exp_time / 2.0) epics.caput(cam_root + 'cam1:FrameRateValAbs', max_framerate, wait=True) #write data to /exchange/data_dark in HDF5 file by passing 1 flag to 'FrameType' epics.caput(cam_root + 'cam1:FrameType', 1) time.sleep(0.25) #Make sure camera is on internal trigger mode, multiple exposure epics.caput(cam_root + 'cam1:ImageMode', 1, wait=True) epics.caput(cam_root + 'cam1:TriggerMode', 0, wait=True) #Start the HDF capture process. This must run until the file is full. epics.caput(cam_root + 'HDF1:Capture', 1, wait=False) time.sleep(0.5) #Start dark frame image acquisition epics.caput(cam_root + 'cam1:Acquire', 1, wait=True) time.sleep(0.5) #Capture bright fields #Make sure that the retrace is done. while not Aerotech_Theta.motor.done_moving: time.sleep(0.1) peu.fopen_A_shutter() #Move to correct x and y position origx = sample_x_motor.drive origy = sample_y_motor.drive sample_x_motor.move(bright_x_pos.get(), wait=True) sample_y_motor.move(bright_y_pos.get(), wait=True) time.sleep(0.25) #Set the desired exposure time exposure_time_PV.put(bright_exp.get()) #write data to /exchange/data_white in HDF5 file by passing 2 flag to 'FrameType' epics.caput(cam_root + 'cam1:FrameType', 2) time.sleep(0.25) epics.caput(cam_root + 'cam1:Acquire', 1, wait=True) print("Bright and dark fields done. Starting Scan...") #move back to previous motor position & exposure time. sample_x_motor.move(origx, wait=True) sample_y_motor.move(origy, wait=True) #Set up the number of images and put us in multiple exposure mode num_images_PV.put(num_proj_PV.value, wait=True) #Set up the HDF plugin to stream images to HDF5. #write data to /exchange/data in HDF5 file by passing 0 flag to 'FrameType' epics.caput(cam_root + 'cam1:FrameType', 0) #Make sure camera is on external trigger mode, multiple exposures epics.caput(cam_root + 'cam1:ImageMode', 1, wait=True) epics.caput(cam_root + 'cam1:TriggerMode', 3, wait=True) time.sleep(0.1) exposure_time_PV.put(data_dark_exp_time, wait=True) time.sleep(0.2) #Program the PSO for this motion fly_scan_pos.fprogram_PSO() #Compute how long it should take to save data set total_time = (end_PV.value - start_PV.value) / speed_PV.value print("Scan should take {:5.2f} s.".format(total_time)) #Trigger the PVs we want to trigger for key, value in trigger_PVs.items(): trig_pv_dict[key].put(value) time.sleep(1.0) #Trigger the stage to move Aerotech_Theta.motor.move(fly_scan_pos.motor_end) start_time = time.time() #Now, start looking at whether we've finished or have aborted. counter = 0 time.sleep(1.0) while (time.time() - start_time) < total_time * 1.5 + 3.0: counter += 1 if trigger_busy_PV.value == 0: print("Aborting scan.") #Stop the image acquisition peu.fclose_A_shutter() epics.caput(cam_root + 'cam1:Acquire', 0, wait=True) epics.caput(cam_root + 'HDF1:Capture', 0, wait=True) #Stop the motor Aerotech_Theta.motor.put('stop_go', 0, wait=True) Aerotech_Theta.motor.move( Aerotech_Theta.motor.get_position(readback=True)) time.sleep(1.0) Aerotech_Theta.motor.put('stop_go', 3, wait=True) #Break so we can clean up break #See if all of the triggered PVs are done. If so, success! trigger_pv_value_sum = 0 for key in trigger_PVs.keys(): trigger_pv_value_sum += trig_pv_dict[key].value if not trigger_pv_value_sum: print("Finished all triggers. Successful scan!") successful_scan = True break else: #If the rotation stage is done moving and we're here, the scan has hung. if not Aerotech_Theta.motor.get('MOVN'): print( 'Rotation stage is done but the camera is still triggering. Abort.' ) trigger_busy_PV.put(0, wait=True) time.sleep(0.5) continue if counter % 5 == 0: print("Elapsed time = {:5.2f} s.".format( time.time() - start_time)) time.sleep(0.5) else: print("Never finished images in time. Error!") #Stop the image acquisition epics.caput(cam_root + 'cam1:Acquire', 0, wait=True) epics.caput(cam_root + 'HDF1:Capture', 0, wait=True) #Trigger the cleanup print("Cleaning up the scan.") Aerotech_Theta.fcleanup_PSO() time.sleep(0.5) trigger_busy_PV.put('Done', wait=True) time.sleep(0.5) #Break out of the while loop: we are done break else: time.sleep(0.05) finally: peu.fclose_A_shutter() trigger_busy_PV.put('Done') return successful_scan
class Test(unittest.TestCase): MSTA_BIT_HOMED = 1 << (15 - 1) MSTA_BIT_MINUS_LS = 1 << (14 - 1) MSTA_BIT_PROBLEM = 1 << (10 - 1) MSTA_BIT_PLUS_LS = 1 << (3 - 1) m1 = epics.Motor(os.getenv("TESTEDMOTORAXIS")) per10_dialPosition = round((9 * m1.DLLM + 1 * m1.DHLM) / 10) range_postion = m1.DHLM - m1.DLLM homing_velocity = m1.HVEL jogging_velocity = m1.JVEL moving_velocity = m1.VELO acceleration = m1.ACCL msta = int(m1.MSTA) print "m1.DLLM=%d m1.DHLM=%d per10_dialPosition=%d" % (m1.DLLM, m1.DHLM, per10_dialPosition) def setUp(self): print 'set up' print 'self.m1.DLLM=%f self.m1.DHLM=%f self.per10_dialPosition=%f' % ( self.m1.DLLM, self.m1.DHLM, self.per10_dialPosition) def tearDown(self): print 'clean up' self.m1.put('STOP', 1) # Assert if motor is not homed def test_TC_1311(self): tc_no = "TC-1311" if not (self.msta & self.MSTA_BIT_HOMED): self.assertNotEqual(0, self.msta & self.MSTA_BIT_HOMED, 'MSTA.homed (Axis has been homed)') # per10 dialPosition def test_TC_1312(self): if (self.msta & self.MSTA_BIT_HOMED): tc_no = "TC-1312-30-percent-dialPosition" print '%s' % tc_no destination = self.per10_dialPosition moveDialPosition(self.m1, tc_no, destination, self.moving_velocity, self.acceleration) dialPosition = self.m1.get_position(readback=True, dial=True) print '%s postion=%f per10_dialPosition=%f' % ( tc_no, dialPosition, self.per10_dialPosition) assert calcAlmostEqual(self.m1, tc_no, destination, dialPosition, 2) # Low soft limit JOGR def test_TC_1313(self): if (self.msta & self.MSTA_BIT_HOMED): tc_no = "TC-1313-low-soft-limit JOGR" print '%s' % tc_no jogDirection(self.m1, tc_no, 0, self.jogging_velocity, self.acceleration) lvio = int(self.m1.get('LVIO')) msta = int(self.m1.get('MSTA')) self.assertEqual(0, msta & self.MSTA_BIT_PROBLEM, 'No Error MSTA.Problem JOGR') self.assertEqual(0, msta & self.MSTA_BIT_MINUS_LS, 'Minus hard limit not reached JOGR') self.assertEqual(0, msta & self.MSTA_BIT_PLUS_LS, 'Plus hard limit not reached JOGR') self.assertEqual(1, lvio, 'LVIO == 1 JOGR') self.m1.put('JOGF', 0) # per10 dialPosition def test_TC_1314(self): if (self.msta & self.MSTA_BIT_HOMED): tc_no = "TC-1314-30-percent-dialPosition" print '%s' % tc_no destination = self.per10_dialPosition moveDialPosition(self.m1, tc_no, destination, self.moving_velocity, self.acceleration) dialPosition = self.m1.get_position(readback=True, dial=True) print '%s postion=%f per10_dialPosition=%f' % ( tc_no, dialPosition, self.per10_dialPosition) assert calcAlmostEqual(self.m1, tc_no, destination, dialPosition, 2) # Low soft limit JOGF + DIR def test_TC_1315(self): if (self.msta & self.MSTA_BIT_HOMED): tc_no = "TC-1315-low-soft-limit JOGF DIR" print '%s' % tc_no saved_DIR = self.m1.get('DIR') self.m1.put('DIR', 1) jogDirection(self.m1, tc_no, 1, self.jogging_velocity, self.acceleration) lvio = int(self.m1.get('LVIO')) msta = int(self.m1.get('MSTA')) self.assertEqual(0, msta & self.MSTA_BIT_PROBLEM, 'No Error MSTA.Problem JOGF DIR') self.assertEqual(0, msta & self.MSTA_BIT_MINUS_LS, 'Minus hard limit not reached JOGF DIR') self.assertEqual(0, msta & self.MSTA_BIT_PLUS_LS, 'Plus hard limit not reached JOGR DIR') ### commit 4efe15e76cefdc060e14dbc3 needed self.assertEqual(1, lvio, 'LVIO == 1 JOGF') self.m1.put('JOGF', 0) self.m1.put('DIR', saved_DIR)
import time sys.path += ['.'] import epics import SampleStage from StageConf import StageConfig epics.ca.DEFAULT_CONNECTION_TIMEOUT = 2.0 epics.ca.initialize_libca() ## read default config file to pre-connect epics motors ## before the GUI is really going. ## this speeds up loading and can avoid unconnected PVs # print SampleStage.CONFIG_DIR configfile = os.path.join(SampleStage.CONFIG_DIR, 'SampleStage.ini') # configfile = 'SampleStage.ini' cnf = StageConfig(configfile) stages = [] #print 'Connecting' for pvname in cnf.config['stages']: stages.append(epics.Motor(name=pvname)) ## fetch motor fields for the side-effect of actually ## making the network connection [(s.DESC, s.VAL) for s in stages] SampleStage.StageApp().MainLoop()
import epics import time camera_prefix = '7bm_pg4' rot_motor = epics.Motor('7bmb1:aero:m3') epics.caput('7bma1:rShtrA:Open', 1) time.sleep(3.0) epics.caput(camera_prefix + ':cam1:Acquire', 1) time.sleep(0.3) epics.move(180, relative=True) epics.caput(camera_prefix + ':cam1:Acquire', 1) time.sleep(0.5) epics.caput('7bma1:rShtrA:Close', 1) epics.move(-180, relative=True)
import sys import epics import epics.devices import time import datetime import numpy as np import os import math import socket from matplotlib import pyplot # initalize logging object logger = Logger() # Define motors fomx = epics.Motor('26idcnpi:m10.') fomy = epics.Motor('26idcnpi:m11.') fomz = epics.Motor('26idcnpi:m12.') #samx = epics.Motor('26idcnpi:m16.') samy = epics.Motor('26idcnpi:m17.') #samz = epics.Motor('26idcnpi:m18.') samth = epics.Motor('atto2:PIC867:1:m1.') osax = epics.Motor('26idcnpi:m13.') osay = epics.Motor('26idcnpi:m14.') osaz = epics.Motor('26idcnpi:m15.') condx = epics.Motor('26idcnpi:m5.') #attox = epics.Motor('atto2:m3.') #attoz = epics.Motor('atto2:m4.') #attoz = epics.Motor('26idcNES:sm27.') attox = epics.Motor('atto2:m4.') attoz = epics.Motor('atto2:m3.')
"VBAS", "LOW", "VELO", "LRLV", "VERS", "LRVL", "VMAX", "LSPG", "ATHM", "LSV", "DCOF", ) collate = dict() for m in motors: pv = epics.Motor(m) print "Querying %s:\t%s" % (m, pv.DESC) this = dict() for f in fields: this[f] = pv.get(f) collate[m] = this file = open("pvsave.json", "w") file.write( json.dumps(collate, sort_keys=True, indent=4, separators=(',', ': '))) file.close() print "you can query the json file like so:" print " cat pvsave.json | jq '.[\"XF:06BM-BI{BCT-Ax:Y}Mtr\"]"
class Test(unittest.TestCase): MSTA_BIT_HOMED = 1 << (15 - 1) MSTA_BIT_MINUS_LS = 1 << (14 - 1) MSTA_BIT_MOVING = 1 << (11 - 1) MSTA_BIT_PROBLEM = 1 << (10 - 1) MSTA_BIT_FOLLOW_ERR = 1 << (7 - 1) MSTA_BIT_PLUS_LS = 1 << (3 - 1) motm1 = epics.Motor(os.getenv("TESTEDMOTORAXIS")) pvm1 = epics.PV(os.getenv("TESTEDMOTORAXIS")) pv_Err = epics.PV(os.getenv("TESTEDMOTORAXIS") + "-Err") pv_nErrorId = epics.PV(os.getenv("TESTEDMOTORAXIS") + "-ErrId") pv_nErrRst = epics.PV(os.getenv("TESTEDMOTORAXIS") + "-ErrRst") pv_MSTA = epics.PV(os.getenv("TESTEDMOTORAXIS") + ".MSTA") pv_VELO = epics.PV(os.getenv("TESTEDMOTORAXIS") + ".VELO") saved_HLM = motm1.get('HLM') saved_LLM = motm1.get('LLM') def setUp(self): print 'set up' def tearDown(self): print 'clean up' # 10% Position def test_TC_202(self): tc_no = "TC-202-10-percent-Position" print '%s' % tc_no val = (self.saved_HLM + 9 * self.saved_LLM) / 10 ret = self.motm1.move(dval, dial=False, wait=True) assert (ret == 0) rbv = self.motm1.get_position(readback=True, dial=False) print '%s val=%f rbv=%f' % (tc_no, val, rbv) assert calcAlmostEqual(self.motm1, tc_no, val, rbv, 2) # Try to move to 90% Position with too high velocity def test_TC_202(self): tc_no = "TC-202-VELO_to_high" saved_VELO = self.pv_VELO.get(use_monitor=False) self.pv_VELO.put(1000) val = (9 * self.saved_HLM + self.saved_LLM) / 10 ret = self.motm1.move(val, dial=False, wait=True) self.motm1.put('VAL', val) printMSTA(tc_no, "after put", self.motm1, self.pv_MSTA) ret = waitForStart(self.motm1, tc_no, 2.0) # dummy wait printMSTA(tc_no, "after waitForStart", self.motm1, self.pv_MSTA) ret = waitForStop(self.motm1, tc_no, 4.0) self.assertEqual(True, ret, 'waitForStop return True') printMSTA(tc_no, "after waitForStop", self.motm1, self.pv_MSTA) msta = int(self.pv_MSTA.get(use_monitor=False)) printMSTA(tc_no, "after get msta", self.motm1, self.pv_MSTA) self.pv_VELO.put(saved_VELO) self.assertNotEqual(0, msta & self.MSTA_BIT_PROBLEM, 'Error MSTA.Problem should be set)') self.assertEqual(0, msta & self.MSTA_BIT_FOLLOW_ERR, 'Error MSTA.Following Error should not be set)') self.assertEqual(0, msta & self.MSTA_BIT_MOVING, 'Error MSTA.Moving)') bError = self.pv_Err.get(use_monitor=False) nErrorId = self.pv_nErrorId.get(use_monitor=False) print '%s Error bError=%d nErrorId=%d' % (tc_no, bError, nErrorId) self.assertNotEqual(0, bError, 'bError') self.assertNotEqual(0, nErrorId, 'nErrorId') self.pv_nErrRst.put(1)
def __init__(self, motor_name, mx_database, parent, panel_id=wx.ID_ANY, panel_name=''): """ Initializes the custom panel. Important parameters here are the ``motor_name``, and the ``mx_database``. :param str motor_name: The motor name in the Mx database. :param Mp.RecordList mx_database: The database instance from Mp. :param wx.Window parent: Parent class for the panel. :param int panel_id: wx ID for the panel. :param str panel_name: Name for the panel. """ wx.Panel.__init__(self, parent, panel_id, name=panel_name) self.mx_database = mx_database self.motor_name = motor_name self.motor = self.mx_database.get_record(self.motor_name) self.mtr_type = self.motor.get_field('mx_type') self.scale = float(self.motor.get_field('scale')) self.offset = float(self.motor.get_field('offset')) self._enabled = True self.scan_frame = None # if platform.system() == 'Darwin': # font = self.GetFont() # else: # font = wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL) # # self.SetFont(font) font = self.GetFont() self.vert_size = font.GetPixelSize()[1] + 5 self.is_epics = False self.is_slit_mtr = False self.epics_motor = None if self.mtr_type == 'epics_motor': self.is_epics = True self.epics_pv_name = self.motor.get_field('epics_record_name') self.epics_motor = epics.Motor(self.epics_pv_name) self.pos_pv = self.epics_motor.PV('RBV') # self.limit_pv = mpca.PV("{}.LVIO".format(self.epics_pv_name)) # self.callback = self.limit_pv.add_callback(mpca.DBE_VALUE, # custom_widgets.on_epics_limit, (self.limit_pv, self)) # self.limit_pv = self.epics_motor.PV('LVIO') if self.scale > 0: nlimit = "LLM" plimit = "HLM" else: nlimit = "HLM" plimit = "LLM" self.nlimit_pv = self.epics_motor.PV(nlimit) self.plimit_pv = self.epics_motor.PV(plimit) self.set_pv = self.epics_motor.PV('SET') self.pos_pv.get() # self.limit_pv.get() self.nlimit_pv.get() self.plimit_pv.get() self.set_pv.get() self.epics_motor.add_callback('LVIO', self._on_epics_soft_limit) self.epics_motor.add_callback('HLS', self._on_epics_hard_limit) self.epics_motor.add_callback('LLS', self._on_epics_hard_limit) self.epics_motor.add_callback('SPMG', self._on_epics_disable) if self.mtr_type == 'network_motor': self.server_record_name = self.motor.get_field('server_record') self.remote_record_name = self.motor.get_field( 'remote_record_name') self.server_record = self.mx_database.get_record( self.server_record_name) self.remote_offset = mp.Net( self.server_record, '{}.offset'.format(self.remote_record_name)) self.remote_scale = mp.Net( self.server_record, '{}.scale'.format(self.remote_record_name)) remote_type_name = '{}.mx_type'.format(self.remote_record_name) remote_type = mp.Net(self.server_record, remote_type_name) r_type = remote_type.get() try: str(r_type) except Exception: r_type = '' if r_type == 'slit_motor': self.is_slit_mtr = True top_sizer = self._create_layout() self.SetSizer(top_sizer)
#!/usr/bin/env python import epics ## ----- configuration ------------------------------------------------------------ x = epics.Motor('xafs_linx') x0 = -104.2 xwidth = 0.65 xstep = 0.0625 y = epics.Motor('xafs_liny') y0 = 56.0 ywidth = 0.65 ystep = 0.0625 filename = 'pinhole.dat' ## -------------------------------------------------------------------------------- from time import sleep from BMMcontrols import IonChambers, StepScan, DCM, Vortex import signal ## ----- deal with plotting import numpy import matplotlib as mpl #mpl.use('TkAgg') import matplotlib.pyplot as plt dcm = DCM() dcm.xtals(crystals='111') scan = StepScan(fname=filename, element='Fe', e0=7112, edge='K')