From 6d3f5ff028f34fdc97c5560cbbe6c90b2c7caa72 Mon Sep 17 00:00:00 2001 From: "FR@29iduser" <rodolakis@anl.gov> Date: Mon, 12 Sep 2022 17:09:37 -0500 Subject: [PATCH] changed iex_vpu --- iexcode.egg-info/SOURCES.txt | 1 + iexcode/cheatsheet.txt | 15 +- iexcode/instruments/IEX_VPU.py | 203 +++++----- iexcode/instruments/IEX_VPU_backup.py | 544 ++++++++++++++++++++++++++ 4 files changed, 648 insertions(+), 115 deletions(-) create mode 100644 iexcode/instruments/IEX_VPU_backup.py diff --git a/iexcode.egg-info/SOURCES.txt b/iexcode.egg-info/SOURCES.txt index 2b4744d..28247ed 100644 --- a/iexcode.egg-info/SOURCES.txt +++ b/iexcode.egg-info/SOURCES.txt @@ -23,6 +23,7 @@ iexcode/instruments/Lakeshore_335.py iexcode/instruments/Logfile.py iexcode/instruments/MPA.py iexcode/instruments/Motors.py +iexcode/instruments/Octupole.py iexcode/instruments/Scienta.py iexcode/instruments/VLS_PGM.py iexcode/instruments/__init__.py diff --git a/iexcode/cheatsheet.txt b/iexcode/cheatsheet.txt index 2cc6961..668cf78 100644 --- a/iexcode/cheatsheet.txt +++ b/iexcode/cheatsheet.txt @@ -99,10 +99,19 @@ BL_mda_filepath => returns the file path in mda scanRecord get_all => gets relavent pv values #IEX_VPU: undulator functions +ID_calc_SP => calculate the set point for maximum flux +ID_wait_for_permission => waits for security access ID_get_all => gets ID_mode, ID_QP_ratio, ID_sp, ID_rbv -ID_off => turns off the ID -ID_start => turns on the ID -ID_restart => turns off the ID and then turns it on with the same set point +ID_energy_range => return max/min for a given mode +ID_ready => looks at the two busy records +ID_off/on => turns off/on the ID +ID_power_status => returns off/on +ID_start => turns on the ID in a given mode +ID_switch_mode => changes the ID mode +ID_get/set => gets rbv / sets val in keV +ID_energy_set => set calibrated energy in eV +ID_rbv_get + #kappa_angle_calcs: fourc2kappa => converts between four-circle angles and kappa angles diff --git a/iexcode/instruments/IEX_VPU.py b/iexcode/instruments/IEX_VPU.py index 45ddf3a..f368beb 100644 --- a/iexcode/instruments/IEX_VPU.py +++ b/iexcode/instruments/IEX_VPU.py @@ -16,14 +16,36 @@ IDcal_path="/home/beams22/29IDUSER/Documents/User_Macros/Macros_29id/IEX_Diction ################################ ID limits and calibration ############################## ############################################################################################################## -def ID_calc_SP(mono_grating,ID_mode,hv_eV,QP_ratio): # Mode = state (0=RCP,1=LCP,2=V,3=H) +pv = 'ID29:' +pvs={'AccessSecurity':pv+'AccessSecurity.VAL', + 'mode_rbv':pv+'ActualMode', + 'mode_val':pv+'DesiredMode.VAL', + 'check_ready':pv+'feedback.VAL', + 'check_busy':pv+'BusyRecord', + 'busy_reset':pv+'Busy.VAL', + 'main_power':pv+'Main_on_off.VAL', + 'energy_rbv':pv+'Energy.VAL', + 'energy_sp':pv+'EnergySet.VAL', + 'start_ramp':pv+'StartRamp.VAL', + 'energy_eV_rbv':pv+'EnergyRBV', + 'energy_eV_sp':pv+'EnergyScanSet.VAL', + 'scan_eV_rbv':pv+'EnergyScanSeteV', + 'scan_eV_val':pv+'EnergySetRBV', + 'table_dir':pv+'TableDirection', + 'By_q':pv+'ByqRdbk', + 'Bx_q':pv+'BxqRdbk', + 'Vcoil':pv+'ByRdbk.VAL', + 'Hcoil':pv+'BxRdbk.VAL', + 'QP_ratio':pv+'QuasiRatio.RVAL',} + + + +def ID_calc_eV(mono_grating,ID_mode,hv_eV,QP_ratio): # Mode = state (0=RCP,1=LCP,2=V,3=H) """Calculate the ID SP for a given polarization mode and energy; with Mode = 0 (RCP),1 (LCP), 2 (V), 3 (H) Previously: ID_Calc - """ - - + """ if type(ID_mode)== str: ID_state=ID_state_mode(ID_mode) try: @@ -32,7 +54,7 @@ def ID_calc_SP(mono_grating,ID_mode,hv_eV,QP_ratio): # Mode = state (0=RCP,1= except KeyError: message_string='Not a valid ID mode!'+"\nValid Modes: "+str(ID_mode_list()) print_warning_message(message_string) - ID=caget("ID29:EnergySeteV") + ID=caget(pvs['energy_rbv']) return round(ID,1) ############################################################################################################## @@ -48,7 +70,7 @@ def ID_wait_for_permission(): Previously: WaitForPermission """ while True: - ID_Access=caget("ID29:AccessSecurity.VAL") + ID_Access=caget(pvs['AccessSecurity']) if (ID_Access!=0): print("Checking ID permission, please wait..."+dateandtime()) sleep(30) @@ -66,8 +88,8 @@ def ID_get_all(verbose=False): vals={ "ID_mode":ID_mode_get(verbose=False), "ID_QP_ratio":ID_QP_ratio_get(verbose=False), - "ID_sp":ID_SP_get_eV(verbose=False), - "ID_rbv":ID_rbv_get_eV(verbose=False) + "ID_sp":caget(pvs['energy_sp']), + "ID_rbv":ID_get_eV(verbose=False) } if verbose: @@ -82,14 +104,12 @@ def ID_energy_range(ID_mode=None): Previously: ID_Range """ if ID_mode == None: - ID_state=caget("ID29:ActualMode") + ID_state=caget(pvs['mode_rbv']) else: ID_state = ID_state_mode(ID_mode) # RCP,LCP, V , H , HN - ID_min_SP = [400,400,440,250,250] - ID_max_SP = 3800 - #hv_min=[390,390,430,245,245] - + ID_min_SP = [.400,.400,.440,.250,.250] + ID_max_SP = 3.800 return ID_min_SP[ID_state],ID_max_SP def ID_mode_list(): @@ -120,14 +140,14 @@ def ID_state_get(): """ Returns the current ID state """ - ID_state = caget("ID29:ActualMode") + ID_state = caget(pvs['mode_rbv']) return ID_state def ID_mode_get(verbose=True): """ Returns the current ID mode """ - ID_state = caget("ID29:ActualMode") + ID_state =ID_state_get() ID_mode = ID_mode_list()[ID_state] if verbose: @@ -138,7 +158,7 @@ def ID_mode_set(ID_mode): """ writes the desired mode to the correct ID pv """ - caput("ID29:DesiredMode.VAL",ID_mode,wait=True,timeout=18000) # RCP + caput(pvs['mode_val'],ID_mode,wait=True,timeout=18000) # RCP def ID_ready(verbose=True): @@ -148,13 +168,13 @@ def ID_ready(verbose=True): Previously: ID_Ready """ while True: - RBV=caget("ID29:Energy.VAL") - checkready=caget("ID29:feedback.VAL") - checkbusy=caget("ID29:BusyRecord") + RBV=caget(pvs['energy_rbv']) + checkready=caget(pvs['check_ready']) + checkbusy=caget(pvs['check_busy']) if (checkready!="Ready") or (RBV < 3.7): sleep(2) elif ((checkready=="Ready") and (RBV > 3.7)) and (checkbusy=="Busy"): - caput("ID29:Busy.VAL",0) + caput(pvs['busy_reset'],0) else: if verbose: print("ID Ready") @@ -164,7 +184,7 @@ def ID_power_status(): """ gets if the ID power supplies are On or Off """ - ID_OnOff=caget('ID29:Main_on_off.VAL') + ID_OnOff=caget(pvs['main_power']) if ID_OnOff == 1: return 'Off' elif ID_OnOff == 0: @@ -175,7 +195,7 @@ def ID_off(verbose=True): waits for permission then turns on the main coils OFF """ ID_wait_for_permission() - caput("ID29:Main_on_off.VAL",1,wait=True,timeout=18000) + caput(pvs['main_power'],1,wait=True,timeout=18000) sleep(5) if verbose: print("ID is now off") @@ -185,12 +205,13 @@ def ID_on(verbose=True): """ waits for permission then turns on the main coils On """ + ID_wait_for_permission() if verbose: print("Starting ID - "+dateandtime()) - caput("ID29:EnergySet.VAL",3.8) - caput("ID29:Main_on_off.VAL",0,wait=True,timeout=18000) + caput(pvs['energy_sp'],3.8) + caput(pvs['main_power'],0,wait=True,timeout=18000) def ID_start(ID_mode='RCP',QP_ratio=None, verbose=True): """ @@ -241,58 +262,40 @@ def ID_switch_mode(ID_mode): except: print_warning_message("Not a valid ID mode") -def ID_SP_get(verbose=False): - """ - returns the ID setpoint in keV - """ - ID_SP = caget("ID29:EnergyScanSet.VAL") - if verbose: - print("ID_SP: ", ID_SP) - return ID_SP - -def ID_SP_get_eV(verbose=False): - """ - returns the ID setpoint in eV - """ - ID_SP = ID_SP_get(verbose=False) - if verbose: - print("ID_SP: ", ID_SP) - return ID_SP - -def ID_rbv_get(verbose=False): +def ID_get(verbose=False): """ returns the readback value for the """ - ID_RBV = caget("ID29:EnergyRBV") + ID_RBV = caget(pvs['energy_rbv']) if verbose: print("ID_RBV: ", ID_RBV) return ID_RBV -def ID_rbv_get_eV(verbose=False): +def ID_get_eV(verbose=False): """ returns the readback value for the """ - ID_RBV = ID_rbv_get(verbose=False) + ID_RBV = ID_get(verbose=False)*1000 if verbose: print("ID_RBV: ", ID_RBV) return ID_RBV -def ID_SP_set(hv_eV,verbose=True): +def ID_set(keV,verbose=True): """ "Sets the ID set point to a specific value (hv(eV)) which will not likely be optimum" Previously: SetID_Raw """ def _ID_write_SP_proc(keV): - caput("ID29:EnergyScanSet.VAL",keV,wait=True,timeout=18000) + caput(pvs['energy_sp'],keV,wait=True,timeout=18000) sleep(0.5) - caput("ID29:EnergyScanSet.VAL",(keV+0.001),wait=True,timeout=18000) - caput('ID29:StartRamp.VAL',1) + caput(pvs['start_ramp'],1) - def _ID_bw_ok(ID_SP): - ID_bw = ID_SP*0.095 - ID_diff = abs(ID_rbv_get()-ID_SP) + def _ID_bw_ok(keV,verbose=False): + ID_SP = caget(pvs['energy_sp']) + ID_bw = ID_SP * 0.095 + ID_diff = abs(ID_get()-keV) if ID_diff > ID_bw: return False else: @@ -304,56 +307,31 @@ def ID_SP_set(hv_eV,verbose=True): #checking if desired is with allowed range, if not printing the nearest allowed value ID_max,ID_min = ID_energy_range() - ID_SP=min(max(hv_eV,ID_min),ID_max)*1.0 - if hv_eV < ID_min or hv_eV > ID_max: + if keV < ID_min or keV > ID_max: message_string="Set point out of BL energy range \nPlease select a different energy." - message_string+="\nClosest allowed value is "+str(ID_SP) + message_string+="\nClosest allowed value is "+str(min(max(keV,ID_min),ID_max)) print_warning_message(message_string) else: #desired energy is within range - ID_SP_RBV=round(caget("ID29:EnergySet.VAL"),3)*1000 - ID_RBV=caget("ID29:EnergyRBV") - if ID_SP == ID_SP_RBV: - #ID is already at the SP energy - if verbose: - print("ID SET : "+"%.1f" % ID_SP, "eV") - print("ID RBV : "+"%.1f" % ID_RBV, "eV") - print(caget('ID29:TableDirection',as_string=True)) - - else: - # ID not at energy - ready = ID_ready(verbose=False) - if ready: - #set the energy - _ID_write_SP_proc(ID_SP/1000) - - while not ID_ready(verbose=False): - sleep(20) - - #is ID within some bandwidth - if _ID_bw_ok(ID_SP) == False: - sleep(20) - if _ID_bw_ok(ID_SP) == False: - print("\nID RBV : "+"%.1f" % ID_RBV, "eV") - ID_start(ID_mode_get()) - if ID_ready(verbose=False): - #set the energy - _ID_write_SP_proc(ID_SP/1000) - - if verbose: - print("\nID SET : "+"%.1f" % ID_SP, "eV") - print("ID RBV : "+"%.1f" % ID_RBV, "eV") - print(caget('ID29:TableDirection',as_string=True)) - - if ID_QP_ratio_get()[0] < 100: - #check ratio - Byq=caget("ID29:ByqRdbk") - Vcoil=caget("ID29:ByRdbk.VAL") - ratio=Byq/Vcoil - ratio_RBV=caget("ID29:QuasiRatio.RVAL") - if verbose: - print("QP ratio =", round(ratio,3)*100,"%") - print("QP RBV =", ratio_RBV,"%") + _ID_write_SP_proc(keV) + # ID not at energy + ready = ID_ready(verbose=False) + if ready: + #set the energy + _ID_write_SP_proc(ID_SP/1000) + while not ID_ready(verbose=False): + sleep(20) + #is ID within some bandwidth + if _ID_bw_ok(ID_SP,verbose=verbose): + if verbose: + ID_SP = caget(pvs['energy_sp']) + ID_RBV = ID_get() + print("ID SET : "+"%.1f" % ID_SP, "eV") + print("ID RBV : "+"%.1f" % ID_RBV, "eV") + print(caget(pvs['table_dir'],as_string=True)) + else: + ID_QP_ratio_get(verbose) + def ID_energy_set(hv_eV,QP_ratio=None): """ @@ -366,8 +344,8 @@ def ID_energy_set(hv_eV,QP_ratio=None): """ ID_mode = ID_mode_list()[ID_state_get()] mono_grating = mono_grating_get() - ID_SP = ID_calc_SP(mono_grating,ID_mode,hv_eV,QP_ratio) - ID_SP_set(ID_SP) + keV = ID_calc_eV(mono_grating,ID_mode,hv_eV,QP_ratio)/1000.0 + ID_set(keV) def ID_QP_ratio_get(verbose=True): @@ -376,13 +354,14 @@ def ID_QP_ratio_get(verbose=True): calculate the QP ratio """ - Byq=caget("ID29:ByqRdbk") - Vcoil=caget("ID29:ByRdbk.VAL") - ratio_calc=Byq/Vcoil - ratio_RBV=caget("ID29:QuasiRatio.RVAL") + Byq=caget(pvs['By_q']) + Vcoil=caget(pvs['Vcoil']) + ratio_calc=round(Byq/Vcoil,3)*100 + ratio_RBV=caget(pvs['QP_ratio']) if verbose: - print("QP ratio =", round(ratio_RBV,3)*100,"%") print("QP RBV =", ratio_RBV,"%") + print("QP calculated ratio =", ratio_calc ,"%") + if abs(ratio_RBV-ratio_calc)>1: message_string="QP RBV and QP calc do not agree \nCheck Interlocks" @@ -479,9 +458,9 @@ def ID_scan_pvs(): """ returns the rbv and val for scanning """ - val_pv="ID29:EnergyScanSeteV" - rbv_pv="ID29:EnergySetRBV" - return val_pv, rbv_pv + val_pv=pvs['scan_eV_val'] + rbv_pv=pvs['scan_eV_rbv'] + return rbv_pv, val_pv def ID_scan_fillin(mda,scan_dim,start,stop,step,**kwargs): """ @@ -491,7 +470,7 @@ def ID_scan_fillin(mda,scan_dim,start,stop,step,**kwargs): """ #Setting up the ScanRecord for ID in Table mode val_pv, rbv_pv = ID_scan_pvs() - mda.fillin(scan_dim,val_pv,rbv_pv,start,stop,step,**kwargs) + mda.fillin(scan_dim,rbv_pv,val_pv,start,stop,step,**kwargs) def ID_scan_fillin_table(mda,scan_dim,ID_array,**kwargs): @@ -501,8 +480,8 @@ def ID_scan_fillin_table(mda,scan_dim,ID_array,**kwargs): **kwargs => scanRecord.fillin kwargs """ #Setting up the ScanRecord for ID in Table mode - val_pv, rbv_pv = ID_scan_pvs() - mda.fillin.table(scan_dim,val_pv,rbv_pv,ID_array,**kwargs) + rbv_pv, val_pv = ID_scan_pvs() + mda.fillin.table(scan_dim,rbv_pv,val_pv,ID_array,**kwargs) ############################################################################################################## ############################## ID direction table ############################## diff --git a/iexcode/instruments/IEX_VPU_backup.py b/iexcode/instruments/IEX_VPU_backup.py new file mode 100644 index 0000000..57ff364 --- /dev/null +++ b/iexcode/instruments/IEX_VPU_backup.py @@ -0,0 +1,544 @@ +from os import path +from math import * +from time import sleep +import numpy.polynomial.polynomial as poly + +from epics import caget, caput + +from iexcode.instruments.userCalcs import userCalcOut_clear +from iexcode.instruments.utilities import dateandtime, print_warning_message, read_dict +from iexcode.instruments.VLS_PGM import mono_grating_get +from iexcode.instruments.shutters import main_shutter_open + +IDcal_path="/home/beams22/29IDUSER/Documents/User_Macros/Macros_29id/IEX_Dictionaries" + +############################################################################################################## +################################ ID limits and calibration ############################## +############################################################################################################## + +def ID_calc_SP(mono_grating,ID_mode,hv_eV,QP_ratio): # Mode = state (0=RCP,1=LCP,2=V,3=H) + """Calculate the ID SP for a given polarization mode and energy; + with Mode = 0 (RCP),1 (LCP), 2 (V), 3 (H) + + Previously: ID_Calc + """ + + + if type(ID_mode)== str: + ID_state=ID_state_mode(ID_mode) + try: + K=ID_coef(mono_grating,ID_state,hv_eV,QP_ratio) + ID=poly.polyval(hv_eV,K) + except KeyError: + message_string='Not a valid ID mode!'+"\nValid Modes: "+str(ID_mode_list()) + print_warning_message(message_string) + ID=caget("ID29:EnergySeteV") + return round(ID,1) + +############################################################################################################## +################################ ID Functions ############################## +############################################################################################################## + + +def ID_wait_for_permission(): + """ + Monitors the ID permissions and waits for the ID to be in User Mode and then breaks + Checks the status every 30 seconds + + Previously: WaitForPermission + """ + while True: + ID_Access=caget("ID29:AccessSecurity.VAL") + if (ID_Access!=0): + print("Checking ID permission, please wait..."+dateandtime()) + sleep(30) + else: + print("ID now in user mode -"+dateandtime()) + break + +############################################################################################################## +def ID_get_all(verbose=False): + """ + returns dictionary with: ID_Mode, ID_QP_ratio, ID_SP, ID_RBV + + Previously: Get_energy + """ + vals={ + "ID_mode":ID_mode_get(verbose=False), + "ID_QP_ratio":ID_QP_ratio_get(verbose=False), + "ID_sp":ID_SP_get_eV(verbose=False), + "ID_rbv":ID_rbv_get_eV(verbose=False) + } + + if verbose: + print(" ID SP : "+"%.2f" % vals["ID_sp"] , "eV ID mode : "+vals["ID_mode"]) + print(" ID RBV : "+"%.2f" % vals['ID_rbv'], "eV QP mode : "+str(vals['ID_QP_ratio']) +" %") + return vals + +def ID_energy_range(ID_mode=None): + """ + Returns the ID_min_SP, ID_max_SP for a given ID mode + + Previously: ID_Range + """ + if ID_mode == None: + ID_state=caget("ID29:ActualMode") + else: + ID_state = ID_state_mode(ID_mode) + # RCP,LCP, V , H , HN + ID_min_SP = [400,400,440,250,250] + ID_max_SP = 3800 + #hv_min=[390,390,430,245,245] + + return ID_min_SP[ID_state],ID_max_SP + +def ID_mode_list(): + """ + returns the ID_mode_List + current mode = + """ + return ["RCP", "LCP", "V", "H", "HN"] + + +def ID_state_mode(ID_mode): + """ + Returns the state number if mode is a string + Returns the mode string if mode is an int or float + + Previously: ID_State2Mode(which,mode) + """ + try: + ID_mode = ID_mode.upper() + ID_state =ID_mode_list().index(ID_mode) + return ID_state + + except: + message_string='Not a valid ID mode!'+"\nValid Modes: "+str(ID_mode_list()) + print_warning_message(message_string) + +def ID_state_get(): + """ + Returns the current ID state + """ + ID_state = caget("ID29:ActualMode") + return ID_state + +def ID_mode_get(verbose=True): + """ + Returns the current ID mode + """ + ID_state = caget("ID29:ActualMode") + ID_mode = ID_mode_list()[ID_state] + + if verbose: + print('ID mode: '+ID_mode) + return ID_mode + +def ID_mode_set(ID_mode): + """ + writes the desired mode to the correct ID pv + """ + caput("ID29:DesiredMode.VAL",ID_mode,wait=True,timeout=18000) # RCP + + +def ID_ready(verbose=True): + """ + check both the read and busy pv every 2 seconds + + Previously: ID_Ready + """ + while True: + RBV=caget("ID29:Energy.VAL") + checkready=caget("ID29:feedback.VAL") + checkbusy=caget("ID29:BusyRecord") + if (checkready!="Ready") or (RBV < 3.7): + sleep(2) + elif ((checkready=="Ready") and (RBV > 3.7)) and (checkbusy=="Busy"): + caput("ID29:Busy.VAL",0) + else: + if verbose: + print("ID Ready") + return True + +def ID_power_status(): + """ + gets if the ID power supplies are On or Off + """ + ID_OnOff=caget('ID29:Main_on_off.VAL') + if ID_OnOff == 1: + return 'Off' + elif ID_OnOff == 0: + return 'On' + +def ID_off(verbose=True): + """ + waits for permission then turns on the main coils OFF + """ + ID_wait_for_permission() + caput("ID29:Main_on_off.VAL",1,wait=True,timeout=18000) + sleep(5) + if verbose: + print("ID is now off") + + +def ID_on(verbose=True): + """ + waits for permission then turns on the main coils On + """ + ID_wait_for_permission() + if verbose: + print("Starting ID - "+dateandtime()) + + caput("ID29:EnergySet.VAL",3.8) + caput("ID29:Main_on_off.VAL",0,wait=True,timeout=18000) + +def ID_start(ID_mode='RCP',QP_ratio=None, verbose=True): + """ + waits for ID permission and then + starts ID with a specific polarization + mode = \"H\", \"V\", \"RCP\" or \"LCP\" + QP ratio if specified + """ + #turns on if ID is off + if ID_power_status =='Off': + ID_on() + #set QP + if ID_ready(): + ID_QP_mode_set(QP_ratio,verbose) + #set ID mode + if ID_ready(): + ID_mode_set(ID_mode, verbose) + #opens the main shutter + if ID_ready(): + main_shutter_open() + + if verbose: + print('ID is now on, please set your energy') + +def ID_switch_mode(ID_mode): + """ + Change ID polarization; which = 'H', 'V', 'RCP' or 'LCP' + if ID_mode = current mode then does nothing + + WARNING: Does not set the energy + + Previously Switch_IDMode + """ + ID_wait_for_permission() + main_shutter_open() + ID_state = ID_state_get() + + try: + if ID_state_mode(ID_mode) != ID_state: + print("Turning ID off...") + ID_off(verbose=True) + sleep(10) + + print("Switching ID mode, please wait...") + ID_mode_set(ID_mode) + ID_ready() + print("ID Mode:",ID_mode) + except: + print_warning_message("Not a valid ID mode") + +def ID_SP_get(verbose=False): + """ + returns the ID setpoint in keV + """ + ID_SP = caget("ID29:EnergyScanSet.VAL") + if verbose: + print("ID_SP: ", ID_SP) + return ID_SP + +def ID_SP_get_eV(verbose=False): + """ + returns the ID setpoint in eV + """ + ID_SP = ID_SP_get(verbose=False) + if verbose: + print("ID_SP: ", ID_SP) + return ID_SP + +def ID_rbv_get(verbose=False): + """ + returns the readback value for the + """ + ID_RBV = caget("ID29:EnergyRBV") + if verbose: + print("ID_RBV: ", ID_RBV) + return ID_RBV + +def ID_rbv_get_eV(verbose=False): + """ + returns the readback value for the + """ + ID_RBV = ID_rbv_get(verbose=False) + if verbose: + print("ID_RBV: ", ID_RBV) + return ID_RBV + + +def ID_SP_set(hv_eV,verbose=True): + """ + "Sets the ID set point to a specific value (hv(eV)) which will not likely be optimum" + + Previously: SetID_Raw + """ + def _ID_write_SP_proc(keV): + caput("ID29:EnergyScanSet.VAL",keV,wait=True,timeout=18000) + sleep(0.5) + caput("ID29:EnergyScanSet.VAL",(keV+0.001),wait=True,timeout=18000) + caput('ID29:StartRamp.VAL',1) + + def _ID_bw_ok(ID_SP): + ID_bw = ID_SP*0.095 + ID_diff = abs(ID_rbv_get()-ID_SP) + if ID_diff > ID_bw: + return False + else: + return True + + #checking permissions and opening the main shutter + ID_wait_for_permission() + main_shutter_open() + + #checking if desired is with allowed range, if not printing the nearest allowed value + ID_max,ID_min = ID_energy_range() + ID_SP=min(max(hv_eV,ID_min),ID_max)*1.0 + if hv_eV < ID_min or hv_eV > ID_max: + message_string="Set point out of BL energy range \nPlease select a different energy." + message_string+="\nClosest allowed value is "+str(ID_SP) + print_warning_message(message_string) + else: + #desired energy is within range + ID_SP_RBV=round(caget("ID29:EnergySet.VAL"),3)*1000 + ID_RBV=caget("ID29:EnergyRBV") + if ID_SP == ID_SP_RBV: + #ID is already at the SP energy + if verbose: + print("ID SET : "+"%.1f" % ID_SP, "eV") + print("ID RBV : "+"%.1f" % ID_RBV, "eV") + print(caget('ID29:TableDirection',as_string=True)) + + else: + # ID not at energy + ready = ID_ready(verbose=False) + if ready: + #set the energy + _ID_write_SP_proc(ID_SP/1000) + + while not ID_ready(verbose=False): + sleep(20) + + #is ID within some bandwidth + if _ID_bw_ok(ID_SP) == False: + ID_QP_ratio_get print("QP ratio =", round(ratio,3)*100,"%") + print("QP RBV =", ratio_RBV,"%") + +def ID_energy_set(hv_eV,QP_ratio=None): + """ + Sets optimum ID set point for hv(eV) (max intensity) + and opens the main shutter + + Note that QP is generally not calibrated + + Previously: SetID + """ + ID_mode = ID_mode_list()[ID_state_get()] + mono_grating = mono_grating_get() + ID_SP = ID_calc_SP(mono_grating,ID_mode,hv_eV,QP_ratio) + ID_SP_set(ID_SP) + + +def ID_QP_ratio_get(verbose=True): + """ + gets the read back for the QP ratio + calculate the QP ratio + + """ + Byq=caget("ID29:ByqRdbk") + Vcoil=caget("ID29:ByRdbk.VAL") + ratio_calc=Byq/Vcoil + ratio_RBV=caget("ID29:QuasiRatio.RVAL") + if verbose: + print("QP ratio =", round(ratio_RBV,3)*100,"%") + print("QP RBV =", ratio_RBV,"%") + + if abs(ratio_RBV-ratio_calc)>1: + message_string="QP RBV and QP calc do not agree \nCheck Interlocks" + print_warning_message(message_string) + return ratio_RBV, ratio_calc + +def ID_QP_mode_set(QP_ratio=None,verbose=True): + """ + switched to QP mode, if not currently in + sets the QP ratio (QP ratio min is 70) and polarization (ID mode) + + WARNING: you will need to set the polarization and mode afterward + + Previously: Switch_IDQP + """ + + #checking if above the minimum allowed value + QP_min = 70 + if QP_ratio < QP_min: + message_string="QP ratio is too small, setting it to minimum allowed value ("+str(QP_min)+")" + print_warning_message(message_string) + QP_ratio=max(70,QP_ratio) + + if QP_ratio != None: + #checking to see if already in specified QP + ratio_RBV, ratio_calc = ID_QP_ratio_get() + #not the same ratio + if ratio_RBV != QP_ratio: + ID_off() + caput("ID29:QuasiRatioIn.C",QP_ratio) + + ID_on() + sleep(15) + + +def ID_coef(grt,ID_state,hv_eV,QP_ratio): # Mode = state (0=RCP,1=LCP,2=V,3=H); + + """Return the ID coeff for a given polarization mode and energy; + with Mode = 0 (RCP),1 (LCP), 2 (V), 3 (H). + Current coefficient dictionary: + /home/beams22/29IDUSER/Documents/User_Macros/Macros_29id/IEX_Dictionaries/Dict_IDCal.txt + + Previously: ID_Coef + """ + + if QP_ratio == None: + QP_ratio = ID_QP_ratio_get()[0] + + def ListRange(grt,ID_state,IDdict): # extract the list of break pts for a given mode/grt + tmp_list=[] + for item in (IDdict[grt][ID_state]): + tmp_list.append(item[0]) + return tmp_list + + + def FindRange(hv_eV,range_list): # returns the index for the corresponding range + B = [x - hv_eV for x in range_list] + #print(B) + index = [i for (i, x) in enumerate(B) if x > 0] + #print(index) + return(index[0]) + + + + if QP_ratio < 100: + if isinstance(QP_ratio,float) or isinstance(QP_ratio,int): + QP_ratio=str(floor(QP_ratio)) + dictfile='Dict_IDCal_QP'+QP_ratio+'.txt' + error_msg="calibration curve might not exist for this QP value" + else: + print('invalid QP value') + return + else: + dictfile='Dict_IDCal.txt' + error_msg="" + try: + IDcal_fpath = path.join(IDcal_path,dictfile) + ID_function=read_dict(IDcal_fpath) + + except KeyError: + print("Unable to read dictionary "+dictfile+" ; "+error_msg) + + try: + Lrange = ListRange(grt,ID_state,ID_function) + Erange = FindRange(hv_eV,Lrange) + K = ID_function[grt][ID_state][Erange][1] + return K + + except KeyError: + print("WARNING: PLease select one of the following: "+str(ID_mode_list())) + + +def ID_scan_pvs(): + """ + returns the rbv and val for scanning + """ + val_pv="ID29:EnergyScanSeteV" + rbv_pv="ID29:EnergySetRBV" + return val_pv, rbv_pv + +def ID_scan_fillin(mda,scan_dim,start,stop,step,**kwargs): + """ + fills in the scanRecord for scanning the ID set point + + **kwargs => scanRecord.fillin kwargs + """ + #Setting up the ScanRecord for ID in Table mode + val_pv, rbv_pv = ID_scan_pvs() + mda.fillin(scan_dim,val_pv,rbv_pv,start,stop,step,**kwargs) + + +def ID_scan_fillin_table(mda,scan_dim,ID_array,**kwargs): + """ + fills in the scanRecord for scanning the ID set point + + **kwargs => scanRecord.fillin kwargs + """ + #Setting up the ScanRecord for ID in Table mode + val_pv, rbv_pv = ID_scan_pvs() + mda.fillin.table(scan_dim,val_pv,rbv_pv,ID_array,**kwargs) + +############################################################################################################## +############################## ID direction table ############################## +############################################################################################################## + +def ID_Table(): + """ + + Previously: ID_Table + """ + table = caget("ID29:TableDirection") # up = 1 , down = 0 + By = caget("ID29:ByPolaritySet") # pos = 1, neg = 0 + + mode = ID_mode_get() + + if By > 0: + print("\nBy > 0") + if table == 1: # By=1, table = 1 => -1 => A=B + print("table = up") + ID_direction = -1 + elif table == 0: # By=1, table = 0 => +1 => A#B + print("table = down") + ID_direction = 1 + elif By <= 0: + print("\nBy < 0") + if table == 1: # By=0, table = 1 => +1 => A=B + print("table = up") + ID_direction = 1 + elif table == 0: # By=0, table = 0 => -1 => A#B + print("table = down") + ID_direction = -1 + + + if mode == "H" and mode == "RCP": + if By > 0 and table == 0: + print_warning_message("will do a long hysteresis if decreasing energy !!!") +# if Mode == "HN" and Mode == "LCP": +# if By = 0 and table == 1: +# print "WARNING: will do a long hysteresis if decreasing energy !!!" + print("ID direction", ID_direction) + return ID_direction + +def ID_table_userCalcOut(): + """ + # Work in progress + + Previously:ID_Table_CalcOut + """ + n=4 + userCalcOut_clear("b",n) + pvstr="29idb:userCalcOut"+str(n) + caput(pvstr+".DESC","ID_Table") + table="ID29:TableDirection" # up = 1 , down = 0 + By="ID29:ByPolaritySet" # pos = 1, neg = 0 + caput(pvstr+".INPA",table+" CP NMS") + caput(pvstr+".INPB",By+" CP NMS") + caput(pvstr+".CALC$","A#B") + caput(pvstr+".OOPT","On Change") + caput(pvstr+".DOPT","Use CALC") \ No newline at end of file -- GitLab