From eae46713aba6b6b20fa5bdc69469a39c9df88e02 Mon Sep 17 00:00:00 2001 From: tangkong Date: Thu, 24 Feb 2022 16:50:25 -0800 Subject: [PATCH] MNT: Checkpoint changes for run 20 --- experiments/c00120.py | 198 +++++++ experiments/ly5320-cam.py | 799 ++++++++++++++++++++++++++ experiments/ly5320.py | 198 +++++++ experiments/x44019.py | 163 ++++++ experiments/x53319.py | 9 + presets/beamline/lib_y.yml | 9 +- presets/beamline/ljh_jet_x.yml | 17 + presets/beamline/ljh_jet_y.yml | 10 + presets/beamline/ljh_jet_z.yml | 5 + presets/beamline/ljh_vh_epix_x.yml | 5 + presets/beamline/tt_ty.yml | 6 + presets/beamline/xcs_pfls_x_motor.yml | 5 + presets/beamline/xcs_pfls_y_motor.yml | 5 + presets/beamline/xcs_xfls_y.yml | 5 + presets/c00120/det_x.yml | 5 + presets/c00120/det_z.yml | 5 + presets/c00120/lib_y.yml | 11 + presets/c00120/ljh_jet_x.yml | 17 + presets/c00120/ljh_jet_y.yml | 15 + presets/c00120/xcs_xfls_x.yml | 5 + presets/c00120/xcs_xfls_y.yml | 5 + presets/c00120/xcs_xfls_z.yml | 5 + presets/lv5719/ljh_jet_x.yml | 10 + xcs/beamline.py | 74 ++- xcs/devices.py | 76 +-- xcsenv | 3 +- 26 files changed, 1608 insertions(+), 57 deletions(-) create mode 100644 experiments/c00120.py create mode 100644 experiments/ly5320-cam.py create mode 100644 experiments/ly5320.py create mode 100755 experiments/x44019.py mode change 100644 => 100755 experiments/x53319.py create mode 100644 presets/beamline/ljh_jet_x.yml create mode 100644 presets/beamline/ljh_jet_y.yml create mode 100644 presets/beamline/ljh_jet_z.yml create mode 100644 presets/beamline/ljh_vh_epix_x.yml create mode 100644 presets/c00120/det_x.yml create mode 100644 presets/c00120/det_z.yml create mode 100644 presets/c00120/lib_y.yml create mode 100644 presets/c00120/ljh_jet_x.yml create mode 100644 presets/c00120/ljh_jet_y.yml create mode 100644 presets/c00120/xcs_xfls_x.yml create mode 100644 presets/c00120/xcs_xfls_y.yml create mode 100644 presets/c00120/xcs_xfls_z.yml create mode 100644 presets/lv5719/ljh_jet_x.yml diff --git a/experiments/c00120.py b/experiments/c00120.py new file mode 100644 index 0000000..46368a2 --- /dev/null +++ b/experiments/c00120.py @@ -0,0 +1,198 @@ +from subprocess import check_output + +import logging +import json +import sys +import time +import os + +import numpy as np +import elog +from hutch_python.utils import safe_load +from ophyd import EpicsSignalRO +from ophyd import EpicsSignal +from bluesky import RunEngine +from bluesky.plans import scan +from bluesky.plans import list_scan +from ophyd import Component as Cpt +from ophyd import Device +from pcdsdevices.interface import BaseInterface +from pcdsdevices.areadetector import plugins +from xcs.db import daq +from xcs.db import camviewer +from xcs.db import RE +from xcs.db import xcs_ccm as ccm +from xcs.delay_scan import delay_scan +from xcs.db import lxt_fast, lxt_fast_enc +from pcdsdevices.device_types import Newport, IMS +from pcdsdevices.evr import Trigger +#from macros import * +import time + +logger = logging.getLogger(__name__) + + +class User(): + def __init__(self): + + with safe_load ('VH_motors'): + self.vh_y = IMS('XCS:USR:MMS:15', name='vh_y') + self.vh_x = IMS('XCS:USR:MMS:16', name='vh_x') + self.vh_rot = IMS('XCS:USR:MMS:39', name='vh_rot') + + with safe_load ('LED'): + self.led = Trigger('XCS:R42:EVR:01:TRIG9', name='led_delay') + self.led_uS = MicroToNano() + +# with safe_load('Laser Phase Motor'): +# from ophyd.epics_motor import EpicsMotor +# self.las_phase = EpicsMotor('LAS:FS4:MMS:PH', name='las_phase') + + def set_current_position(self, motor, value): + motor.set_use_switch.put(1) + motor.set_use_switch.wait_for_connection() + motor.user_setpoint.put(value, force=True) + motor.user_setpoint.wait_for_connection() + motor.set_use_switch.put(0) + + def lxt_fast_set_absolute_zero(self): + currentpos = lxt_fast() + currentenc = lxt_fast_enc.get() + #elog.post('Set current stage position {}, encoder value {} to 0'.format(currentpos,currentenc.pos)) + print('Set current stage position {}, encoder value {} to 0'.format(currentpos,currentenc.pos)) + lxt_fast.set_current_position(0) + lxt_fast_enc.set_zero() + return + + def takeRun(self, nEvents, record=True, use_l3t=False): + daq.configure(events=120, record=record, use_l3t=use_l3t) + daq.begin(events=nEvents) + daq.wait() + daq.end_run() + + def pvascan(self, motor, start, end, nsteps, nEvents, record=None): + currPos = motor.get() + daq.configure(nEvents, record=record, controls=[motor]) + RE(scan([daq], motor, start, end, nsteps)) + motor.put(currPos) + + def pvdscan(self, motor, start, end, nsteps, nEvents, record=None): + daq.configure(nEvents, record=record, controls=[motor]) + currPos = motor.get() + RE(scan([daq], motor, currPos + start, currPos + end, nsteps)) + motor.put(currPos) + + def ascan(self, motor, start, end, nsteps, nEvents, record=True, use_l3t=False): + self.cleanup_RE() + currPos = motor.wm() + daq.configure(nEvents, record=record, controls=[motor], use_l3t=use_l3t) + try: + RE(scan([daq], motor, start, end, nsteps)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + motor.mv(currPos) + + def listscan(self, motor, posList, nEvents, record=True, use_l3t=False): + self.cleanup_RE() + currPos = motor.wm() + daq.configure(nEvents, record=record, controls=[motor], use_l3t=use_l3t) + try: + RE(list_scan([daq], motor, posList)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + motor.mv(currPos) + + def dscan(self, motor, start, end, nsteps, nEvents, record=True, use_l3t=False): + self.cleanup_RE() + daq.configure(nEvents, record=record, controls=[motor], use_l3t=use_l3t) + currPos = motor.wm() + try: + RE(scan([daq], motor, currPos+start, currPos+end, nsteps)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + motor.mv(currPos) + + def a2scan(self, m1, a1, b1, m2, a2, b2, nsteps, nEvents, record=True, use_l3t=False): + self.cleanup_RE() + daq.configure(nEvents, record=record, controls=[m1, m2], use_l3t=use_l3t) + try: + RE(scan([daq], m1, a1, b1, m2, a2, b2, nsteps)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + + def a3scan(self, m1, a1, b1, m2, a2, b2, m3, a3, b3, nsteps, nEvents, record=True): + self.cleanup_RE() + daq.configure(nEvents, record=record, controls=[m1, m2, m3]) + try: + RE(scan([daq], m1, a1, b1, m2, a2, b2, m3, a3, b3, nsteps)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + + def delay_scan(self, start, end, sweep_time, record=True, use_l3t=False, + duration=None): + """Delay scan with the daq.""" + self.cleanup_RE() + daq.configure(events=None, duration=None, record=record, + use_l3t=use_l3t, controls=[lxt_fast]) + try: + RE(delay_scan(daq, lxt_fast, [start, end], sweep_time, + duration=duration)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + + def empty_delay_scan(self, start, end, sweep_time, record=True, + use_l3t=False, duration=None): + """Delay scan without the daq.""" + self.cleanup_RE() + #daq.configure(events=None, duration=None, record=record, + # use_l3t=use_l3t, controls=[lxt_fast]) + try: + RE(delay_scan(None, lxt_fast, [start, end], sweep_time, + duration=duration)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + + def cleanup_RE(self): + if not RE.state.is_idle: + print('Cleaning up RunEngine') + print('Stopping previous run') + try: + RE.stop() + except Exception: + pass + + +class MicroToNano(): + def __init__(self): + self._offset_nano = 0 + + def setOffset_nano(self, offset): + self._offset_nano = offset + + def setOffset_micro(self, offset): + self._offset_nano = offset * 1000 + + def getOffset_nano(self): + return self._offset_nano + + def __call__(self, micro): + return (micro * 1000) + self._offset_nano + + +#LXE is virtual motor easy to have linear power and talks to laser wave plate (newport) Friday +#Saturday LXE_OPA + diff --git a/experiments/ly5320-cam.py b/experiments/ly5320-cam.py new file mode 100644 index 0000000..b7601b6 --- /dev/null +++ b/experiments/ly5320-cam.py @@ -0,0 +1,799 @@ +from subprocess import check_output + +import logging +import json +import sys +import time +import os + +import pickle +import numpy as np +import h5py +from hutch_python.utils import safe_load +from epics import caget, caget_many, PV +from ophyd import EpicsSignalRO +from ophyd import EpicsSignal +from bluesky import RunEngine +from bluesky.plans import scan +from bluesky.plans import list_scan, list_grid_scan +from ophyd import Component as Cpt +from ophyd import Device +from pcdsdevices.interface import BaseInterface +from pcdsdevices.areadetector import plugins +from pcdsdevices.epics_motor import SmarActTipTilt +from pcdsdevices.epics_motor import SmarActOpenLoop +from xcs.db import daq +from xcs.db import camviewer +from xcs.db import RE +from xcs.db import xcs_ccm as ccm +from xcs.delay_scan import delay_scan +from xcs.db import lxt_fast +from pcdsdevices.device_types import Newport, IMS +from elog import HutchELog + +#from macros import * +import time + +pickle.HIGHEST_PROTOCOL = 4 +import pandas as pd + +logger = logging.getLogger(__name__) + +CAMS = [ + 'xcs_gige_lj1' + ] + +CAM_PATH = '/cds/home/opr/xcsopr/experiments/xcsly5320/cam_data/' +SCAN_PATH = '/cds/home/opr/xcsopr/experiments/xcsly5320/scan_data/' + +class CamTools: + _camera = camviewer.xcs_gige_lj1 + _cam_type = 'gige' + _path = CAM_PATH + _images = [] + _timestamps = [] + _cb_uid = None + _num_images = 10 + _state = 'idle' + + @property + def camera(self): + return self._camera + + @camera.setter + def camera(self, camera): + try: + self._camera = getattr(camviewer, camera) + except AttributeError as e: + logger.warning(f'{camera} is not a valid camera: {e}') + + @property + def height(self): + if self.camera: + return self.camera.image2.height.get() + else: + return None + + @property + def width(self): + if self.camera: + return self.camera.image2.width.get() + else: + return None + + @property + def file_path(self): + return self._path + + @file_path.setter + def file_path(self, path): + # We'll have to validate or make path + self._path = path + + @property + def timestamps(self): + return self._timestamps + + @property + def images(self): + return self._images + + @property + def num_images(self): + return self._num_images + + @num_images.setter + def num_images(self, num): + try: + self._num_images = int(num) + except: + logger.warning('number of images must be castable as int') + + @staticmethod + def camera_names(): + return CAMS + + def clear_data(self): + self._images = [] + self._timestamps = [] + + def collect(self, n_img): + """General collection method. If n_img specified, set + property as well""" + if not self.num_images: + if n_img: + self.num_images = n_img + else: + logger.warning('You need to specify number of images to collect') + + if self.images: + logger.info('Leftover image data, clearing') + self._images = [] + self._timestamps = [] + + if not self.camera: + logger.warning('You have not specified a camera') + return + + #if self.camera.cam.acquire.get() is not 1: + # logger.info('Camera has no rate, starting acquisition') + # self.camera.cam.acquire.put(1) + + cam_model = self.camera.cam.model.get() + # TODO: Make dir with explicit cam model + if 'opal' in cam_model: + self._cam_type = 'opal' + else: + self._cam_type = 'gige' + + logger.info(f'Starting data collection for {self.camera.name}') + #self._cb_uid = self.camera.image2.array_data.subscribe(self._data_cb) + self._get_data() + + def _get_data(self): + delay = 0.1 + while len(self.images) < self.num_images: + img = self.camera.image2.array_data.get() + ts = self.camera.image2.array_data.timestamp + if len(self.images) == 0: + self.images.append(np.reshape(img, (self.height, self.width))) + self.timestamps.append(ts) + if not np.array_equal(self.images[-1], img): + print('getting image: ', len(self.images)) + self.images.append(np.reshape(img, (self.height, self.width))) + self.timestamps.append(ts) + print('delay ', time.time() - ts) + time.sleep(delay) + else: + time.sleep(0.01) + logger.info('done collecting image data ') + + def _data_cb(self, **kwargs): + """Area detector cbs does not know thyself""" + obj = kwargs.get('obj') + arr = obj.value + ts = obj.timestamp + self.images.append(np.reshape(arr, (self.height, self.width))) + self.timestamps.append(ts) + logger.info('received image: ', len(self.images), time.time() - ts) + if len(self.images) >= self.num_images: + logger.info('We have collected all our images, stopping collection') + self.camera.image2.array_data.unsubscribe(self._cb_uid) + + def plot(self): + """Let people look at collected images""" + if not self.images: + info.warning('You do not have any images collected') + + num_images = len(self.images) + img_sum = self.images[0] + if num_images is 1: + plt.imshow(img_sum) + else: + for img in self.images[1:]: + img_sum += img + plt.imshow(img_sum / num_images) + + def save(self): + file_name = f'{self.camera.name}-{int(time.time())}.h5' + location = ''.join([self._path, file_name]) + hf = h5py.File(location, 'w') + hf.create_dataset('image_data', data=self.images) + hf.create_dataset('timestamps', data=self.timestamps) + hf.close() + logger.info(f'wrote all image data to {location}') + return location + + +class ImagerHdf5(): + def __init__(self, imager=None): + try: + self.imagerh5 = imager.hdf51 + self.imager = imager.cam + except: + self.imagerh5 = None + self.imager = None + + def setImager(self, imager): + self.imagerh5 = imager.hdf51 + self.imager = imager.cam + + def stop(self): + self.imagerh5.enable.set(0) + + def status(self): + print('Enabled',self.imagerh5.enable.get()) + print('File path',self.imagerh5.file_path.get()) + print('File name',self.imagerh5.file_name.get()) + print('File template (should be %s%s_%d.h5)',self.imagerh5.file_template.get()) + + print('File number',self.imagerh5.file_number.get()) + print('Frame to capture per file',self.imagerh5.num_capture.get()) + print('autoincrement ',self.imagerh5.auto_increment.get()) + print('file_write_mode ',self.imagerh5.file_write_mode.get()) + #IM1L0:XTES:CAM:HDF51:Capture_RBV 0: done, 1: capturing + print('captureStatus ',self.imagerh5.capture.get()) + + def prepare(self, baseName=None, pathName=None, nImages=None, nSec=None): + if self.imagerh5.enable.get() != 'Enabled': + self.imagerh5.enable.put(1) + iocdir=self.imager.prefix.split(':')[0].lower() + if pathName is not None: + self.imagerh5.file_path.set(pathName) + elif len(self.imagerh5.file_path.get())==0: + #this is a terrible hack. + iocdir=self.imager.prefix.replace(':','-').lower()[:-1] + camtype='gige' + self.imagerh5.file_path.put('/reg/d/iocData/ioc-%s/'%(iocdir)) + if 'rix' in iocdir: + self.imagerh5.file_path.put('/reg/d/iocData/ioc-cam-%s/'%(iocdir)) + + if baseName is not None: + self.imagerh5.file_name.put(baseName) + else: + expname = check_output('get_curr_exp').decode('utf-8').replace('\n','') + try: + lastRunResponse = check_output('get_lastRun').decode('utf-8').replace('\n','') + if lastRunResponse == 'no runs yet': + runnr=0 + else: + runnr = int(check_output('get_lastRun').decode('utf-8').replace('\n','')) + except: + runnr = 0 + self.imagerh5.file_name.put('%s_%s_Run%03d'%(iocdir,expname, runnr+1)) + + self.imagerh5.file_template.put('%s%s_%d.h5') + #check that file to be written does not exist + already_present = True + while (already_present): + fnum = self.imagerh5.file_number.get() + fname = self.imagerh5.file_path.get() + self.imagerh5.file_name.get() + \ + '_%d'%fnum + '.h5' + if os.path.isfile(fname): + print('File %s already exists'%fname) + self.imagerh5.file_number.put(1 + fnum) + time.sleep(0.2) + else: + already_present = False + + self.imagerh5.auto_increment.put(1) + self.imagerh5.file_write_mode.put(2) + if nImages is not None: + self.imagerh5.num_capture.put(nImages) + if nSec is not None: + if self.imager.acquire.get() > 0: + rate = self.imager.array_rate.get() + self.imagerh5.num_capture.put(nSec*rate) + else: + print('Imager is not acquiring, cannot use rate to determine number of recorded frames') + + def write(self, nImages=None): + if nImages is not None: + self.imagerh5.num_capture.put(nImages) + if self.imager.acquire.get() == 0: + self.imager.acquire.put(1) + self.imagerh5.capture.put(1) + + def write_wait(self, nImages=None): + while (self.imagerh5.num_capture.get() > + self.imagerh5.num_captured.get()): + time.sleep(0.25) + + def write_stop(self): + self.imagerh5.capture.put(0) + + +class User(): + _cam_tools = CamTools() + def __init__(self): + with safe_load('SmarAct'): + self.las1 = SmarActTipTilt(prefix='XCS:MCS2:01', tip_pv=':m1', tilt_pv=':m2', name='las1') + self.las2 = SmarActTipTilt(prefix='XCS:MCS2:01', tip_pv=':m4', tilt_pv=':m5', name= 'las2') + self.las3 = SmarActTipTilt(prefix='XCS:MCS2:01', tip_pv=':m7', tilt_pv=':m8', name = 'las3') + with safe_load('elog'): + kwargs = dict() + self.elog = HutchELog.from_conf('XCS', **kwargs) + + with safe_load('cameras'): + self. = ImagerHdf5(camviewer.xcs_gige_lj1) +# self.intermediate_fieldh5 = ImagerHdf5(getattr(camviewer,'cam-crix-gige-03')) + + #with safe_load('lw9319_motors'): + # self.bf_det_y = IMS('XCS:USR:MMS:33', name='bf_det_y') + # self.gon_mid_Rz = IMS('XCS:USR:MMS:35', name='gon_mid_Rz') + # self.gon_mid_x = IMS('XCS:USR:MMS:48', name='gon_mid_x') + # self.gon_mid_z = IMS('XCS:USR:MMS:45', name='gon_mid_z') + # self.gon_mid_Rx = IMS('XCS:USR:MMS:44', name='gon_mid_Rx') + # self.crl_df_Rx = IMS('XCS:USR:MMS:39', name='crl_df_Rx') + # self.crl_df_y = IMS('XCS:USR:MMS:40', name='crl_df_y') + # self.crl_df_x = IMS('XCS:USR:MMS:47', name='crl_df_x') + # self.crl_bf_Rx = IMS('XCS:USR:MMS:37', name='crl_bf_Rx') + # self.crl_bf_x = IMS('XCS:USR:MMS:38', name='crl_bf_x') + # self.bf_det_x = IMS('XCS:USR:MMS:34', name='bf_det_x') + # self.gon_mid_y = IMS('XCS:USR:MMS:03', name='gon_mid_y') + # self.crl_bf_y = IMS('XCS:USR:MMS:05', name='crl_bf_y') + # self.gon_mid_Ry = Newport('XCS:USR:MMN:03', name='gon_mid_Ry') + # self.nf_x = Newport('XCS:USR:MMN:07', name='nf_x') + # self.crl_df_Ry = Newport('XCS:USR:MMN:05', name='crl_df_Ry') + # self.crl_bf_z = Newport('XCS:USR:MMN:06',name = 'crl_bf_z') + # self.crl_df_z = Newport('XCS:USR:MMN:05',name = 'crl_df_z') + # self.crl_bf_Ry = Newport('XCS:USR:MMN:04', name='crl_bf_Ry') + # self.bf_det_focus = Newport('XCS:LADM:MMN:01',name = 'bf_det_focus') + # self.df_det_focus = Newport('XCS:LADM:MMN:02',name = 'df_det_focus') + # #self.sam_x = MMC('',name = 'sam_x') + # #self.sam_y = MMC('',name = 'sam_y') + + def takeRun(self, nEvents, record=None, use_l3t=False): + daq.configure(events=120, record=record, use_l3t=use_l3t) + daq.begin(events=nEvents) + daq.wait() + daq.end_run() + + def ascan(self, motor, start, end, nsteps, nEvents, record=None, use_l3t=False, post=False): + self.cleanup_RE() + currPos = motor.wm() + daq.configure(nEvents, record=record, controls=[motor], use_l3t=use_l3t) + try: + RE(scan([daq], motor, start, end, nsteps)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + if post: + run = get_run() + message = 'scan {name} from {min1:.3f} to {max1:.3f} in {num1} steps'.format(name=motor.name, + min1=start,max1=end, + num1=nsteps) + + self.elog.post(message,run=int(run)) + + motor.mv(currPos) + def pv_ascan(self, signal, start, end, nsteps, nEvents, record=None, use_l3t=False, post=False): + self.cleanup_RE() + currPos = signal.get() + #signal.put_complete = True + daq.configure(nEvents, record=record, controls=[signal], use_l3t=use_l3t) + try: + RE(scan([daq], signal, start, end, nsteps)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + + signal.put(currPos) + currPos = signal.get() + + if post: + run = get_run() + message = 'scan {name} from {min1:.3f} to {max1:.3f} in {num1} steps'.format(name=signal.name, + min1=start,max1=end, + num1=nsteps) + self.elog.post(message,run=int(run)) + + def listscan(self, motor, posList, nEvents, record=None, use_l3t=False, post=False): + self.cleanup_RE() + currPos = motor.wm() + daq.configure(nEvents, record=record, controls=[motor], use_l3t=use_l3t) + try: + RE(list_scan([daq], motor, posList)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + motor.mv(currPos) + + if post: + run = get_run() + message = 'scan {name} from {min1:.3f} to {max1:.3f} in {num1} steps'.format(name=motor.name, + min1=posList[0],max1=posList[-1], + num1=posList.size) + self.elog.post(message,run=int(run)) + + + def list2scan(self, m1, p1, m2, p3, nEvents, record=None, use_l3t=False, post=False): + self.cleanup_RE() + currPos1 = m1.wm() + currPos2 = m2.wm() + daq.configure(nEvents, record=record, controls=[m1,m2], use_l3t=use_l3t) + try: + RE(list_grid_scan([daq], m1,p1,m2,p3)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + m1.mv(currPos1) + m2.mv(currPos2) + + if post: + run = get_run() + message = 'grid scan with {name1} from {min1:.3f} to {max1:.3f} in {num1} steps, and {name2} from {min2:.3f} to {max2:.3f} in {num2} steps'.format(name1=m1.name, + min1=p1[0],max1=p1[-1], + num1=p1.size, name2=m2.name, + min2=p2[0],max2=p2[-1],num2=p2.size) + self.elog.post(message,run=int(run)) + + + + + + def loop_newport_dscan(self, m1, start1, stop1, m2, start2, stop2, loop_steps, m3_newport, start3, stop3, run_steps, nEvents, record=None, use_l3t=False, post=False): + # m1 is the slow motor, m2 is the fast motor + self.cleanup_RE() + currPos1 = m1.wm() + currPos2 = m2.wm() + currPos3 = m3_newport.wm() + + m1_pos = np.linspace(start1+currPos1, stop1+currPos1, loop_steps) + m2_pos = np.linspace(start2+currPos2, stop2+currPos2, loop_steps) + + for m1pos, m2pos in zip(m1_pos, m2_pos): + # move to next row and wait until motor gets there + m1.mv(m1pos, wait=True) + m2.mv(m2pos, wait=True) + + self.newport_dscan(m3_newport, start3, stop3, run_steps, nEvents, record=record, use_l3t=use_l3t, post=post) + + # move back to original positions + m1.mv(currPos1) + m2.mv(currPos2) + m3_newport.mv(currPos3-0.1, wait=True) + m3_newport.mv(currPos3, wait=True) + + if post: + run = get_run() + message = f'runs {int(run)-loop_steps+1} to {run} are a quasi-2D scan of {m1.name}, {m2.name} and {m3_newport.name}' + self.elog.post(message,run=int(run)) + + def loop_dscan(self, m1, start1, stop1, loop_steps, m2, start2, stop2, run_steps, nEvents, record=None, use_l3t=False, post=False): + # m1 is the slow motor (assumed to be Newport), m2 is the fast motor + self.cleanup_RE() + currPos1 = m1.wm() + currPos2 = m2.wm() + + m1_pos = np.linspace(start1+currPos1, stop1+currPos1, loop_steps) + + # take care of backlash + m1.mv(currPos1-0.1, wait=True) + + + for m1pos in m1_pos: + # move to next row and wait until motor gets there + m1.mv(m1pos, wait=True) + + self.dscan(m2, start2, stop2, run_steps, nEvents, record=record, use_l3t=use_l3t, post=post) + #if post: + # # get run number + # run = get_run() + # message = '{name1}={pos:.3f}, and scan {name2} from {min2:.3f} to {max2:.3f} in {num2} steps'.format(name1=m1.name,pos=m1pos,name2=m2.name, + # min2=np.min(m2_pos),max2=np.max(m2_pos), + # num2=np.size(m2_pos)) + + # self.elog.post(message,run=int(run)) + m2.mv(currPos2,wait=True) + + # move back to original positions + m1.mv(currPos1-0.1,wait=True) + m1.mv(currPos1) + m2.mv(currPos2) + + + + def loop_d2scan(self, m1, start1, stop1, loop_steps, m2, start2, stop2, m3, start3, stop3, run_steps, nEvents, record=None, use_l3t=False, post=False): + # m1 is the slow motor, m2 is the fast motor + self.cleanup_RE() + currPos1 = m1.wm() + currPos2 = m2.wm() + currPos3 = m3.wm() + + m1_pos = np.linspace(start1+currPos1, stop1+currPos1, loop_steps) + + # take care of backlash + m1.mv(currPos1-0.1, wait=True) + + + for m1pos in m1_pos: + # move to next row and wait until motor gets there + m1.mv(m1pos, wait=True) + + self.d2scan(m2, start2, stop2, m3, start3, stop3, run_steps, nEvents, record=record, use_l3t=use_l3t, post=post) + #if post: + # # get run number + # run = get_run() + # message = '{name1}={pos:.3f}, and scan {name2} from {min2:.3f} to {max2:.3f} in {num2} steps'.format(name1=m1.name,pos=m1pos,name2=m2.name, + # min2=np.min(m2_pos),max2=np.max(m2_pos), + # num2=np.size(m2_pos)) + + # self.elog.post(message,run=int(run)) + m2.mv(currPos2,wait=True) + m3.mv(currPos3,wait=True) + + # move back to original positions + m1.mv(currPos1-0.1,wait=True) + m1.mv(currPos1) + m2.mv(currPos2) + m3.mv(currPos3) + + + def line_scan(self, m1, start1, stop1, steps1, m2, start2, stop2, steps2, nEvents, record=None, use_l3t=False, post=False): + # m1 is the slow motor, m2 is the fast motor + self.cleanup_RE() + currPos1 = m1.wm() + currPos2 = m2.wm() + + if type(steps1)==int: + m1_pos = np.linspace(start1, stop1, steps1) + elif type(steps1)==float: + m1_pos = np.arange(start1, stop1+steps1, steps1) + else: + return + if type(steps2)==int: + m2_pos = np.linspace(start2, stop2, steps2) + elif type(steps2)==float: + m2_pos = np.arange(start2, stop2+steps2, steps2) + else: + return + + for m1pos in m1_pos: + # move to next row and wait until motor gets there + m1.mv(m1pos, wait=True) + + daq.configure(nEvents, record=record, controls=[m2], use_l3t=use_l3t) + try: + RE(list_scan([daq],m2, m2_pos)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + + if post: + # get run number + run = get_run() + message = '{name1}={pos:.3f}, and scan {name2} from {min2:.3f} to {max2:.3f} in {num2} steps'.format(name1=m1.name,pos=m1pos,name2=m2.name, + min2=np.min(m2_pos),max2=np.max(m2_pos), + num2=np.size(m2_pos)) + + self.elog.post(message,run=int(run)) + + m1.mv(currPos1) + m2.mv(currPos2) + + def dline_scan(self, m1, start1, stop1, steps1, m2, start2, stop2, steps2, nEvents, record=None, use_l3t=False, post=False): + + currPos1 = m1.wm() + currPos2 = m2.wm() + self.line_scan(m1,start1+currPos1, stop1+currPos1, steps1, m2, start2+currPos2, stop2+currPos2, steps2, nEvents, record=record, use_l3t=use_l3t, post=post) + + + def list3scan(self, m1, p1, m2, p2, m3, p3, nEvents, record=None, use_l3t=False, post=False): + self.cleanup_RE() + currPos1 = m1.wm() + currPos2 = m2.wm() + currPos3 = m3.wm() + daq.configure(nEvents, record=record, controls=[m1,m2,m3], use_l3t=use_l3t) + try: + RE(list_scan([daq], m1,p1,m2,p2,m3,p3)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + m1.mv(currPos1) + m2.mv(currPos2) + m3.mv(currPos3) + + def dscan(self, motor, start, end, nsteps, nEvents, record=None, use_l3t=False, post=False): + self.cleanup_RE() + daq.configure(nEvents, record=record, controls=[motor], use_l3t=use_l3t) + currPos = motor.wm() + try: + RE(scan([daq], motor, currPos+start, currPos+end, nsteps)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + motor.mv(currPos) + + if post: + run = get_run() + message = 'scan {name} from {min1:.3f} to {max1:.3f} in {num1} steps'.format(name=motor.name, + min1=start+currPos,max1=end+currPos, + num1=nsteps) + self.elog.post(message,run=int(run)) + + def newport_dscan(self, motor, start, end, nsteps, nEvents, record=None, use_l3t=False, post=False): + self.cleanup_RE() + daq.configure(nEvents, record=record, controls=[motor], use_l3t=use_l3t) + currPos = motor.wm() + + # remove backlash for small scans + motor.mvr(-.1, wait=True) + + try: + RE(scan([daq], motor, currPos+start, currPos+end, nsteps)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + + # move back to starting point and remove backlash + motor.mv(currPos, wait=True) + motor.mvr(-0.1, wait=True) + motor.mv(currPos) + + if post: + run = get_run() + message = 'scan {name} from {min1:.3f} to {max1:.3f} in {num1} steps'.format(name=motor.name, + min1=start+currPos,max1=end+currPos, + num1=nsteps) + self.elog.post(message,run=int(run)) + + + + def pv_dscan(self, signal, start, end, nsteps, nEvents, record=None, use_l3t=False, post=False): + self.cleanup_RE() + daq.configure(nEvents, record=record, controls=[signal], use_l3t=use_l3t) + currPos = signal.get() + try: + RE(scan([daq], signal, currPos+start, currPos+end, nsteps)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + signal.put(int(currPos)) + + if post: + run = get_run() + message = 'scan {name} from {min1:.3f} to {max1:.3f} in {num1} steps'.format(name=signal.name, + min1=start+currPos,max1=end+currPos, + num1=nsteps) + self.elog.post(message,run=int(run)) + + def d2scan(self, m1, a1, b1, m2, a2, b2, nsteps, nEvents, record=True, use_l3t=False, post=False): + currPos1 = m1.wm() + currPos2 = m2.wm() + + # just use a2scan + self.a2scan(m1, currPos1+a1, currPos1+b1, m2, currPos2+a2, currPos2+b2, nsteps, nEvents, record=record, use_l3t=use_l3t, post=post) + + def a2scan(self, m1, a1, b1, m2, a2, b2, nsteps, nEvents, record=True, use_l3t=False, post=False): + + currPos1 = m1.wm() + currPos2 = m2.wm() + + self.cleanup_RE() + daq.configure(nEvents, record=record, controls=[m1, m2], use_l3t=use_l3t) + try: + RE(scan([daq], m1, a1, b1, m2, a2, b2, nsteps)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + + # move motors back to starting position + m1.mv(currPos1) + m2.mv(currPos2) + + if post: + run = get_run() + + message = f'scan {m1.name} from {a1:.3f} to {b1:.3f} and {m2.name} from {a2:.3f} to {b2:.3f} in {nsteps} steps' + self.elog.post(message,run=int(run)) + + + + + def a3scan(self, m1, a1, b1, m2, a2, b2, m3, a3, b3, nsteps, nEvents, record=True, post=False): + self.cleanup_RE() + daq.configure(nEvents, record=record, controls=[m1, m2, m3]) + try: + RE(scan([daq], m1, a1, b1, m2, a2, b2, m3, a3, b3, nsteps)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + + def delay_scan(self, start, end, sweep_time, record=None, use_l3t=False, + duration=None, post=False): + """Delay scan with the daq.""" + self.cleanup_RE() + daq.configure(events=None, duration=None, record=record, + use_l3t=use_l3t, controls=[lxt_fast]) + try: + RE(delay_scan(daq, lxt_fast, [start, end], sweep_time, + duration=duration)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + + if post: + run = get_run() + message = 'delay scan from {min1:.2f} to {max1:.2f} in with {sweep:.2f}s sweep time'.format(min1=start,max1=end, + sweep=sweep_time) + self.elog.post(message,run=int(run)) + + + def empty_delay_scan(self, start, end, sweep_time, record=None, + use_l3t=False, duration=None, post=False): + """Delay scan without the daq.""" + self.cleanup_RE() + #daq.configure(events=None, duration=None, record=record, + # use_l3t=use_l3t, controls=[lxt_fast]) + try: + RE(delay_scan(None, lxt_fast, [start, end], sweep_time, + duration=duration)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + + def cleanup_RE(self): + if not RE.state.is_idle: + print('Cleaning up RunEngine') + print('Stopping previous run') + try: + RE.stop() + except Exception: + pass + + @property + def cam_tools(self): + return self._cam_tools + + def scanner(self, motor, start, stop, steps, cam, images=10, post=False): + """General scanner for now because we want to take images""" + + currPos = motor.wm() + steps = np.linspace(start, stop, steps) + times = [] + image_files = [] + self.cam_tools.camera = cam + df = pd.DataFrame() + for step in steps: + motor.mv(step, wait=True) + logger.info(f'Stepper reached {step}, collecting data') + times.append(time.time()) + self.cam_tools.num_images = images + self.cam_tools.collect(images) + f = self.cam_tools.save() + image_files.append(f) + df = df.append(pd.DataFrame([step], columns=[motor.name]), ignore_index=True) + #df = df.append(pd.DataFrame([caget_many(EPICSARCH)], columns=EPICSARCH), ignore_index=True) + df = df.assign(times=times) + df = df.assign(image_files=image_files) + file_name = f'{motor.name}-{int(time.time())}.h5' + location = SCAN_PATH + file_name + df.to_hdf(location, key='metadata') + logger.info(f'wrote all data to {location}') + + motor.mv(currPos) + + if post: + run = get_run() + message = 'scan {name} from {min1} to {max1} in {num1} steps, recording images with {cam}'.format(name=motor.name, + min1=start,max1=stop, + num1=steps.size, cam=cam) + message += f"\n\nwrote all data to {location}" + self.elog.post(message) + + + diff --git a/experiments/ly5320.py b/experiments/ly5320.py new file mode 100644 index 0000000..4625795 --- /dev/null +++ b/experiments/ly5320.py @@ -0,0 +1,198 @@ +from subprocess import check_output + +import logging +import json +import sys +import time +import os + +import numpy as np +import elog +from hutch_python.utils import safe_load +from ophyd import EpicsSignalRO +from ophyd import EpicsSignal +from bluesky import RunEngine +from bluesky.plans import scan +from bluesky.plans import list_scan +from ophyd import Component as Cpt +from ophyd import Device +from pcdsdevices.interface import BaseInterface +from pcdsdevices.areadetector import plugins +from xcs.db import daq +from xcs.db import camviewer +from xcs.db import RE +from xcs.db import xcs_ccm as ccm +from xcs.delay_scan import delay_scan +from xcs.db import lxt_fast, lxt_fast_enc +from pcdsdevices.device_types import Newport, IMS +from pcdsdevices.evr import Trigger +#from macros import * +import time + +logger = logging.getLogger(__name__) + + +class User(): + def __init__(self): + + with safe_load ('VH_motors'): + self.vh_y = IMS('XCS:USR:MMS:15', name='vh_y') + self.vh_x = IMS('XCS:USR:MMS:16', name='vh_x') + self.vh_rot = IMS('XCS:USR:MMS:39', name='vh_rot') + + with safe_load ('LED'): + self.led = Trigger('XCS:R42:EVR:01:TRIG9', name='led_delay') + self.led_uS = MicroToNano() + +# with safe_load('Laser Phase Motor'): +# from ophyd.epics_motor import EpicsMotor +# self.las_phase = EpicsMotor('LAS:FS4:MMS:PH', name='las_phase') + + def set_current_position(self, motor, value): + motor.set_use_switch.put(1) + motor.set_use_switch.wait_for_connection() + motor.user_setpoint.put(value, force=True) + motor.user_setpoint.wait_for_connection() + motor.set_use_switch.put(0) + + def lxt_fast_set_absolute_zero(self): + currentpos = lxt_fast() + currentenc = lxt_fast_enc.get() + #elog.post('Set current stage position {}, encoder value {} to 0'.format(currentpos,currentenc.pos)) + print('Set current stage position {}, encoder value {} to 0'.format(currentpos,currentenc.pos)) + lxt_fast.set_current_position(0) + lxt_fast_enc.set_zero() + return + + def takeRun(self, nEvents, record=True, use_l3t=False): + daq.configure(events=120, record=record, use_l3t=use_l3t) + daq.begin(events=nEvents) + daq.wait() + daq.end_run() + + def pvascan(self, motor, start, end, nsteps, nEvents, record=None): + currPos = motor.get() + daq.configure(nEvents, record=record, controls=[motor]) + RE(scan([daq], motor, start, end, nsteps)) + motor.put(currPos) + + def pvdscan(self, motor, start, end, nsteps, nEvents, record=None): + daq.configure(nEvents, record=record, controls=[motor]) + currPos = motor.get() + RE(scan([daq], motor, currPos + start, currPos + end, nsteps)) + motor.put(currPos) + + def ascan(self, motor, start, end, nsteps, nEvents, record=True, use_l3t=False): + self.cleanup_RE() + currPos = motor.wm() + daq.configure(nEvents, record=record, controls=[motor], use_l3t=use_l3t) + try: + RE(scan([daq], motor, start, end, nsteps)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + motor.mv(currPos) + + def listscan(self, motor, posList, nEvents, record=True, use_l3t=False): + self.cleanup_RE() + currPos = motor.wm() + daq.configure(nEvents, record=record, controls=[motor], use_l3t=use_l3t) + try: + RE(list_scan([daq], motor, posList)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + motor.mv(currPos) + + def dscan(self, motor, start, end, nsteps, nEvents, record=True, use_l3t=False): + self.cleanup_RE() + daq.configure(nEvents, record=record, controls=[motor], use_l3t=use_l3t) + currPos = motor.wm() + try: + RE(scan([daq], motor, currPos+start, currPos+end, nsteps)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + motor.mv(currPos) + + def a2scan(self, m1, a1, b1, m2, a2, b2, nsteps, nEvents, record=True, use_l3t=False): + self.cleanup_RE() + daq.configure(nEvents, record=record, controls=[m1, m2], use_l3t=use_l3t) + try: + RE(scan([daq], m1, a1, b1, m2, a2, b2, nsteps)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + + def a3scan(self, m1, a1, b1, m2, a2, b2, m3, a3, b3, nsteps, nEvents, record=True): + self.cleanup_RE() + daq.configure(nEvents, record=record, controls=[m1, m2, m3]) + try: + RE(scan([daq], m1, a1, b1, m2, a2, b2, m3, a3, b3, nsteps)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + + def delay_scan(self, start, end, sweep_time, record=True, use_l3t=False, + duration=None): + """Delay scan with the daq.""" + self.cleanup_RE() + daq.configure(events=None, duration=duration, record=record, + use_l3t=use_l3t, controls=[lxt_fast]) + try: + RE(delay_scan(daq, lxt_fast, [start, end], sweep_time, + duration=duration)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + + def empty_delay_scan(self, start, end, sweep_time, record=True, + use_l3t=False, duration=None): + """Delay scan without the daq.""" + self.cleanup_RE() + #daq.configure(events=None, duration=None, record=record, + # use_l3t=use_l3t, controls=[lxt_fast]) + try: + RE(delay_scan(None, lxt_fast, [start, end], sweep_time, + duration=duration)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + + def cleanup_RE(self): + if not RE.state.is_idle: + print('Cleaning up RunEngine') + print('Stopping previous run') + try: + RE.stop() + except Exception: + pass + + +class MicroToNano(): + def __init__(self): + self._offset_nano = 0 + + def setOffset_nano(self, offset): + self._offset_nano = offset + + def setOffset_micro(self, offset): + self._offset_nano = offset * 1000 + + def getOffset_nano(self): + return self._offset_nano + + def __call__(self, micro): + return (micro * 1000) + self._offset_nano + + +#LXE is virtual motor easy to have linear power and talks to laser wave plate (newport) Friday +#Saturday LXE_OPA + diff --git a/experiments/x44019.py b/experiments/x44019.py new file mode 100755 index 0000000..9d72e5e --- /dev/null +++ b/experiments/x44019.py @@ -0,0 +1,163 @@ +from subprocess import check_output + +import logging +import json +import sys +import time +import os + +import numpy as np +from hutch_python.utils import safe_load +from ophyd import EpicsSignalRO +from ophyd import EpicsSignal +from bluesky import RunEngine +from bluesky.plans import scan +from bluesky.plans import list_scan +from ophyd import Component as Cpt +from ophyd import Device +from pcdsdevices.interface import BaseInterface +from pcdsdevices.areadetector import plugins +from xcs.db import daq +from xcs.db import camviewer +from xcs.db import RE +from xcs.db import xcs_ccm as ccm +from xcs.delay_scan import delay_scan +from xcs.db import lxt_fast +from pcdsdevices.device_types import Newport, IMS + +#from macros import * +import time + +logger = logging.getLogger(__name__) + +class User(): + def __init__(self): + pass + + + def takeRun(self, nEvents, record=None, use_l3t=False): + daq.configure(events=120, record=record, use_l3t=use_l3t) + daq.begin(events=nEvents) + daq.wait() + daq.end_run() + + def ascan(self, motor, start, end, nsteps, nEvents, record=None, use_l3t=False): + self.cleanup_RE() + currPos = motor.wm() + daq.configure(nEvents, record=record, controls=[motor], use_l3t=use_l3t) + try: + RE(scan([daq], motor, start, end, nsteps)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + motor.mv(currPos) + + def pvascan(self, motor, start, end, nsteps, nEvents, record=None): + currPos = motor.get() + daq.configure(nEvents, record=record, controls=[motor]) + RE(scan([daq], motor, start, end, nsteps)) + motor.put(currPos) + + def pvdscan(self, motor, start, end, nsteps, nEvents, record=None): + daq.configure(nEvents, record=record, controls=[motor]) + currPos = motor.get() + RE(scan([daq], motor, currPos + start, currPos + end, nsteps)) + motor.put(currPos) + + def listscan(self, motor, posList, nEvents, record=None, use_l3t=False): + self.cleanup_RE() + currPos = motor.wm() + daq.configure(nEvents, record=record, controls=[motor], use_l3t=use_l3t) + try: + RE(list_scan([daq], motor, posList)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + motor.mv(currPos) + + def list3scan(self, m1, p1, m2, p2, m3, p3, nEvents, record=None, use_l3t=False): + self.cleanup_RE() + currPos1 = m1.wm() + currPos2 = m2.wm() + currPos3 = m3.wm() + daq.configure(nEvents, record=record, controls=[m1,m2,m3], use_l3t=use_l3t) + try: + RE(list_scan([daq], m1,p1,m2,p2,m3,p3)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + m1.mv(currPos1) + m2.mv(currPos2) + m3.mv(currPos3) + + def dscan(self, motor, start, end, nsteps, nEvents, record=None, use_l3t=False): + self.cleanup_RE() + daq.configure(nEvents, record=record, controls=[motor], use_l3t=use_l3t) + currPos = motor.wm() + try: + RE(scan([daq], motor, currPos+start, currPos+end, nsteps)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + motor.mv(currPos) + + def a2scan(self, m1, a1, b1, m2, a2, b2, nsteps, nEvents, record=True, use_l3t=False): + self.cleanup_RE() + daq.configure(nEvents, record=record, controls=[m1, m2], use_l3t=use_l3t) + try: + RE(scan([daq], m1, a1, b1, m2, a2, b2, nsteps)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + + def a3scan(self, m1, a1, b1, m2, a2, b2, m3, a3, b3, nsteps, nEvents, record=True): + self.cleanup_RE() + daq.configure(nEvents, record=record, controls=[m1, m2, m3]) + try: + RE(scan([daq], m1, a1, b1, m2, a2, b2, m3, a3, b3, nsteps)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + + def delay_scan(self, start, end, sweep_time, record=None, use_l3t=False, + duration=None): + """Delay scan with the daq.""" + self.cleanup_RE() + daq.configure(events=None, duration=None, record=record, + use_l3t=use_l3t, controls=[lxt_fast]) + try: + RE(delay_scan(daq, lxt_fast, [start, end], sweep_time, + duration=duration)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + + def empty_delay_scan(self, start, end, sweep_time, record=None, + use_l3t=False, duration=None): + """Delay scan without the daq.""" + self.cleanup_RE() + #daq.configure(events=None, duration=None, record=record, + # use_l3t=use_l3t, controls=[lxt_fast]) + try: + RE(delay_scan(None, lxt_fast, [start, end], sweep_time, + duration=duration)) + except Exception: + logger.debug('RE Exit', exc_info=True) + finally: + self.cleanup_RE() + + def cleanup_RE(self): + if not RE.state.is_idle: + print('Cleaning up RunEngine') + print('Stopping previous run') + try: + RE.stop() + except Exception: + pass diff --git a/experiments/x53319.py b/experiments/x53319.py old mode 100644 new mode 100755 index 0b2ffd7..668b2c6 --- a/experiments/x53319.py +++ b/experiments/x53319.py @@ -33,6 +33,13 @@ class User(): def __init__(self): pass + with safe_load('x533_motors'): + self.th=IMS('STEP:XRT1:442:MOTR',name='th') + self.tth=IMS('STEP:XRT1:443:MOTR',name='tth') + self.xtal_y=IMS('STEP:XRT1:441:MOTR',name='xtal_y') + self.cam_dis=IMS('STEP:XRT1:444:MOTR',name='cam_dis') + self.cam_y=IMS('STEP:XRT1:447:MOTR',name='cam_y') + self.iris=IMS('STEP:XRT1:445:MOTR',name='irs') def takeRun(self, nEvents, record=None, use_l3t=False): @@ -149,3 +156,5 @@ def cleanup_RE(self): RE.stop() except Exception: pass + + diff --git a/presets/beamline/lib_y.yml b/presets/beamline/lib_y.yml index 6375601..b8757bb 100644 --- a/presets/beamline/lib_y.yml +++ b/presets/beamline/lib_y.yml @@ -1,3 +1,9 @@ +'220204': + active: true + history: + 04 Feb 2022 09:12:35: ' 95.5000' + 04 Feb 2022 09:37:56: ' 95.4000' + value: 95.4 all_out: active: true history: @@ -8,10 +14,11 @@ bottom_hole: history: 07 May 2021 11:53:43: ' 103.2000' 10 Dec 2021 22:23:45: ' 88.0000' + 14 Feb 2022 23:53:56: ' 96.9836' 15 Oct 2021 17:42:29: ' 83.2000' 20 May 2021 07:17:17: ' 103.7000' 20 May 2021 08:59:01: ' 104.7000' - value: 88.0 + value: 96.983647896 bottom_hole_ccm: active: true history: diff --git a/presets/beamline/ljh_jet_x.yml b/presets/beamline/ljh_jet_x.yml new file mode 100644 index 0000000..f8113fa --- /dev/null +++ b/presets/beamline/ljh_jet_x.yml @@ -0,0 +1,17 @@ +jet: + active: true + history: + 09 Feb 2022 15:24:02: ' -0.0001' + value: -9.999999999976694e-05 +tape: + active: true + history: + 17 Feb 2022 14:26:55: ' 34.9747' + 17 Feb 2022 14:27:55: ' 35.9754' + value: 35.9754 +yag: + active: true + history: + 04 Feb 2022 15:24:25: ' -8.5982' + 14 Feb 2022 23:55:25: ' 13.4900' + value: 13.490000000000002 diff --git a/presets/beamline/ljh_jet_y.yml b/presets/beamline/ljh_jet_y.yml new file mode 100644 index 0000000..8b1a1c3 --- /dev/null +++ b/presets/beamline/ljh_jet_y.yml @@ -0,0 +1,10 @@ +jet: + active: true + history: + 09 Feb 2022 15:25:25: ' 0.0001' + value: 7.500000000071338e-05 +yag: + active: true + history: + 04 Feb 2022 15:24:30: ' 0.0697' + value: 0.06973749999999956 diff --git a/presets/beamline/ljh_jet_z.yml b/presets/beamline/ljh_jet_z.yml new file mode 100644 index 0000000..d136eb6 --- /dev/null +++ b/presets/beamline/ljh_jet_z.yml @@ -0,0 +1,5 @@ +yag: + active: true + history: + 04 Feb 2022 15:24:37: ' 3.9999' + value: 3.9998999999999993 diff --git a/presets/beamline/ljh_vh_epix_x.yml b/presets/beamline/ljh_vh_epix_x.yml new file mode 100644 index 0000000..b177fe6 --- /dev/null +++ b/presets/beamline/ljh_vh_epix_x.yml @@ -0,0 +1,5 @@ +Ly53: + active: true + history: + 09 Feb 2022 15:50:02: ' 13.7164' + value: 13.7164 diff --git a/presets/beamline/tt_ty.yml b/presets/beamline/tt_ty.yml index 1b6dcca..6b82969 100644 --- a/presets/beamline/tt_ty.yml +++ b/presets/beamline/tt_ty.yml @@ -18,6 +18,12 @@ Si3N4_2um: history: 01 Jul 2021 11:22:49: ' 5.8911' value: 5.89111328125 +Ti: + active: true + history: + 01 Feb 2022 15:11:49: ' 1.3953 Initial add of Ti preset' + 01 Feb 2022 15:13:40: ' -30.5078 Fix Ti preset' + value: -30.5078125 YAG_20um: active: true history: diff --git a/presets/beamline/xcs_pfls_x_motor.yml b/presets/beamline/xcs_pfls_x_motor.yml index 4d86207..4a06a7d 100644 --- a/presets/beamline/xcs_pfls_x_motor.yml +++ b/presets/beamline/xcs_pfls_x_motor.yml @@ -1,3 +1,8 @@ +R20_Pack2: + active: true + history: + 29 Jan 2022 10:21:19: ' -0.7502' + value: -0.7501904296875 pack1_ccm: active: true history: diff --git a/presets/beamline/xcs_pfls_y_motor.yml b/presets/beamline/xcs_pfls_y_motor.yml index 1ad72eb..a233218 100644 --- a/presets/beamline/xcs_pfls_y_motor.yml +++ b/presets/beamline/xcs_pfls_y_motor.yml @@ -1,3 +1,8 @@ +R20_Pack2: + active: true + history: + 29 Jan 2022 10:21:23: ' 20.9082' + value: 20.908203125 out: active: true history: diff --git a/presets/beamline/xcs_xfls_y.yml b/presets/beamline/xcs_xfls_y.yml index bae94b0..db5365e 100644 --- a/presets/beamline/xcs_xfls_y.yml +++ b/presets/beamline/xcs_xfls_y.yml @@ -1,3 +1,8 @@ +R20_9p5_mono: + active: true + history: + 04 Feb 2022 09:36:53: ' 64.6411' + value: 64.64111328125 out: active: true history: diff --git a/presets/c00120/det_x.yml b/presets/c00120/det_x.yml new file mode 100644 index 0000000..a753f71 --- /dev/null +++ b/presets/c00120/det_x.yml @@ -0,0 +1,5 @@ +out: + active: true + history: + 31 Jan 2022 18:25:12: ' -240.0025' + value: -240.00249999999997 diff --git a/presets/c00120/det_z.yml b/presets/c00120/det_z.yml new file mode 100644 index 0000000..b9ccf8b --- /dev/null +++ b/presets/c00120/det_z.yml @@ -0,0 +1,5 @@ +out: + active: true + history: + 31 Jan 2022 18:25:16: ' 216.0037' + value: 216.00375 diff --git a/presets/c00120/lib_y.yml b/presets/c00120/lib_y.yml new file mode 100644 index 0000000..532888d --- /dev/null +++ b/presets/c00120/lib_y.yml @@ -0,0 +1,11 @@ +R20_bothole: + active: true + history: + 28 Jan 2022 00:54:00: ' 91.6500' + value: 91.65 +bot_hole_shift2: + active: true + history: + 28 Jan 2022 22:33:08: ' 92.7500' + 29 Jan 2022 05:04:57: ' 93.7500' + value: 93.75 diff --git a/presets/c00120/ljh_jet_x.yml b/presets/c00120/ljh_jet_x.yml new file mode 100644 index 0000000..bf079e5 --- /dev/null +++ b/presets/c00120/ljh_jet_x.yml @@ -0,0 +1,17 @@ +Fe: + active: true + history: + 03 Feb 2022 16:26:59: ' -16.9846' + 28 Jan 2022 22:22:37: ' -25.8164' + value: -16.9846 +tape: + active: true + history: + 03 Feb 2022 10:50:38: ' 10.0004' + value: 10.000399999999999 +yag: + active: true + history: + 03 Feb 2022 16:24:35: ' -12.9871' + 28 Jan 2022 22:13:34: ' -21.8140' + value: -12.987100000000002 diff --git a/presets/c00120/ljh_jet_y.yml b/presets/c00120/ljh_jet_y.yml new file mode 100644 index 0000000..d220e51 --- /dev/null +++ b/presets/c00120/ljh_jet_y.yml @@ -0,0 +1,15 @@ +Fe: + active: true + history: + 28 Jan 2022 22:22:40: ' 1.5522' + value: 1.5522 +jet: + active: true + history: + 04 Feb 2022 13:53:15: ' 0.0001' + value: 0.00013749999999923546 +yag: + active: true + history: + 28 Jan 2022 22:13:20: ' 2.5526' + value: 2.5526 diff --git a/presets/c00120/xcs_xfls_x.yml b/presets/c00120/xcs_xfls_x.yml new file mode 100644 index 0000000..c7b02ff --- /dev/null +++ b/presets/c00120/xcs_xfls_x.yml @@ -0,0 +1,5 @@ +R20LJ9p8: + active: true + history: + 28 Jan 2022 00:49:41: ' 0.1163' + value: 0.11630859374999991 diff --git a/presets/c00120/xcs_xfls_y.yml b/presets/c00120/xcs_xfls_y.yml new file mode 100644 index 0000000..f7e18fc --- /dev/null +++ b/presets/c00120/xcs_xfls_y.yml @@ -0,0 +1,5 @@ +R20LJ9p8: + active: true + history: + 28 Jan 2022 00:49:34: ' 64.6118' + value: 64.61181640625 diff --git a/presets/c00120/xcs_xfls_z.yml b/presets/c00120/xcs_xfls_z.yml new file mode 100644 index 0000000..ac47c90 --- /dev/null +++ b/presets/c00120/xcs_xfls_z.yml @@ -0,0 +1,5 @@ +R20LJ9p8: + active: true + history: + 28 Jan 2022 00:49:37: ' -190.0024' + value: -190.00244140625 diff --git a/presets/lv5719/ljh_jet_x.yml b/presets/lv5719/ljh_jet_x.yml new file mode 100644 index 0000000..39fd032 --- /dev/null +++ b/presets/lv5719/ljh_jet_x.yml @@ -0,0 +1,10 @@ +JetGaf: + active: true + history: + 14 Feb 2022 22:39:04: ' 36.4918' + value: 36.4918 +YagGaf: + active: true + history: + 14 Feb 2022 22:40:47: ' 16.4911' + value: 16.491100000000003 diff --git a/xcs/beamline.py b/xcs/beamline.py index 3384511..fb0ed8c 100644 --- a/xcs/beamline.py +++ b/xcs/beamline.py @@ -274,6 +274,7 @@ class XFLS(BaseInterface, Device): from xcs.db import xcs_txt as txt from xcs.db import xcs_lxt_fast as lxt_fast + from xcs.db import xcs_lodcm as lom from xcs.db import xcs_ccm as ccm #from xcs.db import xcs_xfls as crl2 from xcs.db import xcs_pfls as crl1 @@ -305,10 +306,15 @@ class XFLS(BaseInterface, Device): lib_y: 'default' } -with safe_load('Syringe Pump'): +#with safe_load('Syringe Pump'): +# #from xcs.syringepump import SyringePump +# from xcs.devices import SyringePump +# syringepump=SyringePump('solvent_topup',"XCS:USR:ao1:0","XCS:USR:ao1:1") + +with safe_load('Syringe_Pump'): #from xcs.syringepump import SyringePump - from xcs.devices import SyringePump - syringepump=SyringePump('solvent_topup',"XCS:USR:ao1:0","XCS:USR:ao1:1") + from xcs.devices import Syringe_Pump + syringe_pump=Syringe_Pump() with safe_load('import macros'): from xcs.macros import * @@ -324,10 +330,34 @@ class XFLS(BaseInterface, Device): with safe_load('bluesky setup'): from bluesky.callbacks.mpl_plotting import initialize_qt_teleporter initialize_qt_teleporter() + with safe_load('ladm_det'): xcsdet_y = IMS('XCS:LAM:MMS:07',name = 'xcsdet_y') xcsdet_x = IMS('XCS:LAM:MMS:06',name = 'xcsdet_x') +with safe_load('LADM'): + from pcdsdevices.ladm import LADM, LADMMotors, Beamstops + from pcdsdevices.positioner import FuncPositioner + lm = LADMMotors('XCS:LAM', name='ladm_motors') + bs = Beamstops('XCS:LAM', name='ladm_beamstops') + theta_pv = EpicsSignal('XCS:VARS:LAM:Theta', name = 'LADM_theta') + gamma_pv = EpicsSignal('XCS:VARS:LAM:Gamma', name='LADM_gamma') + ladm = LADM( + lm.x1_us, + lm.y1_us, + lm.x2_ds, + lm.y2_ds, + lm.z_us, + theta_pv, gamma_pv + ) + ladmTheta = FuncPositioner(name='ladmTheta',move=ladm.moveTheta,get_pos=ladm.wmTheta,set_pos=ladm.setTheta) + ladm.theta = ladmTheta + ladmXT = FuncPositioner(name='ladmXT',move=ladm.moveX, get_pos=ladm.wmX, set_pos=ladm._setX, egu='mm', limits=(ladm._get_lowlimX, ladm._get_hilimX)) + ladm.XT = ladmXT + + #ladm.__lowlimX=ladm._set_lowlim(-10) + #ladm.__hilimX=ladm._set_hilim(2000) + with safe_load('drift monitor'): import numpy as np import json @@ -364,7 +394,8 @@ def tt_rough_FB(ttamp_th = 0.02, ipm4_th = 500, tt_window = 0.05): #ipm2val = float((ttdata.split(" "))[5]) #ttfwhm = float((ttdata.split(" "))[7]) if(dlen%10 == 0): - print("tt_value",current_tt,"ttamp",ttamp,"ipm4",ipm4val) + #print("tt_value",current_tt,"ttamp",ttamp,"ipm4",ipm4val) + print("tt_value:%0.3f" %current_tt + " ttamp:%0.3f " %ttamp +" ipm4:%d" %ipm4val) if (ttamp > ttamp_th)and(ipm4val > ipm4_th)and(ttfwhm < 130)and(ttfwhm > 30)and(current_tt != tenshots_tt[-1,]):# for filtering the last one is for when DAQ is stopping tenshots_tt = np.insert(tenshots_tt,dlen,current_tt) dlen = np.shape(tenshots_tt)[0] @@ -480,3 +511,38 @@ def tt_find(ini_delay = 10e-9):#tt signal find tool the ini_delay is now input a print('\033[1m'+"Switch to binary search"+'\033[0m') break prebs = bs#the correlation change? + + +with safe_load('gige hdf5 beta'): + from pcdsdevices.areadetector.detectors import PCDSHDF5BlueskyTriggerable + xcs_gige_lj1_hdf5 = PCDSHDF5BlueskyTriggerable( + 'XCS:GIGE:LJ1:', + name='xcs_gige_lj1_hdf5', + write_path='/cds/data/iocData/ioc-xcs-gige-lj1', + ) + +def snd_park(): + with safe_load('Split and Delay'): + from hxrsnd.sndsystem import SplitAndDelay + from xcs.db import daq, RE + snd = SplitAndDelay('XCS:SND', name='snd', daq=daq, RE=RE) + snd.t1.L.mv(250,wait = True) + snd.t4.L.mv(250,wait = True) + + snd.dd.x.mv(-270,wait = False) + snd.di.x.mv(-90,wait = False) + snd.do.x.mv(-100,wait = False) + snd.dci.x.mv(70,wait = False) + snd.dco.x.mv(70,wait = False) + snd.dcc.x.mv(120,wait = False) + + snd.t1.tth.mv(0,wait = True) + snd.t4.tth.mv(0,wait = True) + + snd.t2.x.mv(70,wait = False) + + snd.t1.x.mv(90) + snd.t4.x.mv(90) + + snd.t3.x.mv(70) + return True diff --git a/xcs/devices.py b/xcs/devices.py index afac60c..4823203 100644 --- a/xcs/devices.py +++ b/xcs/devices.py @@ -11,6 +11,7 @@ from pcdsdevices.inout import InOutPositioner from subprocess import check_output import time +from pcdsdevices.analog_signals import Acromag class LaserShutter(InOutPositioner): """Controls shutter controlled by Analog Output""" @@ -41,59 +42,32 @@ def _do_move(self, state): #TTL I/O Operational Trigger -class SyringePump: - def __init__(self,name,base,ttl,vlow=0,vhigh=5): - self.name=name - self.base=PV(base) - self.ttl=PV(ttl) - self.vlow=vlow - self.vhigh=vhigh - self.delta=0.5 - self._is_initialized=False - def _initialize(self): - if not self._is_initialized: - self.base.put(self.vhigh) - self.ttl.put(self.vlow) - self._is_initialized=True - def _uninitialize(self): - if self._is_initialized: - self.base.put(self.vlow) - self.ttl.put(self.vlow) - self._is_initialized=False +class Syringe_Pump(): + def __init__(self): + self.signals = Acromag('XCS:USR', name='syringe_pump_channels') + self.base = self.signals.ao1_0 + self.ttl = self.signals.ao1_1 def on(self): - if not self._is_initialized: - self._initialize() - self.ttl.put(self.vhigh) - sleep(1) - self.ttl.put(self.vlow) - sleep(1) - self.ttl.put(self.vhigh) + ttl = self.ttl.get() + self.base.put(5) + if ttl == 5: + self.ttl.put(0) + print('Initialized and on') + if ttl == 0: + self.ttl.put(5) + sleep(1) + self.ttl.put(0) + print("Syringe pump is on") def off(self): - if not self._is_initialized: - self._initialize() - self.ttl.put(self.vhigh) - sleep(1) - self.ttl.put(self.vlow) - def status_string(self): - status_string='Syringepump is in unknown state' - if not self._is_initialized: - status_string='Syringepump is not initialized' - else: - if abs(self.ttl.get()-self.vhigh)