From 33a776796a95796a2df03fb7920806a798994148 Mon Sep 17 00:00:00 2001 From: jmcchesn <jmcchesn@aps.anl.gov> Date: Tue, 6 Sep 2022 16:36:27 -0500 Subject: [PATCH] diff April Sept --- build/lib/iexcode/instruments/Kappa.py | 6 +- build/lib/iexcode/instruments/xrays.py | 2 +- build/lib/iexcode/macros/start_of_the_week.py | 2 +- iexcode/cheatsheet.txt | 253 +++++ iexcode/instruments/FMB_mirrors.py | 2 +- iexcode/instruments/IEX_VPU.py | 251 ++--- iexcode/instruments/Kappa.py | 94 +- iexcode/instruments/MPA.py | 25 +- iexcode/instruments/Motors.py | 6 +- iexcode/instruments/current_amplifiers.py | 57 +- iexcode/instruments/electron_analyzer.py | 8 +- iexcode/instruments/m3r.py | 36 +- iexcode/instruments/scalers.py | 2 +- iexcode/instruments/scanRecord.py | 13 +- iexcode/instruments/slits.py | 46 +- iexcode/instruments/staff.py | 37 +- iexcode/instruments/utilities.py | 21 + iexcode/instruments/vortex.py | 155 +++- iexcode/instruments/xrays.py | 38 +- iexcode/macros/ID_energy_calibration.py | 511 +++++++++++ iexcode/macros/Kappa_optimization.py | 164 +++- iexcode/macros/commissioning.py | 298 ++---- iexcode/macros/quick_plot.py | 742 --------------- iexcode/macros/start_of_the_week.py | 867 ++++++++++++++---- 24 files changed, 2193 insertions(+), 1443 deletions(-) create mode 100644 iexcode/cheatsheet.txt create mode 100644 iexcode/macros/ID_energy_calibration.py diff --git a/build/lib/iexcode/instruments/Kappa.py b/build/lib/iexcode/instruments/Kappa.py index 2d6bb23..1789225 100644 --- a/build/lib/iexcode/instruments/Kappa.py +++ b/build/lib/iexcode/instruments/Kappa.py @@ -343,7 +343,7 @@ def Kappa_get_all(verbose=True): vals.update(beamline_info) mesh.get() - vals.update({'mesh':mesh.current}) + vals.update({'mesh':mesh.current_Amp}) if verbose: print("-----------------------------------------------------------") @@ -382,8 +382,8 @@ def _Kappa_log_entries(): TA = vals['TA'] TB = vals['TB'] mesh.get() - tey_current = tey.current - mesh_current = mesh.current + tey_current = tey.current_Amp + mesh_current = mesh.current_Amp det_name = tthdet.name mpa_HV = iex.mpa.HV_get() m3r_centroid = vals['kphi'] diff --git a/build/lib/iexcode/instruments/xrays.py b/build/lib/iexcode/instruments/xrays.py index 382804e..a86cc09 100644 --- a/build/lib/iexcode/instruments/xrays.py +++ b/build/lib/iexcode/instruments/xrays.py @@ -156,7 +156,7 @@ def _xrays_log_entries(**kwargs): #beamline info ID_mode = ID_mode_get(verbose=False) if iex.BL.xrays else "no_xrays" - ID_QP_ratio = ID_QP_ratio_get (verbose=False) if iex.BL.xrays else "no_xrays" + ID_QP_ratio = ID_QP_ratio_get(verbose=False)[0] if iex.BL.xrays else "no_xrays" ID_sp = round(ID_SP_get_eV()) if iex.BL.xrays else 0 ID_rbv = round(ID_rbv_get_eV,4) if iex.BL.xrays else 0 hv = mono_energy_get() if iex.BL.xrays else 0 diff --git a/build/lib/iexcode/macros/start_of_the_week.py b/build/lib/iexcode/macros/start_of_the_week.py index f0d0881..d2be15d 100644 --- a/build/lib/iexcode/macros/start_of_the_week.py +++ b/build/lib/iexcode/macros/start_of_the_week.py @@ -65,7 +65,7 @@ def start_of_the_week(grt,branch,wait=False,**kwargs): ### checking QP ratio: - QP_ratio = ID_QP_ratio_get() + QP_ratio = ID_QP_ratio_get()[] if QP_ratio != 100: foo=input('QP on!!! Continue (y or n)? >') if foo.lower() == 'y' or foo.lower() == 'yes': diff --git a/iexcode/cheatsheet.txt b/iexcode/cheatsheet.txt new file mode 100644 index 0000000..a33f305 --- /dev/null +++ b/iexcode/cheatsheet.txt @@ -0,0 +1,253 @@ +import iexcode.instruments.cfg as iex + +#ARPES: ARPES specific functions + +#AD_untilites: functions for common area detector operations + +#bakeout: functions for monitoring a bakeout + +#cameras: used for taking images from epics +cam_snap => takes a single image +cam_scan_setup => configures the scanRecord to take an image at each polarization +cam_live => puts the camera back in live/free-run mode +cam_done => turns off acquisition + +#cfg: config file which holds global variable BL and MPA +usage => import iexcode.instruments.cfg as iex + +#converstions_constants: +h => Planck's constant (eV/s) +c => speed of light (m/s) +deg2rad => converts degree to radian +rad2deg => converts radian to degrees +eV2Lambda => converts eV to Angstroms +Lambda2eV => converts Angstroms to eV + +#current_amplifiers: +Keithley => class for Keithley current amplifiers +ca_detector_list => list of detectors which are used in a given branch ('b for beamline) +ca_average => turns on averaging for all Keithleys in ca_list +ca_reset_all => resets all Keithleys in all branches +SRS => class for SRS current amplifiers +current2flux => calculates the flux based on the current reading in an AUX100 photodiode +flux2current => calculates the current reading for a given flux for and AUX100 photodiode + +#diagnostics: bemaline diagnostics +diagnostics_list_all => prints the name of all the diagnostics_all_in +diagnostic => moves the specified diagnostic in/out +diagnostics_all_out => moves all beamline diagnostics out +diagnostics_all_in => moves all beamline diagnostics in; Note that they can shadow/block downstream diagnostics +mesh_W => moves W-mesh in the A-hutch in/out +diode_c => moves diode in c-branch in/out +diode_c_read => reads the current amplifier for the c-branch diode +diode_d => moves diode in c-branch in/out; located just before the kappa endstation +mesh_d => moves mesh in d-branch in/out; used for normalization +mesh_d_read => reads the current amplifier for the d-branch mesh + + +#electron_analyzer: beamline specific calls to Scienta +EA => electron analyzer class +EA_ioc_init => initializes the ioc after a reboot (eventually goes in AutoSave) +folders_EA => sets the folder for the Scienta spectra saving (called by Folders_ARPES) +SES_slit_get => gets the analyzer slit number +SES_slit_set => sets the analyzer slit to the given value +scanEA => takes a spectra +scanFM => takes a Fermi map +mvth_interp => moves to an interpolated theta value +scanEA_hv => takes a spectra at each photon energy +scanEA_motor => takes a spectra at each motor point +resolution_EA => get the analyzer contribution to the resolution + +#encoder: beamline absolute encoders +encoder_name_list => lists names in encoder dictionary +encoder_sync => syncs all the encoders associated with name +encoders_slit2B_reset_zero => resets the center for the slit2B encoder + +#files_and_folders: general scripts for dealing with files and directories +path_dserv => path to user data directory on the dserve +check_run => returns the current run based on todays date +make_ftp => creates the folders on the ftp server, kip +make_user_folders => creates all the appropriate user folders +folder_mda => creates/set the user folder for the scanRecord +folder_SPEC +get_last_fileNumber => gets the last file number in the directory + +FMB_mirrors: functions for M0,M1,M3R +FMB_mirror_get => get the current position of all axes for a given mirror +FMB_mirror_move => moves the specified axis ('Tx','Ty','Tz','Rx','Ry','Rz') for the given mirror +FMB_mirror_move_all => moves all the axes to the positions specified in position_list +FMB_mirror_tweak => relative moves +FMB_mirror_scan => scan a mirror axis +M0M1_Table => reads the dictionary file to get the previous mirror positions +M0M1_SP => writes the values form M0M1_Table to the set points (still need to push move) + +#hxp_mirrors: Newport hexapods +hxp_sync => syncs the motor setpoint and readback values for a given mirror +hxp_get => gets a mirror position +hxp_get_all => gets all the mirror positions + + +#IEX_BL_config: used to access current beamline configuration, based on instance initialization not pv +Beamline_Config => class to carry all configuration info gets stored in iexcode\instruments\cft BL +BL_ioc => returns the scan ioc +BL_branch => returns the branch (shutter not mirror position) +BL_mode => returns the current mode (user/staff) +BL_mda_prefix => return prefix for mda scanRecord +BL_mda_filepath => returns the file path in mda scanRecord +get_all => gets relavent pv values + +#IEX_VPU: undulator functions +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 + +#kappa_angle_calcs: +fourc2kappa => converts between four-circle angles and kappa angles +kappa2fourc => converts between kappa dn four-circle angles + +#kappa_det: defines kappa tth detector class and other functions +Kappa_Detector => for detset etc in kappa chamber + +#kappa: kappa specific functions + +#Logfile: functions for writing logfile.txt, gets set by IEX_BL_config +log_print => print a comment in the logfile +log_update => updates the logfile with the current info (used if script is aborted) +log_name_set => change name of logfile + +#m3r: functions for dealin with m3r +m3r_tweak_pitch => tweaks the pitch of m3r +m3r_table => go to the default position specified branch +m3r_branch => returns the branch based on mirror position +m3r_switch_branch => moves the mirror to the default position for a given branch +m3r_centroid => returns the centroid position for m3r +m3r_align => aligns the m3r + +#Motors: motor class and common name functions +Motor => class definition get set in Beamline_Config +mvx => moves motor x +dmvx => relative move of x +scanx => scan of x motor +dscanx => relative scan of x motor +... + +#resolution +resolution => gives the resolution for the current settings + +#scalers +scaler_cts => sets the scaler counter for the current endstation + +#scanRecord: functions and class for handling the scanRecord +ScanRecord => class for handling scanRecord_user +scan_fillin => same as iex.BL.mda.fillin +scan_fillin_table => same as iex.BL.mda.fillin_table +scan_go => same as iex.BL.mda.go +.current_run +.user_name +.empty_scan => scan with no positioners +.time_scan => scan with positioner readback as time and detector settling as minutes +.lastFileNum + + +#Scienta: base functions for taking spectra, called by electron_analyzer + +#shutters: main shutter and branch shutter functions +shutter_check => checks and then opens main and branch shutters +main_shutter_open => checks status then opens if not open +main_shutter_close => checks status then closes if not closed +main_shutter_status => returns open=True/False +branch_shutter_open => checks status then opens iex.BL.mda.branch shuttter if not open +branch_shutter_close => checks status then closes iex.BL.mda.branch shuttter if not closed +branch_shutter_status => returns open=True/False + +#slits: beamline slits and aperatures +slit_name_list => list all slits/apertures +slits_synch => syncs the motor position with the slit table for a given slit +slits_synch_all => +slits_get_all => +slits_set => sets the slit/aperature to the specified size and position +slits_get => gets the slit/aperature size and position +slits_set_size +slits_set_center +slits_scan_size +slits_scan_center +slit1A_scribe_marks => moves the slits so that the scribe marks should align +slit1A_get/set +slit2B_get/set +slit2B_encoders_reset => resets the encords to be zero at the specified position +slit3C_get/set +slit3D_get/set +exit_slit => uses iex.BL.branch to set correct exit slit size + +#staff +folders_startup => makes folder structure for a new run + +#storage ring +wait_for_beam => waits for storage ring current to be above ring_current + +#userCals: functions for filling in user calcs and string Sequences + +#utilities: general functions +dateandtime => prints current date and time +today => returns a string with the date +print_warning_message => prints a warning message_string +wait_for_it => waits for future time +input_timeout => used to break for an input +playsound +range_up/down => loop for noninteger counting (inclusive of last point) +take_closest_value => takes the closest value from a list +read_dict => reads text files in iexcode.IEX_dictionaries +make_table => makes a table array from a list of lists + +#valves: control valves via epics +branch_valve_close/open +valve_close/open + +#VLS_PGM: mono functions +mono_get_all => returns the current mono settings from most common parameters +mono_get_all_extended => returns all the current mono settings +mono_grating_get/set +mono_energy_get/set +mono_reset_pitch => resets the motors after a following error +mono_stop => stops the mono motors +mono_enage => reenables the mono motors +mono_limits_reset => sets the energy lower limit to 200 +mono_cff_print +mono_parameters_get +mono_parameters_history_read +mono_parameters_history_write +mono_temperature_interlock => moving this to EPS +mono_scan_fillin/_table +mono_scan_after +mono_motor_move +mono_motor_scan_fillin +mono_zero_order +mono_angles_set +mono_pink_beam +mono_grating_offset_set +mono_mirror_offset_set +mono_grating_mirror_offsets_set +mono_grating_b2_set +mono_cff_set +mono_arm_set + +#xrays +energy_get_all +energy_get => retuns the mono energy +getE => same as energy_get +energy => set the ID, aperatures and mono +qp => set the qp ratio +apertures_set => decrease aperature size/cutting flux +mvID => moves the ID to a given set point (not calibrated) +mvID_calibrated => moves the ID for max flux +mvmono => sets mono energy +grating/_get => switches gratings/gets the current grating +polarization/_get => changes the polariation/gets current polarization +scanXAS => table scan of the energy +shutter_check => checks main and branch shutter +switch_branch => moves m3R to default position for the branch; close/reopens shutters too +get_mirros => gets all the FMB mirror positions +slit => sets the exit_slit +slit_get => gets the exit slit +apertures_set => sets beamline aperatures \ No newline at end of file diff --git a/iexcode/instruments/FMB_mirrors.py b/iexcode/instruments/FMB_mirrors.py index 86a1317..1c92a07 100644 --- a/iexcode/instruments/FMB_mirrors.py +++ b/iexcode/instruments/FMB_mirrors.py @@ -51,7 +51,7 @@ def FMB_mirror_get(mirror_num,verbose=True): message = "\nM"+str(mirror_num)+" @ " for axis in axis_labels: rbv,sp = FMB_mirror_axis_position(mirror_num,axis, verbose=False) - vals.append(rbv) + vals.append(round(rbv,3)) message =+ "%.3f"+"/" % rbv if verbose: print(message) diff --git a/iexcode/instruments/IEX_VPU.py b/iexcode/instruments/IEX_VPU.py index a408465..b3fd766 100644 --- a/iexcode/instruments/IEX_VPU.py +++ b/iexcode/instruments/IEX_VPU.py @@ -1,23 +1,22 @@ - - +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.shutters import main_shutter_check_open from iexcode.instruments.VLS_PGM import mono_grating_get -from iexcode.instruments.userCalcs import userCalcOut_clear +from iexcode.instruments.shutters import main_shutter_open -IDcal_fpath="/home/beams22/29IDUSER/Documents/User_Macros/Macros_29id/IEX_Dictionaries/Dict_IDCal.txt" +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): # Mode = state (0=RCP,1=LCP,2=V,3=H) +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) @@ -28,7 +27,7 @@ def ID_calc_SP(mono_grating,ID_mode,hv_eV): # Mode = state (0=RCP,1=LCP,2=V,3 if type(ID_mode)== str: ID_state=ID_state_mode(ID_mode) try: - K=ID_coef(mono_grating,ID_state,hv_eV) + 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()) @@ -60,7 +59,7 @@ def ID_wait_for_permission(): ############################################################################################################## def ID_get_all(verbose=False): """ - returns dictionart with: ID_Mode, ID_QP_ratio, ID_SP, ID_RBV + returns dictionary with: ID_Mode, ID_QP_ratio, ID_SP, ID_RBV Previously: Get_energy """ @@ -157,51 +156,61 @@ def ID_ready(verbose=True): elif ((checkready=="Ready") and (RBV > 3.7)) and (checkbusy=="Busy"): caput("ID29:Busy.VAL",0) else: - break - if verbose: - print("ID Ready") + if verbose: + print("ID Ready") + return True -def ID_stop(verbose=True): +def ID_power_status(): """ - waits for the ID to be in user mode and then turns it off + 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' - Previously: ID_Stop +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_off(): +def ID_on(verbose=True): """ - calls ID_stop + waits for permission then turns on the main coils On """ - ID_stop() - + 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'): +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 """ - - ID_wait_for_permission() - #turning on the ID; default mode = RCP - print("Starting ID - "+dateandtime()) - caput("ID29:EnergySet.VAL",3.8) - caput("ID29:Main_on_off.VAL",0,wait=True,timeout=18000) - ID_ready() - ID_mode_set(ID_mode) - - ID_wait_for_permission() - main_shutter_check_open() + if ID_power_status =='Off' + ID_on() + if ID_ready(): + ID_QP_mode_set(QP_ratio,verbose) + if ID_ready(): + ID_mode_set(ID_mode, verbose) - print('ID is now on, please set your energy') + if ID_ready(): + main_shutter_open() + + if verbose: + print('ID is now on, please set your energy') def ID_switch_mode(ID_mode): """ @@ -213,13 +222,13 @@ def ID_switch_mode(ID_mode): Previously Switch_IDMode """ ID_wait_for_permission() - main_shutter_check_open() + main_shutter_open() ID_state = ID_state_get() try: if ID_state_mode(ID_mode) != ID_state: print("Turning ID off...") - ID_stop(verbose=True) + ID_off(verbose=True) sleep(10) print("Switching ID mode, please wait...") @@ -265,24 +274,6 @@ def ID_rbv_get_eV(verbose=False): print("ID_RBV: ", ID_RBV) return ID_RBV -def ID_restart(): - """ - turns off the ID and turns it back on with the same set point - - Previously: ID_Restart - """ - ID_state = ID_state_get() - ID_mode = ID_mode_list()[ID_state] - hv = ID_SP_get_eV(verbose=False) - - print("Restarting ID", dateandtime()) - ID_stop(verbose=False) - ID_ready(verbose=False) - - ID_start(verbose=False) - - print("ID is back ON", dateandtime()) - ID_SP_set(hv) def ID_SP_set(hv_eV,verbose=True): """ @@ -290,48 +281,78 @@ def ID_SP_set(hv_eV,verbose=True): 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_check_open() + 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 - if ID_SP == ID_SP_RBV: # checks if ID is already at the SP energy - ID_RBV=caget("ID29:EnergyRBV") + 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: - caput("ID29:EnergyScanSet.VAL",ID_SP/1000,wait=True,timeout=18000) - sleep(0.5) - caput("ID29:EnergyScanSet.VAL",(ID_SP+0.001)/1000,wait=True,timeout=18000) - caput('ID29:StartRamp.VAL',1) - - sleep(5) - ID_ready(verbose=False) - - ID_RBV=caget("ID29:EnergyRBV") - print("\nID SET : "+"%.1f" % ID_SP, "eV") - print("ID RBV : "+"%.1f" % ID_RBV, "eV") - print(caget('ID29:TableDirection',as_string=True)) - - ID_diff = abs(ID_RBV-ID_SP) - ID_bw = ID_SP*0.095 - if ID_diff > ID_bw: - sleep(20) - ID_RBV=caget("ID29:EnergyRBV") - ID_diff = abs(ID_RBV-ID_SP) - print("\nID RBV : "+"%.1f" % ID_RBV, "eV") - if ID_diff > ID_bw: - ID_restart - -def ID_energy_set(hv_eV): + # 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,"%") + +def ID_energy_set(hv_eV,QP_ratio=None): """ Sets optimum ID set point for hv(eV) (max intensity) and opens the main shutter @@ -342,9 +363,8 @@ def ID_energy_set(hv_eV): """ ID_mode = ID_mode_list()[ID_state_get()] mono_grating = mono_grating_get() - ID_SP = ID_calc_SP(mono_grating,ID_mode,hv_eV) - - ID_SP(hv_eV) + 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): @@ -352,7 +372,6 @@ 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") @@ -367,38 +386,36 @@ def ID_QP_ratio_get(verbose=True): print_warning_message(message_string) return ratio_RBV, ratio_calc -def ID_QP_mode_set(ID_mode,QP_ratio): +def ID_QP_mode_set(QP_ratio=None,verbose=True): """ switched to QP mode, if not currently in - sets the QP ratio (QP ration min is 70) and polarization (ID mode) + sets the QP ratio (QP ratio min is 70) and polarization (ID mode) - does not set the energy, need to use ID_SP + 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) - - ratio_RBV, ratio_calc=ID_QP_ratio_get() - if ratio_RBV != QP_ratio: - ID_stop() - caput("ID29:QuasiRatioIn.C",QP_ratio) - - ID_start(ID_mode) - sleep(15) - Byq=caget("ID29:ByqRdbk") - Vcoil=caget("ID29:ByRdbk.VAL") - ratio=Byq/Vcoil - ratio_RBV=caget("ID29:QuasiRatio.RVAL") - print("QP ratio =", round(ratio,3)*100,"%") - print("QP RBV =", ratio_RBV,"%") - sleep(15) + 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): # Mode = state (0=RCP,1=LCP,2=V,3=H); + +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). @@ -408,6 +425,9 @@ def ID_coef(grt,ID_state,hv_eV): # Mode = state (0=RCP,1=LCP,2=V,3=H); 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]): @@ -421,12 +441,26 @@ def ID_coef(grt,ID_state,hv_eV): # Mode = state (0=RCP,1=LCP,2=V,3=H); 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") + print("Unable to read dictionary "+dictfile+" ; "+error_msg) try: Lrange = ListRange(grt,ID_state,ID_function) @@ -435,11 +469,8 @@ def ID_coef(grt,ID_state,hv_eV): # Mode = state (0=RCP,1=LCP,2=V,3=H); return K except KeyError: - print("WARNING: PLease select one of the following:") - print(" mode 0 = RCP") - print(" mode 1 = LCP") - print(" mode 2 = V") - print(" mode 3 = H") + print("WARNING: PLease select one of the following: "+str(ID_mode_list())) + def ID_scan_pvs(): """ diff --git a/iexcode/instruments/Kappa.py b/iexcode/instruments/Kappa.py index cca859d..d5b1668 100644 --- a/iexcode/instruments/Kappa.py +++ b/iexcode/instruments/Kappa.py @@ -27,7 +27,7 @@ from iexcode.instruments.slits import slit3D_get #endstation specific from iexcode.instruments.kappa_det import kappa_Detector from iexcode.instruments.scalers import scaler_cts -from iexcode.instruments.MPA import MPA +from iexcode.instruments.MPA import MPA, mpa_ROI_reset from iexcode.instruments.spec_stuff import folders_spec default_ioc = '29idKappa:' @@ -121,9 +121,11 @@ def _kappa_detector_dictionary(**kwargs): kwargs.setdefault('add_vortex',False) det_dict={} vortex={ - 15:"", 16:"", 17:"", + 49:"", + 50:"", + } sample_temp={ 23:"29idd:LS331:TC1:SampleA", @@ -298,9 +300,10 @@ def kappa_reset(): print("resetting the scanRecord - "+iex.BL.ioc) iex.BL.mda.reset_all() - #resetting the current amplifiers + #resetting the MPA ROIs if iex.BL.xray: - ca_reset_all() + mpa_ROI_reset() + #resetting mono and anyother beamline stuff if iex.BL.xrays: @@ -337,7 +340,7 @@ def kappa_get_all(verbose=True): vals.update(key,caget(extra_pvs[key])) if iex.BL.xrays: vals.update('exit_slit',slit3D_get()) - vals.update({'mesh':mesh.current}) + vals.update({'mesh':mesh.current_Amp}) if verbose: for key in vals: print(key+" = "+vals[key]) @@ -385,8 +388,8 @@ def _kappa_log_entries(): TA = vals['TA'] TB = vals['TB'] mesh.get() - tey_current = tey.current - mesh_current = mesh.current + tey_current = tey.current_Amp + mesh_current = mesh.current_Amp det_name = tthdet.name mpa_HV = iex.mpa.HV_get() m3r_centroid = vals['kphi'] @@ -703,7 +706,7 @@ def th2th_scan_sensitivity(th_table,gain_num_table,gain_unit_table,**kwargs): iex.BL.mda.table_reset_after(**kwargs) scaler_cts(verbose=False) -def scan_th2th(tth_start,tth_stop,tth_step,th_offset,**kwargs): +def scanth2th(tth_start,tth_stop,tth_step,th_offset,**kwargs): """ Used for a linear (not table) scan where th = tth /2 + th_offset **kwargs @@ -728,6 +731,7 @@ def scan_th2th(tth_start,tth_stop,tth_step,th_offset,**kwargs): th_val,th_rbv,th_spmg,th_pv = _kappa_motor_dictionary['th'] tth_val,tth_rbv,tth_spmg,tth_pv = _kappa_motor_dictionary['tth'] + kwargs.update("positioner_num",2) iex.BL.mda.fillin(th_val,th_rbv,th_start,th_stop,th_step,**kwargs) @@ -741,36 +745,44 @@ def scan_th2th(tth_start,tth_stop,tth_step,th_offset,**kwargs): #clean up after scan scaler_cts(verbose=False) - -def th2th_table(tth_table,th0,**kwargs): +def dscanth2th(tth_start_rel,tth_stop_rel,tth_step,th_offset,**kwargs): """ - Create a table for tth, e.g.: - mytable_tth=[] - for q in range(2,41,1): - mytable_tth.append(q) - print(mytable_tth) - - th0 = th value at grazing incidence - cts = counting time (default is 1s) - + relative (about current tth position) linear (not table) scan where th = tth /2 + th_offset **kwargs scan_dim: 1 (default) cts: integration time for scalers and mpa/mcp => 0.1 (default) execute: True/False to start the scan => True (default) - Previously: scanth2th_table + Previously: scanth2th + """ + tth_rbv= kappa_Motors.get('tth',verbose=False) + tth_start = tth_rbv+tth_start_rel + tth_stop = tth_rbv+tth_stop_rel + + scanth2th(tth_start,tth_stop,tth_step,th_offset,**kwargs) + + +def scanth2th_table(tth_table,th_offset, **kwargs): + """ + Used for constant q scans (tth is none linear) + **kwargs + scan_dim: 1 (default) + cts: integration time for scalers and mpa/mcp => 0.1 (default) + execute: True/False to start the scan => True (default) + Previously: scanth2th """ + kwargs.setdefault('scan_dim',1) kwargs.setdefault('cts',0.1) kwargs.setdefault('execute',True) - - tth_table=np.asarray(tth_table) - th_table=tth_table/2.0+th0 + + tth_table = np.asarray(tth_table) + th_table = tth_table/2.0 + th_offset + #write to the scanRecord th_val,th_rbv,th_spmg,th_pv = _kappa_motor_dictionary['th'] tth_val,tth_rbv,tth_spmg,tth_pv = _kappa_motor_dictionary['tth'] - #write to the scanRecord kwargs.update("positioner_num",1) iex.BL.mda.fillin_table(tth_val,tth_rbv,tth_table,**kwargs) @@ -890,20 +902,22 @@ def kappa_safe_state(**kwargs): def uan(tth,th): """ Moves tth and th motors simultaneously in the in the kappa chamber """ - if iex.BL.endstation == 'kappa': - #move tth and th - kappa_Motors.move('th',th,wait=False) - kappa_Motors.move('tth',tth,wait=False) - time.sleep(0.2) - while True: - status = kappa_Motors.status() - if status == 0: - time.sleep(0.2) - else: - tth_RBV=round(kappa_Motors.get('tth',verbose=False),3) - th_RBV=round(kappa_Motors.get('th',verbose=False),3) - print('tth='+str(tth_RBV)+' th='+str(th_RBV)) - break - else: - print("not a defined move") \ No newline at end of file + #move tth and th + kappa_Motors.move('th',th,wait=False) + kappa_Motors.move('tth',tth,wait=False) + time.sleep(0.2) + + while True: + status = kappa_Motors.status() + if status == 0: + time.sleep(0.2) + else: + tth_RBV=round(kappa_Motors.get('tth',verbose=False),3) + th_RBV=round(kappa_Motors.get('th',verbose=False),3) + print('tth='+str(tth_RBV)+' th='+str(th_RBV)) + break + + #double check both moved to the correct position + kappa_Motors.move('th',th) + kappa_Motors.move('tfh',tth) diff --git a/iexcode/instruments/MPA.py b/iexcode/instruments/MPA.py index 6856fb6..539c975 100644 --- a/iexcode/instruments/MPA.py +++ b/iexcode/instruments/MPA.py @@ -23,6 +23,7 @@ To do, get busy record in the mpa ioc, get user calcs in the mpa ioc ############################## PVs ############################## ############################################################################################################## mpa_pv = "29iddMPA:" +mpa_PR = mpa_pv+"det1:" mpa_busy = "29idcScienta:mybusy2" userCalc_ioc = "29idTest:" DAC_pv = '29iddau1:dau1:011:DAC' @@ -150,14 +151,23 @@ class MPA: ############################################################################################################## ############################## MCP Scripts ############################## ############################################################################################################## + def mpa_ROI_reset(): + """ + Previously: + """ + return 'TBD' + def ROI_setup(self,ROI_num=1,xcenter=535,ycenter=539,xsize=50,ysize=50,binX=1,binY=1): """ usage: center of MCP, roiNum = 1 => MPA_ROI_SetUp(1,535,539,50,50) to set up all use: mpa_ROI_setup_all(xcenter,ycenter) """ - AD_ROI_setup('29iddMPA',ROI_num,xcenter,ycenter,xsize,ysize,binX,binY) - self._ROI_stats(ROI_num) + try: + AD_ROI_setup(mpa_PR,ROI_num,xcenter,ycenter,xsize,ysize,binX,binY) + self._ROI_stats(ROI_num) + except: + print(mpa_PR+' not connected; ROIs not reset') def ROI_setup_all(self,xcenter=535,ycenter=539): """ @@ -168,11 +178,12 @@ class MPA: 4 => size = 200 x 200 """ - self._ROI_setup(1,xcenter,ycenter,xsize=50,ysize=50) - self._ROI_setup(2,xcenter,ycenter,xsize=100,ysize=100) - self._ROI_setup(3,xcenter,ycenter,xsize=150,ysize=150) - self._ROI_setup(4,xcenter,ycenter,xsize=200,ysize=200) - + if PV(mpa_PR+'Acquire').connected: + self._ROI_setup(1,xcenter,ycenter,xsize=50,ysize=50) + self._ROI_setup(2,xcenter,ycenter,xsize=100,ysize=100) + self._ROI_setup(3,xcenter,ycenter,xsize=200,ysize=200) + self._ROI_setup(4,xcenter,ycenter,xsize=400,ysize=400) + print(mpa_PR+' not connected; ROIs not reset') def ROI_stats(self,ROI_num): """ diff --git a/iexcode/instruments/Motors.py b/iexcode/instruments/Motors.py index 9978ef5..e4e9a2c 100644 --- a/iexcode/instruments/Motors.py +++ b/iexcode/instruments/Motors.py @@ -112,13 +112,14 @@ class Motors: self.move(name,val,relative=True,wait=kwargs['wait'],verbose=kwargs['verbose']) - def mprint(self): + def mprint(self,name=''): """ prints current position of the physical motors """ - position_list = [] + position_list = [name] for motor in self.physical_motors: position_list.append(self.get(motor,verbose=False)) + return position_list def mvsample(self,position_list,verbose=True): @@ -166,6 +167,7 @@ class Motors: #for kappa only kwargs.setdefault('cts',0.1) kwargs.setdefault('mpa',False) + motor_pvs = self._motor_dictionary.get(name) if motor_pvs: rbv_pv,val_pv,sgm_pv,pv = motor_pvs diff --git a/iexcode/instruments/current_amplifiers.py b/iexcode/instruments/current_amplifiers.py index ee29440..4ac0ed8 100644 --- a/iexcode/instruments/current_amplifiers.py +++ b/iexcode/instruments/current_amplifiers.py @@ -333,8 +333,14 @@ class SRS: self.scaler_value self.gain - self.unit - self.current + self.current_Amp + self.current_unit + self.invert + self.baseline + self.offset_value + self.offset_unit + self.offset_sign + self.offset_factor self.get(verbose=False) def get(self): @@ -343,10 +349,25 @@ class SRS: """ self.scaler_value = caget(self._scaler_pv) self.gain = float(caget(self._scaler_pv+'sens_num.VAL',as_string=True)) - self.unit = caget(self._scaler_pv+'sens_unit.VAL',as_string=True) - CA = {'pA':1e-12, 'nA':1e-9, 'uA':1e-6, 'mA':1e-3} - self.current = self.scaler_value * self.gain * CA[self.unit] - + self.current_unit = caget(self._scaler_pv+'sens_unit.VAL',as_string=True) + self.invert = caget(self._scaler_pv+'invert_on.VAL',as_string=True) + unit_sciNote = {'pA':1e-12, 'nA':1e-9, 'uA':1e-6, 'mA':1e-3} + self.current_Amp = self.scaler_value * self.gain * unit_sciNote[self.current_unit] + + self.offset_value=caget(self._scaler_pv+"offset_num.VAL",as_string=True) + self.offset_unit=caget(self._scaler_pv+"offset_unit.VAL",as_string=True) + self.offset_sign=caget(self._scaler_pv+"offset_sign.VAL",as_string=True) + self.offset_factor=caget(self._scaler_pv+"off_u_put.VAL",as_string=True) + self.baseline = self.offset_factor * self.offset_value * unit_sciNote[self.offset_unit] + + self.filter_type=caget(self._scaler_pv+'filter_type.VAL',as_string=True) + self.filter_low=caget(self._scaler_pv+'low_freq.VAL',as_string=True) + self.filter_high=caget(self._scaler_pv+'high_freq.VAL',as_string=True) + self.blank=caget(self._scaler_pv+'blank_on.VAL',as_string=True) + self.bias_OnOff=caget(self._scaler_pv+'bias_on.VAL',as_string=True) + self.bias_value=caget(self._scaler_pv+'bias_put.VAL',as_string=True) + + def setgain(self,gain,unit): """ gain = 1,2,5,10,20,50,100,200,500 @@ -360,23 +381,17 @@ class SRS: """ prints SRS setting """ + self.get() - invert=caget(self._srs_pv+'invert_on.VAL',as_string=True) - currentUnit=caget(self._srs_pv+'sens_unit.VAL',as_string=True) - currentValue=caget(self._srs_pv+'sens_num.VAL',as_string=True) - offsetValue=caget(self._srs_pv+"offset_num.VAL",as_string=True) - offsetUnit=caget(self._srs_pv+"offset_unit.VAL",as_string=True) - offsetSign=caget(self._srs_pv+"offset_sign.VAL",as_string=True) - offsetFactor=caget(self._srs_pv+"off_u_put.VAL",as_string=True) - print('Gain: '+currentValue+' '+currentUnit+' (invert '+invert+')') - print('Baseline: '+offsetSign+' '+offsetFactor+' x '+offsetValue+" "+offsetUnit) + print('Gain: '+self.scaler_value+' '+self.current_unit+' (invert '+self.invert+')') + print('Baseline: '+self.offset_sign+' '+self.offset_factor+' x '+self.offset_value+" "+self.offset_unit) if long: - filterType=caget(self._srs_pv+'filter_type.VAL',as_string=True) - filterLow=caget(self._srs_pv+'low_freq.VAL',as_string=True) - filterHigh=caget(self._srs_pv+'high_freq.VAL',as_string=True) - blank=caget(self._srs_pv+'blank_on.VAL',as_string=True) - biasOnOff=caget(self._srs_pv+'bias_on.VAL',as_string=True) - biasValue=caget(self._srs_pv+'bias_put.VAL',as_string=True) + filterType = self.filter_type + filterLow = self.filter_low + filterHigh = self.filter_high + blank = self.blank + biasOnOff = self.bias_OnOff + biasValue = self.bias_value print('Filter: '+filterType+' - Low/High: '+filterLow+' -'+filterHigh) print('Bias: '+biasOnOff+'- '+biasValue) print('Blank: '+blank) diff --git a/iexcode/instruments/electron_analyzer.py b/iexcode/instruments/electron_analyzer.py index 726f96a..52fd4ff 100644 --- a/iexcode/instruments/electron_analyzer.py +++ b/iexcode/instruments/electron_analyzer.py @@ -17,7 +17,7 @@ from iexcode.instruments.IEX_BL_config import * from iexcode.instruments.scanRecord import * from iexcode.instruments.conversions_constants import * -from iexcode.instruments.xrays import energy, scanXAS_BL, BL_energy_tables +from iexcode.instruments.xrays import energy, scanXAS, BL_energy_tables from iexcode.instruments.shutters import branch_shutter_close from iexcode.instruments.VLS_PGM import mono_energy_get from iexcode.instruments.files_and_folders import get_next_fileNumber @@ -546,6 +546,7 @@ def scanEA_hv(hv_start_stop_step_lists,EAlist=[],**kwargs): **kwargs execute: True/False to start the scan => True (default) debug: default => False + QP_ratio: if other than fully periodic (Note: scan_dim=2 is hardcoded for photon energy) @@ -568,8 +569,9 @@ def scanEA_hv(hv_start_stop_step_lists,EAlist=[],**kwargs): #Setting up the ScanRecord for Mono and ID in Table mode kwargs["scan_dim"]=2 kwargs["execute"]=False - mono_array,ID_array = BL_energy_tables(hv_start_stop_step_lists) - scanXAS_BL(hv_start_stop_step_lists,**kwargs) + mono_array,ID_array = BL_energy_tables(hv_start_stop_step_lists,**kwargs) + kwargs.update({"ID_tracking":True}) + scanXAS(hv_start_stop_step_lists,**kwargs) if scanGo == True: #Setting the beamline energy to the first point, and EA at first KE diff --git a/iexcode/instruments/m3r.py b/iexcode/instruments/m3r.py index b601fe4..8712977 100644 --- a/iexcode/instruments/m3r.py +++ b/iexcode/instruments/m3r.py @@ -1,4 +1,5 @@ from cgi import print_arguments +from build.lib.iexcode.instruments.VLS_PGM import mono_energy_get from epics import caget, caput @@ -18,6 +19,21 @@ M3R_align_pv = "29idKappa:align_m3r:" ############################################################################################################## ################################ M3R default positions ############################## ############################################################################################################## +def m3r_position_dictionary(): + """ + dictionary for the default positions for a given branch + """ + positions={ + "c":[10,0,0,0,0,0], + "d":[-2.5,0,0,-13.955,-16.322,-8.5], + "e":[-2.000,0,0,-13.960,-16.614,-7.500] + } + + + # d => optimized for MEG @ 500 eV on 2/29/def start + # e => 2018_3-- JM changed for RSoXS alignment max diode current + return positions + def m3r_get(verbose=True): position = FMB_mirror_get(3,verbose) return position @@ -50,20 +66,7 @@ def m3r_tweak_pitch(sign,val=0.005): elif sign == "-": m3r_tweak(axis,-val) -def m3r_position_dictionary(): - """ - dictionary for the default positions for a given branch - """ - positions={ - "c":[10,0,0,0,0,0], - "d":[-2.5,0,0,-13.955,-16.450,-5.15], - "e":[-2.000,0,0,-13.960,-16.614,-7.500] - } - - # d => optimized for MEG @ 500 eV on 2/29/def start - # e => 2018_3-- JM changed for RSoXS alignment max diode current - return positions def m3r_table(branch): """ @@ -139,7 +142,12 @@ def m3r_align(pxl=None): try: _m3r_align_start() sleep(1) - if m3r_RY_pos_sp_get() == m3r_RY_pos_sp(): + if mono_energy_get()>2100: _m3r_align_start() + sleep(1) + sleep(1) + min_m3r=caget(M3R_align_pv+'motor_min') + if m3r_RY_pos_sp_get() == min_m3r: + align_m3r_epics() except: print('Unable to align; check camera settings.') \ No newline at end of file diff --git a/iexcode/instruments/scalers.py b/iexcode/instruments/scalers.py index 82bba65..4ddad3b 100644 --- a/iexcode/instruments/scalers.py +++ b/iexcode/instruments/scalers.py @@ -25,7 +25,7 @@ def Kappa_scaler(time_seconds=0.1,verbose=True): pv=PV(mpa_NumFilter) if pv.connected(): - caput(mpa_NumFilter,floor(time_seconds)) + caput(mpa_NumFilter,max(floor(time_seconds),1)) if verbose: print("Integration time set to:", str(time_seconds)) diff --git a/iexcode/instruments/scanRecord.py b/iexcode/instruments/scanRecord.py index 41ecc6d..98a7a31 100644 --- a/iexcode/instruments/scanRecord.py +++ b/iexcode/instruments/scanRecord.py @@ -207,7 +207,7 @@ class ScanRecord: """ return saveData_get_all(self.ioc)['baseName'] - def scanRecord_run(self): + def current_run(self): """ returns the current run by parsing the filepath in the SaveData for ioc @@ -218,7 +218,7 @@ class ScanRecord: current_run=filepath[m:m+6] return current_run - def scanRecord_user(self): + def user_name(self): """ returns the current user by parsing the filepath in the SaveData for ioc @@ -227,7 +227,7 @@ class ScanRecord: subdir=saveData_get_all(self.ioc)['subDir'] m=subdir.find('/mda') if m == 0 : - current_user='Staff' + current_user='staff' elif m > 0: current_user=subdir[1:m] else: @@ -320,7 +320,6 @@ class ScanRecord: def reset_scan_dim(self,scan_dim,**kwargs): """ Resets all the scanRecords (scanDIM=1,2,3,4) for a given IOC - uses Reset_Scan() **kwargs: detector_dictionary trigger_dictionary @@ -651,22 +650,26 @@ class ScanRecord: ############################################################################################################## ############################# table scans ############################## ############################################################################################################## - def fillin_table(self,scan_dim,val_pv,rbv_pv,myarray,**kwargs): + def fillin_table(self,val_pv,rbv_pv,myarray,**kwargs): """ Fills in the scan record for table scans given positioner=posNum myarray can be generated by myarray=Scan_MakeTable(StartStopStepLists) kwargs: positioner_num: default => 1 + scan_dim: default =>1 detector_settling_time: positioner_settling_time Previously: Scan_FillIn_Table """ + kwargs.setdefault("scan_dim",1) kwargs.setdefault("positioner_num",1) kwargs.setdefault('detector_settling_time',default_detector_settling_time) kwargs.setdefault('positioner_settling_time',default_positioner_settling_time) + scan_dim = kwargs['scan_dim'] + self.progress(scan_dim) scan_pv = self.ioc+"scan"+str(scan_dim) diff --git a/iexcode/instruments/slits.py b/iexcode/instruments/slits.py index dcfa558..4244806 100644 --- a/iexcode/instruments/slits.py +++ b/iexcode/instruments/slits.py @@ -7,6 +7,7 @@ from iexcode.instruments.shutters import main_shutter_close from iexcode.instruments.utilities import print_warning_message from iexcode.instruments.encoders import encoders_reset_zero + slit_ioc="29idb:" def _slits_dictionary(): @@ -45,7 +46,7 @@ def _slits_wide_open_dictionary(): } return d -def _slits_pvs(slit_name): +def slits_pvs(slit_name): """ returns the rbv and drive for the size,center (rbv_size,val_size),(rvb_center,val_center) @@ -116,7 +117,7 @@ def slits_set(slit_name,size,center,verbose=True): size = _slits_wide_open_dictionary()[slit_name] if d[slit_name] != None: for i,slit_HV in enumerate(d[slit_name]): #H and V - (size_rbv,size_val),(center_rbv,center_val) = _slits_pvs(slit_HV) + (size_rbv,size_val),(center_rbv,center_val) = slits_pvs(slit_HV) if center_rbv != None: caput(center_val, center[i],timeout=180) if size_rbv != None: @@ -139,7 +140,7 @@ def slits_get(slit_name,verbose=True): slits_synch(slit_name) for slit_HV in d[slit_name]: #H and V - (size_rbv,size_val),(center_rbv,center_val) = _slits_pvs(slit_HV) + (size_rbv,size_val),(center_rbv,center_val) = slits_pvs(slit_HV) if size_rbv != None: size.append(caget(size_rbv)) if center_rbv != None: @@ -188,9 +189,9 @@ def slits_scan_size(slit_name,direction,start,stop,step,**kwargs): slit_H,slit_V = _slits_dictionary()[slit_name] if direction == 'H': - (size_rbv,size_val),(center_rbv,center_val) = _slits_pvs(slit_H) + (size_rbv,size_val),(center_rbv,center_val) = slits_pvs(slit_H) if direction == 'V': - (size_rbv,size_val),(center_rbv,center_val) = _slits_pvs(slit_V) + (size_rbv,size_val),(center_rbv,center_val) = slits_pvs(slit_V) #set slit center slits_set_center(slit_name,kwargs['center']) @@ -205,6 +206,8 @@ def slits_scan_center(slit_name,direction,start,stop,step,**kwargs): direction = 'H', 'V' **kwargs size: slits size, if not specified then uses current size + + Previously: Scan_NarrowSlit_Go """ kwargs.setdefault('size',slits_get(slit_name,verbose=False)[0]) kwargs.setdefault('execute',True) @@ -212,9 +215,9 @@ def slits_scan_center(slit_name,direction,start,stop,step,**kwargs): slit_H,slit_V = _slits_dictionary()[slit_name] if direction == 'H': - (size_rbv,size_val),(center_rbv,center_val) = _slits_pvs(slit_H) + (size_rbv,size_val),(center_rbv,center_val) = slits_pvs(slit_H) if direction == 'V': - (size_rbv,size_val),(center_rbv,center_val) = _slits_pvs(slit_V) + (size_rbv,size_val),(center_rbv,center_val) = slits_pvs(slit_V) #set slit center slits_set_size(slit_name,kwargs['size']) @@ -223,6 +226,7 @@ def slits_scan_center(slit_name,direction,start,stop,step,**kwargs): if kwargs['execute']: iex.BL.mda.go(**kwargs) + def slit1A_scribe_marks(): """ moves slit1A to the position which corresponds to the scribe marks @@ -315,33 +319,39 @@ def slit3C_get(size,verbose=True): slit_name = "slit3C" return slits_get(slit_name,verbose=verbose) -def slit3D_set(V_size,verbose=True,**kwargs): +def slit3D_set(V_size,position=None,verbose=True): """ - sets the clean up aperture / slit downstream of the mono to the specificed size - if Hsize / Vsize = inf then goes to maximim 6 / 8 - - **kwargs - center = slit center, by default => current value + set the exit slit for the D-branch Previously: SetSlit3D """ - kwargs.setdefault('center',slit3D_get(verbose=False)[1]) slit_name = "slit3D" if V_size in [inf,nan,None]: V_size=2000 size = (V_size) - center = kwargs['center'] - slits_set(slit_name,size,center,verbose=verbose) + if position == None: + center = slit3D_get()[1] + else: + center = (position) + + slits_set(slit_name,size,center,verbose=False) + if position == None: + size,center = slit3D_get() + print("Slit-3D = "+str(size)+"um") + else: + print("Slit-3D = "+str(size)+'@ '+str(center)+"um") + + def slit3D_get(verbose=True): """ returns the current V_size,V_center """ - slit_name = "slit1A" - (V_size),(V_center) = slits_get(slit_name) + slit_name = "slit3D" + (V_size),(V_center) = slits_get(slit_name,verbose) V_size = round(V_size,3) V_center = round(V_center,3) diff --git a/iexcode/instruments/staff.py b/iexcode/instruments/staff.py index a31ba22..2624d35 100644 --- a/iexcode/instruments/staff.py +++ b/iexcode/instruments/staff.py @@ -1,8 +1,8 @@ from os import listdir,mkdir,chmod from os.path import join, isfile, exists -from iexcode.instruments.ARPES import folders_ARPES -from iexcode.instruments.kappa import folders_kappa +from iexcode.instruments.ARPES import folders_ARPES, ARPES_init +from iexcode.instruments.kappa import folders_kappa, kappa_init def folders_startup(run): """ @@ -78,4 +78,35 @@ def staff_detector_dictionary(): det_dict.update(diodes) det_dict.update(slits_apertures) det_dict.update(mono_details) - return det_dict \ No newline at end of file + return det_dict + + +############################################################################################################## +################################ setting the mda folder ############################## +############################################################################################################## + +def staff_init(endstation_name=None,**kwargs): + """ + endstation_name : sets the scan record and BL + set_folders: sets the mda and EA folders; default => False + reset: resets the scanRecord (detectors,triggers...) + + **kwargs: + xrays: sets global variable; default => True + BL_mode: 'user' / 'staff' => used for saving, detectors + + Previously: folders_staff + """ + kwargs.setdefault('mode','staff') + kwargs.setdefault('xrays',True) + kwargs.setdefault('set_folders',True) + kwargs.setdefault('reset',True) + + if endstation_name is None: + endstation_name = iex.BL.endstation + + if endstation_name == 'ARPES': + ARPES_init('staff',**kwargs) + if endstation_name == 'Kappa': + kappa_init('staff',**kwargs) + diff --git a/iexcode/instruments/utilities.py b/iexcode/instruments/utilities.py index 7b04586..fb052f8 100644 --- a/iexcode/instruments/utilities.py +++ b/iexcode/instruments/utilities.py @@ -211,3 +211,24 @@ def AbortScript(): except KeyboardInterrupt as e: raise e +def input_timeout(question,t): + print("You have "+str(t)+" seconds to answer!") + i, o, e = select.select( [sys.stdin], [], [], t ) + if (i): + print("You said", sys.stdin.readline().strip()) + else: + print("You said nothing!") + +def input_d(question): + """ + ask a question (e.g 'Are you sure you want to reset tth0 (y or n)? >') + return the answer + """ + try: + print(question) + foo = input() + return foo + except KeyboardInterrupt as e: + raise e + except: + return \ No newline at end of file diff --git a/iexcode/instruments/vortex.py b/iexcode/instruments/vortex.py index 81deb73..e813756 100644 --- a/iexcode/instruments/vortex.py +++ b/iexcode/instruments/vortex.py @@ -1,18 +1,15 @@ -#!/usr/bin/env python - -from epics import caget, caput -from time import sleep, gmtime, strftime, localtime #Define caput with wait function def caputw(PVname,PVinput): - return caput(PVname,PVinput,wait=True, timeout = 100000) + return caput(PVname,PVinput,wait=True,timeout = 100000) -def dateandtime(): - return strftime("%a %d %b %Y %H:%M:%S",localtime()) -def vortex(energy,time=1): +def vortex(energy): + '''Sets the energy window for the vortex''' cen, wid = vortex_Ecal(energy) set_roi1(cen,wid) + caput('29idKappa:userCalcOut3.A',energy) + def set_roi1(cen,wid): caput('29idVORTEX:mca1.R0LO',round(cen-wid/2)) @@ -27,65 +24,125 @@ def vortex_Ecal(energy): wid = 120 return cen, wid -def mcacounttime(time): - caput('29idVORTEX:mca1.PRTM',time) +def mcacounttime(t): + '''Sets acquisition time for vortex and SRS to t(s)''' + caput('29idVORTEX:mca1.PRTM',t) + caput('29idMZ0:scaler1.TP',t) -def runmca(time): - caput('29idVORTEX:mca1.PRTM',time) +def runmca(t): + caput('29idVORTEX:mca1.PRTM',t) sleep(0.1) caputw('29idVORTEX:mca1EraseStart',1) def mcaoff(): + '''Power vortex OFF''' caput('29idd:Unidig1Bo1',1) + print('Vortex power OFF') def mcaon(): + '''Power vortex ON''' caput('29idd:Unidig1Bo1',0) + print('Vortex power ON') + -def savemca(): - caput('29idKappa:scan1.T2PV','29idVORTEX:scanH.EXSC') - caput('29idKappa:scan1.D16PV','29idVORTEX:mca1.R0') - caput('29idKappa:scan1.D17PV','29idVORTEX:mca1.R1') - caput('29idKappa:scan1.D49PV','29idd:userTran1.D') - caput('29idKappa:scan1.D50PV','29idd:userTran1.E') - sleep(1) - -def nosavemca(): - caput('29idKappa:scan1.T2PV','29idVORTEX:mca1EraseStart') - caput('29idKappa:scan1.D16PV','29idVORTEX:mca1.R0') - caput('29idKappa:scan1.D17PV','29idVORTEX:mca1.R1') - caput('29idKappa:scan1.D49PV','29idd:userTran1.D') - caput('29idKappa:scan1.D50PV','29idd:userTran1.E') - sleep(1) -def nomca(): - caput('29idKappa:scan1.T2PV','') - caput('29idKappa:scan1.D16PV','') - caput('29idKappa:scan1.D17PV','') - caput('29idKappa:scan1.D49PV','') - caput('29idKappa:scan1.D50PV','') - sleep(1) +def mcascan(add_vortex=True,save_image=False): + ''' + add_vortex=True (default): set up scan to save vortex as a detector + add_vortex=False: remove the vortex from the scan detector + save_image=True: save the individual mca files + ''' + def scan_num(): + scan = caget('29idKappa:saveData_message') + loc = scan.find('.') + if (loc==-1): + scannum=0 + else: + scannum =int(scan[loc-4:loc]) + return scannum -def scan_num(): - scan = caget('29idKappa:saveData_message') - loc = scan.find('.') - if (loc==-1): - scannum=0 + def mcafileinit(): + # mainpath = '/net/s4data/export/sector4/4idc/mda' + scanrecpath = caget('29idKappa:saveData_subDir') + scan = scan_num()+1 + caput('29idVORTEX:saveData_subDir', '/'+ scanrecpath+'/S'+str(scan)) + caput('29idVORTEX:saveData_scanNumber',1) + if add_vortex: + if save_image: + mcafileinit() + chkmcasave() + caput('29idKappa:scan1.T2PV','29idVORTEX:scanH.EXSC') + caput('29idKappa:scan1.D16PV','29idVORTEX:mca1.R0') + caput('29idKappa:scan1.D17PV','29idVORTEX:mca1.R1') + caput('29idKappa:scan1.D49PV','29idd:userTran1.D') + caput('29idKappa:scan1.D50PV','29idd:userTran1.E') + sleep(1) + else: + caput('29idKappa:scan1.T2PV','29idVORTEX:mca1EraseStart') + caput('29idKappa:scan1.D16PV','29idVORTEX:mca1.R0') + caput('29idKappa:scan1.D17PV','29idVORTEX:mca1.R1') + caput('29idKappa:scan1.D49PV','29idd:userTran1.D') + caput('29idKappa:scan1.D50PV','29idd:userTran1.E') + sleep(1) else: - scannum =int(scan[loc-4:loc]) - return scannum - -def mcafileinit(): - # mainpath = '/net/s4data/export/sector4/4idc/mda' - scanrecpath = caget('29idKappa:saveData_subDir') - scan = scan_num()+1 - caput('4idcVORTEX:saveData_subDir', '/'+ scanrecpath+'/S'+str(scan)) - caput('4idcVORTEX:saveData_scanNumber',1) + caput('29idKappa:scan1.T2PV','') + caput('29idKappa:scan1.D16PV','') + caput('29idKappa:scan1.D17PV','') + caput('29idKappa:scan1.D49PV','') + caput('29idKappa:scan1.D50PV','') + sleep(1) - def chkmcasave(): if (caget('29idKappa:scan1.T2PV')=='29idVORTEX:scanH.EXSC'): print('Saving mca files') mcafileinit() + + +# def savemca(): +# caput('29idKappa:scan1.T2PV','29idVORTEX:scanH.EXSC') +# caput('29idKappa:scan1.D16PV','29idVORTEX:mca1.R0') +# caput('29idKappa:scan1.D17PV','29idVORTEX:mca1.R1') +# caput('29idKappa:scan1.D49PV','29idd:userTran1.D') +# caput('29idKappa:scan1.D50PV','29idd:userTran1.E') +# sleep(1) + +# def nosavemca(): +# caput('29idKappa:scan1.T2PV','29idVORTEX:mca1EraseStart') +# caput('29idKappa:scan1.D16PV','29idVORTEX:mca1.R0') +# caput('29idKappa:scan1.D17PV','29idVORTEX:mca1.R1') +# caput('29idKappa:scan1.D49PV','29idd:userTran1.D') +# caput('29idKappa:scan1.D50PV','29idd:userTran1.E') +# sleep(1) + +# def nomca(): +# caput('29idKappa:scan1.T2PV','') +# caput('29idKappa:scan1.D16PV','') +# caput('29idKappa:scan1.D17PV','') +# caput('29idKappa:scan1.D49PV','') +# caput('29idKappa:scan1.D50PV','') +# sleep(1) + +# def scan_num(): +# scan = caget('29idKappa:saveData_message') +# loc = scan.find('.') +# if (loc==-1): +# scannum=0 +# else: +# scannum =int(scan[loc-4:loc]) +# return scannum + +# def mcafileinit(): +# # mainpath = '/net/s4data/export/sector4/4idc/mda' +# scanrecpath = caget('29idKappa:saveData_subDir') +# scan = scan_num()+1 +# caput('29idVORTEX:saveData_subDir', '/'+ scanrecpath+'/S'+str(scan)) +# caput('29idVORTEX:saveData_scanNumber',1) + + +# def chkmcasave(): +# if (caget('29idKappa:scan1.T2PV')=='29idVORTEX:scanH.EXSC'): +# print('Saving mca files') +# mcafileinit() diff --git a/iexcode/instruments/xrays.py b/iexcode/instruments/xrays.py index 67ed2f8..0dd8445 100644 --- a/iexcode/instruments/xrays.py +++ b/iexcode/instruments/xrays.py @@ -156,7 +156,7 @@ def _xrays_log_entries(**kwargs): #beamline info ID_mode = ID_mode_get(verbose=False) if iex.BL.xrays else "no_xrays" - ID_QP_ratio = ID_QP_ratio_get (verbose=False) if iex.BL.xrays else "no_xrays" + ID_QP_ratio = ID_QP_ratio_get(verbose=False)[0] if iex.BL.xrays else "no_xrays" ID_sp = round(ID_SP_get_eV()) if iex.BL.xrays else 0 ID_rbv = round(ID_rbv_get_eV,4) if iex.BL.xrays else 0 hv = mono_energy_get() if iex.BL.xrays else 0 @@ -222,7 +222,7 @@ def energy_get(): hv = mono_energy_get() return hv -def energy(hv_eV,slit_coeff=1,m3r=True,verbose=True): +def energy(hv_eV,slit_coeff=1,m3r=True,QP_ratio=100,verbose=True): """ sets the ID for optimal flux based on calibration sets the mono @@ -239,7 +239,7 @@ def energy(hv_eV,slit_coeff=1,m3r=True,verbose=True): print_warning_message(message_string) - ID_energy_set(hv_eV,verbose=verbose) + ID_energy_set(hv_eV,QP_ratio,verbose=verbose) mono_energy_set(hv_eV,verbose=verbose) apertures_set(c_2B=slit_coeff,c_1A=1,verbose=verbose) @@ -268,6 +268,18 @@ def _energy_range_check(hv): hv = np.max(hv_min,hv) return hv +def qp(QP_ratio): + """ + Used to set the QP (quasiperiodicity) of the ID for harmonic rejection + QP_ratio => + 100 fully periodic; max flux + 70 minimum allowed value, most quasiperiodic + + After changing QP, you will need to set + polarization + energy + """ + ID_QP_mode_set(QP_ratio) ############################################################################################################## ################################ beamline slits = apertures ############################## ############################################################################################################## @@ -313,24 +325,23 @@ def apertures_set(c_2B=1,c_1A=1,verbose=True): slit1A_set(Size2B[0],Size2B[1],H2_center,V2_center,verbose) -def mvID(val): +def mvID(val,QP_ratio=100): """ Sets the ID absolute set point (not optimized , mono & apertures stay fixed). to go to most flux use energy """ - ID_energy_set(val) - ID_SP_set(val) + ID_SP_set(val,QP_ratio=100) -def mvID_calibrated(val): +def mvID_calibrated(val,QP_ratio=100): """ Sets the ID peak to val (calibrated). """ - ID_energy_set(val) + ID_energy_set(val,QP_ratio) -def _scan_ID(ID_sp_start,ID_sp_stop,ID_sp_step,**kwargs): +def scan_ID(ID_sp_start,ID_sp_stop,ID_sp_step,**kwargs): """ scan the ID set point """ @@ -428,6 +439,7 @@ def scanXAS(start_stop_step_lists,ID_eV=None,ID_tracking=False, **kwargs): m3r: if True the mirror is optimized before the start of the scan mcp execute: True/False to start the scan => True (default) + QP_ratio: if other than fully periodic Normalization: - If in the D-branch the Mesh is put in but is not removed @@ -442,7 +454,7 @@ def scanXAS(start_stop_step_lists,ID_eV=None,ID_tracking=False, **kwargs): scan_dim=kwargs['scan_dim'] #Setting up the ScanRecord for Mono and ID in Table mode - mono_array,ID_array = BL_energy_tables(start_stop_step_lists) + mono_array,ID_array = BL_energy_tables(start_stop_step_lists,**kwargs) kwargs.update('positioner_num',1) mono_scan_fillin_table(iex.BL.mda,scan_dim,mono_array,**kwargs) if ID_tracking == True: @@ -479,15 +491,17 @@ def scanXAS(start_stop_step_lists,ID_eV=None,ID_tracking=False, **kwargs): print("WARNING: Mesh"+iex.BL.branch+" is still In") -def BL_energy_tables(start_stop_step_lists): +def BL_energy_tables(start_stop_step_lists,**kwargs): """ returns mono_array and ID_array for BL energy scans *energies: start,stop,step ListofLists, e.g.{[400,420,1],[420,425,0.25]...} - + **kwargs: + QP_ratio = 100; completely periodic, normal operations Previously: Tables_BLenergy """ + kwargs.setdefault('QP_ratio', 100) mono_array = make_table(start_stop_step_lists) ID_array=np.array([]) ID_mode,ID_QP_ratio,ID_sp,ID_rbv,hv,grt = energy_get_all(verbose=False) diff --git a/iexcode/macros/ID_energy_calibration.py b/iexcode/macros/ID_energy_calibration.py new file mode 100644 index 0000000..f61c17e --- /dev/null +++ b/iexcode/macros/ID_energy_calibration.py @@ -0,0 +1,511 @@ +from os.path import join, isfile, exists, dirname +from time import sleep + +### Data analysis: +from inspect import CO_ASYNC_GENERATOR +from sre_constants import CATEGORY_DIGIT +import matplotlib.pyplot as plt +import matplotlib.image as mpimg +import numpy as np +from math import * + +from epics import caget, caput + +import iexcode.instruments.cfg as iex + +from iexcode.instruments.xrays import * +from iexcode.instruments.xrays import _energy_range_min_max +from iexcode.instruments.current_amplifiers import current2flux +from iexcode.instruments.diagnostics import _diagnostics_dict, diagnostics_all_out, diagnostics_all_in,diode_c,diode_d +from iexcode.instruments.m3r import * +from iexcode.instruments.slits import * +from iexcode.instruments.utilities import * +from iexcode.instruments.Logfile import log_name_set,log_print +from iexcode.macros.quick_plot import * + +############################################################################################################## +################################ ID calibration scripts ############################## +############################################################################################################## + +###### Energy range follows ID ######## + +def ID_calibration_scan(ID_start,ID_stop,ID_step,bandwidth=10,QP=None,Harm=1,scanIOC=None): + """ + Sets the ID_SP and scans the mono: + start,stop,step are for ID + if QP is not None adjusts the mono range to offset accordingly + !!! DOES NOT CHANGE QP VALUE !!!! + !!! Doesn't put diodes in !!! + """ + + print(""" + !!! DOES NOT CHANGE QP VALUE !!!! + !!! Doesn't put diodes in !!!""") + + log_name_set(iex.BL.endstation,filename_suffix='IDCalibration') + + #Getting mono max range based on grating + grt_density = mono_grating_density_get() + c=grt_density/1200 # c = 1 for MEG, 2 for HEG + if c == 1: + maxhv = 3000 + elif c == 2: + maxhv = 2000 + + log_print(comment="====== Starting Mono Scan vs ID ======") + + for ID_energy in range_up(ID_start,ID_stop,ID_step): + print("\n------------------ ID-SP @ "+str(ID_energy)+" ------------------") + mono_energy_set(min(ID_energy,2999)) + ID_SP_set(ID_energy) + apertures_set() + branch = m3r_branch() + if branch == 'd': + m3r_align() + if QP is None: + start_hv=min(ID_energy-ID_energy/(bandwidth*1.0)*Harm,maxhv) # FR update range 11/20/2019 + stop_hv=min(ID_energy+ID_energy/(bandwidth*2.0)*Harm,maxhv) + step_hv=round(ID_energy/300.0,1) +# start_hv=min(ID_energy-ID_energy/(bandwidth*2.0)*Harm,maxhv) # shift the window by doing -BW*2/+BW*1 instead of -BW*1'/'+BW*2 +# stop_hv=min(ID_energy+ID_energy/(bandwidth*1.0)*Harm,maxhv) +# step_hv=round(ID_energy/500.0,1) + else: + start_hv=min(ID_energy-ID_energy/(bandwidth*2.5)*Harm,maxhv) + stop_hv=min(ID_energy+ID_energy/(bandwidth*0.7)*Harm,maxhv) + step_hv=round(ID_energy/300.0,1) + + mono_scan_fillin(start_hv,stop_hv,step_hv) + iex.BL.mda.go() + sleep(1) + + FileNum = iex.BL.mda.lastFileNum() + if ID_energy == ID_start: + FirstFileNum = FileNum # Record First Scan Number + + LastFileNum = FileNum # Record Last Scan Number + + print("Use: update_id_dict("+str(FirstFileNum)+","+str(LastFileNum)+"ignore=[] ,update_file,path=None,prefix='ARPES',q=True)") + + + +def ID_calibration_mode(ID_mode,start=None,stop=None,step=25,Harm=1,bandwidth=10): + ''' + Runs full calibration with a 25 eV step (by default) for a given mode: + which = 'RCP','LCP', 'V','H' + Better to run each mode in a separated cell (print statement at the end helps with calibration) + ''' + branch = m3r_branch() + diagnostics_all_out(diode_stay_in=True) + + polarization(ID_mode) + + grt = mono_grating_get() + + QP_ratio = ID_QP_ratio_get() + + hv_min,hv_max = _energy_range_min_max() + if start == None: + start = hv_min + if stop == None: + stop=hv_max-50 + + if QP_ratio <100: + stop=min(stop,1500) + QP_ratio=1 + else: + QP_ratio=None + + ID_calibration_scan(start,stop,step,bandwidth=bandwidth,QP=QP_ratio,Harm=Harm) + +############################################################################################### +######################################### IDCalibration New ################################### +############################################################################################### + + + +def id_calibration_fit(first_scan,last_scan,det,PolyRank,**kwargs): + + + #id_calibration_fit(FirstLast[0],FirstLast[1],det,poly_order,mytitle=mytitle,countby=countby,plotMin=plt_min,plotMax=plt_max,plotType=plotType,filepath=filepath,prefix=prefix) + """ + Fits calibration curves fpr each GRTs and modes included in the data set. Creates 3 dictionnaries: + + coefs={[GRT][mode][[breakpoint1,[coefs]],[breakpoint2,[coefs]...} + xdata= {[GRT][mode][[breakpoint1,[flux curve x axis]],[breakpoint2,[flux curve x axis]...} + fdata= {[GRT][mode][[breakpoint1,[flux curve y axis]],[breakpoint2,[flux curve y axis]...} + + kwargs: + countby = 1 by default + mytitle = '' by default + plotMin = min x range for plotting (default 250) + plotMax = max x range for plotting (default 3000) + plotType = ['dif,'fit,'flux'], full set by default + filepath = None, uses current mda filepath unless specified + e.g. user : filepath='/net/s29data/export/data_29idc/2018_2/UserName/mda/' + e.g. staff: filepath='/net/s29data/export/data_29idb/2018_2/mda/' + prefix = None, uses current mda prefix unless specified + scanIOC = None, uses BL_ioc() unless specified + """ + + kwargs.setdefault('countby',1) + kwargs.setdefault('mytitle','') + #kwargs.setdefault('plotMin',2000) + kwargs.setdefault('plotMin',225) + kwargs.setdefault('plotMax',3000) + kwargs.setdefault('plotType',['fit','dif','flux']) + kwargs.setdefault('filepath',iex.BL.mda.filepath()) + kwargs.setdefault('prefix',iex.BL.mda.prefix()) + + countby=kwargs['countby'] + mytitle=kwargs['mytitle'] + plotMin=kwargs['plotMin'] + plotMax=kwargs['plotMax'] + filepath=kwargs['filepath'] + prefix=kwargs['prefix'] + + + def calibration_curve(first,last,det,countby,filepath,prefix): + mono_list=[] + ID_list=[] + max_list=[] + flux_list=[] + print("filepath = ",filepath) + print("prefix = ",prefix) + print("First scan = ",first) + print("Last scan = ",last) + for i in range(first,last,countby): + x,y,x_name,y_name=mda_1D(i,det,1,0,filepath,prefix) #mda_1D(ScanNum,DetectorNum,coeff=1,bckg=0,filepath=None,prefix=None,scanIOC=None): + v,w,v_name,w_name=mda_1D(i, 4 ,1,0,filepath,prefix) + if y != []: + n=y.index(max(y)) # finds the peak max intensity index + e=round(x[n],2) # finds the corresponding mono energy + sp=round(w[2]*1000,0) # reads the ID set point + mono_list.append(e) + max_list.append(max(y)) + ID_list.append(sp) + flux_list.append(current2flux(max(y),e,p=None)) + return mono_list,ID_list,max_list,flux_list + + Mono_max,ID_SP,int_max,flux=calibration_curve(first_scan,last_scan+1,det,countby,filepath,prefix) + nPt_gaus=200 + x_HR = np.linspace(Mono_max[0], Mono_max[-1], nPt_gaus) + + # Data + xdata = np.array(Mono_max) + ydata = np.array(ID_SP) + zdata = np.array(int_max) + fdata = np.array(flux) + # Fitting + coefs = poly.polyfit(xdata, ydata, PolyRank) + ffit_HR = poly.polyval(x_HR, coefs) + ffit_Coarse = poly.polyval(xdata, coefs) + # Residual + Dif=np.array(ID_SP)-np.array(ffit_Coarse) + ratio=(np.array(ID_SP)-np.array(ffit_Coarse))/(np.array(ID_SP)/100) + # Plot differences + #print('plotMin = ',str(plotMin)) + if 'dif' in kwargs['plotType']: + fig = plt.figure(figsize=(12,6)) + plt.plot(Mono_max,ID_SP,marker='x',markersize=5,color='g',linewidth=0,label='data') + plt.plot(x_HR,ffit_HR,color='b',label='SP-fit') + plt.plot(xdata,Dif*100,marker='x',color='r',label='Dif x100') + plt.plot(xdata,ratio*1000,marker='x',color='g',label='Difx1000/ID') + plt.ylabel('ID SP') + plt.xlabel('Mono') + plt.xlim(plotMin,plotMax) + plt.legend(ncol=2, shadow=True, title=mytitle, fancybox=True) + plt.grid(linestyle='-', linewidth='0.5', color='grey') + plt.show() + # Plot raw data + fit + if 'fit' in kwargs['plotType']: + fig = plt.figure(figsize=(12,6)) + a1 = fig.add_axes([0,0,1,1]) + a1.plot(xdata+Dif,zdata,marker='*',markersize=10,color='r',linewidth=0,label='Interpolated ID SP') + for i in range(first_scan,last_scan+1): + x,y,x_name,y_name=mda_1D(i,det,1,0,filepath,prefix) + a1.plot(x,y,color='b') + a1.set_xlim(plotMin,plotMax) + a1.set(xlabel='Mono') + a1.set(ylabel='ID SP') + a1.ticklabel_format(style='sci', axis='y', scilimits=(0,0)) + a1.grid(linestyle='-', linewidth='0.5', color='grey') + plt.legend(ncol=2, shadow=True, title=mytitle, fancybox=True) + plt.show() + # Plot flux curves: + fdata_x=xdata+Dif + if 'flux' in kwargs['plotType']: + fig = plt.figure(figsize=(12,6)) + a1 = fig.add_axes([0,0,1,1]) + a1.plot(fdata_x,fdata,color='r',linewidth=1,label='Flux curves') + a1.set_xlim(plotMin,plotMax) + a1.set(xlabel='Mono') + a1.set(ylabel='ID SP') + a1.set_yscale('log') + #a1.ticklabel_format(style='sci', axis='y', scilimits=(0,0)) + a1.grid(linestyle='-', linewidth='0.5', color='grey') + plt.legend(ncol=2, shadow=True, title=mytitle, fancybox=True) + plt.show() + return coefs, fdata_x,fdata + + + + + + +def read_id_files(first,last,filepath=None,prefix=None,q=True): + """ + Reads extra PVs + Return a list of [[ScanNum,ID_SP,grt,mode],...] for mda files between first and last. + """ + if filepath == None: + filepath=iex.BL.mda.filepath() + if prefix == None: + prefix=iex.BL.mda.prefix()[:-1] + elif prefix[-1] == "_": + prefix=prefix[:-1] + mydata=mdaFile(first,last,filepath=filepath,prefix=prefix,q=q) + value=[] + modeDict={'CW, RCP':'RCP','CCW, LCP':'LCP','H':'H','V':'V'} + grtDict={1200:'MEG',2400:'HEG'} + for mdaNum in mydata.scanList: + if first<=mdaNum<=last: + extraPVs=mydata.header[mdaNum].all + try: + ID=round(extraPVs['ID29:EnergySet.VAL'][2][0]*1000,2) + mode=modeDict[extraPVs['ID29:ActualMode'][2]] # extraPVs return 'CW, RCP' + grt=grtDict[extraPVs['29idmono:GRT_DENSITY'][2][0]] # extraPVs return 1200 + except KeyError: + ID=round(extraPVs[b'ID29:EnergySet.VAL'][2][0]*1000,2) + mode=modeDict[str(extraPVs[b'ID29:ActualMode'][2])[2:-1]] + grt=grtDict[extraPVs[b'29idmono:GRT_DENSITY'][2][0]] # extraPVs return 1200 + if len(value)>0 and value[-1][1:] == [ID,grt,mode]: + pass + else: + value.append([mdaNum,ID,grt,mode]) + return value + + + +def id2num(ID,grt,mode,first=0,last=inf,ignore=[],filepath=None,prefix=None,q=True): # Not efficient - requires to read all 600 files everytime + """ + Return ScanNum corresponding to a given ID_SP from ExtraPVs (using mdaFile) + """ + if filepath == None: + filepath=BL.mda.filepath() + if prefix == None: + prefix=BL.mda.prefix()[:-1] + elif prefix[-1] == "_": + prefix=prefix[:-1] + ScanNum = 0 + data_list = read_id_files(first,last,filepath,prefix,q) + data_short=[x for x in data_list if x[2:]==[grt,mode] and x[0] not in ignore] + step=data_short[1][1]-data_short[0][1] + precision=int(step/2) + ID1=ID-precision + ID2=ID+precision + ScanNum=[x[0] for x in data_short if ID1<= x[1]<= ID2] + if len(ScanNum)==0: result=None + else: result=ScanNum[0] + return result + + + +def num2id(ScanNum,grt,mode,first=0,last=inf,ignore=[],filepath=None,prefix=None,q=True): # Not efficient - requires to read all 600 files everytime + """ + Return ID SP corresponding to a given ScanNum from ExtraPVs (using mdaFile) + """ + if filepath == None: + filepath=BL.mda.filepath() + if prefix == None: + prefix=BL.mda.prefix()[:-1] + elif prefix[-1] == "_": + prefix=prefix[:-1] + ID = 0 + data_short=[] + data_list = read_id_files(first,last,filepath,prefix,q) + data_short=[x for x in data_list if x[2:]==[grt,mode] and x[0] not in ignore] + ID=[x[1] for x in data_short if x[0] == ScanNum] + return ID[0] + + + +def extract_id(first,last,ignore=[],breakpts={'RCP':[600],'H':[400,600],'V':[600],'LCP':[600],'HEG':[],'MEG':[2200,2475]},filepath=None,prefix=None,q=True): + """ + Breaksdown the info from a calibration files into grt & mode with the corresponding breakpoints (hardcoded): + [[first, last, 'HEG', 'RCP', [600]], + [first, last, 'HEG', 'H', [400, 600]]...] + """ + if filepath == None: + filepath=BL.mda.filepath() + if prefix == None: + prefix=BL.mda.prefix()[:-1] + elif prefix[-1] == "_": + prefix=prefix[:-1] + IDlog=read_id_files(first,last,filepath,prefix,q) + #breakpts={'RCP':[600],'H':[400,600],'V':[600],'LCP':[600],'HEG':[],'MEG':[2200]} + #breakpts={'RCP':[600],'H':[400,600],'V':[600],'LCP':[600],'HEG':[],'MEG':[2200]} + #breakpts={'RCP':[600],'H':[600],'V':[600],'LCP':[600],'HEG':[],'MEG':[2200,2475]} # FR changed H breakpoints, missing low energy scans 06/14/2021 + data=[] + for grt in ['HEG','MEG']: + for mode in ['RCP','H','V','LCP']: + tmp=[x for x in IDlog if x[2:]==[grt,mode] and x[0] not in ignore] + #print(tmp) + if len(tmp)>0: + tmp=[tmp[0][0],tmp[-1][0],grt,mode,breakpts[mode]+breakpts[grt]] + data.append(tmp) + return data + + + +def update_id_dict(first,last,det,update_file,ignore,**kwargs): + """ + Calculate new calibration curve for a full set of data.' + But what if the set is not complete? To be addressed by Future Me + If update_file == True (ONLY): + \tupdate the ID dictionary '/home/beams22/29IDUSER/Documents/User_Macros/Macros_29id/IEX_Dictionaries/Dict_IDCal.txt' + """ + + if update_file == True: + foo=input('\nAre you sure you want to update the ID calibration dictionary?\n>') + if foo == 'Y' or foo == 'y' or foo == 'yes'or foo == 'YES' or foo == 'Yes': + foo = 'yes' + print('\nWill save new dictionary to: \'/home/beams22/29IDUSER/Documents/User_Macros/Macros_29id/IEX_Dictionaries/Dict_IDCal.txt\'\n') + else: + print('\nCalibration curves will not be saved.\n') + else: + print('\nCalibration curves will not be saved.\n') + + kwargs.setdefault('countby',1) + kwargs.setdefault('mytitle','') + kwargs.setdefault('plotMin',225) + kwargs.setdefault('plotMax',3000) + kwargs.setdefault('plotType',['fit','dif','flux']) + kwargs.setdefault('filepath',iex.BL.mda.filepath()) + kwargs.setdefault('prefix',iex.BL.mda.prefix()) + kwargs.setdefault('q',True) + kwargs.setdefault('breakpts',{'RCP':[600],'H':[400,600],'V':[600],'LCP':[600],'HEG':[],'MEG':[2200,2475]}) + + + breakpts=kwargs['breakpts'] + plotType=kwargs['plotType'] + filepath=kwargs['filepath'] + prefix=kwargs['prefix'] + q=kwargs['q'] + + ID_data=extract_id(first,last,ignore,breakpts,filepath,prefix,q) + + ##### Extract parameters: + + mode_dict ={'RCP':0,'LCP':1,'V':2,'H':3} + id_coef={} + new_id_function={} + id_flux={} + flux_dict={} + id_energy={} + energy_dict={} + for mylist in ID_data: + if len(mylist) > 0: # in case of incomplete data set + tmp0,tmp1,tmp2=[],[],[] + first_scan=mylist[0] + last_scan=mylist[1] + scan_list=[[first_scan,last_scan]] + countby=1 + #det=15 + #det=33 + poly_order=4 + grt=mylist[2] + mode=mylist[3] + breakpts_energy=mylist[4] + breakpts_scan=[] + mytitle=mode+' - '+grt + + ## generating list of scans depending on breakpoints: + if breakpts_energy != []: + scan_list=[] + for x in breakpts_energy: + breakpts_scan.append(id2num(x,grt,mode,first,last,ignore,filepath,prefix,q)) + breakpts_scan = [i for i in breakpts_scan if i] + print(breakpts_scan) + for c,x in enumerate(breakpts_scan): # can get the number by extracting step size then /2 + if c == 0: + if x == first_scan: pass + else: scan_list.append([first_scan,x]) + if 0 < c < len(breakpts_scan)-1: + scan_list.append([breakpts_scan[c-1],x]) + scan_list.append([x,breakpts_scan[c+1]]) + if c == len(breakpts_scan)-1 and (c-1) == 0: + scan_list.append([breakpts_scan[c-1],x]) + if c == len(breakpts_scan)-1: + scan_list.append([x,last_scan]) + final_list = [i for n, i in enumerate(scan_list) if i not in scan_list[:n]] # remove doubles + energy_list=[] + for x in final_list: + ID1=num2id(x[0],grt,mode,first,last,ignore,filepath,prefix,q) + ID2=num2id(x[1],grt,mode,first,last,ignore,filepath,prefix,q) + energy_list.append([ID1,ID2]) + energy_list_2=energy_list # we need the final value for plot purposes (max value) + if grt == 'HEG': + energy_list_2[-1][-1]=2500 # but we don't want it to be a cutoff for ID_Calc in dict + for (FirstLast,ID,cutoff) in zip(final_list,energy_list,energy_list_2): + plt_min=ID[0]-200 + plt_max=ID[1]+100 + if grt=='MEG' and ID[1]>2900: + poly_order=5 + plt_min=ID[0]-200 + print('det =',det) + print('poly_order =',poly_order) + + subkwargs=kwargs # kwargs contains plotType, filepath, prefix and q + newkwargs={'mytitle':mytitle,'countby':countby,"plotMin":plt_min,'plotMax':plt_max} + subkwargs.update(newkwargs) + #print(newkwargs) + #print(FirstLast[0],FirstLast[1]) + #result,energy_data,flux_data=id_calibration_fit(FirstLast[0],FirstLast[1],det,poly_order,subkwargs) + result,energy_data,flux_data=id_calibration_fit(FirstLast[0],FirstLast[1],det,poly_order,mytitle=mytitle,countby=countby,plotMin=plt_min,plotMax=plt_max,plotType=['fit','dif'],filepath=filepath,prefix=prefix) + tmp0.append([cutoff[1],result.tolist()]) + tmp1.append([cutoff[1],energy_data]) + tmp2.append([cutoff[1],flux_data]) + + if 2900<tmp0[-1][0]<3000: tmp0[-1][0]=3000 + id_coef[mode_dict[mode]]=tmp0 # dictionary that + new_id_function[grt]=id_coef # dictionary containing all the calibration curves forthe data set + id_energy[mode_dict[mode]]=tmp1 # dictionary that + energy_dict[grt]=id_energy + id_flux[mode_dict[mode]]=tmp2 # dictionary that + flux_dict[grt]=id_flux + + ##### Read & update old dictionary: + + try: + id_function=read_dict('Dict_IDCal.txt') + print(id_function) + id_function.update(new_id_function) + + except KeyError: + print("Unable to read previous dictionary") + + + if update_file == True and foo == 'yes': + filepath = "/home/beams22/29IDUSER/Documents/User_Macros/Macros_29id/IEX_Dictionaries/" + filename = 'Dict_IDCal.txt' + + with open(join(filepath, filename), "a+") as f: + f.write('\n======= '+today()+': \n') + f.write(str(id_function)) + f.write('\n') + print('\nWriting dictionary to:',join(filepath, filename)) + + if update_file == True and foo == 'yes': + filepath = "/home/beams22/29IDUSER/Documents/User_Macros/Macros_29id/IEX_Dictionaries/" + filename = 'Flux_Curves.txt' + + with open(join(filepath, filename), "a+") as f: + f.write('\n======= '+today()+': \n') + f.write('\n----- flux_x:\n') + f.write(str(energy_dict)) + f.write('\n----- flux_y:\n') + f.write(str(flux_dict)) + f.write('\n') + print('\nWriting flux curves to:',join(filepath, filename)) + + return id_function,energy_dict,flux_dict diff --git a/iexcode/macros/Kappa_optimization.py b/iexcode/macros/Kappa_optimization.py index 353d201..54a89ae 100644 --- a/iexcode/macros/Kappa_optimization.py +++ b/iexcode/macros/Kappa_optimization.py @@ -1,12 +1,144 @@ -import matplotlib.pyplot as plt -from epics import caget,caput -from ..instruments.kappa import * -from ..instruments.Motors import * -from .quick_plot import fit_mda, mda_1D -##### Kappa Optimization scans ##### +##### Kappa Optimization scans - 2022 versions ##### + +def Find_kth_zero(th_0,th_180): + """ + th_0 is the motor position for specular near zero + th_180 is motor position for spectular near 180 + """ + + Offset =0.5*(180 - th_180 - th_0) + + print("with motor at 0, the actual value is ",Offset) + + +def align_d4(z0,th): + ''' th = 0 or 180 + ''' + setdet('d4') + sleep(1) + uan(0,th) + mvz(z0-1500) + setgain('d4',10,'uA') + dscantth(-0.25,0.25,0.01) + sleep(1) + setgain('d4',1,'nA') + mvz(z0) + n=LastMDA() + fit_mda(n,25,0,'poly',graph=False) + tth0=fit_d4(n) + print('tth0 = '+str(round(tth0,3))) + playsound() + return tth0 + + +def align_z0_chi0(question=True): + if question: + foo=input_d('Are you at th=90/270, chi=0, phi=90 (Y or N)? >') + if foo == 'Y'.lower() or foo == 'yes'.lower(): + setdet('d3') + sleep(1) + mvtth(0) + dscanz(-750,750,50) + sleep(1) + n=LastMDA() + fit_mda(n,25,0,'poly',graph=False) + z0=fit_z(n) + print('z0 = '+str(round(z0,0))) + playsound() + return z0 + else: + print('Canceling') + return + else: + setdet('d3') + sleep(1) + mvtth(0) + dscanz(-750,750,50) + sleep(1) + n=LastMDA() + fit_mda(n,25,0,'poly',graph=False) + z0=fit_z(n) + print('z0 = '+str(round(z0,0))) + playsound() + return z0 + + + +def align_z0(omega): + setdet('d3') + sleep(1) + uan(0,omega) + dscanz(-750,750,50) + sleep(1) + n=LastMDA() + #fit_mda(n,25,0,'poly',graph=False) + #z0=fit_z(n) + #print('z0 = '+str(round(z0,0))) + playsound() + #return z0 + + +def align_z180(omega): + setdet('d3') + sleep(1) + uan(0,180+omega) + dscanz(-750,750,50) + sleep(1) + n=LastMDA() + #fit_mda(n,25,0,'poly',graph=False) + #z180=fit_z(n) + #print('z180 = '+str(round(z180,0))) + playsound() + #return z180 + +def align_th0(omega,z): + setdet('d4') + sleep(1) + #uan(20,10+omega) + uan(30,15+omega) + mvz(z) + sleep(30) + setgain('d4',1,'nA') + dscanth(-0.25,0.25,0.01) + n=LastMDA() + fit_mda(n,25,0,'poly',graph=False) + th_spec=fit_d4(n) + print('th specular = '+str(round(th_spec,3))) + tth=round(caget('29idKappa:m9.RBV'),3) + omega=th_spec-tth/2 + print('omega = th-tth/2 = '+str(round(omega,3))) + playsound() + return omega + + +def align_th180(omega,z): + setdet('d4') + sleep(1) + uan(-30,180+omega-15) + #uan(-20,180+omega-10) + mvz(z) + setgain('d4',1,'nA') + dscanth(-0.25,0.25,0.01) + n=LastMDA() + fit_mda(n,25,0,'poly',graph=False) + th_spec=fit_d4(n) + print('th specular = '+str(round(th_spec,3))) + tth=round(caget('29idKappa:m9.RBV'),3) + omega180=th_spec-tth/2-180 + print('omega180 = th-tth/2-180 = '+str(round(omega180,3))) + playsound() + return omega180 + + + + +##### Kappa Optimization scans - old versions ##### + + + def Opt_d4(iteration,moveZ,graph='y',srs=None,start=-0.5,stop=0.5,step=0.04): tth_w=0.1 if srs==None: det=21 @@ -15,13 +147,13 @@ def Opt_d4(iteration,moveZ,graph='y',srs=None,start=-0.5,stop=0.5,step=0.04): current_det=caget('29idKappa:userStringSeq6.STR1',as_string=True) if current_det != 'd4': print('Switching detector to d4') - tthdet.set('d4',move=False) - mvtth(0) + setdet('d4') + mvtth(0) if moveZ is not None: mvz(z-1000) for i in range(iteration): scantth(start,stop,step,'relative') - scannum = mda.lastFileNum() + scannum=LastMDA() tth0=fit_mda(scannum,det,tth_w,'gauss',graph=graph) mvtth(tth0) mvz(z) @@ -32,7 +164,7 @@ def Opt_z0(iteration,movetth,movekth,det='d4',srs=None,graph='y'): current_det=caget('29idKappa:userStringSeq6.STR1',as_string=True) if current_det != det: print('Switching detector to '+det) - tthdet.set(det,move=False) + setdet(det) if det=='d3' and srs==None: det=20 if det=='d3' and srs!=None: det=33 if det=='d4' and srs==None: det=21 @@ -43,11 +175,11 @@ def Opt_z0(iteration,movetth,movekth,det='d4',srs=None,graph='y'): mvkth(movekth) if iteration>1: scanz(-2000,2000,250,'relative') - scannum=mda.fileNum() + scannum=LastMDA() z0=fit_mda(scannum,det,z_w,'erf',graph=graph) mvz(z0) scanz(-700,700,50,'relative') - scannum = mda.lastFileNum() + scannum=LastMDA() z0=fit_mda(scannum,det,z_w,'erf',graph=graph) mvz(z0) return z0,scannum @@ -56,7 +188,7 @@ def Opt_kth(kth_0,theta,det='d4',srs=None,graph='y'): current_det=caget('29idKappa:userStringSeq6.STR1',as_string=True) if current_det != det: print('Switching detector to '+det) - tthdet.set(det,move=False) + setdet(det) if det == 'd4': if srs==None: det=21 else: det=34 @@ -68,12 +200,12 @@ def Opt_kth(kth_0,theta,det='d4',srs=None,graph='y'): mvtth(theta*2) mvkth(kth_0+theta) scankth(-0.5*i,0.5*i,0.05*i,'relative') - new_kth=fit_mda(mda.lastFileNum(),det,0.1,'gauss',graph=graph) + new_kth=fit_mda(LastMDA(),det,0.1,'gauss',graph=graph) mvkth(new_kth) scankth(-0.2*i,0.2*i,0.02*i,'relative') - new_kth=fit_mda(mda.lastFileNum(),det,0.1,'gauss',graph=graph) + new_kth=fit_mda(LastMDA(),det,0.1,'gauss',graph=graph) mvkth(new_kth) - scannum=mda.lastFileNum + scannum=LastMDA() kth0=round(new_kth-theta,3) print('\nkth0 = ',kth0) print('To plot use:') diff --git a/iexcode/macros/commissioning.py b/iexcode/macros/commissioning.py index ca2263c..5400079 100644 --- a/iexcode/macros/commissioning.py +++ b/iexcode/macros/commissioning.py @@ -1,94 +1,32 @@ -""" -Functions for commissioning, alignment and start of the week - -""" from os.path import join, isfile, exists, dirname from time import sleep from epics import caget, caput +import iexcode.instruments.cfg as iex -from ..instruments.files_and_folders import check_run, folder_mda -from ..instruments.scanRecord import scanRecord_run,scanRecord_filepath -from ..instruments.xrays import energy -from ..instruments.m3r import M3R_branch +from iexcode.instruments.ARPES import ARPES_init +from iexcode.instruments.kappa import kappa_init +from iexcode.instruments.xrays import * +from iexcode.instruments.xrays import _energy_range_min_max +from iexcode.instruments.current_amplifiers import current2flux +from iexcode.instruments.diagnostics import _diagnostics_dict, diagnostics_all_out, diagnostics_all_in,diode_c,diode_d +from iexcode.instruments.m3r import * +from iexcode.instruments.slits import * +from iexcode.instruments.utilities import * +from iexcode.instruments.electron_analyzer import scanEA +from iexcode.instruments.Logfile import log_name_set,log_print +from iexcode.instruments.cameras import * -from ..instruments.IEX_VPU import ID_switch_mode -from ..instruments.diagnostics import diagnostics_all_out, diagnostics_all_in,diode_c,diodeD -from ..instruments.current_amplifiers import current2flux -from ..instruments.slits import set_exit_slit -from ..instruments.Logfile import * -from ..instruments.cameras import * -from ..instruments.ARPES import * -from ..instruments.electron_analyzer import * -from ..instruments.kappa import * -from .quick_plot import fit_mda, mda_1D -############################################################################################################## -################################ setting the mda folder ############################## -############################################################################################################## -def staff_init(endstation_name=None,set_folders=True,reset=True): - """ - endstation_name : sets the scan record and BL - set_folders: sets the mda and EA folders; default => False - reset: resets the scanRecord (detectors,triggers...) - - **kwargs: - xrays: sets global variable; default => True - BL_mode: 'user' / 'staff' => used for saving, detectors - Previously: folders_staff - """ - if endstation_name is None: - endstation_name = BL.endstation - - if endstation_name == 'ARPES': - ARPES_init(set_folders,reset,BL_mode='staff') - if endstation_name == 'Kappa': - Kappa_init(set_folders,reset,BL_mode='staff') - - - -def check_staff_directory(BL, **kwargs): - """ - Switchs to the staff directory - **kwargs for folder_ARPES +from .quick_plot import fit_mda, mda_1D - Previously: Check_Staff_Directory - """ - - ioc = BL.ioc() - run = check_run() - - directory = scanRecord_filepath(ioc) - current_run = scanRecord_run(ioc) - - if directory.find('data_29idb') < 1 or current_run != run: - print('You are not currently saving in the Staff directory and/or the desired run.') - # foo=input('\nAre you ready to switch to the '+run+' Staff directory (y or n)? >') - # if foo.lower() == 'y' or foo.lower() == 'yes': - if not (exists(directory)): - print('Staff directory does not exist for this run.') - print('Open ipython as 29id to create a new run directory using:\n\tFolder_'+ioc+'(run,"Staff")') - foo=input('\nPress enter when done >') - if foo == '': pass - print('Switching directory...') - if ioc=='ARPES': - folders_ARPES('Staff',mdaOnly=True,**kwargs) - elif ioc=='Kappa': - folders_Kappa('Staff',create_only=False) - else: - print('\nFolder not set.') - else: - print('Staff directory OK.') - directory = scanRecord_filepath(ioc) - print('\nCurrent directory: '+directory) - ############################################################################################################## @@ -110,15 +48,15 @@ def check_flux(hv=500,ID_mode='RCP',stay=False): if m3r_branch() == "c": current_slit=caget('29idb:Slit3CFit.A') diode_c('In') - set_exit_slit(50) + exit_slit(50) sleep(10) - diode=diodeC_read() + diode=diode_c_read() elif m3r_branch() == "d": current_slit=caget('29idb:Slit4Vsize.VAL') sleep(10) - diodeD("In") - set_exit_slit(50) - diode=caget('29idb:ca14:read') + diode_d("In") + exit_slit(50) + diode=diode_d_read() flux=current2flux(diode) print("\n----- Current on diode : %.3e" % diode, "A") print("----- Corresponding flux: %.3e" % flux, "ph/s \n") @@ -127,7 +65,7 @@ def check_flux(hv=500,ID_mode='RCP',stay=False): if not stay: diagnostics_all_out() - set_exit_slit(current_slit) + exit_slit(current_slit) def check_m0m1(hv=500,stay=True,wire=True,**kwargs): """ @@ -140,7 +78,7 @@ def check_m0m1(hv=500,stay=True,wire=True,**kwargs): """ switch_branch('c') - switch_gratings('HEG') + grating('HEG') print("\nFlux at hv=500 as off Feb 2019: ~3.3e-06 A = ~1.5e+11 ph/s") branch_shutter_open() check_flux(hv=hv,stay=stay) @@ -171,13 +109,13 @@ def scan_wire(direction,all_diag=True,**kwargs): elif direction == 'V': name = "V-wire" - diag = diagnostics_dict() + diag = _diagnostics_dict() pv = "29idb:m"+str(diag["motor"][name]) print("\n================== "+name+" scan (29idb:ca2):") - BL.mda.fillin(pv+".VAL",pv+".RBV",1,-17,-30,-0.25,**kwargs) + iex.BL.mda.fillin(pv+".VAL",pv+".RBV",1,-17,-30,-0.25,**kwargs) if kwargs['execute']: - BL.mda.go(**kwargs) + iex.BL.mda.go(**kwargs) if all_diag: diagnostics_all_out() @@ -228,7 +166,7 @@ def scan_narrow_slit(slit='2V',slit_parameters=[0.25,-2,2,0.5],**kwargs): slits_scan_center(slit_name,direction,start,stop,step,**kwargs) if kwargs['execute']: - BL.mda.go(kwargs['scan_dim']) + iex.BL.mda.go(kwargs['scan_dim']) def scan_mono_vs_slit(slit='2V',slit_parameters=[0.25,-2,2,0.5],energy_parameters=[470,530,2],**kwargs): @@ -253,13 +191,13 @@ def scan_mono_vs_slit(slit='2V',slit_parameters=[0.25,-2,2,0.5],energy_parameter # Resetting everybody to normal: mono_energy_set((hv_start+hv_stop)/2.0) - slits_set_BL() + apertures_set() ############################################################################################################## ################################ mono alignment ############################## ############################################################################################################## -def mono_MIR_GRT_find_offset(grating,slit_list,**kwargs): +def mono_MIR_GRT_find_offset(grt,slit_list,**kwargs): """ Find MIR-GRT offset by scanning 0 order through exit slit **kwargs: @@ -269,7 +207,7 @@ def mono_MIR_GRT_find_offset(grating,slit_list,**kwargs): """ kwargs.setdefault("detNum",15) - switch_gratings(grating) + grating(grt) exit_slit(50) diode_c('In') slit2B_set(2,0.5,0,0) @@ -284,11 +222,11 @@ def mono_MIR_GRT_find_offset(grating,slit_list,**kwargs): print("\r") mono_motor_scan_fillin("GRT:P",ang-0.0005*s, ang+0.0005*s ,0.00002*s) - BL.mda.go(**kwargs) + iex.BL.mda.go(**kwargs) sleep(1) print("\r") - grating_ang = fit_mda(mda.fileNum(),kwargs['detNum'],.1,'gauss') + grating_ang = fit_mda(iex.BL.mda.fileNum(),kwargs['detNum'],.1,'gauss') print("Peak: ",grating_ang) print("\r") print("-------------------------") @@ -346,7 +284,7 @@ def scan_energy_along_grating(hv,peakBE=84,pts=11,r=0.75,i=1,**kwargs): scanEA(EAlist,**kwargs) #reset the slits - slits_set_BL() + apertures_set() @@ -427,9 +365,9 @@ def scan_pinhole(H_list,V_list,**kwargs): +str(H_list[0])+"/"+str(H_list[1])+"/"+str(H_list[2])+"/"+str(H_list[3])+"/" +str(V_list[0])+"/"+str(V_list[1])+"/"+str(V_list[2])+"/"+str(V_list[3])) - BL.mda.go(max(kwargs['H_scan_dim'],kwargs['V_scan_dim'])) + iex.BL.mda.go(max(kwargs['H_scan_dim'],kwargs['V_scan_dim'])) print("\rNow setting the slits back to:") - slits_set_BL() + apertures_set() print("\r") print_warning_message("Don't forget to pull all of the diagnostics out.") @@ -439,9 +377,9 @@ def scan_pinhole(H_list,V_list,**kwargs): ############################################################################################################## ################## Slit Calibration & Beam Steering scripts ################## ############################################################################################################## +FMB_mirror_move - -def Notes_from_20191212(): +def notes_20191212(): print(""" looking at diode 3 in scattering chamber, open 3D all the way (2000) WARNING: 10% energy detune is enough to see the 2 lobes with 2B but not for 1A => 20% Red shifted (485eV) = edges give center of the grating @@ -450,27 +388,27 @@ def Notes_from_20191212(): => 5 urad down = 1 mm negative motion on 2B-V with HEG""") -def procedure_alignment_M1(): +def procedure_align_m1(): print("""\n-Start with a very red shifted line cut to localize the edges of the grating: Set_IDraw(510) mono(485) - Scan_NarrowSlit('2V',[0.25,-8,8,0.5]) - Scan_NarrowSlit('2H',[0.25,-4,4,0.5]) + scan_narrow_slit('2V',[0.25,-8,8,0.5]) + scan_narrow_slit('2H',[0.25,-4,4,0.5]) => Verticaly: The edges/center of the grating define the center of 2V => Horizontaly: The edges are defined by the aperture upstream. As long as the beam makes it through the pipe to the next mirror, we are good. Each M1 pitch will have its own slit-2H zero It can be a good idea to check that GRT or M2 translation does not change anything. \n-Once the slits are centered on the grating, center resonant beam on the grating (zero slit): - Get_Mirror(1) # to get current values - for roll in RangeUp(3,4,0.2): - print('\\n') - Move_M1('RZ',roll) + FMB_mirror_get(1) # to get current values + for roll_value in RangeUp(3,4,0.2): + print('\\nRZ = '+str(roll_value)) + FMB_mirror_move(1,'RZ',roll_value) sleep(5) scan_mono_vs_slit('2V',[0.25,-0.5,0.5,0.25],[490,530,2]) - for pitch in RangeUp(8.5,8.7,0.05): - print('\\nMove_M1('RY',pitch)') - Move_M1('RY',pitch) + for pitch_value in RangeUp(8.5,8.7,0.05): + print('\\nRY = '+str(pitch_value)) + FMB_mirror_move(1,'RY',pitch_value) sleep(5) scan_mono_vs_slit('2H',[0.25,-0.5,0.5,0.25],[490,530,2]) => The resonant beam is the slit value for the most blue shifted curve. @@ -489,15 +427,17 @@ def beamsteering_2B(v_position): vroll=round(v_position*0.05/0.04,3) if v_position<0: v_direction=' +' else: v_direction=' -' - v_steering=v_direction+str(vroll)+' urad' - return v_steering - -def beamsteering_1A(h_position,v_position): - hrad=round(h_position*10/0.25,0) - vrad=round(v_position*10/0.25,0) - if h_position<0: h_direction=' urad outboard' + v_steering=v_direction+str(abs(vroll))+' urad' + return v_steering,float(v_steering.split(" ")[1]) + +def beamsteering_1A(h_position,v_position,FE_center_h=0,FE_center_v=0): + h_correction=FE_center_h-h_position + v_correction=FE_center_v-v_position + hrad=round(abs(h_correction)*10/0.25,0) + vrad=round(abs(v_correction)*10/0.25,0) + if h_correction<0: h_direction=' urad outboard' else: h_direction=' urad inboard' - if v_position<0: v_direction=' urad up' + if v_correction<0: v_direction=' urad up' else: v_direction=' urad down' h_steering=str(hrad)+h_direction v_steering=str(vrad)+v_direction @@ -536,9 +476,9 @@ def check_slit1A(step=0.1): m=9 VAL='29idb:m'+str(m)+'.VAL' RBV='29idb:m'+str(m)+'.RBV' - BL.mda.fillin(VAL,RBV,-4,4.0,step) - BL.mda.go() - FileNum1 = BL.mda.lastFileNum() + iex.BL.mda.fillin(VAL,RBV,-4,4.0,step) + iex.BL.mda.go() + FileNum1 = iex.BL.mda.lastFileNum() #scanning inboard-blade slit1A_set(8,8,0,0) # aperture wide open @@ -546,9 +486,9 @@ def check_slit1A(step=0.1): m=10 VAL='29idb:m'+str(m)+'.VAL' RBV='29idb:m'+str(m)+'.RBV' - BL.mda.fillin(VAL,RBV,-4,4.0,step) - BL.mda.go() - FileNum2 = BL.mda.lastFileNum() + iex.BL.mda.fillin(VAL,RBV,-4,4.0,step) + iex.BL.mda.go() + FileNum2 = iex.BL.mda.lastFileNum() return FileNum1, FileNum2 @@ -625,7 +565,7 @@ def ID_beam_profile(grt,slit_list,c_slit=1,c_energy=1,**kwargs): Previously """ - switch_gratings(grt) + grating(grt) grt_density = mono_grating_density_get() c=grt_density/1200 ID=500 @@ -656,9 +596,9 @@ def CheckAllSlits_long(hv_list=[500],slit_list=["1H","1V","2H","2V"],**kwargs): For both gratings """ for grt in ["HEG","MEG"]: # One full loop for a given grating and 3 energies takes 5h for average 20 - switch_gratings(grt) + grating(grt) for hv in hv_list: - slits_set_BL(hv) + apertures_set(hv) step=hv/100.0 start=hv-step stop=hv+step @@ -681,7 +621,7 @@ def CheckSlitCalibration(slit_list,BL=500,hvList=[485,510],scanIOC=None,**kwargs if scanIOC is None: scanIOC=BL_ioc() exit_slit(50) - slits_set_BL(BL) + apertures_set(BL) for hv in hvList: mono_energy_set(hv) for slit in slit_list: @@ -715,7 +655,7 @@ def check_ID_beam_steering(slit): #here size,start,stop,step = 0.25*c,-4*c,4*c,0.2*c scan_slit_center(slit,start,stop,step,size=size) - slits_set_BL() + apertures_set() ############################################################################################################## @@ -752,109 +692,15 @@ def QP_curves(ID_energy,ID_mode_list,hv_start,hv_stop,hv_step): for ID_mode in ID_mode_list: polarization(ID_mode) ID_SP_set(ID_energy) - slits_set_BL()() + apertures_set()() mono_energy_set(250) mono_scan_fillin(hv_start,hv_stop,hv_step) - BL.mda.go() + iex.BL.mda.go() #Switch_IDQP("off") #Switch_Grating("HEG") #Switch_IDMode("RCP") -############################################################################################################## -################################ ID calibration scripts ############################## -############################################################################################################## - -###### Energy range follows ID ######## - -def ID_calibration_scan(ID_start,ID_stop,ID_step,bandwidth=10,QP=None,Harm=1,scanIOC=None): - """ - Sets the ID_SP and scans the mono: - start,stop,step are for ID - if QP is not None adjusts the mono range to offset accordingly - !!! DOES NOT CHANGE QP VALUE !!!! - !!! Doesn't put diodes in !!! - """ - - print(""" - !!! DOES NOT CHANGE QP VALUE !!!! - !!! Doesn't put diodes in !!!""") - - logfile_name_set(BL.endstation,filename_suffix='IDCalibration') - - #Getting mono max range based on grating - grt_density = mono_grating_density_get() - c=grt_density/1200 # c = 1 for MEG, 2 for HEG - if c == 1: - maxhv = 3000 - elif c == 2: - maxhv = 2000 - - log_print(comment="====== Starting Mono Scan vs ID ======") - - for ID_energy in range_up(ID_start,ID_stop,ID_step): - print("\n------------------ ID-SP @ "+str(ID_energy)+" ------------------") - mono_energy_set(ID_energy) - ID_SP_set(ID_energy) - slits_set_BL() - branch = m3r_branch() - if branch == 'd': - m3r_align() - if QP is None: - start_hv=min(ID_energy-ID_energy/(bandwidth*1.0)*Harm,maxhv) # FR update range 11/20/2019 - stop_hv=min(ID_energy+ID_energy/(bandwidth*2.0)*Harm,maxhv) - step_hv=round(ID_energy/300.0,1) -# start_hv=min(ID_energy-ID_energy/(bandwidth*2.0)*Harm,maxhv) # shift the window by doing -BW*2/+BW*1 instead of -BW*1'/'+BW*2 -# stop_hv=min(ID_energy+ID_energy/(bandwidth*1.0)*Harm,maxhv) -# step_hv=round(ID_energy/500.0,1) - else: - start_hv=min(ID_energy-ID_energy/(bandwidth*2.5)*Harm,maxhv) - stop_hv=min(ID_energy+ID_energy/(bandwidth*0.7)*Harm,maxhv) - step_hv=round(ID_energy/300.0,1) - - mono_scan_fillin(start_hv,stop_hv,step_hv) - BL.mda.go() - sleep(1) - - FileNum = BL.mda.lastFileNum - if ID_energy == ID_start: - FirstFileNum = FileNum # Record First Scan Number - - LastFileNum = FileNum # Record Last Scan Number - - print("Use: update_id_dict("+str(FirstFileNum)+","+str(LastFileNum)+"ignore=[] ,update_file,path=None,prefix='ARPES',q=True)") - - - - -def ID_calibration_mode(ID_mode,start=None,stop=None,step=25,Harm=1): - ''' - Runs full calibration with a 25 eV step (by default) for a given mode: - which = 'RCP','LCP', 'V','H' - Better to run each mode in a separated cell (print statement at the end helps with calibration) - ''' - branch = m3r_branch() - diagnostics_all_out(diode_stay_in=True) - - polarization(ID_mode) - - grt = mono_grating_get() - - QP_ratio = ID_QP_ratio_get() - - hv_min,hv_max = energy_range_min_max() - if start == None: - start = hv_min - if stop == None: - stop=hv_max-50 - - if QP_ratio <100: - stop=min(stop,1500) - QP_ratio=1 - else: - QP_ratio=None - - ID_calibration_scan(start,stop,step,QP=QP_ratio,Harm=Harm) ############################################################################################################## @@ -869,11 +715,7 @@ def scan_cam_motor(motor_name,start,stop,step,cam_num,ExposureTime): """ cam_scan_setup(cam_num,ADtype='TIFF') - if BL.branch == 'ARPES': - ARPES_Motors.scan(motor_name,start,stop,step) - if BL.branch == 'Kappa': - Kappa_Motors.scan(motor_name,start,stop,step) - + iex.BL.motors.scan(motor_name,start,stop,step) cam_live() @@ -886,7 +728,7 @@ def scan_cam_hv(start,stop,step,cam_num,**kwargs): Previously: BeamMotion_Vs_BL_Go """ cam_scan_setup(cam_num,ADtype='TIFF') - scanhv(start,stop,step,**kwargs) + scanmono(start,stop,step,**kwargs) cam_live() diff --git a/iexcode/macros/quick_plot.py b/iexcode/macros/quick_plot.py index 8a169e2..c49d213 100755 --- a/iexcode/macros/quick_plot.py +++ b/iexcode/macros/quick_plot.py @@ -1671,748 +1671,6 @@ def Find_kth_zero(th_0,th_180): # return center -############################################################################################### -######################################### Start Of The Week ################################### -############################################################################################### - -def plot_StartOfTheWeek_DetDict(branch): - """ - returns the detectors for a given branch - - """ - DetDict={'c':(9,7,8,15),'d':(9,7,8,14)} - return DetDict[branch] - -def StartOfTheWeek_plot(branch,FirstScanNum,**kwargs): - """ - Plots the data from StartOfTheWeek - - branch is used to set the detectors - detCA4,detH,detV,detDiode=plot_StartOfTheWeek_Det(branch) - - FirstScanNum is based on slit1A - slit1A-H = FirstScanNum - slit1A-V = FirstScanNum + 1 - wire1-H = FirstScanNum + 2 - wire1-V = FirstScanNum + 3 - monoVslit = FirstScanNum + 4/5/6/7 - flux = FirstScanNum + 8 - - Slit 1A and Wire scans: determine ID steering and Slit1A position - Scan_MonoVsSlit: determine the steering from M0/M1 - by default the full range is plotted (pnt_first=0, pnt_last=inf) - refine the plot via - plot_StartOfTheWeek_mono(branch,FirstScanNum,pnt_first,pnt_last) - - kwargs: - filepath = None, uses current mda filepath unless specified - e.g. user : filepath='/net/s29data/export/data_29idc/2018_2/UserName/mda/' - e.g. staff: filepath='/net/s29data/export/data_29idb/2018_2/mda/' - prefix = None, uses current mda prefix unless specified - scanIOC = None, uses BL_ioc() unless specified - - scanType = ['slit1','wire','flux','monoVslit'], full set by default - - ref_firstScanNum to plot reference spectra - ref_branch = branch, unless specified - ref_filepath = filepath, unless specified - ref_prefix = prefix, unless specified - - steering out => moves beam more positive (20 urad ~ 0.5 mm) - steering up => moves beam more positive (20 urad ~ 0.5 mm) - -figure, axes = plt.subplots(nrows=2, ncols=2) -axes[0, 0].plot(x, y) - """ - - kwargs.setdefault('filepath',BL.mda.filepath()) - kwargs.setdefault('prefix',BL.mda.prefix()) - - kwargs.setdefault('scanType',['slit1','wire','flux','monoVslit']) - - kwargs.setdefault('ref_firstScanNum',None) - kwargs.setdefault('ref_fpath',None) - kwargs.setdefault('ref_branch',branch) - kwargs.setdefault('ref_filepath',BL.mda.filepath()) - kwargs.setdefault('ref_prefix',BL.mda.prefix()) - - kwargs.setdefault('debug',False) - - - scanNum=FirstScanNum - ref_firstScanNum=kwargs['ref_firstScanNum'] - detCA4,detH,detV,detDiode=plot_StartOfTheWeek_DetDict(branch) - - - if 'slit1' in kwargs['scanType']: - if kwargs['debug']: - print('slit1') - plot_StartOfTheWeek_slit1A(branch,scanNum,**kwargs) - scanNum+=2 - if kwargs['ref_firstScanNum'] is not None: - kwargs.update({'ref_firstScanNum':ref_firstScanNum+2}) - - - if 'wire' in kwargs['scanType']: - if kwargs['debug']: - print('wire') - plot_StartOfTheWeek_wire(branch,scanNum,**kwargs) - scanNum+=2 - if kwargs['ref_firstScanNum'] is not None: - ref_firstScanNum+=2 - kwargs.update({'ref_firstScanNum':ref_firstScanNum+2}) - - if 'monoVslit' in kwargs['scanType']: - d=IEXdata(scanNum,path=kwargs['filepath'],prefix=kwargs['prefix'],q=1) - if d.mda[scanNum].header.all['rank']<2: #quick - print(scanNum, detDiode) - V2=fit_mda(scanNum,detDiode,1,'gauss',filepath=kwargs['filepath'],prefix=kwargs['prefix'],scanIOC=kwargs['scanIOC'],title='2V - mda_'+str(scanNum)) - H2=fit_mda(scanNum+1,detDiode,1,'gauss',filepath=kwargs['filepath'],prefix=kwargs['prefix'],scanIOC=kwargs['scanIOC'],title='2H - mda_'+str(scanNum+1)) - V1=fit_mda(scanNum+2,detDiode,1,'gauss',filepath=kwargs['filepath'],prefix=kwargs['prefix'],scanIOC=kwargs['scanIOC'],title='1V - mda_'+str(scanNum+2)) - H1=fit_mda(scanNum+3,detDiode,1,'gauss',filepath=kwargs['filepath'],prefix=kwargs['prefix'],scanIOC=kwargs['scanIOC'],title='1H - mda_'+str(scanNum+3)) - plt.show() - print('\nFit positions:') - print(f"V2={round(V2,3)}") - print(f"H2={round(H2,3)}") - print(f"V1={round(V1,3)}") - print(f"H1={round(H1,3)}") - - else: #MonoVsSlit - print('\n# To plot the Mono vs Slit data use:\n') - print('\tplot_MonoVsSlit(\"'+branch+'\",'+str(scanNum)+','+str(detDiode)+',0,inf)'+'\t#2V') - print('\tplot_MonoVsSlit(\"'+branch+'\",'+str(scanNum+1)+','+str(detDiode)+',0,inf)'+'\t#2H') - print('\tplot_MonoVsSlit(\"'+branch+'\",'+str(scanNum+2)+','+str(detDiode)+',0,inf)'+'\t#1V') - print('\tplot_MonoVsSlit(\"'+branch+'\",'+str(scanNum+3)+','+str(detDiode)+',0,inf)'+'\t#1H') - print('\n# (pnt_first,pnt_last0=(0,inf) => plots all') - print('# select specific first/last to refine.') - - print('\nREMEMBER to update slit center using: \tupdate_slit_dict()' ) - scanNum+=4 - if kwargs['ref_firstScanNum'] is not None: - kwargs.update({'ref_firstScanNum':ref_firstScanNum+4}) - - if 'flux' in kwargs['scanType']: - if kwargs['debug']: - print('flux') - plot_StartOfTheWeek_flux(branch,scanNum,**kwargs) - -def plot_StartOfTheWeek_slit1A(branch,scanNum,**kwargs): - """ - plots the slit1A scans - scanNum = slit1A-H scanNum - """ - kwargs.setdefault('filepath',BL.mda.filepath()) - kwargs.setdefault('prefix',BL.mda.prefix()) - kwargs.setdefault('plotType',['slit1','wire','flux','monoVslit']) - kwargs.setdefault('ref_firstScanNum',None) - kwargs.setdefault('ref_fpath',None) - kwargs.setdefault('ref_branch',branch) - kwargs.setdefault('ref_filepath',BL.mda.filepath()) - kwargs.setdefault('ref_prefix',BL.mda.prefix()) - kwargs.setdefault('debug',False) - - detCA4,detH,detV,detDiode=plot_StartOfTheWeek_DetDict(branch) - ref_detCA4,ref_detH,ref_detV,ref_detDiode=plot_StartOfTheWeek_DetDict(kwargs['ref_branch']) - - figure, axes = plt.subplots(nrows=1, ncols=2,figsize=(10,3)) - for i,t in enumerate(['1H center scan','1V center scan']): - d=IEXdata(scanNum,path=kwargs['filepath'],prefix=kwargs['prefix'],q=1) - axes[i].plot(d.mda[scanNum].det[detCA4].scale['x'], d.mda[scanNum].det[detCA4].data,marker='x',label=str(scanNum)) - scanNum+=1 - if kwargs['ref_firstScanNum'] is not None: - ref_scanNum=kwargs['ref_firstScanNum']+i - ref_d=IEXdata(ref_scanNum,path=kwargs['ref_filepath'],prefix=kwargs['ref_prefix'],q=1) - axes[i].plot(ref_d.mda[ref_scanNum].det[ref_detCA4].scale['x'], ref_d.mda[ref_scanNum].det[ref_detCA4].data,marker='x',label=str(ref_scanNum)) - axes[i].grid(color='lightgray', linestyle='-', linewidth=0.5) - axes[i].title.set_text(t) - axes[i].legend() - plt.show() - print("\nsteering out => move beam more positive (10 urad ~ 0.25 mm)") - print("steering up => move beam more positive (10 urad ~ 0.25 mm)") - print("\nTo fit beam position use:\n") - print("detCA4,detH,detV,detDiode=plot_StartOfTheWeek_DetDict('"+kwargs['ref_branch']+"')") - print("fit_mda("+str(scanNum-2)+",detCA4,1,'gauss',xrange=(-1,1))") - print("fit_mda("+str(scanNum-1)+",detCA4,1,'gauss',xrange=(-1,1))\n") - - -def plot_StartOfTheWeek_wire(branch,scanNum,**kwargs): - """ - plots the wire scans - scanNum = wire-H scanNum - """ - kwargs.setdefault('filepath',BL.mda.filepath()) - kwargs.setdefault('prefix',BL.mda.prefix()) - kwargs.setdefault('plotType',['slit1','wire','flux','monoVslit']) - kwargs.setdefault('ref_firstScanNum',None) - kwargs.setdefault('ref_fpath',None) - kwargs.setdefault('ref_branch',branch) - kwargs.setdefault('ref_filepath',BL.mda.filepath()) - kwargs.setdefault('ref_prefix',BL.mda.prefix()) - kwargs.setdefault('debug',False) - - detCA4,detH,detV,detDiode=plot_StartOfTheWeek_DetDict(branch) - ref_detCA4,ref_detH,ref_detV,ref_detDiode=plot_StartOfTheWeek_DetDict(kwargs['ref_branch']) - - figure, axes = plt.subplots(nrows=1, ncols=2,figsize=(10,3)) - for i,t in enumerate(['H-wire','V-wire']): - d=IEXdata(scanNum,path=kwargs['filepath'],prefix=kwargs['prefix'],q=1) - #niceplot(d.mda[scanNum].det[DetDict[branch][1+i]],marker='x',label=str(scanNum)) - detNum=plot_StartOfTheWeek_DetDict(branch)[1+i] - axes[i].plot(d.mda[scanNum].det[detNum].scale['x'], d.mda[scanNum].det[detNum].data,marker='x',label=str(scanNum)) - scanNum+=1 - if kwargs['ref_firstScanNum'] is not None: - ref_scanNum=kwargs['ref_firstScanNum']+i - ref_d=IEXdata(ref_scanNum,path=kwargs['ref_filepath'],prefix=kwargs['ref_prefix'],q=1) - #niceplot(ref_d.mda[ref_scanNum].det[DetDict[kwargs["ref_branch"]][1+i]],marker='x',label=str(ref_scanNum)) - detNum=plot_StartOfTheWeek_DetDict(kwargs["ref_branch"])[1+i] - axes[i].plot(ref_d.mda[ref_scanNum].det[detNum].scale['x'], ref_d.mda[ref_scanNum].det[detNum].data,marker='x',label=str(ref_scanNum)) - axes[i].grid(color='lightgray', linestyle='-', linewidth=0.5) - axes[i].title.set_text(t) - axes[i].legend() - plt.show() - -def plot_StartOfTheWeek_flux(branch,scanNum,**kwargs): - """ - plots the wire scans - scanNum = wire-H scanNum - """ - kwargs.setdefault('filepath',BL.mda.filepath()) - kwargs.setdefault('prefix',BL.mda.prefix()) - kwargs.setdefault('plotType',['slit1','wire','flux','monoVslit']) - kwargs.setdefault('ref_firstScanNum',None) - kwargs.setdefault('ref_fpath',None) - kwargs.setdefault('ref_branch',branch) - kwargs.setdefault('ref_filepath',BL.mda.filepath()) - kwargs.setdefault('ref_prefix',BL.mda.prefix()) - kwargs.setdefault('debug',False) - - detCA4,detH,detV,detDiode=plot_StartOfTheWeek_DetDict(branch) - ref_detCA4,ref_detH,ref_detV,ref_detDiode=plot_StartOfTheWeek_DetDict(kwargs['ref_branch']) - - for t in ['ID peak @ 500eV']: - d=IEXdata(scanNum,path=kwargs['filepath'],prefix=kwargs['prefix'],q=1) - niceplot(d.mda[scanNum].det[detDiode],marker='x',label=str(scanNum)) - scanNum+=1 - if kwargs['ref_firstScanNum'] is not None: - ref_scanNum=kwargs['ref_firstScanNum']+2 - ref_d=IEXdata(ref_scanNum,path=kwargs['ref_filepath'],prefix=kwargs['ref_prefix'],q=1) - niceplot(ref_d.mda[ref_scanNum].det[ref_detDiode],marker='x',label=str(ref_scanNum)) - ref_scanNum+=1 - plt.grid(color='lightgray', linestyle='-', linewidth=0.5) - plt.title(t) - plt.legend() - plt.show() - -def plot_MonoVsSlit(branch,ScanNum,detDiode,pnt_first,pnt_last,norm=True,filepath=None,prefix=None,scanIOC=None): - """ - Plots Scan_MonoVsSlit to determine the steering from M0/M1 - To plot the full range (pnt_first=0, pnt_last=inf) - plot_StartofWeek_mono(branch,FirstScanNum+4,pnt_first,pnt_last) - - filepath: by default plot scans for the current data folder (as defined in BL_ioc() ScanRecord SaveData) - or specified folder path ending with '/': - e.g. user : filepath='/net/s29data/export/data_29idc/2018_2/UserName/mda/' - e.g. staff: filepath='/net/s29data/export/data_29idb/2018_2/mda/' - prefix: by default, uses prefix as defined in ScanRecord ("mda_") - """ - x,y,z,x_name,y_name,z_name=mda_2D(ScanNum,detDiode,filepath,prefix,scanIOC) - Which=str(y_name)[10:12] - if pnt_last is inf: - pnt_last=len(z)-1 - for i in range(pnt_first,pnt_last+1): - maxvalue=max(z[i]) - if norm == True: - plt.plot(x,z[i]/maxvalue,label='#'+str(i)+': '+str(round(y[i],2))) - else: - plt.plot(x,z[i],label='#'+str(i)+': '+str(round(y[i],2))) - plt.legend(bbox_to_anchor=(1, 0), loc='lower left', ncol=2,shadow=True, title="ScanNum: "+str(ScanNum)+"\nSlit-"+Which+" position", fancybox=True) - #plt.legend(loc='lower left',ncol=2, shadow=True, title="ScanNum: "+str(ScanNum)+"\nSlit-"+Which+" position", fancybox=True) - plt.grid(color='lightgray', linestyle='-', linewidth=0.5) - plt.show() - - -############################################################################################### -######################################### IDCalibration New ################################### -############################################################################################### - - - -def id_calibration_fit(first_scan,last_scan,det,PolyRank,**kwargs): - - - #id_calibration_fit(FirstLast[0],FirstLast[1],det,poly_order,mytitle=mytitle,countby=countby,plotMin=plt_min,plotMax=plt_max,plotType=plotType,filepath=filepath,prefix=prefix) - """ - Fits calibration curves fpr each GRTs and modes included in the data set. Creates 3 dictionnaries: - - coefs={[GRT][mode][[breakpoint1,[coefs]],[breakpoint2,[coefs]...} - xdata= {[GRT][mode][[breakpoint1,[flux curve x axis]],[breakpoint2,[flux curve x axis]...} - fdata= {[GRT][mode][[breakpoint1,[flux curve y axis]],[breakpoint2,[flux curve y axis]...} - - kwargs: - countby = 1 by default - mytitle = '' by default - plotMin = min x range for plotting (default 250) - plotMax = max x range for plotting (default 3000) - plotType = ['dif,'fit,'flux'], full set by default - filepath = None, uses current mda filepath unless specified - e.g. user : filepath='/net/s29data/export/data_29idc/2018_2/UserName/mda/' - e.g. staff: filepath='/net/s29data/export/data_29idb/2018_2/mda/' - prefix = None, uses current mda prefix unless specified - scanIOC = None, uses BL_ioc() unless specified - """ - - kwargs.setdefault('countby',1) - kwargs.setdefault('mytitle','') - #kwargs.setdefault('plotMin',2000) - kwargs.setdefault('plotMin',225) - kwargs.setdefault('plotMax',3000) - kwargs.setdefault('plotType',['fit','dif','flux']) - kwargs.setdefault('filepath',BL.mda.filepath()) - kwargs.setdefault('prefix',BL.mda.prefix()) - - countby=kwargs['countby'] - mytitle=kwargs['mytitle'] - plotMin=kwargs['plotMin'] - plotMax=kwargs['plotMax'] - filepath=kwargs['filepath'] - prefix=kwargs['prefix'] - - - def calibration_curve(first,last,det,countby,filepath,prefix): - mono_list=[] - ID_list=[] - max_list=[] - flux_list=[] - print("filepath = ",filepath) - print("prefix = ",prefix) - print("First scan = ",first) - print("Last scan = ",last) - for i in range(first,last,countby): - x,y,x_name,y_name=mda_1D(i,det,1,0,filepath,prefix) #mda_1D(ScanNum,DetectorNum,coeff=1,bckg=0,filepath=None,prefix=None,scanIOC=None): - v,w,v_name,w_name=mda_1D(i, 4 ,1,0,filepath,prefix) - if y != []: - n=y.index(max(y)) # finds the peak max intensity index - e=round(x[n],2) # finds the corresponding mono energy - sp=round(w[2]*1000,0) # reads the ID set point - mono_list.append(e) - max_list.append(max(y)) - ID_list.append(sp) - flux_list.append(current2flux(max(y),e,p=None)) - return mono_list,ID_list,max_list,flux_list - - Mono_max,ID_SP,int_max,flux=calibration_curve(first_scan,last_scan+1,det,countby,filepath,prefix) - nPt_gaus=200 - x_HR = np.linspace(Mono_max[0], Mono_max[-1], nPt_gaus) - - # Data - xdata = np.array(Mono_max) - ydata = np.array(ID_SP) - zdata = np.array(int_max) - fdata = np.array(flux) - # Fitting - coefs = poly.polyfit(xdata, ydata, PolyRank) - ffit_HR = poly.polyval(x_HR, coefs) - ffit_Coarse = poly.polyval(xdata, coefs) - # Residual - Dif=np.array(ID_SP)-np.array(ffit_Coarse) - ratio=(np.array(ID_SP)-np.array(ffit_Coarse))/(np.array(ID_SP)/100) - # Plot differences - #print('plotMin = ',str(plotMin)) - if 'dif' in kwargs['plotType']: - fig = plt.figure(figsize=(12,6)) - plt.plot(Mono_max,ID_SP,marker='x',markersize=5,color='g',linewidth=0,label='data') - plt.plot(x_HR,ffit_HR,color='b',label='SP-fit') - plt.plot(xdata,Dif*100,marker='x',color='r',label='Dif x100') - plt.plot(xdata,ratio*1000,marker='x',color='g',label='Difx1000/ID') - plt.ylabel('ID SP') - plt.xlabel('Mono') - plt.xlim(plotMin,plotMax) - plt.legend(ncol=2, shadow=True, title=mytitle, fancybox=True) - plt.grid(linestyle='-', linewidth='0.5', color='grey') - plt.show() - # Plot raw data + fit - if 'fit' in kwargs['plotType']: - fig = plt.figure(figsize=(12,6)) - a1 = fig.add_axes([0,0,1,1]) - a1.plot(xdata+Dif,zdata,marker='*',markersize=10,color='r',linewidth=0,label='Interpolated ID SP') - for i in range(first_scan,last_scan+1): - x,y,x_name,y_name=mda_1D(i,det,1,0,filepath,prefix) - a1.plot(x,y,color='b') - a1.set_xlim(plotMin,plotMax) - a1.set(xlabel='Mono') - a1.set(ylabel='ID SP') - a1.ticklabel_format(style='sci', axis='y', scilimits=(0,0)) - a1.grid(linestyle='-', linewidth='0.5', color='grey') - plt.legend(ncol=2, shadow=True, title=mytitle, fancybox=True) - plt.show() - # Plot flux curves: - fdata_x=xdata+Dif - if 'flux' in kwargs['plotType']: - fig = plt.figure(figsize=(12,6)) - a1 = fig.add_axes([0,0,1,1]) - a1.plot(fdata_x,fdata,color='r',linewidth=1,label='Flux curves') - a1.set_xlim(plotMin,plotMax) - a1.set(xlabel='Mono') - a1.set(ylabel='ID SP') - a1.set_yscale('log') - #a1.ticklabel_format(style='sci', axis='y', scilimits=(0,0)) - a1.grid(linestyle='-', linewidth='0.5', color='grey') - plt.legend(ncol=2, shadow=True, title=mytitle, fancybox=True) - plt.show() - return coefs, fdata_x,fdata - - - - - - -def read_id_files(first,last,filepath=None,prefix=None,q=True): - """ - Reads extra PVs - Return a list of [[ScanNum,ID_SP,grt,mode],...] for mda files between first and last. - """ - if filepath == None: - filepath=BL.mda.filepath() - if prefix == None: - prefix=BL.mda.prefix()[:-1] - elif prefix[-1] == "_": - prefix=prefix[:-1] - mydata=mdaFile(first,last,filepath=filepath,prefix=prefix,q=q) - value=[] - modeDict={'CW, RCP':'RCP','CCW, LCP':'LCP','H':'H','V':'V'} - grtDict={1200:'MEG',2400:'HEG'} - for mdaNum in mydata.scanList: - if first<=mdaNum<=last: - extraPVs=mydata.header[mdaNum].all - try: - ID=round(extraPVs['ID29:EnergySet.VAL'][2][0]*1000,2) - mode=modeDict[extraPVs['ID29:ActualMode'][2]] # extraPVs return 'CW, RCP' - grt=grtDict[extraPVs['29idmono:GRT_DENSITY'][2][0]] # extraPVs return 1200 - except KeyError: - ID=round(extraPVs[b'ID29:EnergySet.VAL'][2][0]*1000,2) - mode=modeDict[str(extraPVs[b'ID29:ActualMode'][2])[2:-1]] - grt=grtDict[extraPVs[b'29idmono:GRT_DENSITY'][2][0]] # extraPVs return 1200 - if len(value)>0 and value[-1][1:] == [ID,grt,mode]: - pass - else: - value.append([mdaNum,ID,grt,mode]) - return value - - - -def id2num(ID,grt,mode,first=0,last=inf,ignore=[],filepath=None,prefix=None,q=True): # Not efficient - requires to read all 600 files everytime - """ - Return ScanNum corresponding to a given ID_SP from ExtraPVs (using mdaFile) - """ - if filepath == None: - filepath=BL.mda.filepath() - if prefix == None: - prefix=BL.mda.prefix()[:-1] - elif prefix[-1] == "_": - prefix=prefix[:-1] - ScanNum = 0 - data_list = read_id_files(first,last,filepath,prefix,q) - data_short=[x for x in data_list if x[2:]==[grt,mode] and x[0] not in ignore] - step=data_short[1][1]-data_short[0][1] - precision=int(step/2) - ID1=ID-precision - ID2=ID+precision - ScanNum=[x[0] for x in data_short if ID1<= x[1]<= ID2] - if len(ScanNum)==0: result=None - else: result=ScanNum[0] - return result - - - -def num2id(ScanNum,grt,mode,first=0,last=inf,ignore=[],filepath=None,prefix=None,q=True): # Not efficient - requires to read all 600 files everytime - """ - Return ID SP corresponding to a given ScanNum from ExtraPVs (using mdaFile) - """ - if filepath == None: - filepath=BL.mda.filepath() - if prefix == None: - prefix=BL.mda.prefix()[:-1] - elif prefix[-1] == "_": - prefix=prefix[:-1] - ID = 0 - data_short=[] - data_list = read_id_files(first,last,filepath,prefix,q) - data_short=[x for x in data_list if x[2:]==[grt,mode] and x[0] not in ignore] - ID=[x[1] for x in data_short if x[0] == ScanNum] - return ID[0] - - - -def extract_id(first,last,ignore=[],breakpts={'RCP':[600],'H':[400,600],'V':[600],'LCP':[600],'HEG':[],'MEG':[2200,2475]},filepath=None,prefix=None,q=True): - """ - Breaksdown the info from a calibration files into grt & mode with the corresponding breakpoints (hardcoded): - [[first, last, 'HEG', 'RCP', [600]], - [first, last, 'HEG', 'H', [400, 600]]...] - """ - if filepath == None: - filepath=BL.mda.filepath() - if prefix == None: - prefix=BL.mda.prefix()[:-1] - elif prefix[-1] == "_": - prefix=prefix[:-1] - IDlog=read_id_files(first,last,filepath,prefix,q) - #breakpts={'RCP':[600],'H':[400,600],'V':[600],'LCP':[600],'HEG':[],'MEG':[2200]} - #breakpts={'RCP':[600],'H':[400,600],'V':[600],'LCP':[600],'HEG':[],'MEG':[2200]} - #breakpts={'RCP':[600],'H':[600],'V':[600],'LCP':[600],'HEG':[],'MEG':[2200,2475]} # FR changed H breakpoints, missing low energy scans 06/14/2021 - data=[] - for grt in ['HEG','MEG']: - for mode in ['RCP','H','V','LCP']: - tmp=[x for x in IDlog if x[2:]==[grt,mode] and x[0] not in ignore] - #print(tmp) - if len(tmp)>0: - tmp=[tmp[0][0],tmp[-1][0],grt,mode,breakpts[mode]+breakpts[grt]] - data.append(tmp) - return data - - - -def update_id_dict(first,last,det,update_file,ignore,**kwargs): - - - - """ - Calculate new calibration curve for a full set of data.' - But what if the set is not complete? To be addressed by Future Me - If update_file == True (ONLY): - \tupdate the ID dictionary '/home/beams22/29IDUSER/Documents/User_Macros/Macros_29id/IEX_Dictionaries/Dict_IDCal.txt' - """ - - if update_file == True: - foo=input('\nAre you sure you want to update the ID calibration dictionary?\n>') - if foo == 'Y' or foo == 'y' or foo == 'yes'or foo == 'YES' or foo == 'Yes': - foo = 'yes' - print('\nWill save new dictionary to: \'/home/beams22/29IDUSER/Documents/User_Macros/Macros_29id/IEX_Dictionaries/Dict_IDCal.txt\'\n') - else: - print('\nCalibration curves will not be saved.\n') - else: - print('\nCalibration curves will not be saved.\n') - - kwargs.setdefault('countby',1) - kwargs.setdefault('mytitle','') - kwargs.setdefault('plotMin',225) - kwargs.setdefault('plotMax',3000) - kwargs.setdefault('plotType',['fit','dif','flux']) - kwargs.setdefault('filepath',BL.mda.filepath()) - kwargs.setdefault('prefix',BL.mda.prefix()) - kwargs.setdefault('q',True) - kwargs.setdefault('breakpts',{'RCP':[600],'H':[400,600],'V':[600],'LCP':[600],'HEG':[],'MEG':[2200,2475]}) - - - breakpts=kwargs['breakpts'] - plotType=kwargs['plotType'] - filepath=kwargs['filepath'] - prefix=kwargs['prefix'] - q=kwargs['q'] - - ID_data=extract_id(first,last,ignore,breakpts,filepath,prefix,q) - - ##### Extract parameters: - - mode_dict ={'RCP':0,'LCP':1,'V':2,'H':3} - id_coef={} - new_id_function={} - id_flux={} - flux_dict={} - id_energy={} - energy_dict={} - for mylist in ID_data: - if len(mylist) > 0: # in case of incomplete data set - tmp0,tmp1,tmp2=[],[],[] - first_scan=mylist[0] - last_scan=mylist[1] - scan_list=[[first_scan,last_scan]] - countby=1 - #det=15 - #det=33 - poly_order=4 - grt=mylist[2] - mode=mylist[3] - breakpts_energy=mylist[4] - breakpts_scan=[] - mytitle=mode+' - '+grt - - ## generating list of scans depending on breakpoints: - if breakpts_energy != []: - scan_list=[] - for x in breakpts_energy: - breakpts_scan.append(id2num(x,grt,mode,first,last,ignore,filepath,prefix,q)) - breakpts_scan = [i for i in breakpts_scan if i] - print(breakpts_scan) - for c,x in enumerate(breakpts_scan): # can get the number by extracting step size then /2 - if c == 0: - if x == first_scan: pass - else: scan_list.append([first_scan,x]) - if 0 < c < len(breakpts_scan)-1: - scan_list.append([breakpts_scan[c-1],x]) - scan_list.append([x,breakpts_scan[c+1]]) - if c == len(breakpts_scan)-1 and (c-1) == 0: - scan_list.append([breakpts_scan[c-1],x]) - if c == len(breakpts_scan)-1: - scan_list.append([x,last_scan]) - final_list = [i for n, i in enumerate(scan_list) if i not in scan_list[:n]] # remove doubles - energy_list=[] - for x in final_list: - ID1=num2id(x[0],grt,mode,first,last,ignore,filepath,prefix,q) - ID2=num2id(x[1],grt,mode,first,last,ignore,filepath,prefix,q) - energy_list.append([ID1,ID2]) - energy_list_2=energy_list # we need the final value for plot purposes (max value) - if grt == 'HEG': - energy_list_2[-1][-1]=2500 # but we don't want it to be a cutoff for ID_Calc in dict - for (FirstLast,ID,cutoff) in zip(final_list,energy_list,energy_list_2): - plt_min=ID[0]-200 - plt_max=ID[1]+100 - if grt=='MEG' and ID[1]>2900: - poly_order=5 - plt_min=ID[0]-200 - print('det =',det) - print('poly_order =',poly_order) - - subkwargs=kwargs # kwargs contains plotType, filepath, prefix and q - newkwargs={'mytitle':mytitle,'countby':countby,"plotMin":plt_min,'plotMax':plt_max} - subkwargs.update(newkwargs) - #print(newkwargs) - #print(FirstLast[0],FirstLast[1]) - #result,energy_data,flux_data=id_calibration_fit(FirstLast[0],FirstLast[1],det,poly_order,subkwargs) - result,energy_data,flux_data=id_calibration_fit(FirstLast[0],FirstLast[1],det,poly_order,mytitle=mytitle,countby=countby,plotMin=plt_min,plotMax=plt_max,plotType=['fit','dif'],filepath=filepath,prefix=prefix) - tmp0.append([cutoff[1],result.tolist()]) - tmp1.append([cutoff[1],energy_data]) - tmp2.append([cutoff[1],flux_data]) - - if 2900<tmp0[-1][0]<3000: tmp0[-1][0]=3000 - id_coef[mode_dict[mode]]=tmp0 # dictionary that - new_id_function[grt]=id_coef # dictionary containing all the calibration curves forthe data set - id_energy[mode_dict[mode]]=tmp1 # dictionary that - energy_dict[grt]=id_energy - id_flux[mode_dict[mode]]=tmp2 # dictionary that - flux_dict[grt]=id_flux - - ##### Read & update old dictionary: - - try: - id_function=read_dict('Dict_IDCal.txt') - print(id_function) - id_function.update(new_id_function) - - except KeyError: - print("Unable to read previous dictionary") - - - if update_file == True and foo == 'yes': - filepath = "/home/beams22/29IDUSER/Documents/User_Macros/Macros_29id/IEX_Dictionaries/" - filename = 'Dict_IDCal.txt' - - with open(join(filepath, filename), "a+") as f: - f.write('\n======= '+today()+': \n') - f.write(str(id_function)) - f.write('\n') - print('\nWriting dictionary to:',join(filepath, filename)) - - if update_file == True and foo == 'yes': - filepath = "/home/beams22/29IDUSER/Documents/User_Macros/Macros_29id/IEX_Dictionaries/" - filename = 'Flux_Curves.txt' - - with open(join(filepath, filename), "a+") as f: - f.write('\n======= '+today()+': \n') - f.write('\n----- flux_x:\n') - f.write(str(energy_dict)) - f.write('\n----- flux_y:\n') - f.write(str(flux_dict)) - f.write('\n') - print('\nWriting flux curves to:',join(filepath, filename)) - - return id_function,energy_dict,flux_dict - - -def update_slit_dict(**kwargs): - """ - Interactive function to update the slit position dictionary (Dict_Slit.txt) - - **kwargs - readOnly == False, if true just pring the current slit dictionary - """ - filepath = "/home/beams22/29IDUSER/Documents/User_Macros/Macros_29id/IEX_Dictionaries/" - filename ='Dict_Slit.txt' - - kwargs.setdefault("readOnly",False) - - print('\n\nWARNING: 2V slit should always be centered at zero ie steer M1 center beam on the grating') - print('Increasing the roll moves the beam more positive: +0.05 pitch => ~ +0.04 slit position; Use:\n') - print("Get_Mirror(1);Move_M1('RZ',x)") - print("energy(500);mono(505);slit(200)") - print("Scan_NarrowSlit_Go(which='2V',slit_parameters=[0.25, -2, 2, 0.25]) #for MEG; slit_parameters=[0.5, -2, 2, 0.25] for HEG") - print("Scan_NarrowSlit_Go(which='2V',slit_parameters=[0.50, -2, 2, 0.25]) #for HEG") - print('Once steering is completed, check 2H position:') - print("Scan_NarrowSlit_Go(which='2H',slit_parameters=[0.25, -6, 6, 0.25]) ") - - try: - slit_position=read_dict(filename) - print('\nCurrent dictionary:\n') - print(slit_position) - - except KeyError: - print("Unable to read previous dictionary") - return - - if kwargs['readOnly']== True: - return slit_position - - else: - grt=input('\nWhich grating do you want to update (HEG or MEG) >') - s2v=input('New Slit 2B-V center >') - s2h=input('New Slit 2B-H center >') - s1v=input('New Slit 1A-V center >') - s1h=input('New Slit 1A-H center >') - - if grt == '' or s1h == '' or s1v == '' or s2h == '' or s2v == '': - print('\nMissing input. No changes made in file.') - return - - if grt[0] == '"' or grt[0]=="'": grt = grt[1:4] - - # new_slit_position={grt.upper():{'S1H':float(s1h),'S1V':float(s1v),'S2H':float(s2h),'S2V':float(s2v)}} # change order to match scan/fit order - new_slit_position={grt.upper():{'S2V':float(s2v),'S2H':float(s2h),'S1V':float(s1v),'S1H':float(s1h)}} - slit_position.update(new_slit_position) - - - with open(join(filepath, filename), "a+") as f: - f.write('\n======= '+today()+': \n') - f.write(str(slit_position)) - f.write('\n') - print('\nWriting dictionary to:',join(filepath, filename)) - - apertures_set() - return slit_position - - - - - - -def read_flux(FileName='Flux_Curves.txt',FilePath="/home/beams22/29IDUSER/Documents/User_Macros/Macros_29id/IEX_Dictionaries/"): - print('test') - with open(join(FilePath, FileName)) as f: - for c,line in enumerate(f.readlines()): - if line[0] == '=': - lastdate=line[8:16] - print(lastdate) - if line[0] == '-' and line[-2] == 'x': - axis='x' - print(axis) - line_x=line - if line[0] == '-' and line[-2] == 'y': - axis='y' - print(axis) - line_y=line - mydict_x=ast.literal_eval(line_x) - mydict_y=ast.literal_eval(line_y) - return mydict_x,mydict_y - - diff --git a/iexcode/macros/start_of_the_week.py b/iexcode/macros/start_of_the_week.py index be2a73b..ec9555c 100644 --- a/iexcode/macros/start_of_the_week.py +++ b/iexcode/macros/start_of_the_week.py @@ -1,29 +1,28 @@ +import datetime import matplotlib.pyplot as plt -from ..instruments.diagnostics import diode_c -from ..instruments.files_and_folders import check_run -from ..instruments.utilities import wait_for_it -from ..instruments.current_amplifiers import Keithley -from ..instruments.IEX_VPU import * -from ..instruments.VLS_PGM import * -from ..instruments.xrays import * -from ..instruments.shutters import * -from ..instruments.slits import * +import iexcode.instruments.cfg as iex +from iexcode.instruments.staff import staff_init -from ..instruments.kappa import * -from ..instruments.ARPES import * +from iexcode.instruments.diagnostics import _diagnostics_dict, diagnostics_all_out, diagnostics_all_in,diode_c,diode_d +from iexcode.instruments.current_amplifiers import * +from iexcode.instruments.xrays import * +from iexcode.instruments.VLS_PGM import * +from iexcode.instruments.Logfile import log_name_set,log_print +from iexcode.instruments.shutters import branch_shutter_open, branch_shutter_status +from iexcode.instruments.utilities import * +from iexcode.macros.commissioning import * +from iexcode.macros.quick_plot import * -from .commissioning import * -from .quick_plot import * - -def start_of_the_week(grt,branch,wait=False,**kwargs): +def StartOfTheWeek(GRT,branch,wait=False,**kwargs): """ This should be run every at the start of every week; 50 min total. Switch to C-branch,. If wait=True, wait for next day a 8:05. kwargs defaults: - run = None: used today's date to set run appropriatetly + mode = polarization + run = None: used today's date to set run appropriately repeat = False: sets everything: switches branch, sets BL_Mode to Staff, resets scan/CAs/mono scanType = ['slit1','wire','flux','monoVslit'] sound = False; no sounds @@ -36,61 +35,61 @@ def start_of_the_week(grt,branch,wait=False,**kwargs): M1 steering: (monoVslit-2V and 2H) Roll: Rz more positive => 2V more positive (0.25 => .25 mm) Pitch: Ry more positive => 2H more positive (0.03 => .5 mm - - Previously: StartOfTheWeek """ + kwargs.setdefault('mode','RCP') kwargs.setdefault('repeat',False) - kwargs.setdefault('run',check_run()) kwargs.setdefault('quick',True) - kwargs.setdefault('interactive',True) kwargs.setdefault('scanType',['slit1','wire','flux','monoVslit']) kwargs.setdefault('sound',True) kwargs.setdefault('extended_range',False) - + + branch=branch.lower() + if iex.BL == None or kwargs['repeat']==False: + if branch == 'c': + staff_init('ARPES') + switch_branch(branch) + else: + staff_init('kappa') + switch_branch(branch) + FileName='StartOfTheWeek_log.txt' + log_name_set(FileName) + for scan in kwargs['scanType']: if scan not in ['slit1','wire','flux','monoVslit']: print(scan+" is not a valid scan scanType=['slit1','wire','flux','monoVslit']") return - - + ### checking diode settings: if branch == 'c': - diode = Keithley('b',15) - diode.autoscale() + ca15 = Keithley('b',15) + ca15.autoscale('Off') diode_c('In') else: foo=input('Do you have a diode in direct beam (y or n)? >') if foo.lower() == 'y' or foo.lower() == 'yes': print('Resuming...') - - ### checking QP ratio: - QP_ratio = ID_QP_ratio_get() - if QP_ratio != 100: - foo=input('QP on!!! Continue (y or n)? >') - if foo.lower() == 'y' or foo.lower() == 'yes': - print('Resuming...') - ### Stuff that doesn't need beam & does not need to be run if repeating SoTW: print("\n\n================== Sets Beamline & Scans:") - grating(grt) - - if not kwargs['repeat']: - switch_branch(branch) + grating(GRT) - print("\n\n================== Sets Directory:") - - if branch=='c': - ARPES_init(BL_mode='staff') - - fname='StartOfTheWeek_log.txt' - logfile_name_set(BL.endstation,filename=fname) - - ### checking branch shutter: - if branch_shutter_status() == False: - branch_shutter_open() + shutter_open = branch_shutter_status() + if shutter_open == False: + foo=input_d('Shutter '+branch.upper()+' is closed, do you want to open it (y or n)? >') + if foo.lower() == 'y' or foo.lower() == 'yes': + branch_shutter_open() + else: + print('Aborting...') + return + + ### checking QP ratio: + QP=caget('ID29:QuasiRatio.RVAL') + if QP != 100: + foo=input('QP on!!! Continue (y or n)? >') + if foo.lower() == 'y' or foo.lower() == 'yes': + print('Resuming...') ### Wait for next 8AM: if wait: @@ -101,159 +100,281 @@ def start_of_the_week(grt,branch,wait=False,**kwargs): wait_for_it(1,8,5) ### checking ID: - print("\n\n================== Start ID:") - polarization('RCP') - - + polarization(kwargs['mode']) + ### Ready to start: - FirstScan=BL.mda.fileNum+1 - + FirstScan=iex.BL.mda.filenum() if not kwargs['repeat']: - log_print("\n\n================== Start Of The Week @ "+today('slash')+':\n') + log_print("\n\n================== Start Of The Week @ "+today('slash')+':\n',FileName=FileName) - def interactive_fct(comment='scans'): - foo=input('\nRepeat '+comment+' (y or n)? >') - if foo.lower() == 'y' or foo.lower() == 'yes': - print('\nRepeating...\n');flag=True - - else: - print('\nResuming...\n'); flag=False + + def interactive_fct(mirror=False): + options='0,1,2,3' + if not mirror: + print('''\nDo you want to: + \t (0) write comment + \t (1) continue + \t (2) repeat scan + \t (3) adjust xrange for fit + ''') + else: + print('''\nDo you want to: + \t (0) write comment + \t (1) continue + \t (2) repeat scan + \t (3) adjust xrange for fit + \t (4) move M1 roll + ''') + options=options+',4' + flag=input('\nType ('+options+') >') + if flag not in options.split(","): + print('\ninvalid input; please try again...\n') + flag=input('\nType ('+options+') >') + if flag == '0': + cmt=input('\nType comment >') + print('\n================================') + log_print(cmt) + print('================================\n') + flag=input('\nType ('+options+') >') + if flag == '1': print('\nresuming script...\n'); flag=1 + if flag == '2': print('\nrepeating scan...\n'); flag=2 + if flag == '3': flag=3 + if mirror: + if flag == '4': flag=4 + return flag + + + + # if foo.lower() == 'y' or foo.lower() == 'yes': + # print('\nType any comments here - you have 30s! >') + # i, o, e = select.select( [sys.stdin], [], [], 5 ) + # if (i): + # print ('\n==============\n'+sys.stdin.readline().strip()+'\n==============\n') + # else: + # print('\nTimeout...'); + # print('\nRepeating scan...\n');flag=2 + + # else: + # print('\nResuming script...\n'); flag=3 + # return flag + + + + def iex_steering(h_position,v_position): + print('\nBeam position:') + print(' - horizontal: '+str(h_position)) + print(' - vertical: '+str(v_position)) + h_steering,v_steering=beamsteering_1A(h_position,v_position) + print('\nBeam steering:') + print(' - horizontal: '+h_steering) + print(' - vertical: '+v_steering) + print('\n') + return h_steering,v_steering DetDict={'c':(9,7,8,15),'d':(9,7,8,14)} detCA4,detH,detV,detDiode=DetDict[branch] + list_position=[GRT,0,0,0,0] ###### Scan front-end slit center: if 'slit1' in kwargs['scanType']: print("\n\n================== Slit 1A scans:") - ID_SP_set(2000) - flag=True - while flag: - - #Scan_SlitCenter('1H',-3,3,0.1,comment='Slit center - 1H') - #Scan_SlitCenter('1V',-3,3,0.1,comment='Slit center - 1V') - scan_narrow_slit('1H',[0.25,-3,3,0.1],comment='Slit center - 1H') - scan_narrow_slit('1V',[0.25,-3,3,0.1],comment='Slit center - 1V') - #SetSlit1A(4.5,4.5,0,0) - slit1A_set((4.5,4.5),(0,0)) - m=BL.mda.lastFileNum() + mvID(2000) + flag=2 + while flag==2: + slits_scan_center('slit1A','H',-3,3,0.1,size=(0.25,inf),comment='Slit center - 1H') + slits_scan_center('slit1A','V',-3,3,0.1,size=(inf,0.25),comment='Slit center - 1V') + slit1A_set(4.5,4.5,0,0) + m=iex.BL.mda.last_mda() print('\nsteering out => move beam more positive (10 urad ~ 0.25 mm)') - print('steering up => move beam more positive (10 urad ~ 0.25 mm)') + print('steering up => move beam more positive (10 urad ~ 0.25 mm)\n') try: h_position=fit_mda(m-1,detCA4,1,'gauss',xrange=[-1,1]);plt.show() v_position=fit_mda(m ,detCA4,1,'gauss',xrange=[-1,1]);plt.show() - print('\nBeam position:') - print(' - horizontal: '+str(h_position)) - print(' - vertical: '+str(v_position)) - h_steering,v_steering=beamsteering_1A(h_position,v_position) - print('\nBeam steering:') - print(' - horizontal: '+h_steering) - print(' - vertical: '+v_steering) - print('\n') + iex_steering(h_position,v_position) except: - print('Unable to fit position; try to tweak xrange or FWHM:') - print('fit_mda('+str(m)+','+str(detCA4)+',1,"gauss",xrange=[-1,1])') - print('fit_mda('+str(m+1)+','+str(detCA4)+',1,"gauss",xrange=[-1,1])') - print('\n') + print('\nUnable to fit position; try to adjust xrange.\n') + # print('h_position=fit_mda('+str(m-1)+','+str(detCA4)+',1,"gauss",xrange=[-1,1])') + # print('v_position=fit_mda('+str(m)+','+str(detCA4)+',1,"gauss",xrange=[-1,1])') + # print('\nThen use:') + # print('\tbeamsteering_1A(h_position,v_position)') if kwargs['sound']:playsound() - if kwargs['interactive']: flag=interactive_fct() - else: break + flag=interactive_fct() + while flag == 3: + try: + fitH=input('do you want to fit mda #'+str(m-1)+' ie horizontal (y or n)? >') + if fitH.lower() == 'y' or fitH.lower() == 'yes': + x1=input('x1 >') + x2=input('x2 >') + h_position=fit_mda(m-1,detCA4,1,'gauss',xrange=[float(x1),float(x2)]);plt.show() + fitV=input('do you want to fit mda #'+str(m)+' ie vertical (y or n)? >') + if fitV.lower() == 'y' or fitV.lower() == 'yes': + x1=input('x1 >') + x2=input('x2 >') + v_position=fit_mda(m ,detCA4,1,'gauss',xrange=[float(x1),float(x2)]);plt.show() + iex_steering(h_position,v_position) + foo=input('\nare you happy with the fit (y or n)? >') + if foo.lower() == 'y' or foo.lower() == 'yes': + flag=interactive_fct() + except: + print('\nUnable to fit position; try to tweak xrange again\n') + flag=interactive_fct() ###### Wire scans: if 'wire' in kwargs['scanType']: - ID_SP_set(2000) + mvID(2000) slit1A_set(4.5,4.5,0,0) scan_wire('H',comment='Wire scan - H',all_diag=False) # by default puts all meshes in + DiodeC scan_wire('V',comment='Wire scan - V',all_diag=False) - m=BL.mda.lastFileNum() + m=iex.BL.mda.last_mda() try: plot_mda(m-1,detH,m,detV,title='wire-H (blue) & wire-V (orange)');plt.show() except: - print('Unable to plot.') + print('Unable to plot. Try:') + print("plot_mda("+str(m-1)+","+str(detH)+","+str(m)+","+str(detV)+",title='wire-H (blue) & wire-V (orange)');plt.show()") if kwargs['sound']:playsound() - + ###### Mono/slit scans: - list_position=[] - if 'monoVslit' in kwargs['scanType']: - if grt=="HEG": + if 'monoVslit' in kwargs['scanType']: + c=mono_grating_density_get()/1200 + if c==2: slit(300) - c=2 - else: + else: slit(200) - c=1 print("\n\n================== Mono/slit scans:") if 'quick' in kwargs: energy(500) - mono_energy_set(505) + mvmono(505) print('\n---------- Scanning slit 2B:\n') - flag=True - while flag: - scan_narrow_slit('2V',[0.25*c, -8, 8, 0.25]) - sleep(1) - scan_narrow_slit('2H',[0.25, -6, 6, 0.25]) - sleep(1) - m=BL.mda.lastFileNum() + flag=2 + while flag==2: + slits_scan_center('slit2B','V',-8,8,0.25,size=(inf,0.25*c));sleep(1) + slits_scan_center('slit2B','H',-6,6,0.25,size=(0.25,inf));sleep(1) + m=iex.BL.mda.last_mda() try: - V2=fit_mda(m-1,detDiode,1*c,'gauss') - plt.show() - H2=fit_mda(m ,detDiode,1,'gauss') - plt.show() - list_position.append(V2) - list_position.append(H2) + V2=fit_mda(m-1,detDiode,1*c,'gauss');plt.show() + H2=fit_mda(m ,detDiode,1,'gauss');plt.show() + list_position[1]=V2 + list_position[2]=H2 #print(f"V2 = {round(V2,3)}") #print(f"H2 = {round(H2,3)}") print('\nBeam position:') - print(f" - vertical: V1 = {round(V2,3)}") - print(f" - horizontal: H1 = {round(H2,3)}") + print(f" - vertical: V2 = {round(V2,3)}") + print(f" - horizontal: H2 = {round(H2,3)}") v_steering=beamsteering_2B(V2) - print('\nM1 roll (RZ) steering:') - print(' - vertical: ~ '+v_steering) - print(' - horizontal: reset slit 2BH center to ',str(H2)) - print('\n') - - print('\n\nWARNING: 2V slit should always be centered at zero') - print('Increasing M1 roll moves the beam more positive on 2V:') - print('\t+0.05 pitch => ~ +0.04 slit position') - print('To steer M1, use:') - print("\tGet_Mirror(1);Move_M1('RZ',x)") + m1_roll=beamsteering_2B(V2)[1] + print('\nCurrent position:') + current_roll=FMB_mirror_get(1)[5] + new_roll=current_roll+m1_roll + print('\nREMEMBER: 2V slit should always be centered at zero by steering M1 roll!') + print(" - vertical: "+str(current_roll)+str(v_steering[1])+" => Move_M1('RZ',"+str(new_roll)+")") + print(' - horizontal: reset slit 2BH center to ',str(H2)) + except: - print('Unable to fit position.') + print('Unable to fit position; try to adjust xrange.') + # print('c='+str(c)) + # print('V2=fit_mda('+str(m-1)+','+str(detDiode)+',1*c+,"gauss")') + # print('H2=fit_mda('+str(m)+','+str(detDiode)+',1,"gauss")') + # print('\nThen use:') + # print('\tbeamsteering_2B(V2)') + # list_position.append(np.nan) + # list_position.append(np.nan) + flag=interactive_fct(mirror=True) + if kwargs['sound']:playsound() - if kwargs['interactive']: flag=interactive_fct('slit 2B') - else: break + flag=interactive_fct(mirror=True) + while flag == 3: + fitV2=input('do you want to FIT mda #'+str(m-1)+' ie slit2-V (y or n)? >') + if fitV2.lower() == 'y' or fitV2.lower() == 'yes': + x1=input('x1 >') + x2=input('x2 >') + V2=fit_mda(m-1,detDiode,1,'gauss',xrange=[float(x1),float(x2)]);plt.show() + foo=input('do you want to replace slit2-V value in list_position (y or n)? >') + if foo.lower() == 'y' or foo.lower() == 'yes': + list_position[1]=V2 + fitH2=input('do you want to FIT mda #'+str(m)+' ie slit2-H (y or n)? >') + if fitH2.lower() == 'y' or fitH2.lower() == 'yes': + x1=input('x1 >') + x2=input('x2 >') + H2=fit_mda(m ,detDiode,1,'gauss',xrange=[float(x1),float(x2)]);plt.show() + foo=input('do you want to REPLACE slit2-H value in list_position (y or n)? >') + if foo.lower() == 'y' or foo.lower() == 'yes': + list_position[1]=H2 + foo=input('\nare you happy with the fit (y or n)? >') + if foo.lower() == 'y' or foo.lower() == 'yes': + flag=interactive_fct(mirror=True) + if flag == 4: + x=input('New M1 roll value >') + x=float(x) + try: + FMB_mirror_move(1,'RZ',x) + sleep(2); + FMB_mirror_get(1) + print('\nrepeating scan...\n') + flag=2 + except: + print('\ninvalid input; unable to move M1...\n') + flag=interactive_fct(mirror=True) print('\n---------- Scanning slit 1A:\n') - flag=True - while flag: - scan_narrow_slit('1V',[0.25, -4, 4, 0.1]) - sleep(1) - scan_narrow_slit('1H',[0.25, -3, 3, 0.1]) - sleep(1) + flag=2 + while flag==2: + slits_scan_center('slit1A','V',-4, 4, 0.1,size=(inf,0.25)) + slits_scan_center('slit1A','H',-3, 3, 0.1,size=(0.25,inf)) apertures_set() - m=BL.mda.lastFileNum() + m=iex.BL.mda.last_mda() try: V1=fit_mda(m-1,detDiode,1,'gauss');plt.show() H1=fit_mda(m ,detDiode,1,'gauss');plt.show() - list_position.append(V1) - list_position.append(H1) + list_position[3]=V1 + list_position[4]=H1 print('\nBeam position:') print(f" - vertical: V1 = {round(V1,3)}") print(f" - horizontal: H1 = {round(H1,3)}") except: - print('Unable to fit position.') + print('\nUnable to fit position; try to adjust xrange.') + # print('V1=fit_mda('+str(m-1)+','+str(detDiode)+',1,"gauss")') + # print('H1=fit_mda('+str(m)+','+str(detDiode)+',1,"gauss")') + # list_position.append(np.nan) + # list_position.append(np.nan) if kwargs['sound']:playsound() - if kwargs['interactive']: flag=interactive_fct('slit 1A') - else: break - print('\nBeam center fit @ [2V,2H,1V,1H]:',list_position) - print('\nTo update slit center using: update_slit_dict()\n') + flag=interactive_fct() #interactive_fct('slit 1A') + while flag == 3: + fitV1=input('do you want to fit mda #'+str(m-1)+' ie slit1-V (y or n)? >') + if fitV1.lower() == 'y' or fitV1.lower() == 'yes': + x1=input('x1 >') + x2=input('x2 >') + V1=fit_mda(m-1,detDiode,1,'gauss',xrange=[float(x1),float(x2)]);plt.show() + foo=input('do you want to replace slit1-V value in list_position (y or n)? >') + if foo.lower() == 'y' or foo.lower() == 'yes': + list_position[3]=V1 + fitH1=input('do you want to fit mda #'+str(m)+' ie slit1-H (y or n)? >') + if fitH1.lower() == 'y' or fitH1.lower() == 'yes': + x1=input('x1 >') + x2=input('x2 >') + H1=fit_mda(m ,detDiode,1,'gauss',xrange=[float(x1),float(x2)]);plt.show() + foo=input('do you want to replace slit1-H value in list_position (y or n)? >') + if foo.lower() == 'y' or foo.lower() == 'yes': + list_position[4]=H1 + foo=input('\nare you happy with the fit (y or n)? >') + if foo.lower() == 'y' or foo.lower() == 'yes': + flag=interactive_fct() + print('\nBeam center fit @ ['+GRT+',2V,2H,1V,1H]:',list_position) + foo=input('do you want to update the slit dictionary (y or n)? >') + if foo.lower() == 'y' or foo.lower() == 'yes': + slit_list=input('do you want to use '+str(list_position)+' (y or n)? >') + if foo.lower() == 'y' or foo.lower() == 'yes': + update_slit_dict(list_position) + else: + update_slit_dict() else: # longer full slit scans - ID_SP_set(500) - flag=True - while flag: - mono_energy_set(500) + mvID(500) + flag=2 + while flag==2: + mvmono(500) apertures_set() n=2 if 'extended_range' in kwargs else 1 scan_mono_vs_slit('2V',[0.25*c,-2*c*n,2*c*n,0.5],[475,515,2],comment='Mono/Slit - 2V') #10/20 min for MEG/HEG @@ -261,43 +382,457 @@ def start_of_the_week(grt,branch,wait=False,**kwargs): scan_mono_vs_slit('1V',[0.5,-0.75*n,0.75*n,0.25*c],[475,515,2],comment='Mono/Slit - 1V') #10min scan_mono_vs_slit('1H',[0.5,-0.75*n,0.75*n,0.25],[475,515,2],comment='Mono/Slit - 1H') #10min #interactive - if kwargs['interactive']: flag=interactive_fct() - else: break + flag=interactive_fct() ###### Check flux: if 'flux' in kwargs['scanType']: - if m3r_branch == 'c': - diode_c('In') + diode_c('In') print("\n\n================== Check Flux:") - flag=True - while flag: - check_flux(stay=True) - exit_slit(50) + flag=2 + while flag==2: + check_flux(stay='y') + slit(50) energy(500) scanmono(475,525,1,comment='Mono Scan @ 500eV') + m=iex.BL.mda.last_mda() try: - m=BL.mda.lastFileNum() - plot_mda(m,detDiode,flux=3);plt.show() + plot_mda(m,detDiode,Flux=3);plt.show() except: - print('Unable to fit position.') - ### interactive - if kwargs['interactive']: flag=interactive_fct() - else: break + print('Unable to plot. Try:') + print("plot_mda("+str(m)+","+str(detDiode)+",flux=3);plt.show()") + flag=interactive_fct() diagnostics_all_out() print("\n\n================== All done:") print("\nDon't forget to put back the user folder !!!!") - ###### Plotting instructions and return first scan number - if FirstScan is not None: - log_print(comment="\nFirstScan = "+str(FirstScan)) - print('StartOfTheWeek_plot("'+branch+'",'+str(FirstScan)+')' ) - print('Beam center fit @ [2V,2H,1V,1H]:',list_position) - print('\nREMEMBER to update slit center using: update_slit_dict()') - + + ###### The end: + if list_position: + print('\nBeam center fit @ ['+GRT+',2V,2H,1V,1H]:',list_position) if kwargs['sound']: playsound() return list_position + + + +def update_slit_dict(mylist=None,**kwargs): + """ + Interactive function to update the slit position dictionary (Dict_Slit.txt) + mylist=['GRT',2V,2H,1V,1H] + **kwargs + readOnly == False, if true just pring the current slit dictionary + """ + filepath = "/home/beams22/29IDUSER/Documents/User_Macros/Macros_29id/IEX_Dictionaries/" + filename ='Dict_Slit.txt' + + kwargs.setdefault("readOnly",False) + + # print('\n\nWARNING: 2V slit should always be centered at zero ie steer M1 center beam on the grating') + # print('Increasing the roll moves the beam more positive: +0.05 pitch => ~ +0.04 slit position; Use:\n') + # print("Get_Mirror(1);Move_M1('RZ',x)") + # print("energy(500);mono(505);slit(200)") + # print("Scan_NarrowSlit_Go(which='2V',slit_parameters=[0.25, -2, 2, 0.25]) #for MEG; slit_parameters=[0.5, -2, 2, 0.25] for HEG") + # print("Scan_NarrowSlit_Go(which='2V',slit_parameters=[0.50, -2, 2, 0.25]) #for HEG") + # print('Once steering is completed, check 2H position:') + # print("Scan_NarrowSlit_Go(which='2H',slit_parameters=[0.25, -6, 6, 0.25]) ") + + + try: + slit_position=read_dict(filename) + print('\nCurrent dictionary:\n') + print(slit_position) + + except KeyError: + print("Unable to read dictionary") + return + + if kwargs['readOnly']== True: + return slit_position + + else: + if mylist: + if len(mylist) == 5: + grt,s2v,s2h,s1v,s1h=mylist + else: + print('\nInvalid list. No changes made in file.') + return + + else: + grt=input('\nWhich grating do you want to update (HEG or MEG) >') + s2v=input('New Slit 2B-V center >') + s2h=input('New Slit 2B-H center >') + s1v=input('New Slit 1A-V center >') + s1h=input('New Slit 1A-H center >') + + if grt == '' or s1h == '' or s1v == '' or s2h == '' or s2v == '': + print('\nMissing input. No changes made in file.') + return + + if grt[0] == '"' or grt[0]=="'": grt = grt[1:4] + + # new_slit_position={grt.upper():{'S1H':float(s1h),'S1V':float(s1v),'S2H':float(s2h),'S2V':float(s2v)}} # change order to match scan/fit order + if grt.upper() == 'MEG' or grt.upper() == 'HEG': + new_slit_position={grt.upper():{'S2V':float(s2v),'S2H':float(s2h),'S1V':float(s1v),'S1H':float(s1h)}} + else: + print('\nInvalid grating name. No changes made in file.') + return + + + slit_position.update(new_slit_position) + + + with open(join(filepath, filename), "a+") as f: + f.write('\n======= '+today()+': \n') + f.write(str(slit_position)) + f.write('\n') + print('\nWriting dictionary to:',join(filepath, filename)) + sleep(2) + apertures_set() + return slit_position + + + +def update_slit_dict(**kwargs): + """ + Interactive function to update the slit position dictionary (Dict_Slit.txt) + + **kwargs + readOnly == False, if true just pring the current slit dictionary + """ + filepath = "/home/beams22/29IDUSER/Documents/User_Macros/Macros_29id/IEX_Dictionaries/" + filename ='Dict_Slit.txt' + + kwargs.setdefault("readOnly",False) + + print('\n\nWARNING: 2V slit should always be centered at zero ie steer M1 center beam on the grating') + print('Increasing the roll moves the beam more positive: +0.05 pitch => ~ +0.04 slit position; Use:\n') + print("Get_Mirror(1);Move_M1('RZ',x)") + print("energy(500);mono(505);slit(200)") + print("Scan_NarrowSlit_Go(which='2V',slit_parameters=[0.25, -2, 2, 0.25]) #for MEG; slit_parameters=[0.5, -2, 2, 0.25] for HEG") + print("Scan_NarrowSlit_Go(which='2V',slit_parameters=[0.50, -2, 2, 0.25]) #for HEG") + print('Once steering is completed, check 2H position:') + print("Scan_NarrowSlit_Go(which='2H',slit_parameters=[0.25, -6, 6, 0.25]) ") + + try: + slit_position=read_dict(filename) + print('\nCurrent dictionary:\n') + print(slit_position) + + except KeyError: + print("Unable to read previous dictionary") + return + + if kwargs['readOnly']== True: + return slit_position + + else: + grt=input('\nWhich grating do you want to update (HEG or MEG) >') + s2v=input('New Slit 2B-V center >') + s2h=input('New Slit 2B-H center >') + s1v=input('New Slit 1A-V center >') + s1h=input('New Slit 1A-H center >') + + if grt == '' or s1h == '' or s1v == '' or s2h == '' or s2v == '': + print('\nMissing input. No changes made in file.') + return + + if grt[0] == '"' or grt[0]=="'": grt = grt[1:4] + + # new_slit_position={grt.upper():{'S1H':float(s1h),'S1V':float(s1v),'S2H':float(s2h),'S2V':float(s2v)}} # change order to match scan/fit order + new_slit_position={grt.upper():{'S2V':float(s2v),'S2H':float(s2h),'S1V':float(s1v),'S1H':float(s1h)}} + slit_position.update(new_slit_position) + + + with open(join(filepath, filename), "a+") as f: + f.write('\n======= '+today()+': \n') + f.write(str(slit_position)) + f.write('\n') + print('\nWriting dictionary to:',join(filepath, filename)) + + apertures_set() + return slit_position + +############################################################################################### +######################################### Start Of The Week plotting -- old!!!! ################################### +############################################################################################### + +def plot_StartOfTheWeek_DetDict(branch): + """ + returns the detectors for a given branch + + """ + DetDict={'c':(9,7,8,15),'d':(9,7,8,14)} + return DetDict[branch] + +def StartOfTheWeek_plot(branch,FirstScanNum,**kwargs): + """ + Plots the data from StartOfTheWeek + + branch is used to set the detectors + detCA4,detH,detV,detDiode=plot_StartOfTheWeek_Det(branch) + + FirstScanNum is based on slit1A + slit1A-H = FirstScanNum + slit1A-V = FirstScanNum + 1 + wire1-H = FirstScanNum + 2 + wire1-V = FirstScanNum + 3 + monoVslit = FirstScanNum + 4/5/6/7 + flux = FirstScanNum + 8 + + Slit 1A and Wire scans: determine ID steering and Slit1A position + Scan_MonoVsSlit: determine the steering from M0/M1 + by default the full range is plotted (pnt_first=0, pnt_last=inf) + refine the plot via + plot_StartOfTheWeek_mono(branch,FirstScanNum,pnt_first,pnt_last) + + kwargs: + filepath = None, uses current mda filepath unless specified + e.g. user : filepath='/net/s29data/export/data_29idc/2018_2/UserName/mda/' + e.g. staff: filepath='/net/s29data/export/data_29idb/2018_2/mda/' + prefix = None, uses current mda prefix unless specified + scanIOC = None, uses BL_ioc() unless specified + + scanType = ['slit1','wire','flux','monoVslit'], full set by default + + ref_firstScanNum to plot reference spectra + ref_branch = branch, unless specified + ref_filepath = filepath, unless specified + ref_prefix = prefix, unless specified + + steering out => moves beam more positive (20 urad ~ 0.5 mm) + steering up => moves beam more positive (20 urad ~ 0.5 mm) + +figure, axes = plt.subplots(nrows=2, ncols=2) +axes[0, 0].plot(x, y) + """ + + kwargs.setdefault('filepath',BL.mda.filepath()) + kwargs.setdefault('prefix',BL.mda.prefix()) + + kwargs.setdefault('scanType',['slit1','wire','flux','monoVslit']) + + kwargs.setdefault('ref_firstScanNum',None) + kwargs.setdefault('ref_fpath',None) + kwargs.setdefault('ref_branch',branch) + kwargs.setdefault('ref_filepath',BL.mda.filepath()) + kwargs.setdefault('ref_prefix',BL.mda.prefix()) + + kwargs.setdefault('debug',False) + + + scanNum=FirstScanNum + ref_firstScanNum=kwargs['ref_firstScanNum'] + detCA4,detH,detV,detDiode=plot_StartOfTheWeek_DetDict(branch) + + + if 'slit1' in kwargs['scanType']: + if kwargs['debug']: + print('slit1') + plot_StartOfTheWeek_slit1A(branch,scanNum,**kwargs) + scanNum+=2 + if kwargs['ref_firstScanNum'] is not None: + kwargs.update({'ref_firstScanNum':ref_firstScanNum+2}) + + + if 'wire' in kwargs['scanType']: + if kwargs['debug']: + print('wire') + plot_StartOfTheWeek_wire(branch,scanNum,**kwargs) + scanNum+=2 + if kwargs['ref_firstScanNum'] is not None: + ref_firstScanNum+=2 + kwargs.update({'ref_firstScanNum':ref_firstScanNum+2}) + + if 'monoVslit' in kwargs['scanType']: + d=IEXdata(scanNum,path=kwargs['filepath'],prefix=kwargs['prefix'],q=1) + if d.mda[scanNum].header.all['rank']<2: #quick + print(scanNum, detDiode) + V2=fit_mda(scanNum,detDiode,1,'gauss',filepath=kwargs['filepath'],prefix=kwargs['prefix'],scanIOC=kwargs['scanIOC'],title='2V - mda_'+str(scanNum)) + H2=fit_mda(scanNum+1,detDiode,1,'gauss',filepath=kwargs['filepath'],prefix=kwargs['prefix'],scanIOC=kwargs['scanIOC'],title='2H - mda_'+str(scanNum+1)) + V1=fit_mda(scanNum+2,detDiode,1,'gauss',filepath=kwargs['filepath'],prefix=kwargs['prefix'],scanIOC=kwargs['scanIOC'],title='1V - mda_'+str(scanNum+2)) + H1=fit_mda(scanNum+3,detDiode,1,'gauss',filepath=kwargs['filepath'],prefix=kwargs['prefix'],scanIOC=kwargs['scanIOC'],title='1H - mda_'+str(scanNum+3)) + plt.show() + print('\nFit positions:') + print(f"V2={round(V2,3)}") + print(f"H2={round(H2,3)}") + print(f"V1={round(V1,3)}") + print(f"H1={round(H1,3)}") + + else: #MonoVsSlit + print('\n# To plot the Mono vs Slit data use:\n') + print('\tplot_MonoVsSlit(\"'+branch+'\",'+str(scanNum)+','+str(detDiode)+',0,inf)'+'\t#2V') + print('\tplot_MonoVsSlit(\"'+branch+'\",'+str(scanNum+1)+','+str(detDiode)+',0,inf)'+'\t#2H') + print('\tplot_MonoVsSlit(\"'+branch+'\",'+str(scanNum+2)+','+str(detDiode)+',0,inf)'+'\t#1V') + print('\tplot_MonoVsSlit(\"'+branch+'\",'+str(scanNum+3)+','+str(detDiode)+',0,inf)'+'\t#1H') + print('\n# (pnt_first,pnt_last0=(0,inf) => plots all') + print('# select specific first/last to refine.') + + print('\nREMEMBER to update slit center using: \tupdate_slit_dict()' ) + scanNum+=4 + if kwargs['ref_firstScanNum'] is not None: + kwargs.update({'ref_firstScanNum':ref_firstScanNum+4}) + + if 'flux' in kwargs['scanType']: + if kwargs['debug']: + print('flux') + plot_StartOfTheWeek_flux(branch,scanNum,**kwargs) + +def plot_StartOfTheWeek_slit1A(branch,scanNum,**kwargs): + """ + plots the slit1A scans + scanNum = slit1A-H scanNum + """ + kwargs.setdefault('filepath',BL.mda.filepath()) + kwargs.setdefault('prefix',BL.mda.prefix()) + kwargs.setdefault('plotType',['slit1','wire','flux','monoVslit']) + kwargs.setdefault('ref_firstScanNum',None) + kwargs.setdefault('ref_fpath',None) + kwargs.setdefault('ref_branch',branch) + kwargs.setdefault('ref_filepath',BL.mda.filepath()) + kwargs.setdefault('ref_prefix',BL.mda.prefix()) + kwargs.setdefault('debug',False) + + detCA4,detH,detV,detDiode=plot_StartOfTheWeek_DetDict(branch) + ref_detCA4,ref_detH,ref_detV,ref_detDiode=plot_StartOfTheWeek_DetDict(kwargs['ref_branch']) + + figure, axes = plt.subplots(nrows=1, ncols=2,figsize=(10,3)) + for i,t in enumerate(['1H center scan','1V center scan']): + d=IEXdata(scanNum,path=kwargs['filepath'],prefix=kwargs['prefix'],q=1) + axes[i].plot(d.mda[scanNum].det[detCA4].scale['x'], d.mda[scanNum].det[detCA4].data,marker='x',label=str(scanNum)) + scanNum+=1 + if kwargs['ref_firstScanNum'] is not None: + ref_scanNum=kwargs['ref_firstScanNum']+i + ref_d=IEXdata(ref_scanNum,path=kwargs['ref_filepath'],prefix=kwargs['ref_prefix'],q=1) + axes[i].plot(ref_d.mda[ref_scanNum].det[ref_detCA4].scale['x'], ref_d.mda[ref_scanNum].det[ref_detCA4].data,marker='x',label=str(ref_scanNum)) + axes[i].grid(color='lightgray', linestyle='-', linewidth=0.5) + axes[i].title.set_text(t) + axes[i].legend() + plt.show() + print("\nsteering out => move beam more positive (10 urad ~ 0.25 mm)") + print("steering up => move beam more positive (10 urad ~ 0.25 mm)") + print("\nTo fit beam position use:\n") + print("detCA4,detH,detV,detDiode=plot_StartOfTheWeek_DetDict('"+kwargs['ref_branch']+"')") + print("fit_mda("+str(scanNum-2)+",detCA4,1,'gauss',xrange=(-1,1))") + print("fit_mda("+str(scanNum-1)+",detCA4,1,'gauss',xrange=(-1,1))\n") + + +def plot_StartOfTheWeek_wire(branch,scanNum,**kwargs): + """ + plots the wire scans + scanNum = wire-H scanNum + """ + kwargs.setdefault('filepath',BL.mda.filepath()) + kwargs.setdefault('prefix',BL.mda.prefix()) + kwargs.setdefault('plotType',['slit1','wire','flux','monoVslit']) + kwargs.setdefault('ref_firstScanNum',None) + kwargs.setdefault('ref_fpath',None) + kwargs.setdefault('ref_branch',branch) + kwargs.setdefault('ref_filepath',BL.mda.filepath()) + kwargs.setdefault('ref_prefix',BL.mda.prefix()) + kwargs.setdefault('debug',False) + + detCA4,detH,detV,detDiode=plot_StartOfTheWeek_DetDict(branch) + ref_detCA4,ref_detH,ref_detV,ref_detDiode=plot_StartOfTheWeek_DetDict(kwargs['ref_branch']) + + figure, axes = plt.subplots(nrows=1, ncols=2,figsize=(10,3)) + for i,t in enumerate(['H-wire','V-wire']): + d=IEXdata(scanNum,path=kwargs['filepath'],prefix=kwargs['prefix'],q=1) + #niceplot(d.mda[scanNum].det[DetDict[branch][1+i]],marker='x',label=str(scanNum)) + detNum=plot_StartOfTheWeek_DetDict(branch)[1+i] + axes[i].plot(d.mda[scanNum].det[detNum].scale['x'], d.mda[scanNum].det[detNum].data,marker='x',label=str(scanNum)) + scanNum+=1 + if kwargs['ref_firstScanNum'] is not None: + ref_scanNum=kwargs['ref_firstScanNum']+i + ref_d=IEXdata(ref_scanNum,path=kwargs['ref_filepath'],prefix=kwargs['ref_prefix'],q=1) + #niceplot(ref_d.mda[ref_scanNum].det[DetDict[kwargs["ref_branch"]][1+i]],marker='x',label=str(ref_scanNum)) + detNum=plot_StartOfTheWeek_DetDict(kwargs["ref_branch"])[1+i] + axes[i].plot(ref_d.mda[ref_scanNum].det[detNum].scale['x'], ref_d.mda[ref_scanNum].det[detNum].data,marker='x',label=str(ref_scanNum)) + axes[i].grid(color='lightgray', linestyle='-', linewidth=0.5) + axes[i].title.set_text(t) + axes[i].legend() + plt.show() + +def plot_StartOfTheWeek_flux(branch,scanNum,**kwargs): + """ + plots the wire scans + scanNum = wire-H scanNum + """ + kwargs.setdefault('filepath',BL.mda.filepath()) + kwargs.setdefault('prefix',BL.mda.prefix()) + kwargs.setdefault('plotType',['slit1','wire','flux','monoVslit']) + kwargs.setdefault('ref_firstScanNum',None) + kwargs.setdefault('ref_fpath',None) + kwargs.setdefault('ref_branch',branch) + kwargs.setdefault('ref_filepath',BL.mda.filepath()) + kwargs.setdefault('ref_prefix',BL.mda.prefix()) + kwargs.setdefault('debug',False) + + detCA4,detH,detV,detDiode=plot_StartOfTheWeek_DetDict(branch) + ref_detCA4,ref_detH,ref_detV,ref_detDiode=plot_StartOfTheWeek_DetDict(kwargs['ref_branch']) + + for t in ['ID peak @ 500eV']: + d=IEXdata(scanNum,path=kwargs['filepath'],prefix=kwargs['prefix'],q=1) + niceplot(d.mda[scanNum].det[detDiode],marker='x',label=str(scanNum)) + scanNum+=1 + if kwargs['ref_firstScanNum'] is not None: + ref_scanNum=kwargs['ref_firstScanNum']+2 + ref_d=IEXdata(ref_scanNum,path=kwargs['ref_filepath'],prefix=kwargs['ref_prefix'],q=1) + niceplot(ref_d.mda[ref_scanNum].det[ref_detDiode],marker='x',label=str(ref_scanNum)) + ref_scanNum+=1 + plt.grid(color='lightgray', linestyle='-', linewidth=0.5) + plt.title(t) + plt.legend() + plt.show() + +def plot_MonoVsSlit(branch,ScanNum,detDiode,pnt_first,pnt_last,norm=True,filepath=None,prefix=None,scanIOC=None): + """ + Plots Scan_MonoVsSlit to determine the steering from M0/M1 + To plot the full range (pnt_first=0, pnt_last=inf) + plot_StartofWeek_mono(branch,FirstScanNum+4,pnt_first,pnt_last) + + filepath: by default plot scans for the current data folder (as defined in BL_ioc() ScanRecord SaveData) + or specified folder path ending with '/': + e.g. user : filepath='/net/s29data/export/data_29idc/2018_2/UserName/mda/' + e.g. staff: filepath='/net/s29data/export/data_29idb/2018_2/mda/' + prefix: by default, uses prefix as defined in ScanRecord ("mda_") + """ + x,y,z,x_name,y_name,z_name=mda_2D(ScanNum,detDiode,filepath,prefix,scanIOC) + Which=str(y_name)[10:12] + if pnt_last is inf: + pnt_last=len(z)-1 + for i in range(pnt_first,pnt_last+1): + maxvalue=max(z[i]) + if norm == True: + plt.plot(x,z[i]/maxvalue,label='#'+str(i)+': '+str(round(y[i],2))) + else: + plt.plot(x,z[i],label='#'+str(i)+': '+str(round(y[i],2))) + plt.legend(bbox_to_anchor=(1, 0), loc='lower left', ncol=2,shadow=True, title="ScanNum: "+str(ScanNum)+"\nSlit-"+Which+" position", fancybox=True) + #plt.legend(loc='lower left',ncol=2, shadow=True, title="ScanNum: "+str(ScanNum)+"\nSlit-"+Which+" position", fancybox=True) + plt.grid(color='lightgray', linestyle='-', linewidth=0.5) + plt.show() + + +def read_flux(FileName='Flux_Curves.txt',FilePath="/home/beams22/29IDUSER/Documents/User_Macros/Macros_29id/IEX_Dictionaries/"): + print('test') + with open(join(FilePath, FileName)) as f: + for c,line in enumerate(f.readlines()): + if line[0] == '=': + lastdate=line[8:16] + print(lastdate) + if line[0] == '-' and line[-2] == 'x': + axis='x' + print(axis) + line_x=line + if line[0] == '-' and line[-2] == 'y': + axis='y' + print(axis) + line_y=line + mydict_x=ast.literal_eval(line_x) + mydict_y=ast.literal_eval(line_y) + return mydict_x,mydict_y + + -- GitLab